Fossil

Check-in [af72cc75]
Login

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

Overview
Comment:Minor error handling cleanups (nicer resultText strings). Removed a call to sqlite3_config() from the JSON bootstrap code which _seems_ to be the cause of an SQLITE_MISUSE warning.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | json-multitag-test | json
Files: files | file ages | folders
SHA1:af72cc7599d357f15cabba936ca3d891bbfd7c44
User & Date: stephan 2011-10-02 23:59:26
Context
2011-10-04
09:06
/json/wiki/get argument handling cleanup so that it works with the newer command=... approach. check-in: 96fe10ab user: stephan tags: json-multitag-test, json
2011-10-02
23:59
Minor error handling cleanups (nicer resultText strings). Removed a call to sqlite3_config() from the JSON bootstrap code which _seems_ to be the cause of an SQLITE_MISUSE warning. check-in: af72cc75 user: stephan tags: json-multitag-test, json
23:43
Accommodated recent API changes. check-in: 901a0133 user: stephan tags: json-multitag-test, json
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/json.c.

897
898
899
900
901
902
903
904



905



906
907
908
909
910
911
912
    g.isHTTP = 1;
  }

  if(g.isHTTP){
    cgi_set_content_type(json_guess_content_type())
      /* reminder: must be done after g.json.jsonp is initialized */
      ;
    /* avoids debug messages on stderr in JSON mode */



    sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);



  }

  g.json.cmd.v = cson_value_new_array();
  g.json.cmd.a = cson_value_get_array(g.json.cmd.v);
  json_gc_add( FossilJsonKeys.commandPath, g.json.cmd.v, 1 );
  /*
    The following if/else block translates the PATH_INFO path (in







|
>
>
>
|
>
>
>







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
    g.isHTTP = 1;
  }

  if(g.isHTTP){
    cgi_set_content_type(json_guess_content_type())
      /* reminder: must be done after g.json.jsonp is initialized */
      ;
#if 0
    /* Calling this seems to trigger an SQLITE_MISUSE warning???
       Maybe it's not legal to set the logger more than once?
    */
    sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0)
        /* avoids debug messages on stderr in JSON mode */
        ;
#endif
  }

  g.json.cmd.v = cson_value_new_array();
  g.json.cmd.a = cson_value_get_array(g.json.cmd.v);
  json_gc_add( FossilJsonKeys.commandPath, g.json.cmd.v, 1 );
  /*
    The following if/else block translates the PATH_INFO path (in

Changes to src/json_branch.c.

67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
...
306
307
308
309
310
311
312



313
314
315
316
317
318
319
320
321

322
323
324
325
326
327
328
  cson_value * listV;
  cson_array * list;
  char const * range = NULL;
  int which = 0;
  char * sawConversionError = NULL;
  Stmt q;
  if( !g.perm.Read ){
    g.json.resultCode = FSL_JSON_E_DENIED;

    return NULL;
  }
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  listV = cson_value_new_array();
  list = cson_value_get_array(listV);
  if(!g.isHTTP){
................................................................................
  /* arugable for JSON mode? */
  if( !g.isHTTP && !isPrivate ) autosync(AUTOSYNC_PUSH);
#endif
  return 0;
}





static cson_value * json_branch_create(){
  cson_value * payV = NULL;
  cson_object * pay = NULL;
  int rc = 0;
  BranchCreateOptions opt;
  char * zUuid = NULL;
  int rid = 0;
  if( !g.perm.Write ){
    g.json.resultCode = FSL_JSON_E_DENIED;

    return NULL;
  }
  if(0){
    char const * x = json_command_arg(g.json.dispatchDepth+1);
    fprintf(stderr,"command arg=%s\n",x);
    assert(0);
  }







|
>







 







>
>
>








|
>







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  cson_value * listV;
  cson_array * list;
  char const * range = NULL;
  int which = 0;
  char * sawConversionError = NULL;
  Stmt q;
  if( !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' permissions.");
    return NULL;
  }
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  listV = cson_value_new_array();
  list = cson_value_get_array(listV);
  if(!g.isHTTP){
................................................................................
  /* arugable for JSON mode? */
  if( !g.isHTTP && !isPrivate ) autosync(AUTOSYNC_PUSH);
#endif
  return 0;
}


/*
** Impl of /json/branch/create.
*/
static cson_value * json_branch_create(){
  cson_value * payV = NULL;
  cson_object * pay = NULL;
  int rc = 0;
  BranchCreateOptions opt;
  char * zUuid = NULL;
  int rid = 0;
  if( !g.perm.Write ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'i' permissions.");
    return NULL;
  }
  if(0){
    char const * x = json_command_arg(g.json.dispatchDepth+1);
    fprintf(stderr,"command arg=%s\n",x);
    assert(0);
  }

Changes to src/json_timeline.c.

51
52
53
54
55
56
57










58
59
60
61
62
63
64
...
373
374
375
376
377
378
379
380
381



382
383
384
385
386
387
388
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
...
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554

/*
** Implements the /json/timeline family of pages/commands. Far from
** complete.
**
*/
cson_value * json_page_timeline(){










  return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]);
}

/*
** Create a temporary table suitable for storing timeline data.
*/
static void json_timeline_temp_table(void){
................................................................................
  cson_array * list = NULL;
  int check = 0;
  int showFiles = 0;
  Stmt q = empty_Stmt;
  char warnRowToJsonFailed = 0;
  char warnStringToArrayFailed = 0;
  Blob sql = empty_blob;
  if( !g.perm.Read/* && !g.perm.RdTkt && !g.perm.RdWiki*/ ){
    g.json.resultCode = FSL_JSON_E_DENIED;



    return NULL;
  }
  if( g.isHTTP ){
    showFiles = json_getenv_bool("files",0);
  }else{
    showFiles = 0!=find_option("files", "f",0);
  }
................................................................................
  cson_object * pay = NULL;
  cson_value * tmp = NULL;
  cson_value * listV = NULL;
  cson_array * list = NULL;
  int check = 0;
  Stmt q = empty_Stmt;
  Blob sql = empty_blob;
  if( !g.perm.Read || !g.perm.RdWiki ){
    g.json.resultCode = FSL_JSON_E_DENIED;
    return NULL;
  }
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  check = json_timeline_setup_sql( "w", &sql, pay );
  if(check){
    g.json.resultCode = check;
................................................................................
  cson_object * pay = NULL;
  cson_value * tmp = NULL;
  cson_value * listV = NULL;
  cson_array * list = NULL;
  int check = 0;
  Stmt q = empty_Stmt;
  Blob sql = empty_blob;
  if( !g.perm.Read || !g.perm.RdTkt ){
    g.json.resultCode = FSL_JSON_E_DENIED;
    return NULL;
  }
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  check = json_timeline_setup_sql( "t", &sql, pay );
  if(check){
    g.json.resultCode = check;







>
>
>
>
>
>
>
>
>
>







 







|
|
>
>
>







 







|
|







 







|
|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
...
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

/*
** Implements the /json/timeline family of pages/commands. Far from
** complete.
**
*/
cson_value * json_page_timeline(){
#if 0
  /* The original timeline code does not require 'h' access,
     but it arguably should. For JSON mode i think one could argue
     that History permissions are required.
  */
  if(! g.perm.History && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED, "Timeline requires 'h' or 'o' access.");
    return NULL;
  }
#endif
  return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]);
}

/*
** Create a temporary table suitable for storing timeline data.
*/
static void json_timeline_temp_table(void){
................................................................................
  cson_array * list = NULL;
  int check = 0;
  int showFiles = 0;
  Stmt q = empty_Stmt;
  char warnRowToJsonFailed = 0;
  char warnStringToArrayFailed = 0;
  Blob sql = empty_blob;
  if( !g.perm.Read ){
    /* IMO this falls more under the category of g.perm.History, but
       i'm following the original timeline impl here.
    */
    json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'o' access." );
    return NULL;
  }
  if( g.isHTTP ){
    showFiles = json_getenv_bool("files",0);
  }else{
    showFiles = 0!=find_option("files", "f",0);
  }
................................................................................
  cson_object * pay = NULL;
  cson_value * tmp = NULL;
  cson_value * listV = NULL;
  cson_array * list = NULL;
  int check = 0;
  Stmt q = empty_Stmt;
  Blob sql = empty_blob;
  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err( FSL_JSON_E_DENIED, "Wiki timeline requires 'o' or 'j' access.");
    return NULL;
  }
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  check = json_timeline_setup_sql( "w", &sql, pay );
  if(check){
    g.json.resultCode = check;
................................................................................
  cson_object * pay = NULL;
  cson_value * tmp = NULL;
  cson_value * listV = NULL;
  cson_array * list = NULL;
  int check = 0;
  Stmt q = empty_Stmt;
  Blob sql = empty_blob;
  if( !g.perm.RdTkt && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED, "Ticket timeline requires 'o' or 'r' access.");
    return NULL;
  }
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  check = json_timeline_setup_sql( "t", &sql, pay );
  if(check){
    g.json.resultCode = check;

Changes to src/json_wiki.c.

58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73

74
75
76
77
78
79
80
..
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
...
174
175
176
177
178
179
180
181


182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199


200
201
202
203


204
205
206
207
208
209
210
211
212

213
214
215
216
217
218

219
220
221
222
223
224
225
...
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
...
292
293
294
295
296
297
298
299
300
301


302
303
304
305
  int rid;
  Manifest *pWiki = 0;
  char const * zBody = NULL;
  char const * zPageName;
  char const * zFormat = NULL;
  char * zUuid = NULL;
  Stmt q;
  if( !g.perm.RdWiki ){
    g.json.resultCode = FSL_JSON_E_DENIED;

    return NULL;
  }
  zPageName = g.isHTTP
    ? json_getenv_cstr("page")
    : find_option("page","p",1);
  if(!zPageName||!*zPageName){
    g.json.resultCode = FSL_JSON_E_MISSING_ARGS;

    return NULL;
  }

  zFormat = g.isHTTP
    ? json_getenv_cstr("format")
    : find_option("format","f",1);
  if(!zFormat || !*zFormat){
................................................................................
             " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' "
             " AND b.rid=x.rid"
             " ORDER BY x.mtime DESC LIMIT 1",
             zPageName 
             );
  if( (SQLITE_ROW != db_step(&q)) ){
    manifest_destroy(pWiki);
    g.json.resultCode = FSL_JSON_E_UNKNOWN;

    return NULL;
  }
  rid = db_column_int(&q,0);
  zUuid = db_column_malloc(&q,1);
  db_finalize(&q);
  
  if( (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
    zBody = pWiki->zWiki;
  }
  if( zBody==0 ){
    manifest_destroy(pWiki);
    free(zUuid);
    g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;

    return NULL;
  }

  {
    unsigned int len;
    cson_value * payV = cson_value_new_object();
    cson_object * pay = cson_value_get_object(payV);
................................................................................
  char const * zContent;
  char const * zBody = NULL;
  char const * zPageName;
  unsigned int contentLen = 0;
  int rid;
  if( (createMode && !g.perm.NewWiki)
      || (!createMode && !g.perm.WrWiki)){
    g.json.resultCode = FSL_JSON_E_DENIED;


    return NULL;
  }
  nameV = json_req_payload_get("name");
  if(!nameV){
    g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
    goto error;

  }
  zPageName = cson_string_cstr(cson_value_get_string(nameV));
  rid = db_int(0,
     "SELECT x.rid FROM tag t, tagxref x"
     " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
     " ORDER BY x.mtime DESC LIMIT 1",
     zPageName
  );

  if(rid){
    if(createMode){
      g.json.resultCode = FSL_JSON_E_RESOURCE_ALREADY_EXISTS;


      goto error;
    }
  }else if(!allowCreateIfExists){
    g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;


    goto error;
  }

  contentV = json_req_payload_get("content");
  if( !contentV ){
    if( createMode || (!rid && allowCreateIfExists) ){
      contentV = emptyContent = cson_value_new_string("",0);
    }else{
      g.json.resultCode = FSL_JSON_E_MISSING_ARGS;

      goto error;
    }
  }
  if( !cson_value_is_string(nameV)
      || !cson_value_is_string(contentV)){
    g.json.resultCode = FSL_JSON_E_INVALID_ARGS;

    goto error;
  }
  jstr = cson_value_get_string(contentV);
  contentLen = (int)cson_string_length_bytes(jstr);
  if(contentLen){
    blob_append(&content, cson_string_cstr(jstr),contentLen);
  }
................................................................................
/*
** Implementation of /json/wiki/list.
*/
static cson_value * json_wiki_list(){
  cson_value * listV = NULL;
  cson_array * list = NULL;
  Stmt q;
  if( !g.perm.RdWiki ){
    g.json.resultCode = FSL_JSON_E_DENIED;

    return NULL;
  }
  db_prepare(&q,"SELECT"
             " substr(tagname,6) as name"
             " FROM tag WHERE tagname GLOB 'wiki-*'"
             " ORDER BY lower(name)");
  listV = cson_value_new_array();
................................................................................
    }else if( 0 != cson_array_append( list, v ) ){
      cson_value_free(v);
      goto error;
    }
  }
  goto end;
  error:
  g.json.resultCode = FSL_JSON_E_UNKNOWN;
  cson_value_free(listV);
  listV = NULL;


  end:
  db_finalize(&q);
  return listV;
}







|
|
>






|
>







 







|
>












|
>







 







|
>
>




|
|
>











|
>
>



|
>
>








|
>





|
>







 







|
|
>







 







<


>
>




58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
...
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320
  int rid;
  Manifest *pWiki = 0;
  char const * zBody = NULL;
  char const * zPageName;
  char const * zFormat = NULL;
  char * zUuid = NULL;
  Stmt q;
  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' or 'j' access.");
    return NULL;
  }
  zPageName = g.isHTTP
    ? json_getenv_cstr("page")
    : find_option("page","p",1);
  if(!zPageName||!*zPageName){
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "'page' argument is missing.");
    return NULL;
  }

  zFormat = g.isHTTP
    ? json_getenv_cstr("format")
    : find_option("format","f",1);
  if(!zFormat || !*zFormat){
................................................................................
             " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' "
             " AND b.rid=x.rid"
             " ORDER BY x.mtime DESC LIMIT 1",
             zPageName 
             );
  if( (SQLITE_ROW != db_step(&q)) ){
    manifest_destroy(pWiki);
    json_set_err(FSL_JSON_E_UNKNOWN,
                 "Error reading wiki page manifest.");
    return NULL;
  }
  rid = db_column_int(&q,0);
  zUuid = db_column_malloc(&q,1);
  db_finalize(&q);
  
  if( (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
    zBody = pWiki->zWiki;
  }
  if( zBody==0 ){
    manifest_destroy(pWiki);
    free(zUuid);
    json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
                 "Wiki body is empty (is that possible?)");
    return NULL;
  }

  {
    unsigned int len;
    cson_value * payV = cson_value_new_object();
    cson_object * pay = cson_value_get_object(payV);
................................................................................
  char const * zContent;
  char const * zBody = NULL;
  char const * zPageName;
  unsigned int contentLen = 0;
  int rid;
  if( (createMode && !g.perm.NewWiki)
      || (!createMode && !g.perm.WrWiki)){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires '%c' permissions.",
                 (createMode ? 'f' : 'k'));
    return NULL;
  }
  nameV = json_req_payload_get("name");
  if(!nameV){
    json_set_err( FSL_JSON_E_MISSING_ARGS,
                  "'name' parameter is missing.");
    return NULL;
  }
  zPageName = cson_string_cstr(cson_value_get_string(nameV));
  rid = db_int(0,
     "SELECT x.rid FROM tag t, tagxref x"
     " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
     " ORDER BY x.mtime DESC LIMIT 1",
     zPageName
  );

  if(rid){
    if(createMode){
      json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
                   "Wiki page '%s' already exists.",
                   zPageName);
      goto error;
    }
  }else if(!allowCreateIfExists){
    json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
                 "Wiki page '%s' not found.",
                 zPageName);
    goto error;
  }

  contentV = json_req_payload_get("content");
  if( !contentV ){
    if( createMode || (!rid && allowCreateIfExists) ){
      contentV = emptyContent = cson_value_new_string("",0);
    }else{
      json_set_err(FSL_JSON_E_MISSING_ARGS,
                   "'content' parameter is missing.");
      goto error;
    }
  }
  if( !cson_value_is_string(nameV)
      || !cson_value_is_string(contentV)){
    json_set_err(FSL_JSON_E_INVALID_ARGS,
                 "'name' and 'content' parameters must be strings.");
    goto error;
  }
  jstr = cson_value_get_string(contentV);
  contentLen = (int)cson_string_length_bytes(jstr);
  if(contentLen){
    blob_append(&content, cson_string_cstr(jstr),contentLen);
  }
................................................................................
/*
** Implementation of /json/wiki/list.
*/
static cson_value * json_wiki_list(){
  cson_value * listV = NULL;
  cson_array * list = NULL;
  Stmt q;
  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'j' or 'o' permissions.");
    return NULL;
  }
  db_prepare(&q,"SELECT"
             " substr(tagname,6) as name"
             " FROM tag WHERE tagname GLOB 'wiki-*'"
             " ORDER BY lower(name)");
  listV = cson_value_new_array();
................................................................................
    }else if( 0 != cson_array_append( list, v ) ){
      cson_value_free(v);
      goto error;
    }
  }
  goto end;
  error:

  cson_value_free(listV);
  listV = NULL;
  json_set_err(FSL_JSON_E_UNKNOWN,
               "Error creating wiki page list.");
  end:
  db_finalize(&q);
  return listV;
}