Fossil

Check-in [2dcc2397]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:minor cleanups to the json "command path" handling.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | json
Files: files | file ages | folders
SHA1:2dcc2397b5802610c16ced0809045bb27a7fb44b
User & Date: stephan 2011-09-16 17:53:36
Context
2011-09-16
18:29
more cleanups in the json arg/path handling. check-in: 35b9edba user: stephan tags: json
17:53
minor cleanups to the json "command path" handling. check-in: 2dcc2397 user: stephan tags: json
17:26
Consolidated server/cgi/cli path/arg handling (will break when add --options to CLI mode). check-in: c5fbcced user: stephan tags: json
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/json.c.

74
75
76
77
78
79
80

81
82

83
84
85
86
87
88
89
...
253
254
255
256
257
258
259


260
261
262
263
264
265
266
267
268
269
270
271
272
273













274
275
276
277

278
279
280
281
282
283
284
285
286
287
288


289
290
291

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
318
319
320
321
322
323
324
325
326
327



328
329
330
331


332
333
334
335
336
337
338
...
904
905
906
907
908
909
910
911
912
913
914

915
916
917
918
919
920
921
#endif

/*
** Holds keys used for various JSON API properties.
*/
static const struct FossilJsonKeys_{
  char const * authToken;

} FossilJsonKeys = {
  "authToken"  /*authToken*/

};

/*
** Given a FossilJsonCodes value, it returns a string suitable for use
** as a resultText string. Returns some unspecified string if errCode
** is not one of the FossilJsonCodes values.
*/
................................................................................
** Implicitly sets up the login information state in CGI mode,
** but does not perform any authentication here. It _might_
** (haven't tested this) die with an error if an auth cookie
** is malformed.
*/
static void json_mode_bootstrap(){
  char const * zPath = P("PATH_INFO");


  g.json.isJsonMode = 1;
  g.json.resultCode = 0;
  g.json.cmdOffset = -1;
  if( !g.isCGI && g.fullHttpReply ){
    g.isCGI = 1;
  }
  /*json_err( 1000, zPath, 1 ); exit(0);*/
  if( !zPath || !*zPath ){
    zPath = cson_string_cstr(cson_value_get_string(cson_cgi_getenv(&g.json.cgiCx,"e","PATH_INFO")));
  }
#if defined(NDEBUG)
  /* avoids debug messages on stderr in JSON mode */
  sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);
#endif













  if( zPath ){
    /* Translate fossil's PATH_INFO into cson_cgi for later
       convenience, to help consolidate how we handle CGI/server
       modes.

    */
    char const * p = zPath;
    char const * head = p;
    unsigned int len = 0;
    cson_value * piece = NULL;
    cson_value * arV = cson_value_new_array();
    cson_array * ar = cson_value_get_array(arV);
#if 0
    cson_cgi_setenv( &g.json.cgiCx, "FOSSIL_PATH_INFO", cson_value_new_string(zPath,strlen(zPath)) );
#endif
    cson_cgi_setenv( &g.json.cgiCx, "COMMAND_PATH", arV );


    for( ;*p!='?'; ++p){
      if( !*p || ('/' == *p) ){
        if( len ) {

          assert( head != p );
          piece = cson_value_new_string(head, len);
          cson_array_append( ar, piece );
          len = 0;
        }
        if( !*p ) break;
        head = p+1;
        continue;
      }
      ++len;
    }
  }
  /* g.json.reqPayload exists only to simplify some of our access to
     the request payload. We only use this in the context of Object
     payloads, not Arrays, strings, etc. */
  g.json.reqPayload.v = cson_cgi_getenv( &g.json.cgiCx, "p", "payload" );
  if( g.json.reqPayload.v ){
    g.json.reqPayload.o = cson_value_get_object( g.json.reqPayload.v )
        /* g.json.reqPayload.o may legally be NULL, which means only that
           g.json.reqPayload.v is-not-a Object.
        */;
  }
................................................................................
  else{
    db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
  }

}

/*
** Returns the ndx'th item in the PATH_INFO path, where index 0 is
** the position of the "json" part of the path. Returns NULL if ndx
** is out of bounds or there is no "json" path element.



*/
static char const * json_path_part(unsigned char ndx){
  cson_array * ar = g.isCGI
    ? cson_value_get_array(cson_cgi_getenv(&g.json.cgiCx,"a","COMMAND_PATH"))


    : NULL;
  if( g.isCGI ){
    assert((NULL!=ar) && "Internal error.");
  }
  if( g.json.cmdOffset < 0 ){
    /* first-time setup. */
    short i = g.isCGI ? 0 : 1;
................................................................................
void json_cmd_top(void){
  char const * cmd = NULL;
  unsigned int n;
  int rc = 1002;
  cson_value * payload = NULL;
  JsonPageDef const * pageDef;
  json_mode_bootstrap();
  db_find_and_open_repository(0, 0);
  if( g.argc<3 ){
    goto usage;
  }

  cmd = json_path_part(1);
  n = cmd ? strlen(cmd) : 0;
  if( n==0 ){
    goto usage;
  }
  cgi_set_content_type( cson_cgi_guess_content_type(&g.json.cgiCx) );
  pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]);







>

|
>







 







>
>







<
<
<




>
>
>
>
>
>
>
>
>
>
>
>
>
|


<
>

|
|
|
<
|
|
<
<
<
|
>
>



>

|
|










|
|







 







|
|
|
>
>
>



|
>
>







 







<



>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

291
292
293
294
295

296
297



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
...
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936
937
938
939
#endif

/*
** Holds keys used for various JSON API properties.
*/
static const struct FossilJsonKeys_{
  char const * authToken;
  char const * commandPath;
} FossilJsonKeys = {
  "authToken"  /*authToken*/,
  "COMMAND_PATH" /*commandPath*/
};

/*
** Given a FossilJsonCodes value, it returns a string suitable for use
** as a resultText string. Returns some unspecified string if errCode
** is not one of the FossilJsonCodes values.
*/
................................................................................
** Implicitly sets up the login information state in CGI mode,
** but does not perform any authentication here. It _might_
** (haven't tested this) die with an error if an auth cookie
** is malformed.
*/
static void json_mode_bootstrap(){
  char const * zPath = P("PATH_INFO");
  cson_value * pathSplit =
    cson_cgi_getenv(&g.json.cgiCx,"e","PATH_INFO_SPLIT");
  g.json.isJsonMode = 1;
  g.json.resultCode = 0;
  g.json.cmdOffset = -1;
  if( !g.isCGI && g.fullHttpReply ){
    g.isCGI = 1;
  }
  /*json_err( 1000, zPath, 1 ); exit(0);*/



#if defined(NDEBUG)
  /* avoids debug messages on stderr in JSON mode */
  sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);
#endif

  /*
    The following if/else block translates the PATH_INFO path into an
    internal list so that we can simplify command dispatching later
    on.
  */
  if( pathSplit ){
    /* cson_cgi already did this, so let's just re-use it. This does
       not happen in "plain server" mode, but does in CGI mode.
    */
    cson_cgi_setenv( &g.json.cgiCx,
                     FossilJsonKeys.commandPath,
                     pathSplit );
  }else if( zPath ){
    /* Translate fossil's PATH_INFO into cson_cgi for later
       convenience, to help consolidate how we handle CGI/server

       modes. This block is hit when running in plain server mode.
    */
    char const * p = zPath; /* current byte */
    char const * head = p;  /* current start-of-token */
    unsigned int len = 0;   /* current token's lengh */

    cson_value * arV = cson_value_new_array(); /* value to store path in */
    cson_array * ar = cson_value_get_array(arV); /* the real array object */



    cson_cgi_setenv( &g.json.cgiCx,
                     FossilJsonKeys.commandPath,
                     arV );
    for( ;*p!='?'; ++p){
      if( !*p || ('/' == *p) ){
        if( len ) {
          cson_value * part;
          assert( head != p );
          part = cson_value_new_string(head, len);
          cson_array_append( ar, part );
          len = 0;
        }
        if( !*p ) break;
        head = p+1;
        continue;
      }
      ++len;
    }
  }
  /* g.json.reqPayload exists only to simplify some of our access to
     the request payload. We currently only use this in the context of
     Object payloads, not Arrays, strings, etc. */
  g.json.reqPayload.v = cson_cgi_getenv( &g.json.cgiCx, "p", "payload" );
  if( g.json.reqPayload.v ){
    g.json.reqPayload.o = cson_value_get_object( g.json.reqPayload.v )
        /* g.json.reqPayload.o may legally be NULL, which means only that
           g.json.reqPayload.v is-not-a Object.
        */;
  }
................................................................................
  else{
    db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
  }

}

/*
** Returns the ndx'th item in the "command path", where index 0 is the
** position of the "json" part of the path. Returns NULL if ndx is out
** of bounds or there is no "json" path element.
**
** In CLI mode the "path" is the list of arguments (skipping argv[0]).
** In server/CGI modes the path is the PATH_INFO.
*/
static char const * json_path_part(unsigned char ndx){
  cson_array * ar = g.isCGI
    ? cson_value_get_array(cson_cgi_getenv(&g.json.cgiCx,
                                           "a",
                                           FossilJsonKeys.commandPath))
    : NULL;
  if( g.isCGI ){
    assert((NULL!=ar) && "Internal error.");
  }
  if( g.json.cmdOffset < 0 ){
    /* first-time setup. */
    short i = g.isCGI ? 0 : 1;
................................................................................
void json_cmd_top(void){
  char const * cmd = NULL;
  unsigned int n;
  int rc = 1002;
  cson_value * payload = NULL;
  JsonPageDef const * pageDef;
  json_mode_bootstrap();

  if( g.argc<3 ){
    goto usage;
  }
  db_find_and_open_repository(0, 0);
  cmd = json_path_part(1);
  n = cmd ? strlen(cmd) : 0;
  if( n==0 ){
    goto usage;
  }
  cgi_set_content_type( cson_cgi_guess_content_type(&g.json.cgiCx) );
  pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]);

Changes to src/main.c.

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  FILE *httpIn;           /* Accept HTTP input from here */
  FILE *httpOut;          /* Send HTTP output here */
  int xlinkClusterOnly;   /* Set when cloning.  Only process clusters */
  int fTimeFormat;        /* 1 for UTC.  2 for localtime.  0 not yet selected */
  int *aCommitFile;       /* Array of files to be committed */
  int markPrivate;        /* All new artifacts are private if true */
  int clockSkewSeen;      /* True if clocks on client and server out of sync */
  int isCGI;              /* True if running in HTTP/CGI mode, else assume CLI. */

  int urlIsFile;          /* True if a "file:" url */
  int urlIsHttps;         /* True if a "https:" url */
  int urlIsSsh;           /* True if an "ssh:" url */
  char *urlName;          /* Hostname for http: or filename for file: */
  char *urlHostname;      /* The HOST: parameter on http headers */
  char *urlProtocol;      /* "http" or "https" */







|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  FILE *httpIn;           /* Accept HTTP input from here */
  FILE *httpOut;          /* Send HTTP output here */
  int xlinkClusterOnly;   /* Set when cloning.  Only process clusters */
  int fTimeFormat;        /* 1 for UTC.  2 for localtime.  0 not yet selected */
  int *aCommitFile;       /* Array of files to be committed */
  int markPrivate;        /* All new artifacts are private if true */
  int clockSkewSeen;      /* True if clocks on client and server out of sync */
  int isCGI;              /* True if running in server/CGI modes, else assume CLI. */

  int urlIsFile;          /* True if a "file:" url */
  int urlIsHttps;         /* True if a "https:" url */
  int urlIsSsh;           /* True if an "ssh:" url */
  char *urlName;          /* Hostname for http: or filename for file: */
  char *urlHostname;      /* The HOST: parameter on http headers */
  char *urlProtocol;      /* "http" or "https" */