Fossil SCM

more cleanups in the json arg/path handling.

stephan 2011-09-16 18:29 UTC json
Commit 35b9edba835d0adf255af2069f99cba414bf62c1
1 file changed +63 -37
+63 -37
--- src/json.c
+++ src/json.c
@@ -219,12 +219,13 @@
219219
if( !g.json.authToken ){
220220
/* Try to get an authorization token from GET parameter, POSTed
221221
JSON, or fossil cookie (in that order). */
222222
g.json.authToken = cson_cgi_getenv(&g.json.cgiCx, "gp", FossilJsonKeys.authToken)
223223
/* reminder to self: cson_cgi does not have access to the cookies
224
- because fossil's core consumes them. Thus we cannot use "gpc"
225
- here.
224
+ because fossil's core consumes them. Thus we cannot use "agpc"
225
+ here. We use "a" (App-specific) as a place to store fossil's
226
+ cookie value.
226227
*/;
227228
if( g.json.authToken){
228229
/* tell fossil to use this login info.
229230
230231
FIXME: because the JSON bits don't carry around login_cookie_name(),
@@ -250,26 +251,34 @@
250251
return g.json.authToken;
251252
}
252253
253254
/*
254255
** Performs some common initialization of JSON-related state.
255
-** Implicitly sets up the login information state in CGI mode,
256
-** but does not perform any authentication here. It _might_
257
-** (haven't tested this) die with an error if an auth cookie
258
-** is malformed.
256
+** Implicitly sets up the login information state in CGI mode, but
257
+** does not perform any authentication here. It _might_ (haven't
258
+** tested this) die with an error if an auth cookie is malformed.
259
+**
260
+** This must be called by the top-level JSON command dispatching code
261
+** before they do any work.
262
+**
263
+** This must only be called once, or an assertion may be triggered.
259264
*/
260265
static void json_mode_bootstrap(){
266
+ static char once = 0 /* guard against multiple runs */;
261267
char const * zPath = P("PATH_INFO");
262268
cson_value * pathSplit =
263269
cson_cgi_getenv(&g.json.cgiCx,"e","PATH_INFO_SPLIT");
270
+ assert( (0==once) && "json_mode_bootstrap() called too many times!");
271
+ if( once ) return;
272
+ else once = 1;
264273
g.json.isJsonMode = 1;
265274
g.json.resultCode = 0;
266275
g.json.cmdOffset = -1;
267276
if( !g.isCGI && g.fullHttpReply ){
277
+ /* workaround for server mode, so we see it as CGI mode. */
268278
g.isCGI = 1;
269279
}
270
- /*json_err( 1000, zPath, 1 ); exit(0);*/
271280
#if defined(NDEBUG)
272281
/* avoids debug messages on stderr in JSON mode */
273282
sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);
274283
#endif
275284
@@ -280,40 +289,58 @@
280289
*/
281290
if( pathSplit ){
282291
/* cson_cgi already did this, so let's just re-use it. This does
283292
not happen in "plain server" mode, but does in CGI mode.
284293
*/
294
+ assert( g.isCGI && "g.isCGI should have been set by now." );
285295
cson_cgi_setenv( &g.json.cgiCx,
286296
FossilJsonKeys.commandPath,
287297
pathSplit );
288
- }else if( zPath ){
289
- /* Translate fossil's PATH_INFO into cson_cgi for later
290
- convenience, to help consolidate how we handle CGI/server
291
- modes. This block is hit when running in plain server mode.
292
- */
293
- char const * p = zPath; /* current byte */
294
- char const * head = p; /* current start-of-token */
295
- unsigned int len = 0; /* current token's lengh */
296
- cson_value * arV = cson_value_new_array(); /* value to store path in */
297
- cson_array * ar = cson_value_get_array(arV); /* the real array object */
298
+ }else{ /* either CLI or server mode... */
299
+ cson_value * arV /* value to store path in */;
300
+ cson_array * ar /* the "real" array object */;
301
+ arV = cson_value_new_array();
302
+ ar = cson_value_get_array(arV);
298303
cson_cgi_setenv( &g.json.cgiCx,
299304
FossilJsonKeys.commandPath,
300305
arV );
301
- for( ;*p!='?'; ++p){
302
- if( !*p || ('/' == *p) ){
303
- if( len ) {
304
- cson_value * part;
305
- assert( head != p );
306
- part = cson_value_new_string(head, len);
307
- cson_array_append( ar, part );
308
- len = 0;
309
- }
310
- if( !*p ) break;
311
- head = p+1;
312
- continue;
313
- }
314
- ++len;
306
+ if( zPath ){
307
+ /* Translate fossil's PATH_INFO into cson_cgi for later
308
+ convenience, to help consolidate how we handle CGI/server
309
+ modes. This block is hit when running in plain server mode.
310
+ */
311
+ char const * p = zPath /* current byte */;
312
+ char const * head = p /* current start-of-token */;
313
+ unsigned int len = 0 /* current token's lengh */;
314
+ assert( g.isCGI && "g.isCGI should have been set by now." );
315
+ for( ;*p!='?'; ++p){
316
+ if( !*p || ('/' == *p) ){
317
+ if( len ) {
318
+ cson_value * part;
319
+ assert( head != p );
320
+ part = cson_value_new_string(head, len);
321
+ cson_array_append( ar, part );
322
+ len = 0;
323
+ }
324
+ if( !*p ) break;
325
+ head = p+1;
326
+ continue;
327
+ }
328
+ ++len;
329
+ }
330
+ }else{
331
+ /* assume CLI mode */
332
+ int i;
333
+ char const * arg;
334
+ cson_value * part;
335
+ assert( (!g.isCGI) && "g.isCGI set and we do not expect that to be the case here." );
336
+ for(i = 1; i < g.argc; ++i ){
337
+ arg = g.argv[i];
338
+ if( !arg || !*arg ) continue;
339
+ part = cson_value_new_string(arg,strlen(arg));
340
+ cson_array_append(ar, part);
341
+ }
315342
}
316343
}
317344
/* g.json.reqPayload exists only to simplify some of our access to
318345
the request payload. We currently only use this in the context of
319346
Object payloads, not Arrays, strings, etc. */
@@ -324,25 +351,24 @@
324351
g.json.reqPayload.v is-not-a Object.
325352
*/;
326353
}
327354
json_auth_token()/* will copy our auth token, if any, to fossil's core. */;
328355
if( g.isCGI ){
329
- login_check_credentials();
356
+ login_check_credentials()/* populates g.perm */;
330357
}
331358
else{
332359
db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
333360
}
334
-
335361
}
336362
337363
/*
338364
** Returns the ndx'th item in the "command path", where index 0 is the
339365
** position of the "json" part of the path. Returns NULL if ndx is out
340366
** of bounds or there is no "json" path element.
341367
**
342368
** In CLI mode the "path" is the list of arguments (skipping argv[0]).
343
-** In server/CGI modes the path is the PATH_INFO.
369
+** In server/CGI modes the path is taken from PATH_INFO.
344370
*/
345371
static char const * json_path_part(unsigned char ndx){
346372
cson_array * ar = g.isCGI
347373
? cson_value_get_array(cson_cgi_getenv(&g.json.cgiCx,
348374
"a",
@@ -351,11 +377,11 @@
351377
if( g.isCGI ){
352378
assert((NULL!=ar) && "Internal error.");
353379
}
354380
if( g.json.cmdOffset < 0 ){
355381
/* first-time setup. */
356
- short i = g.isCGI ? 0 : 1;
382
+ short i = g.isCGI ? 0 : 1/*skip argv[0] in CLI mode*/;
357383
#define PARTAT cson_string_cstr( \
358384
cson_value_get_string( \
359385
cson_array_get(ar,i) \
360386
))
361387
#define NEXT (g.isCGI \
@@ -367,14 +393,14 @@
367393
g.json.cmdOffset = i;
368394
break;
369395
}
370396
++i;
371397
tok = NEXT;
398
+ }
399
+ }
372400
#undef NEXT
373401
#undef PARTAT
374
- }
375
- }
376402
if( g.json.cmdOffset < 0 ){
377403
return NULL;
378404
}else{
379405
ndx = g.json.cmdOffset + ndx;
380406
return g.isCGI
381407
--- src/json.c
+++ src/json.c
@@ -219,12 +219,13 @@
219 if( !g.json.authToken ){
220 /* Try to get an authorization token from GET parameter, POSTed
221 JSON, or fossil cookie (in that order). */
222 g.json.authToken = cson_cgi_getenv(&g.json.cgiCx, "gp", FossilJsonKeys.authToken)
223 /* reminder to self: cson_cgi does not have access to the cookies
224 because fossil's core consumes them. Thus we cannot use "gpc"
225 here.
 
226 */;
227 if( g.json.authToken){
228 /* tell fossil to use this login info.
229
230 FIXME: because the JSON bits don't carry around login_cookie_name(),
@@ -250,26 +251,34 @@
250 return g.json.authToken;
251 }
252
253 /*
254 ** Performs some common initialization of JSON-related state.
255 ** Implicitly sets up the login information state in CGI mode,
256 ** but does not perform any authentication here. It _might_
257 ** (haven't tested this) die with an error if an auth cookie
258 ** is malformed.
 
 
 
 
259 */
260 static void json_mode_bootstrap(){
 
261 char const * zPath = P("PATH_INFO");
262 cson_value * pathSplit =
263 cson_cgi_getenv(&g.json.cgiCx,"e","PATH_INFO_SPLIT");
 
 
 
264 g.json.isJsonMode = 1;
265 g.json.resultCode = 0;
266 g.json.cmdOffset = -1;
267 if( !g.isCGI && g.fullHttpReply ){
 
268 g.isCGI = 1;
269 }
270 /*json_err( 1000, zPath, 1 ); exit(0);*/
271 #if defined(NDEBUG)
272 /* avoids debug messages on stderr in JSON mode */
273 sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);
274 #endif
275
@@ -280,40 +289,58 @@
280 */
281 if( pathSplit ){
282 /* cson_cgi already did this, so let's just re-use it. This does
283 not happen in "plain server" mode, but does in CGI mode.
284 */
 
285 cson_cgi_setenv( &g.json.cgiCx,
286 FossilJsonKeys.commandPath,
287 pathSplit );
288 }else if( zPath ){
289 /* Translate fossil's PATH_INFO into cson_cgi for later
290 convenience, to help consolidate how we handle CGI/server
291 modes. This block is hit when running in plain server mode.
292 */
293 char const * p = zPath; /* current byte */
294 char const * head = p; /* current start-of-token */
295 unsigned int len = 0; /* current token's lengh */
296 cson_value * arV = cson_value_new_array(); /* value to store path in */
297 cson_array * ar = cson_value_get_array(arV); /* the real array object */
298 cson_cgi_setenv( &g.json.cgiCx,
299 FossilJsonKeys.commandPath,
300 arV );
301 for( ;*p!='?'; ++p){
302 if( !*p || ('/' == *p) ){
303 if( len ) {
304 cson_value * part;
305 assert( head != p );
306 part = cson_value_new_string(head, len);
307 cson_array_append( ar, part );
308 len = 0;
309 }
310 if( !*p ) break;
311 head = p+1;
312 continue;
313 }
314 ++len;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315 }
316 }
317 /* g.json.reqPayload exists only to simplify some of our access to
318 the request payload. We currently only use this in the context of
319 Object payloads, not Arrays, strings, etc. */
@@ -324,25 +351,24 @@
324 g.json.reqPayload.v is-not-a Object.
325 */;
326 }
327 json_auth_token()/* will copy our auth token, if any, to fossil's core. */;
328 if( g.isCGI ){
329 login_check_credentials();
330 }
331 else{
332 db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
333 }
334
335 }
336
337 /*
338 ** Returns the ndx'th item in the "command path", where index 0 is the
339 ** position of the "json" part of the path. Returns NULL if ndx is out
340 ** of bounds or there is no "json" path element.
341 **
342 ** In CLI mode the "path" is the list of arguments (skipping argv[0]).
343 ** In server/CGI modes the path is the PATH_INFO.
344 */
345 static char const * json_path_part(unsigned char ndx){
346 cson_array * ar = g.isCGI
347 ? cson_value_get_array(cson_cgi_getenv(&g.json.cgiCx,
348 "a",
@@ -351,11 +377,11 @@
351 if( g.isCGI ){
352 assert((NULL!=ar) && "Internal error.");
353 }
354 if( g.json.cmdOffset < 0 ){
355 /* first-time setup. */
356 short i = g.isCGI ? 0 : 1;
357 #define PARTAT cson_string_cstr( \
358 cson_value_get_string( \
359 cson_array_get(ar,i) \
360 ))
361 #define NEXT (g.isCGI \
@@ -367,14 +393,14 @@
367 g.json.cmdOffset = i;
368 break;
369 }
370 ++i;
371 tok = NEXT;
 
 
372 #undef NEXT
373 #undef PARTAT
374 }
375 }
376 if( g.json.cmdOffset < 0 ){
377 return NULL;
378 }else{
379 ndx = g.json.cmdOffset + ndx;
380 return g.isCGI
381
--- src/json.c
+++ src/json.c
@@ -219,12 +219,13 @@
219 if( !g.json.authToken ){
220 /* Try to get an authorization token from GET parameter, POSTed
221 JSON, or fossil cookie (in that order). */
222 g.json.authToken = cson_cgi_getenv(&g.json.cgiCx, "gp", FossilJsonKeys.authToken)
223 /* reminder to self: cson_cgi does not have access to the cookies
224 because fossil's core consumes them. Thus we cannot use "agpc"
225 here. We use "a" (App-specific) as a place to store fossil's
226 cookie value.
227 */;
228 if( g.json.authToken){
229 /* tell fossil to use this login info.
230
231 FIXME: because the JSON bits don't carry around login_cookie_name(),
@@ -250,26 +251,34 @@
251 return g.json.authToken;
252 }
253
254 /*
255 ** Performs some common initialization of JSON-related state.
256 ** Implicitly sets up the login information state in CGI mode, but
257 ** does not perform any authentication here. It _might_ (haven't
258 ** tested this) die with an error if an auth cookie is malformed.
259 **
260 ** This must be called by the top-level JSON command dispatching code
261 ** before they do any work.
262 **
263 ** This must only be called once, or an assertion may be triggered.
264 */
265 static void json_mode_bootstrap(){
266 static char once = 0 /* guard against multiple runs */;
267 char const * zPath = P("PATH_INFO");
268 cson_value * pathSplit =
269 cson_cgi_getenv(&g.json.cgiCx,"e","PATH_INFO_SPLIT");
270 assert( (0==once) && "json_mode_bootstrap() called too many times!");
271 if( once ) return;
272 else once = 1;
273 g.json.isJsonMode = 1;
274 g.json.resultCode = 0;
275 g.json.cmdOffset = -1;
276 if( !g.isCGI && g.fullHttpReply ){
277 /* workaround for server mode, so we see it as CGI mode. */
278 g.isCGI = 1;
279 }
 
280 #if defined(NDEBUG)
281 /* avoids debug messages on stderr in JSON mode */
282 sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);
283 #endif
284
@@ -280,40 +289,58 @@
289 */
290 if( pathSplit ){
291 /* cson_cgi already did this, so let's just re-use it. This does
292 not happen in "plain server" mode, but does in CGI mode.
293 */
294 assert( g.isCGI && "g.isCGI should have been set by now." );
295 cson_cgi_setenv( &g.json.cgiCx,
296 FossilJsonKeys.commandPath,
297 pathSplit );
298 }else{ /* either CLI or server mode... */
299 cson_value * arV /* value to store path in */;
300 cson_array * ar /* the "real" array object */;
301 arV = cson_value_new_array();
302 ar = cson_value_get_array(arV);
 
 
 
 
 
303 cson_cgi_setenv( &g.json.cgiCx,
304 FossilJsonKeys.commandPath,
305 arV );
306 if( zPath ){
307 /* Translate fossil's PATH_INFO into cson_cgi for later
308 convenience, to help consolidate how we handle CGI/server
309 modes. This block is hit when running in plain server mode.
310 */
311 char const * p = zPath /* current byte */;
312 char const * head = p /* current start-of-token */;
313 unsigned int len = 0 /* current token's lengh */;
314 assert( g.isCGI && "g.isCGI should have been set by now." );
315 for( ;*p!='?'; ++p){
316 if( !*p || ('/' == *p) ){
317 if( len ) {
318 cson_value * part;
319 assert( head != p );
320 part = cson_value_new_string(head, len);
321 cson_array_append( ar, part );
322 len = 0;
323 }
324 if( !*p ) break;
325 head = p+1;
326 continue;
327 }
328 ++len;
329 }
330 }else{
331 /* assume CLI mode */
332 int i;
333 char const * arg;
334 cson_value * part;
335 assert( (!g.isCGI) && "g.isCGI set and we do not expect that to be the case here." );
336 for(i = 1; i < g.argc; ++i ){
337 arg = g.argv[i];
338 if( !arg || !*arg ) continue;
339 part = cson_value_new_string(arg,strlen(arg));
340 cson_array_append(ar, part);
341 }
342 }
343 }
344 /* g.json.reqPayload exists only to simplify some of our access to
345 the request payload. We currently only use this in the context of
346 Object payloads, not Arrays, strings, etc. */
@@ -324,25 +351,24 @@
351 g.json.reqPayload.v is-not-a Object.
352 */;
353 }
354 json_auth_token()/* will copy our auth token, if any, to fossil's core. */;
355 if( g.isCGI ){
356 login_check_credentials()/* populates g.perm */;
357 }
358 else{
359 db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
360 }
 
361 }
362
363 /*
364 ** Returns the ndx'th item in the "command path", where index 0 is the
365 ** position of the "json" part of the path. Returns NULL if ndx is out
366 ** of bounds or there is no "json" path element.
367 **
368 ** In CLI mode the "path" is the list of arguments (skipping argv[0]).
369 ** In server/CGI modes the path is taken from PATH_INFO.
370 */
371 static char const * json_path_part(unsigned char ndx){
372 cson_array * ar = g.isCGI
373 ? cson_value_get_array(cson_cgi_getenv(&g.json.cgiCx,
374 "a",
@@ -351,11 +377,11 @@
377 if( g.isCGI ){
378 assert((NULL!=ar) && "Internal error.");
379 }
380 if( g.json.cmdOffset < 0 ){
381 /* first-time setup. */
382 short i = g.isCGI ? 0 : 1/*skip argv[0] in CLI mode*/;
383 #define PARTAT cson_string_cstr( \
384 cson_value_get_string( \
385 cson_array_get(ar,i) \
386 ))
387 #define NEXT (g.isCGI \
@@ -367,14 +393,14 @@
393 g.json.cmdOffset = i;
394 break;
395 }
396 ++i;
397 tok = NEXT;
398 }
399 }
400 #undef NEXT
401 #undef PARTAT
 
 
402 if( g.json.cmdOffset < 0 ){
403 return NULL;
404 }else{
405 ndx = g.json.cmdOffset + ndx;
406 return g.isCGI
407

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button