Fossil SCM

Add /json/settings/get and set APIs, per discussion in [forum:04b7159d63d4abe4|forum post 04b7159d63d4abe4].

stephan 2023-01-23 00:12 trunk merge
Commit a80f27485a0aab56c4ddb71c976f39fca94d9642c885783bdb31e37f119095a0
+14 -6
--- src/json.c
+++ src/json.c
@@ -288,11 +288,11 @@
288288
va_list vargs;
289289
va_start(vargs,fmt);
290290
zStr = vmprintf(fmt,vargs);
291291
va_end(vargs);
292292
v = cson_value_new_string(zStr, strlen(zStr));
293
- free(zStr);
293
+ fossil_free(zStr);
294294
return v;
295295
}
296296
297297
cson_value * json_new_int( i64 v ){
298298
return cson_value_new_integer((cson_int_t)v);
@@ -630,13 +630,20 @@
630630
** is not called to flush the output.
631631
**
632632
** If g.json.jsonp is not NULL then the content type is set to
633633
** text/javascript and the output is wrapped in a jsonp
634634
** wrapper.
635
+**
636
+** This function works only the first time it is called. It "should
637
+** not" ever be called more than once but certain calling
638
+** constellations might trigger that, in which case the second and
639
+** subsequent calls are no-ops.
635640
*/
636641
void json_send_response( cson_value const * pResponse ){
642
+ static int once = 0;
637643
assert( NULL != pResponse );
644
+ if( once++ ) return;
638645
if( g.isHTTP ){
639646
cgi_reset_content();
640647
if( g.json.jsonp ){
641648
cgi_set_content_type("text/javascript");
642649
cgi_printf("%s(",g.json.jsonp);
@@ -844,11 +851,11 @@
844851
char * msg;
845852
va_start(vargs,fmt);
846853
msg = vmprintf(fmt,vargs);
847854
va_end(vargs);
848855
cson_object_set(obj,"text", cson_value_new_string(msg,strlen(msg)));
849
- free(msg);
856
+ fossil_free(msg);
850857
}
851858
}
852859
853860
/*
854861
** Splits zStr (which must not be NULL) into tokens separated by the
@@ -1623,11 +1630,11 @@
16231630
**
16241631
** code must be in the inclusive range 1000..9999.
16251632
*/
16261633
int json_set_err( int code, char const * fmt, ... ){
16271634
assert( (code>=1000) && (code<=9999) );
1628
- free(g.zErrMsg);
1635
+ fossil_free(g.zErrMsg);
16291636
g.json.resultCode = code;
16301637
if(!fmt || !*fmt){
16311638
g.zErrMsg = mprintf("%s", json_err_cstr(code));
16321639
}else{
16331640
va_list vargs;
@@ -1771,11 +1778,11 @@
17711778
char * tags = info_tags_of_checkin(rid, propagatingOnly);
17721779
if(tags){
17731780
if(*tags){
17741781
v = json_string_split2(tags,',',0);
17751782
}
1776
- free(tags);
1783
+ fossil_free(tags);
17771784
}
17781785
return v;
17791786
}
17801787
17811788
/*
@@ -2006,14 +2013,14 @@
20062013
jv = cson_value_new_object();
20072014
jo = cson_value_get_object(jv);
20082015
20092016
zTmp = db_get("project-name",NULL);
20102017
cson_object_set(jo, "projectName", json_new_string(zTmp));
2011
- free(zTmp);
2018
+ fossil_free(zTmp);
20122019
zTmp = db_get("project-description",NULL);
20132020
cson_object_set(jo, "projectDescription", json_new_string(zTmp));
2014
- free(zTmp);
2021
+ fossil_free(zTmp);
20152022
zTmp = NULL;
20162023
fsize = file_size(g.zRepositoryName, ExtFILE);
20172024
cson_object_set(jo, "repositorySize",
20182025
cson_value_new_integer((cson_int_t)fsize));
20192026
@@ -2247,10 +2254,11 @@
22472254
{"logout",json_page_logout,0},
22482255
{"query",json_page_query,0},
22492256
{"rebuild",json_page_rebuild,0},
22502257
{"report", json_page_report, 0},
22512258
{"resultCodes", json_page_resultCodes,0},
2259
+{"settings",json_page_settings,0},
22522260
{"stat",json_page_stat,0},
22532261
{"status", json_page_status, 0},
22542262
{"tag", json_page_tag,0},
22552263
/*{"ticket", json_page_nyi,0},*/
22562264
{"timeline", json_page_timeline,0},
22572265
--- src/json.c
+++ src/json.c
@@ -288,11 +288,11 @@
288 va_list vargs;
289 va_start(vargs,fmt);
290 zStr = vmprintf(fmt,vargs);
291 va_end(vargs);
292 v = cson_value_new_string(zStr, strlen(zStr));
293 free(zStr);
294 return v;
295 }
296
297 cson_value * json_new_int( i64 v ){
298 return cson_value_new_integer((cson_int_t)v);
@@ -630,13 +630,20 @@
630 ** is not called to flush the output.
631 **
632 ** If g.json.jsonp is not NULL then the content type is set to
633 ** text/javascript and the output is wrapped in a jsonp
634 ** wrapper.
 
 
 
 
 
635 */
636 void json_send_response( cson_value const * pResponse ){
 
637 assert( NULL != pResponse );
 
638 if( g.isHTTP ){
639 cgi_reset_content();
640 if( g.json.jsonp ){
641 cgi_set_content_type("text/javascript");
642 cgi_printf("%s(",g.json.jsonp);
@@ -844,11 +851,11 @@
844 char * msg;
845 va_start(vargs,fmt);
846 msg = vmprintf(fmt,vargs);
847 va_end(vargs);
848 cson_object_set(obj,"text", cson_value_new_string(msg,strlen(msg)));
849 free(msg);
850 }
851 }
852
853 /*
854 ** Splits zStr (which must not be NULL) into tokens separated by the
@@ -1623,11 +1630,11 @@
1623 **
1624 ** code must be in the inclusive range 1000..9999.
1625 */
1626 int json_set_err( int code, char const * fmt, ... ){
1627 assert( (code>=1000) && (code<=9999) );
1628 free(g.zErrMsg);
1629 g.json.resultCode = code;
1630 if(!fmt || !*fmt){
1631 g.zErrMsg = mprintf("%s", json_err_cstr(code));
1632 }else{
1633 va_list vargs;
@@ -1771,11 +1778,11 @@
1771 char * tags = info_tags_of_checkin(rid, propagatingOnly);
1772 if(tags){
1773 if(*tags){
1774 v = json_string_split2(tags,',',0);
1775 }
1776 free(tags);
1777 }
1778 return v;
1779 }
1780
1781 /*
@@ -2006,14 +2013,14 @@
2006 jv = cson_value_new_object();
2007 jo = cson_value_get_object(jv);
2008
2009 zTmp = db_get("project-name",NULL);
2010 cson_object_set(jo, "projectName", json_new_string(zTmp));
2011 free(zTmp);
2012 zTmp = db_get("project-description",NULL);
2013 cson_object_set(jo, "projectDescription", json_new_string(zTmp));
2014 free(zTmp);
2015 zTmp = NULL;
2016 fsize = file_size(g.zRepositoryName, ExtFILE);
2017 cson_object_set(jo, "repositorySize",
2018 cson_value_new_integer((cson_int_t)fsize));
2019
@@ -2247,10 +2254,11 @@
2247 {"logout",json_page_logout,0},
2248 {"query",json_page_query,0},
2249 {"rebuild",json_page_rebuild,0},
2250 {"report", json_page_report, 0},
2251 {"resultCodes", json_page_resultCodes,0},
 
2252 {"stat",json_page_stat,0},
2253 {"status", json_page_status, 0},
2254 {"tag", json_page_tag,0},
2255 /*{"ticket", json_page_nyi,0},*/
2256 {"timeline", json_page_timeline,0},
2257
--- src/json.c
+++ src/json.c
@@ -288,11 +288,11 @@
288 va_list vargs;
289 va_start(vargs,fmt);
290 zStr = vmprintf(fmt,vargs);
291 va_end(vargs);
292 v = cson_value_new_string(zStr, strlen(zStr));
293 fossil_free(zStr);
294 return v;
295 }
296
297 cson_value * json_new_int( i64 v ){
298 return cson_value_new_integer((cson_int_t)v);
@@ -630,13 +630,20 @@
630 ** is not called to flush the output.
631 **
632 ** If g.json.jsonp is not NULL then the content type is set to
633 ** text/javascript and the output is wrapped in a jsonp
634 ** wrapper.
635 **
636 ** This function works only the first time it is called. It "should
637 ** not" ever be called more than once but certain calling
638 ** constellations might trigger that, in which case the second and
639 ** subsequent calls are no-ops.
640 */
641 void json_send_response( cson_value const * pResponse ){
642 static int once = 0;
643 assert( NULL != pResponse );
644 if( once++ ) return;
645 if( g.isHTTP ){
646 cgi_reset_content();
647 if( g.json.jsonp ){
648 cgi_set_content_type("text/javascript");
649 cgi_printf("%s(",g.json.jsonp);
@@ -844,11 +851,11 @@
851 char * msg;
852 va_start(vargs,fmt);
853 msg = vmprintf(fmt,vargs);
854 va_end(vargs);
855 cson_object_set(obj,"text", cson_value_new_string(msg,strlen(msg)));
856 fossil_free(msg);
857 }
858 }
859
860 /*
861 ** Splits zStr (which must not be NULL) into tokens separated by the
@@ -1623,11 +1630,11 @@
1630 **
1631 ** code must be in the inclusive range 1000..9999.
1632 */
1633 int json_set_err( int code, char const * fmt, ... ){
1634 assert( (code>=1000) && (code<=9999) );
1635 fossil_free(g.zErrMsg);
1636 g.json.resultCode = code;
1637 if(!fmt || !*fmt){
1638 g.zErrMsg = mprintf("%s", json_err_cstr(code));
1639 }else{
1640 va_list vargs;
@@ -1771,11 +1778,11 @@
1778 char * tags = info_tags_of_checkin(rid, propagatingOnly);
1779 if(tags){
1780 if(*tags){
1781 v = json_string_split2(tags,',',0);
1782 }
1783 fossil_free(tags);
1784 }
1785 return v;
1786 }
1787
1788 /*
@@ -2006,14 +2013,14 @@
2013 jv = cson_value_new_object();
2014 jo = cson_value_get_object(jv);
2015
2016 zTmp = db_get("project-name",NULL);
2017 cson_object_set(jo, "projectName", json_new_string(zTmp));
2018 fossil_free(zTmp);
2019 zTmp = db_get("project-description",NULL);
2020 cson_object_set(jo, "projectDescription", json_new_string(zTmp));
2021 fossil_free(zTmp);
2022 zTmp = NULL;
2023 fsize = file_size(g.zRepositoryName, ExtFILE);
2024 cson_object_set(jo, "repositorySize",
2025 cson_value_new_integer((cson_int_t)fsize));
2026
@@ -2247,10 +2254,11 @@
2254 {"logout",json_page_logout,0},
2255 {"query",json_page_query,0},
2256 {"rebuild",json_page_rebuild,0},
2257 {"report", json_page_report, 0},
2258 {"resultCodes", json_page_resultCodes,0},
2259 {"settings",json_page_settings,0},
2260 {"stat",json_page_stat,0},
2261 {"status", json_page_status, 0},
2262 {"tag", json_page_tag,0},
2263 /*{"ticket", json_page_nyi,0},*/
2264 {"timeline", json_page_timeline,0},
2265
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -246,11 +246,11 @@
246246
** If the "format" (CLI: -f) flag is set function returns the same as
247247
** json_wiki_get_content_format_flag(), else it returns true (non-0)
248248
** if either the includeContent (HTTP) or -content|-c boolean flags
249249
** (CLI) are set.
250250
*/
251
-static int json_artifact_get_content_format_flag(){
251
+static int json_artifact_get_content_format_flag(void){
252252
enum { MagicValue = -9 };
253253
int contentFormat = json_wiki_get_content_format_flag(MagicValue);
254254
if(MagicValue == contentFormat){
255255
contentFormat = json_find_option_bool("includeContent","content","c",0) /* deprecated */ ? -1 : 0;
256256
}
@@ -398,11 +398,11 @@
398398
399399
/*
400400
** Impl of /json/artifact. This basically just determines the type of
401401
** an artifact and forwards the real work to another function.
402402
*/
403
-cson_value * json_page_artifact(){
403
+cson_value * json_page_artifact(void){
404404
cson_object * pay = NULL;
405405
char const * zName = NULL;
406406
char const * zType = NULL;
407407
char const * zUuid = NULL;
408408
cson_value * entry = NULL;
409409
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -246,11 +246,11 @@
246 ** If the "format" (CLI: -f) flag is set function returns the same as
247 ** json_wiki_get_content_format_flag(), else it returns true (non-0)
248 ** if either the includeContent (HTTP) or -content|-c boolean flags
249 ** (CLI) are set.
250 */
251 static int json_artifact_get_content_format_flag(){
252 enum { MagicValue = -9 };
253 int contentFormat = json_wiki_get_content_format_flag(MagicValue);
254 if(MagicValue == contentFormat){
255 contentFormat = json_find_option_bool("includeContent","content","c",0) /* deprecated */ ? -1 : 0;
256 }
@@ -398,11 +398,11 @@
398
399 /*
400 ** Impl of /json/artifact. This basically just determines the type of
401 ** an artifact and forwards the real work to another function.
402 */
403 cson_value * json_page_artifact(){
404 cson_object * pay = NULL;
405 char const * zName = NULL;
406 char const * zType = NULL;
407 char const * zUuid = NULL;
408 cson_value * entry = NULL;
409
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -246,11 +246,11 @@
246 ** If the "format" (CLI: -f) flag is set function returns the same as
247 ** json_wiki_get_content_format_flag(), else it returns true (non-0)
248 ** if either the includeContent (HTTP) or -content|-c boolean flags
249 ** (CLI) are set.
250 */
251 static int json_artifact_get_content_format_flag(void){
252 enum { MagicValue = -9 };
253 int contentFormat = json_wiki_get_content_format_flag(MagicValue);
254 if(MagicValue == contentFormat){
255 contentFormat = json_find_option_bool("includeContent","content","c",0) /* deprecated */ ? -1 : 0;
256 }
@@ -398,11 +398,11 @@
398
399 /*
400 ** Impl of /json/artifact. This basically just determines the type of
401 ** an artifact and forwards the real work to another function.
402 */
403 cson_value * json_page_artifact(void){
404 cson_object * pay = NULL;
405 char const * zName = NULL;
406 char const * zType = NULL;
407 char const * zUuid = NULL;
408 cson_value * entry = NULL;
409
--- src/json_branch.c
+++ src/json_branch.c
@@ -22,12 +22,12 @@
2222
#if INTERFACE
2323
#include "json_detail.h"
2424
#endif
2525
2626
27
-static cson_value * json_branch_list();
28
-static cson_value * json_branch_create();
27
+static cson_value * json_branch_list(void);
28
+static cson_value * json_branch_create(void);
2929
/*
3030
** Mapping of /json/branch/XXX commands/paths to callbacks.
3131
*/
3232
static const JsonPageDef JsonPageDefs_Branch[] = {
3333
{"create", json_branch_create, 0},
@@ -40,11 +40,11 @@
4040
/*
4141
** Implements the /json/branch family of pages/commands. Far from
4242
** complete.
4343
**
4444
*/
45
-cson_value * json_page_branch(){
45
+cson_value * json_page_branch(void){
4646
return json_page_dispatch_helper(&JsonPageDefs_Branch[0]);
4747
}
4848
4949
/*
5050
** Impl for /json/branch/list
@@ -60,11 +60,11 @@
6060
** HTTP mode options:
6161
**
6262
** "range" GET/POST.payload parameter. FIXME: currently we also use
6363
** POST, but really want to restrict this to POST.payload.
6464
*/
65
-static cson_value * json_branch_list(){
65
+static cson_value * json_branch_list(void){
6666
cson_value * payV;
6767
cson_object * pay;
6868
cson_value * listV;
6969
cson_array * list;
7070
char const * range = NULL;
@@ -313,11 +313,11 @@
313313
314314
315315
/*
316316
** Impl of /json/branch/create.
317317
*/
318
-static cson_value * json_branch_create(){
318
+static cson_value * json_branch_create(void){
319319
cson_value * payV = NULL;
320320
cson_object * pay = NULL;
321321
int rc = 0;
322322
BranchCreateOptions opt;
323323
char * zUuid = NULL;
324324
--- src/json_branch.c
+++ src/json_branch.c
@@ -22,12 +22,12 @@
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26
27 static cson_value * json_branch_list();
28 static cson_value * json_branch_create();
29 /*
30 ** Mapping of /json/branch/XXX commands/paths to callbacks.
31 */
32 static const JsonPageDef JsonPageDefs_Branch[] = {
33 {"create", json_branch_create, 0},
@@ -40,11 +40,11 @@
40 /*
41 ** Implements the /json/branch family of pages/commands. Far from
42 ** complete.
43 **
44 */
45 cson_value * json_page_branch(){
46 return json_page_dispatch_helper(&JsonPageDefs_Branch[0]);
47 }
48
49 /*
50 ** Impl for /json/branch/list
@@ -60,11 +60,11 @@
60 ** HTTP mode options:
61 **
62 ** "range" GET/POST.payload parameter. FIXME: currently we also use
63 ** POST, but really want to restrict this to POST.payload.
64 */
65 static cson_value * json_branch_list(){
66 cson_value * payV;
67 cson_object * pay;
68 cson_value * listV;
69 cson_array * list;
70 char const * range = NULL;
@@ -313,11 +313,11 @@
313
314
315 /*
316 ** Impl of /json/branch/create.
317 */
318 static cson_value * json_branch_create(){
319 cson_value * payV = NULL;
320 cson_object * pay = NULL;
321 int rc = 0;
322 BranchCreateOptions opt;
323 char * zUuid = NULL;
324
--- src/json_branch.c
+++ src/json_branch.c
@@ -22,12 +22,12 @@
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26
27 static cson_value * json_branch_list(void);
28 static cson_value * json_branch_create(void);
29 /*
30 ** Mapping of /json/branch/XXX commands/paths to callbacks.
31 */
32 static const JsonPageDef JsonPageDefs_Branch[] = {
33 {"create", json_branch_create, 0},
@@ -40,11 +40,11 @@
40 /*
41 ** Implements the /json/branch family of pages/commands. Far from
42 ** complete.
43 **
44 */
45 cson_value * json_page_branch(void){
46 return json_page_dispatch_helper(&JsonPageDefs_Branch[0]);
47 }
48
49 /*
50 ** Impl for /json/branch/list
@@ -60,11 +60,11 @@
60 ** HTTP mode options:
61 **
62 ** "range" GET/POST.payload parameter. FIXME: currently we also use
63 ** POST, but really want to restrict this to POST.payload.
64 */
65 static cson_value * json_branch_list(void){
66 cson_value * payV;
67 cson_object * pay;
68 cson_value * listV;
69 cson_array * list;
70 char const * range = NULL;
@@ -313,11 +313,11 @@
313
314
315 /*
316 ** Impl of /json/branch/create.
317 */
318 static cson_value * json_branch_create(void){
319 cson_value * payV = NULL;
320 cson_object * pay = NULL;
321 int rc = 0;
322 BranchCreateOptions opt;
323 char * zUuid = NULL;
324
+219 -5
--- src/json_config.c
+++ src/json_config.c
@@ -21,12 +21,12 @@
2121
2222
#if INTERFACE
2323
#include "json_detail.h"
2424
#endif
2525
26
-static cson_value * json_config_get();
27
-static cson_value * json_config_save();
26
+static cson_value * json_config_get(void);
27
+static cson_value * json_config_save(void);
2828
2929
/*
3030
** Mapping of /json/config/XXX commands/paths to callbacks.
3131
*/
3232
static const JsonPageDef JsonPageDefs_Config[] = {
@@ -34,18 +34,38 @@
3434
{"save", json_config_save, 0},
3535
/* Last entry MUST have a NULL name. */
3636
{NULL,NULL,0}
3737
};
3838
39
+static cson_value * json_settings_get(void);
40
+static cson_value * json_settings_set(void);
41
+/*
42
+** Mapping of /json/settings/XXX commands/paths to callbacks.
43
+*/
44
+static const JsonPageDef JsonPageDefs_Settings[] = {
45
+{"get", json_settings_get, 0},
46
+{"set", json_settings_set, 0},
47
+/* Last entry MUST have a NULL name. */
48
+{NULL,NULL,0}
49
+};
50
+
3951
4052
/*
4153
** Implements the /json/config family of pages/commands.
4254
**
4355
*/
44
-cson_value * json_page_config(){
56
+cson_value * json_page_config(void){
4557
return json_page_dispatch_helper(&JsonPageDefs_Config[0]);
4658
}
59
+
60
+/*
61
+** Implements the /json/settings family of pages/commands.
62
+**
63
+*/
64
+cson_value * json_page_settings(void){
65
+ return json_page_dispatch_helper(&JsonPageDefs_Settings[0]);
66
+}
4767
4868
4969
/*
5070
** JSON-internal mapping of config options to config groups. This is
5171
** mostly a copy of the config options in configure.c, but that data
@@ -105,11 +125,11 @@
105125
106126
/*
107127
** Impl of /json/config/get. Requires setup rights.
108128
**
109129
*/
110
-static cson_value * json_config_get(){
130
+static cson_value * json_config_get(void){
111131
cson_object * pay = NULL;
112132
Stmt q = empty_Stmt;
113133
Blob sql = empty_blob;
114134
char const * zName = NULL;
115135
int confMask = 0;
@@ -181,10 +201,204 @@
181201
/*
182202
** Impl of /json/config/save.
183203
**
184204
** TODOs:
185205
*/
186
-static cson_value * json_config_save(){
206
+static cson_value * json_config_save(void){
187207
json_set_err(FSL_JSON_E_NYI, NULL);
188208
return NULL;
189209
}
210
+
211
+/*
212
+** Impl of /json/settings/get.
213
+*/
214
+static cson_value * json_settings_get(void){
215
+ cson_object * pay = cson_new_object(); /* output payload */
216
+ int nSetting, i; /* setting count and loop var */
217
+ const Setting *aSetting = setting_info(&nSetting);
218
+ const char * zRevision = 0; /* revision to look for
219
+ versioned settings in */
220
+ char * zUuid = 0; /* Resolved UUID of zRevision */
221
+ Stmt q = empty_Stmt; /* Config-search query */
222
+ Stmt qFoci = empty_Stmt; /* foci query */
223
+
224
+ if( !g.perm.Read ){
225
+ json_set_err( FSL_JSON_E_DENIED, "Fetching settings requires 'o' access." );
226
+ return NULL;
227
+ }
228
+ zRevision = json_find_option_cstr("version",NULL,NULL);
229
+ if( 0!=zRevision ){
230
+ int rid = name_to_uuid2(zRevision, "ci", &zUuid);
231
+ if(rid<=0){
232
+ json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
233
+ "Cannot find the given version.");
234
+ return NULL;
235
+ }
236
+ db_multi_exec("CREATE VIRTUAL TABLE IF NOT EXISTS "
237
+ "temp.foci USING files_of_checkin;");
238
+ db_prepare(&qFoci,
239
+ "SELECT uuid FROM temp.foci WHERE "
240
+ "checkinID=%d AND filename='.fossil-settings/' || :name",
241
+ rid);
242
+ }
243
+ zRevision = 0;
244
+
245
+ if( g.localOpen ){
246
+ db_prepare(&q,
247
+ "SELECT 'checkout', value FROM vvar WHERE name=:name"
248
+ " UNION ALL "
249
+ "SELECT 'repo', value FROM config WHERE name=:name"
250
+ );
251
+ }else{
252
+ db_prepare(&q,
253
+ "SELECT 'repo', value FROM config WHERE name=:name"
254
+ );
255
+ }
256
+ for(i=0; i<nSetting; ++i){
257
+ const Setting *pSet = &aSetting[i];
258
+ cson_object * jSet;
259
+ cson_value * pVal = 0, * pSrc = 0;
260
+ jSet = cson_new_object();
261
+ cson_object_set(pay, pSet->name, cson_object_value(jSet));
262
+ cson_object_set(jSet, "versionable", cson_value_new_bool(pSet->versionable));
263
+ cson_object_set(jSet, "sensitive", cson_value_new_bool(pSet->sensitive));
264
+ cson_object_set(jSet, "defaultValue", (pSet->def && pSet->def[0])
265
+ ? json_new_string(pSet->def)
266
+ : cson_value_null());
267
+ if( 0==pSet->sensitive || 0!=g.perm.Setup ){
268
+ if( pSet->versionable ){
269
+ /* Check to see if this is overridden by a versionable
270
+ ** settings file */
271
+ if( 0!=zUuid ){
272
+ /* Attempt to find a versioned setting stored in the given
273
+ ** check-in version. */
274
+ db_bind_text(&qFoci, ":name", pSet->name);
275
+ if( SQLITE_ROW==db_step(&qFoci) ){
276
+ int frid = fast_uuid_to_rid(db_column_text(&qFoci, 0));
277
+ Blob content;
278
+ blob_zero(&content);
279
+ if( 0!=content_get(frid, &content) ){
280
+ pSrc = json_new_string("versioned");
281
+ pVal = json_new_string(blob_str(&content));
282
+ }
283
+ blob_reset(&content);
284
+ }
285
+ db_reset(&qFoci);
286
+ }
287
+ if( 0==pSrc && g.localOpen ){
288
+ /* Pull value from a checkout-local .fossil-settings/X file,
289
+ ** if one exists. */
290
+ Blob versionedPathname;
291
+ blob_zero(&versionedPathname);
292
+ blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
293
+ g.zLocalRoot, pSet->name);
294
+ if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
295
+ Blob content;
296
+ blob_zero(&content);
297
+ blob_read_from_file(&content, blob_str(&versionedPathname), ExtFILE);
298
+ pSrc = json_new_string("versioned");
299
+ pVal = json_new_string(blob_str(&content));
300
+ blob_reset(&content);
301
+ }
302
+ blob_reset(&versionedPathname);
303
+ }
304
+ }
305
+ if( 0==pSrc ){
306
+ /* Setting is not versionable or we had no versioned value, so
307
+ ** use the value from localdb.vvar or repository.config (in
308
+ ** that order). */
309
+ db_bind_text(&q, ":name", pSet->name);
310
+ if( SQLITE_ROW==db_step(&q) ){
311
+ pSrc = json_new_string(db_column_text(&q, 0));
312
+ pVal = json_new_string(db_column_text(&q, 1));
313
+ }
314
+ db_reset(&q);
315
+ }
316
+ }
317
+ cson_object_set(jSet, "valueSource", pSrc ? pSrc : cson_value_null());
318
+ cson_object_set(jSet, "value", pVal ? pVal : cson_value_null());
319
+ }/*aSetting loop*/
320
+ db_finalize(&q);
321
+ db_finalize(&qFoci);
322
+ fossil_free(zUuid);
323
+ return cson_object_value(pay);
324
+}
325
+
326
+/*
327
+** Impl of /json/settings/set.
328
+**
329
+** Input payload is an object mapping setting names to values. All
330
+** values are set in the repository.config table. It has no response
331
+** payload.
332
+*/
333
+static cson_value * json_settings_set(void){
334
+ Stmt q = empty_Stmt; /* Config-set query */
335
+ cson_object_iterator objIter = cson_object_iterator_empty;
336
+ cson_kvp * pKvp;
337
+ int nErr = 0, nProp = 0;
338
+
339
+ if( 0==g.perm.Setup ){
340
+ json_set_err( FSL_JSON_E_DENIED, "Setting settings requires 's' access." );
341
+ return NULL;
342
+ }
343
+ else if( 0==g.json.reqPayload.o ){
344
+ json_set_err(FSL_JSON_E_MISSING_ARGS,
345
+ "Missing payload of setting-to-value mappings.");
346
+ return NULL;
347
+ }
348
+
349
+ db_unprotect(PROTECT_CONFIG);
350
+ db_prepare(&q,
351
+ "INSERT OR REPLACE INTO config (name, value, mtime) "
352
+ "VALUES(:name, :value, CAST(strftime('%%s') AS INT))"
353
+ );
354
+ db_begin_transaction();
355
+ cson_object_iter_init( g.json.reqPayload.o, &objIter );
356
+ while( (pKvp = cson_object_iter_next(&objIter)) ){
357
+ char const * zKey = cson_string_cstr( cson_kvp_key(pKvp) );
358
+ cson_value * pVal;
359
+ const Setting *pSetting = db_find_setting( zKey, 0 );
360
+ if( 0==pSetting ){
361
+ nErr = json_set_err(FSL_JSON_E_INVALID_ARGS,
362
+ "Unknown setting: %s", zKey);
363
+ break;
364
+ }
365
+ pVal = cson_kvp_value(pKvp);
366
+ switch( cson_value_type_id(pVal) ){
367
+ case CSON_TYPE_NULL:
368
+ db_multi_exec("DELETE FROM config WHERE name=%Q", pSetting->name);
369
+ continue;
370
+ case CSON_TYPE_BOOL:
371
+ db_bind_int(&q, ":value", cson_value_get_bool(pVal) ? 1 : 0);
372
+ break;
373
+ case CSON_TYPE_INTEGER:
374
+ db_bind_int64(&q, ":value", cson_value_get_integer(pVal));
375
+ break;
376
+ case CSON_TYPE_DOUBLE:
377
+ db_bind_double(&q, ":value", cson_value_get_double(pVal));
378
+ break;
379
+ case CSON_TYPE_STRING:
380
+ db_bind_text(&q, ":value", cson_value_get_cstr(pVal));
381
+ break;
382
+ default:
383
+ nErr = json_set_err(FSL_JSON_E_USAGE,
384
+ "Invalid value type for setting '%s'.",
385
+ pSetting->name);
386
+ break;
387
+ }
388
+ if( 0!=nErr ) break;
389
+ db_bind_text(&q, ":name", zKey);
390
+ db_step(&q);
391
+ db_reset(&q);
392
+ ++nProp;
393
+ }
394
+ db_finalize(&q);
395
+ if( 0==nErr && 0==nProp ){
396
+ nErr = json_set_err(FSL_JSON_E_INVALID_ARGS,
397
+ "Payload contains no settings to set.");
398
+ }
399
+ db_end_transaction(nErr);
400
+ db_protect_pop();
401
+ return NULL;
402
+}
403
+
190404
#endif /* FOSSIL_ENABLE_JSON */
191405
--- src/json_config.c
+++ src/json_config.c
@@ -21,12 +21,12 @@
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 static cson_value * json_config_get();
27 static cson_value * json_config_save();
28
29 /*
30 ** Mapping of /json/config/XXX commands/paths to callbacks.
31 */
32 static const JsonPageDef JsonPageDefs_Config[] = {
@@ -34,18 +34,38 @@
34 {"save", json_config_save, 0},
35 /* Last entry MUST have a NULL name. */
36 {NULL,NULL,0}
37 };
38
 
 
 
 
 
 
 
 
 
 
 
 
39
40 /*
41 ** Implements the /json/config family of pages/commands.
42 **
43 */
44 cson_value * json_page_config(){
45 return json_page_dispatch_helper(&JsonPageDefs_Config[0]);
46 }
 
 
 
 
 
 
 
 
47
48
49 /*
50 ** JSON-internal mapping of config options to config groups. This is
51 ** mostly a copy of the config options in configure.c, but that data
@@ -105,11 +125,11 @@
105
106 /*
107 ** Impl of /json/config/get. Requires setup rights.
108 **
109 */
110 static cson_value * json_config_get(){
111 cson_object * pay = NULL;
112 Stmt q = empty_Stmt;
113 Blob sql = empty_blob;
114 char const * zName = NULL;
115 int confMask = 0;
@@ -181,10 +201,204 @@
181 /*
182 ** Impl of /json/config/save.
183 **
184 ** TODOs:
185 */
186 static cson_value * json_config_save(){
187 json_set_err(FSL_JSON_E_NYI, NULL);
188 return NULL;
189 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190 #endif /* FOSSIL_ENABLE_JSON */
191
--- src/json_config.c
+++ src/json_config.c
@@ -21,12 +21,12 @@
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 static cson_value * json_config_get(void);
27 static cson_value * json_config_save(void);
28
29 /*
30 ** Mapping of /json/config/XXX commands/paths to callbacks.
31 */
32 static const JsonPageDef JsonPageDefs_Config[] = {
@@ -34,18 +34,38 @@
34 {"save", json_config_save, 0},
35 /* Last entry MUST have a NULL name. */
36 {NULL,NULL,0}
37 };
38
39 static cson_value * json_settings_get(void);
40 static cson_value * json_settings_set(void);
41 /*
42 ** Mapping of /json/settings/XXX commands/paths to callbacks.
43 */
44 static const JsonPageDef JsonPageDefs_Settings[] = {
45 {"get", json_settings_get, 0},
46 {"set", json_settings_set, 0},
47 /* Last entry MUST have a NULL name. */
48 {NULL,NULL,0}
49 };
50
51
52 /*
53 ** Implements the /json/config family of pages/commands.
54 **
55 */
56 cson_value * json_page_config(void){
57 return json_page_dispatch_helper(&JsonPageDefs_Config[0]);
58 }
59
60 /*
61 ** Implements the /json/settings family of pages/commands.
62 **
63 */
64 cson_value * json_page_settings(void){
65 return json_page_dispatch_helper(&JsonPageDefs_Settings[0]);
66 }
67
68
69 /*
70 ** JSON-internal mapping of config options to config groups. This is
71 ** mostly a copy of the config options in configure.c, but that data
@@ -105,11 +125,11 @@
125
126 /*
127 ** Impl of /json/config/get. Requires setup rights.
128 **
129 */
130 static cson_value * json_config_get(void){
131 cson_object * pay = NULL;
132 Stmt q = empty_Stmt;
133 Blob sql = empty_blob;
134 char const * zName = NULL;
135 int confMask = 0;
@@ -181,10 +201,204 @@
201 /*
202 ** Impl of /json/config/save.
203 **
204 ** TODOs:
205 */
206 static cson_value * json_config_save(void){
207 json_set_err(FSL_JSON_E_NYI, NULL);
208 return NULL;
209 }
210
211 /*
212 ** Impl of /json/settings/get.
213 */
214 static cson_value * json_settings_get(void){
215 cson_object * pay = cson_new_object(); /* output payload */
216 int nSetting, i; /* setting count and loop var */
217 const Setting *aSetting = setting_info(&nSetting);
218 const char * zRevision = 0; /* revision to look for
219 versioned settings in */
220 char * zUuid = 0; /* Resolved UUID of zRevision */
221 Stmt q = empty_Stmt; /* Config-search query */
222 Stmt qFoci = empty_Stmt; /* foci query */
223
224 if( !g.perm.Read ){
225 json_set_err( FSL_JSON_E_DENIED, "Fetching settings requires 'o' access." );
226 return NULL;
227 }
228 zRevision = json_find_option_cstr("version",NULL,NULL);
229 if( 0!=zRevision ){
230 int rid = name_to_uuid2(zRevision, "ci", &zUuid);
231 if(rid<=0){
232 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
233 "Cannot find the given version.");
234 return NULL;
235 }
236 db_multi_exec("CREATE VIRTUAL TABLE IF NOT EXISTS "
237 "temp.foci USING files_of_checkin;");
238 db_prepare(&qFoci,
239 "SELECT uuid FROM temp.foci WHERE "
240 "checkinID=%d AND filename='.fossil-settings/' || :name",
241 rid);
242 }
243 zRevision = 0;
244
245 if( g.localOpen ){
246 db_prepare(&q,
247 "SELECT 'checkout', value FROM vvar WHERE name=:name"
248 " UNION ALL "
249 "SELECT 'repo', value FROM config WHERE name=:name"
250 );
251 }else{
252 db_prepare(&q,
253 "SELECT 'repo', value FROM config WHERE name=:name"
254 );
255 }
256 for(i=0; i<nSetting; ++i){
257 const Setting *pSet = &aSetting[i];
258 cson_object * jSet;
259 cson_value * pVal = 0, * pSrc = 0;
260 jSet = cson_new_object();
261 cson_object_set(pay, pSet->name, cson_object_value(jSet));
262 cson_object_set(jSet, "versionable", cson_value_new_bool(pSet->versionable));
263 cson_object_set(jSet, "sensitive", cson_value_new_bool(pSet->sensitive));
264 cson_object_set(jSet, "defaultValue", (pSet->def && pSet->def[0])
265 ? json_new_string(pSet->def)
266 : cson_value_null());
267 if( 0==pSet->sensitive || 0!=g.perm.Setup ){
268 if( pSet->versionable ){
269 /* Check to see if this is overridden by a versionable
270 ** settings file */
271 if( 0!=zUuid ){
272 /* Attempt to find a versioned setting stored in the given
273 ** check-in version. */
274 db_bind_text(&qFoci, ":name", pSet->name);
275 if( SQLITE_ROW==db_step(&qFoci) ){
276 int frid = fast_uuid_to_rid(db_column_text(&qFoci, 0));
277 Blob content;
278 blob_zero(&content);
279 if( 0!=content_get(frid, &content) ){
280 pSrc = json_new_string("versioned");
281 pVal = json_new_string(blob_str(&content));
282 }
283 blob_reset(&content);
284 }
285 db_reset(&qFoci);
286 }
287 if( 0==pSrc && g.localOpen ){
288 /* Pull value from a checkout-local .fossil-settings/X file,
289 ** if one exists. */
290 Blob versionedPathname;
291 blob_zero(&versionedPathname);
292 blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
293 g.zLocalRoot, pSet->name);
294 if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
295 Blob content;
296 blob_zero(&content);
297 blob_read_from_file(&content, blob_str(&versionedPathname), ExtFILE);
298 pSrc = json_new_string("versioned");
299 pVal = json_new_string(blob_str(&content));
300 blob_reset(&content);
301 }
302 blob_reset(&versionedPathname);
303 }
304 }
305 if( 0==pSrc ){
306 /* Setting is not versionable or we had no versioned value, so
307 ** use the value from localdb.vvar or repository.config (in
308 ** that order). */
309 db_bind_text(&q, ":name", pSet->name);
310 if( SQLITE_ROW==db_step(&q) ){
311 pSrc = json_new_string(db_column_text(&q, 0));
312 pVal = json_new_string(db_column_text(&q, 1));
313 }
314 db_reset(&q);
315 }
316 }
317 cson_object_set(jSet, "valueSource", pSrc ? pSrc : cson_value_null());
318 cson_object_set(jSet, "value", pVal ? pVal : cson_value_null());
319 }/*aSetting loop*/
320 db_finalize(&q);
321 db_finalize(&qFoci);
322 fossil_free(zUuid);
323 return cson_object_value(pay);
324 }
325
326 /*
327 ** Impl of /json/settings/set.
328 **
329 ** Input payload is an object mapping setting names to values. All
330 ** values are set in the repository.config table. It has no response
331 ** payload.
332 */
333 static cson_value * json_settings_set(void){
334 Stmt q = empty_Stmt; /* Config-set query */
335 cson_object_iterator objIter = cson_object_iterator_empty;
336 cson_kvp * pKvp;
337 int nErr = 0, nProp = 0;
338
339 if( 0==g.perm.Setup ){
340 json_set_err( FSL_JSON_E_DENIED, "Setting settings requires 's' access." );
341 return NULL;
342 }
343 else if( 0==g.json.reqPayload.o ){
344 json_set_err(FSL_JSON_E_MISSING_ARGS,
345 "Missing payload of setting-to-value mappings.");
346 return NULL;
347 }
348
349 db_unprotect(PROTECT_CONFIG);
350 db_prepare(&q,
351 "INSERT OR REPLACE INTO config (name, value, mtime) "
352 "VALUES(:name, :value, CAST(strftime('%%s') AS INT))"
353 );
354 db_begin_transaction();
355 cson_object_iter_init( g.json.reqPayload.o, &objIter );
356 while( (pKvp = cson_object_iter_next(&objIter)) ){
357 char const * zKey = cson_string_cstr( cson_kvp_key(pKvp) );
358 cson_value * pVal;
359 const Setting *pSetting = db_find_setting( zKey, 0 );
360 if( 0==pSetting ){
361 nErr = json_set_err(FSL_JSON_E_INVALID_ARGS,
362 "Unknown setting: %s", zKey);
363 break;
364 }
365 pVal = cson_kvp_value(pKvp);
366 switch( cson_value_type_id(pVal) ){
367 case CSON_TYPE_NULL:
368 db_multi_exec("DELETE FROM config WHERE name=%Q", pSetting->name);
369 continue;
370 case CSON_TYPE_BOOL:
371 db_bind_int(&q, ":value", cson_value_get_bool(pVal) ? 1 : 0);
372 break;
373 case CSON_TYPE_INTEGER:
374 db_bind_int64(&q, ":value", cson_value_get_integer(pVal));
375 break;
376 case CSON_TYPE_DOUBLE:
377 db_bind_double(&q, ":value", cson_value_get_double(pVal));
378 break;
379 case CSON_TYPE_STRING:
380 db_bind_text(&q, ":value", cson_value_get_cstr(pVal));
381 break;
382 default:
383 nErr = json_set_err(FSL_JSON_E_USAGE,
384 "Invalid value type for setting '%s'.",
385 pSetting->name);
386 break;
387 }
388 if( 0!=nErr ) break;
389 db_bind_text(&q, ":name", zKey);
390 db_step(&q);
391 db_reset(&q);
392 ++nProp;
393 }
394 db_finalize(&q);
395 if( 0==nErr && 0==nProp ){
396 nErr = json_set_err(FSL_JSON_E_INVALID_ARGS,
397 "Payload contains no settings to set.");
398 }
399 db_end_transaction(nErr);
400 db_protect_pop();
401 return NULL;
402 }
403
404 #endif /* FOSSIL_ENABLE_JSON */
405
--- src/json_detail.h
+++ src/json_detail.h
@@ -149,11 +149,11 @@
149149
** almost certainly will corrupt any HTTP response headers. Output
150150
** sent to stderr ends up in my apache log, so that might be useful
151151
** for debugging in some cases, but no such code should be left
152152
** enabled for non-debugging builds.
153153
*/
154
-typedef cson_value * (*fossil_json_f)();
154
+typedef cson_value * (*fossil_json_f)(void);
155155
156156
/*
157157
** Holds name-to-function mappings for JSON page/command dispatching.
158158
**
159159
** Internally we model page dispatching lists as arrays of these
@@ -260,14 +260,14 @@
260260
**
261261
** Whether or not we need to take args from CLI or POST data makes a
262262
** difference in argument/parameter handling in many JSON routines,
263263
** and thus this distinction.
264264
*/
265
-int fossil_has_json();
265
+int fossil_has_json(void);
266266
267267
enum json_get_changed_files_flags {
268268
json_get_changed_files_ELIDE_PARENT = 1 << 0
269269
};
270270
271271
#endif /* !defined(_RC_COMPILE_) */
272272
#endif/*FOSSIL_JSON_DETAIL_H_INCLUDED*/
273273
#endif /* FOSSIL_ENABLE_JSON */
274274
--- src/json_detail.h
+++ src/json_detail.h
@@ -149,11 +149,11 @@
149 ** almost certainly will corrupt any HTTP response headers. Output
150 ** sent to stderr ends up in my apache log, so that might be useful
151 ** for debugging in some cases, but no such code should be left
152 ** enabled for non-debugging builds.
153 */
154 typedef cson_value * (*fossil_json_f)();
155
156 /*
157 ** Holds name-to-function mappings for JSON page/command dispatching.
158 **
159 ** Internally we model page dispatching lists as arrays of these
@@ -260,14 +260,14 @@
260 **
261 ** Whether or not we need to take args from CLI or POST data makes a
262 ** difference in argument/parameter handling in many JSON routines,
263 ** and thus this distinction.
264 */
265 int fossil_has_json();
266
267 enum json_get_changed_files_flags {
268 json_get_changed_files_ELIDE_PARENT = 1 << 0
269 };
270
271 #endif /* !defined(_RC_COMPILE_) */
272 #endif/*FOSSIL_JSON_DETAIL_H_INCLUDED*/
273 #endif /* FOSSIL_ENABLE_JSON */
274
--- src/json_detail.h
+++ src/json_detail.h
@@ -149,11 +149,11 @@
149 ** almost certainly will corrupt any HTTP response headers. Output
150 ** sent to stderr ends up in my apache log, so that might be useful
151 ** for debugging in some cases, but no such code should be left
152 ** enabled for non-debugging builds.
153 */
154 typedef cson_value * (*fossil_json_f)(void);
155
156 /*
157 ** Holds name-to-function mappings for JSON page/command dispatching.
158 **
159 ** Internally we model page dispatching lists as arrays of these
@@ -260,14 +260,14 @@
260 **
261 ** Whether or not we need to take args from CLI or POST data makes a
262 ** difference in argument/parameter handling in many JSON routines,
263 ** and thus this distinction.
264 */
265 int fossil_has_json(void);
266
267 enum json_get_changed_files_flags {
268 json_get_changed_files_ELIDE_PARENT = 1 << 0
269 };
270
271 #endif /* !defined(_RC_COMPILE_) */
272 #endif/*FOSSIL_JSON_DETAIL_H_INCLUDED*/
273 #endif /* FOSSIL_ENABLE_JSON */
274
+1 -1
--- src/json_diff.c
+++ src/json_diff.c
@@ -83,11 +83,11 @@
8383
**
8484
** Can come from GET, POST.payload, CLI -v1/-v2 or as positional
8585
** parameters following the command name (in HTTP and CLI modes).
8686
**
8787
*/
88
-cson_value * json_page_diff(){
88
+cson_value * json_page_diff(void){
8989
cson_object * pay = NULL;
9090
cson_value * v = NULL;
9191
char const * zFrom;
9292
char const * zTo;
9393
int nContext = 0;
9494
--- src/json_diff.c
+++ src/json_diff.c
@@ -83,11 +83,11 @@
83 **
84 ** Can come from GET, POST.payload, CLI -v1/-v2 or as positional
85 ** parameters following the command name (in HTTP and CLI modes).
86 **
87 */
88 cson_value * json_page_diff(){
89 cson_object * pay = NULL;
90 cson_value * v = NULL;
91 char const * zFrom;
92 char const * zTo;
93 int nContext = 0;
94
--- src/json_diff.c
+++ src/json_diff.c
@@ -83,11 +83,11 @@
83 **
84 ** Can come from GET, POST.payload, CLI -v1/-v2 or as positional
85 ** parameters following the command name (in HTTP and CLI modes).
86 **
87 */
88 cson_value * json_page_diff(void){
89 cson_object * pay = NULL;
90 cson_value * v = NULL;
91 char const * zFrom;
92 char const * zTo;
93 int nContext = 0;
94
+4 -4
--- src/json_dir.c
+++ src/json_dir.c
@@ -21,11 +21,11 @@
2121
2222
#if INTERFACE
2323
#include "json_detail.h"
2424
#endif
2525
26
-static cson_value * json_page_dir_list();
26
+static cson_value * json_page_dir_list(void);
2727
/*
2828
** Mapping of /json/wiki/XXX commands/paths to callbacks.
2929
*/
3030
#if 0 /* TODO: Not used? */
3131
static const JsonPageDef JsonPageDefs_Dir[] = {
@@ -33,11 +33,11 @@
3333
{NULL,NULL,0}
3434
};
3535
#endif
3636
3737
#if 0 /* TODO: Not used? */
38
-static char const * json_dir_path_extra(){
38
+static char const * json_dir_path_extra(void){
3939
static char const * zP = NULL;
4040
if( !zP ){
4141
zP = g.zExtra;
4242
while(zP && *zP && ('/'==*zP)){
4343
++zP;
@@ -49,11 +49,11 @@
4949
5050
/*
5151
** Impl of /json/dir. 98% of it was taken directly
5252
** from browse.c::page_dir()
5353
*/
54
-static cson_value * json_page_dir_list(){
54
+static cson_value * json_page_dir_list(void){
5555
cson_object * zPayload = NULL; /* return value */
5656
cson_array * zEntries = NULL; /* accumulated list of entries. */
5757
cson_object * zEntry = NULL; /* a single dir/file entry. */
5858
cson_array * keyStore = NULL; /* garbage collector for shared strings. */
5959
cson_string * zKeyName = NULL;
@@ -281,14 +281,14 @@
281281
282282
/*
283283
** Implements the /json/dir family of pages/commands.
284284
**
285285
*/
286
-cson_value * json_page_dir(){
286
+cson_value * json_page_dir(void){
287287
#if 1
288288
return json_page_dir_list();
289289
#else
290290
return json_page_dispatch_helper(&JsonPageDefs_Dir[0]);
291291
#endif
292292
}
293293
294294
#endif /* FOSSIL_ENABLE_JSON */
295295
--- src/json_dir.c
+++ src/json_dir.c
@@ -21,11 +21,11 @@
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 static cson_value * json_page_dir_list();
27 /*
28 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
29 */
30 #if 0 /* TODO: Not used? */
31 static const JsonPageDef JsonPageDefs_Dir[] = {
@@ -33,11 +33,11 @@
33 {NULL,NULL,0}
34 };
35 #endif
36
37 #if 0 /* TODO: Not used? */
38 static char const * json_dir_path_extra(){
39 static char const * zP = NULL;
40 if( !zP ){
41 zP = g.zExtra;
42 while(zP && *zP && ('/'==*zP)){
43 ++zP;
@@ -49,11 +49,11 @@
49
50 /*
51 ** Impl of /json/dir. 98% of it was taken directly
52 ** from browse.c::page_dir()
53 */
54 static cson_value * json_page_dir_list(){
55 cson_object * zPayload = NULL; /* return value */
56 cson_array * zEntries = NULL; /* accumulated list of entries. */
57 cson_object * zEntry = NULL; /* a single dir/file entry. */
58 cson_array * keyStore = NULL; /* garbage collector for shared strings. */
59 cson_string * zKeyName = NULL;
@@ -281,14 +281,14 @@
281
282 /*
283 ** Implements the /json/dir family of pages/commands.
284 **
285 */
286 cson_value * json_page_dir(){
287 #if 1
288 return json_page_dir_list();
289 #else
290 return json_page_dispatch_helper(&JsonPageDefs_Dir[0]);
291 #endif
292 }
293
294 #endif /* FOSSIL_ENABLE_JSON */
295
--- src/json_dir.c
+++ src/json_dir.c
@@ -21,11 +21,11 @@
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 static cson_value * json_page_dir_list(void);
27 /*
28 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
29 */
30 #if 0 /* TODO: Not used? */
31 static const JsonPageDef JsonPageDefs_Dir[] = {
@@ -33,11 +33,11 @@
33 {NULL,NULL,0}
34 };
35 #endif
36
37 #if 0 /* TODO: Not used? */
38 static char const * json_dir_path_extra(void){
39 static char const * zP = NULL;
40 if( !zP ){
41 zP = g.zExtra;
42 while(zP && *zP && ('/'==*zP)){
43 ++zP;
@@ -49,11 +49,11 @@
49
50 /*
51 ** Impl of /json/dir. 98% of it was taken directly
52 ** from browse.c::page_dir()
53 */
54 static cson_value * json_page_dir_list(void){
55 cson_object * zPayload = NULL; /* return value */
56 cson_array * zEntries = NULL; /* accumulated list of entries. */
57 cson_object * zEntry = NULL; /* a single dir/file entry. */
58 cson_array * keyStore = NULL; /* garbage collector for shared strings. */
59 cson_string * zKeyName = NULL;
@@ -281,14 +281,14 @@
281
282 /*
283 ** Implements the /json/dir family of pages/commands.
284 **
285 */
286 cson_value * json_page_dir(void){
287 #if 1
288 return json_page_dir_list();
289 #else
290 return json_page_dispatch_helper(&JsonPageDefs_Dir[0]);
291 #endif
292 }
293
294 #endif /* FOSSIL_ENABLE_JSON */
295
--- src/json_finfo.c
+++ src/json_finfo.c
@@ -25,11 +25,11 @@
2525
2626
/*
2727
** Implements the /json/finfo page/command.
2828
**
2929
*/
30
-cson_value * json_page_finfo(){
30
+cson_value * json_page_finfo(void){
3131
cson_object * pay = NULL;
3232
cson_array * checkins = NULL;
3333
char const * zFilename = NULL;
3434
Blob sql = empty_blob;
3535
Stmt q = empty_Stmt;
3636
--- src/json_finfo.c
+++ src/json_finfo.c
@@ -25,11 +25,11 @@
25
26 /*
27 ** Implements the /json/finfo page/command.
28 **
29 */
30 cson_value * json_page_finfo(){
31 cson_object * pay = NULL;
32 cson_array * checkins = NULL;
33 char const * zFilename = NULL;
34 Blob sql = empty_blob;
35 Stmt q = empty_Stmt;
36
--- src/json_finfo.c
+++ src/json_finfo.c
@@ -25,11 +25,11 @@
25
26 /*
27 ** Implements the /json/finfo page/command.
28 **
29 */
30 cson_value * json_page_finfo(void){
31 cson_object * pay = NULL;
32 cson_array * checkins = NULL;
33 char const * zFilename = NULL;
34 Blob sql = empty_blob;
35 Stmt q = empty_Stmt;
36
--- src/json_login.c
+++ src/json_login.c
@@ -26,11 +26,11 @@
2626
2727
/*
2828
** Implementation of the /json/login page.
2929
**
3030
*/
31
-cson_value * json_page_login(){
31
+cson_value * json_page_login(void){
3232
char preciseErrors = /* if true, "complete" JSON error codes are used,
3333
else they are "dumbed down" to a generic login
3434
error code.
3535
*/
3636
#if 1
@@ -181,11 +181,11 @@
181181
182182
/*
183183
** Impl of /json/logout.
184184
**
185185
*/
186
-cson_value * json_page_logout(){
186
+cson_value * json_page_logout(void){
187187
cson_value const *token = g.json.authToken;
188188
/* Remember that json_bootstrap_late() replaces the login cookie
189189
with the JSON auth token if the request contains it. If the
190190
request is missing the auth token then this will fetch fossil's
191191
original cookie. Either way, it's what we want :).
@@ -207,11 +207,11 @@
207207
}
208208
209209
/*
210210
** Implementation of the /json/anonymousPassword page.
211211
*/
212
-cson_value * json_page_anon_password(){
212
+cson_value * json_page_anon_password(void){
213213
cson_value * v = cson_value_new_object();
214214
cson_object * o = cson_value_get_object(v);
215215
unsigned const int seed = captcha_seed();
216216
char const * zCaptcha = captcha_decode(seed);
217217
cson_object_set(o, "seed",
@@ -226,11 +226,11 @@
226226
227227
228228
/*
229229
** Implements the /json/whoami page/command.
230230
*/
231
-cson_value * json_page_whoami(){
231
+cson_value * json_page_whoami(void){
232232
cson_value * payload = NULL;
233233
cson_object * obj = NULL;
234234
Stmt q;
235235
if(!g.json.authToken && g.userUid==0){
236236
/* assume we just logged out. */
237237
--- src/json_login.c
+++ src/json_login.c
@@ -26,11 +26,11 @@
26
27 /*
28 ** Implementation of the /json/login page.
29 **
30 */
31 cson_value * json_page_login(){
32 char preciseErrors = /* if true, "complete" JSON error codes are used,
33 else they are "dumbed down" to a generic login
34 error code.
35 */
36 #if 1
@@ -181,11 +181,11 @@
181
182 /*
183 ** Impl of /json/logout.
184 **
185 */
186 cson_value * json_page_logout(){
187 cson_value const *token = g.json.authToken;
188 /* Remember that json_bootstrap_late() replaces the login cookie
189 with the JSON auth token if the request contains it. If the
190 request is missing the auth token then this will fetch fossil's
191 original cookie. Either way, it's what we want :).
@@ -207,11 +207,11 @@
207 }
208
209 /*
210 ** Implementation of the /json/anonymousPassword page.
211 */
212 cson_value * json_page_anon_password(){
213 cson_value * v = cson_value_new_object();
214 cson_object * o = cson_value_get_object(v);
215 unsigned const int seed = captcha_seed();
216 char const * zCaptcha = captcha_decode(seed);
217 cson_object_set(o, "seed",
@@ -226,11 +226,11 @@
226
227
228 /*
229 ** Implements the /json/whoami page/command.
230 */
231 cson_value * json_page_whoami(){
232 cson_value * payload = NULL;
233 cson_object * obj = NULL;
234 Stmt q;
235 if(!g.json.authToken && g.userUid==0){
236 /* assume we just logged out. */
237
--- src/json_login.c
+++ src/json_login.c
@@ -26,11 +26,11 @@
26
27 /*
28 ** Implementation of the /json/login page.
29 **
30 */
31 cson_value * json_page_login(void){
32 char preciseErrors = /* if true, "complete" JSON error codes are used,
33 else they are "dumbed down" to a generic login
34 error code.
35 */
36 #if 1
@@ -181,11 +181,11 @@
181
182 /*
183 ** Impl of /json/logout.
184 **
185 */
186 cson_value * json_page_logout(void){
187 cson_value const *token = g.json.authToken;
188 /* Remember that json_bootstrap_late() replaces the login cookie
189 with the JSON auth token if the request contains it. If the
190 request is missing the auth token then this will fetch fossil's
191 original cookie. Either way, it's what we want :).
@@ -207,11 +207,11 @@
207 }
208
209 /*
210 ** Implementation of the /json/anonymousPassword page.
211 */
212 cson_value * json_page_anon_password(void){
213 cson_value * v = cson_value_new_object();
214 cson_object * o = cson_value_get_object(v);
215 unsigned const int seed = captcha_seed();
216 char const * zCaptcha = captcha_decode(seed);
217 cson_object_set(o, "seed",
@@ -226,11 +226,11 @@
226
227
228 /*
229 ** Implements the /json/whoami page/command.
230 */
231 cson_value * json_page_whoami(void){
232 cson_value * payload = NULL;
233 cson_object * obj = NULL;
234 Stmt q;
235 if(!g.json.authToken && g.userUid==0){
236 /* assume we just logged out. */
237
--- src/json_query.c
+++ src/json_query.c
@@ -38,11 +38,11 @@
3838
** (default) creates each row as an Object.
3939
**
4040
** TODO: in CLI mode (only) use -S FILENAME to read the sql
4141
** from a file.
4242
*/
43
-cson_value * json_page_query(){
43
+cson_value * json_page_query(void){
4444
char const * zSql = NULL;
4545
cson_value * payV;
4646
char const * zFmt;
4747
Stmt q = empty_Stmt;
4848
int check;
4949
--- src/json_query.c
+++ src/json_query.c
@@ -38,11 +38,11 @@
38 ** (default) creates each row as an Object.
39 **
40 ** TODO: in CLI mode (only) use -S FILENAME to read the sql
41 ** from a file.
42 */
43 cson_value * json_page_query(){
44 char const * zSql = NULL;
45 cson_value * payV;
46 char const * zFmt;
47 Stmt q = empty_Stmt;
48 int check;
49
--- src/json_query.c
+++ src/json_query.c
@@ -38,11 +38,11 @@
38 ** (default) creates each row as an Object.
39 **
40 ** TODO: in CLI mode (only) use -S FILENAME to read the sql
41 ** from a file.
42 */
43 cson_value * json_page_query(void){
44 char const * zSql = NULL;
45 cson_value * payV;
46 char const * zFmt;
47 Stmt q = empty_Stmt;
48 int check;
49
+11 -11
--- src/json_report.c
+++ src/json_report.c
@@ -22,15 +22,15 @@
2222
#if INTERFACE
2323
#include "json_detail.h"
2424
#endif
2525
2626
27
-static cson_value * json_report_create();
28
-static cson_value * json_report_get();
29
-static cson_value * json_report_list();
30
-static cson_value * json_report_run();
31
-static cson_value * json_report_save();
27
+static cson_value * json_report_create(void);
28
+static cson_value * json_report_get(void);
29
+static cson_value * json_report_list(void);
30
+static cson_value * json_report_run(void);
31
+static cson_value * json_report_save(void);
3232
3333
/*
3434
** Mapping of /json/report/XXX commands/paths to callbacks.
3535
*/
3636
static const JsonPageDef JsonPageDefs_Report[] = {
@@ -45,11 +45,11 @@
4545
/*
4646
** Implementation of the /json/report page.
4747
**
4848
**
4949
*/
50
-cson_value * json_page_report(){
50
+cson_value * json_page_report(void){
5151
if(!g.perm.RdTkt && !g.perm.NewTkt ){
5252
json_set_err(FSL_JSON_E_DENIED,
5353
"Requires 'r' or 'n' permissions.");
5454
return NULL;
5555
}
@@ -77,16 +77,16 @@
7777
}
7878
}
7979
return nReport;
8080
}
8181
82
-static cson_value * json_report_create(){
82
+static cson_value * json_report_create(void){
8383
json_set_err(FSL_JSON_E_NYI, NULL);
8484
return NULL;
8585
}
8686
87
-static cson_value * json_report_get(){
87
+static cson_value * json_report_get(void){
8888
int nReport;
8989
Stmt q = empty_Stmt;
9090
cson_value * pay = NULL;
9191
9292
if(!g.perm.TktFmt){
@@ -122,11 +122,11 @@
122122
}
123123
124124
/*
125125
** Impl of /json/report/list.
126126
*/
127
-static cson_value * json_report_list(){
127
+static cson_value * json_report_list(void){
128128
Blob sql = empty_blob;
129129
cson_value * pay = NULL;
130130
if(!g.perm.RdTkt){
131131
json_set_err(FSL_JSON_E_DENIED,
132132
"Requires 'r' privileges.");
@@ -158,11 +158,11 @@
158158
** limit=int (CLI: -limit # or -n #) -n is for compat. with other commands.
159159
**
160160
** format=a|o Specifies result format: a=each row is an arry, o=each
161161
** row is an object. Default=o.
162162
*/
163
-static cson_value * json_report_run(){
163
+static cson_value * json_report_run(void){
164164
int nReport;
165165
Stmt q = empty_Stmt;
166166
cson_object * pay = NULL;
167167
cson_array * tktList = NULL;
168168
char const * zFmt;
@@ -255,9 +255,9 @@
255255
256256
return pay ? cson_object_value(pay) : NULL;
257257
258258
}
259259
260
-static cson_value * json_report_save(){
260
+static cson_value * json_report_save(void){
261261
return NULL;
262262
}
263263
#endif /* FOSSIL_ENABLE_JSON */
264264
--- src/json_report.c
+++ src/json_report.c
@@ -22,15 +22,15 @@
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26
27 static cson_value * json_report_create();
28 static cson_value * json_report_get();
29 static cson_value * json_report_list();
30 static cson_value * json_report_run();
31 static cson_value * json_report_save();
32
33 /*
34 ** Mapping of /json/report/XXX commands/paths to callbacks.
35 */
36 static const JsonPageDef JsonPageDefs_Report[] = {
@@ -45,11 +45,11 @@
45 /*
46 ** Implementation of the /json/report page.
47 **
48 **
49 */
50 cson_value * json_page_report(){
51 if(!g.perm.RdTkt && !g.perm.NewTkt ){
52 json_set_err(FSL_JSON_E_DENIED,
53 "Requires 'r' or 'n' permissions.");
54 return NULL;
55 }
@@ -77,16 +77,16 @@
77 }
78 }
79 return nReport;
80 }
81
82 static cson_value * json_report_create(){
83 json_set_err(FSL_JSON_E_NYI, NULL);
84 return NULL;
85 }
86
87 static cson_value * json_report_get(){
88 int nReport;
89 Stmt q = empty_Stmt;
90 cson_value * pay = NULL;
91
92 if(!g.perm.TktFmt){
@@ -122,11 +122,11 @@
122 }
123
124 /*
125 ** Impl of /json/report/list.
126 */
127 static cson_value * json_report_list(){
128 Blob sql = empty_blob;
129 cson_value * pay = NULL;
130 if(!g.perm.RdTkt){
131 json_set_err(FSL_JSON_E_DENIED,
132 "Requires 'r' privileges.");
@@ -158,11 +158,11 @@
158 ** limit=int (CLI: -limit # or -n #) -n is for compat. with other commands.
159 **
160 ** format=a|o Specifies result format: a=each row is an arry, o=each
161 ** row is an object. Default=o.
162 */
163 static cson_value * json_report_run(){
164 int nReport;
165 Stmt q = empty_Stmt;
166 cson_object * pay = NULL;
167 cson_array * tktList = NULL;
168 char const * zFmt;
@@ -255,9 +255,9 @@
255
256 return pay ? cson_object_value(pay) : NULL;
257
258 }
259
260 static cson_value * json_report_save(){
261 return NULL;
262 }
263 #endif /* FOSSIL_ENABLE_JSON */
264
--- src/json_report.c
+++ src/json_report.c
@@ -22,15 +22,15 @@
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26
27 static cson_value * json_report_create(void);
28 static cson_value * json_report_get(void);
29 static cson_value * json_report_list(void);
30 static cson_value * json_report_run(void);
31 static cson_value * json_report_save(void);
32
33 /*
34 ** Mapping of /json/report/XXX commands/paths to callbacks.
35 */
36 static const JsonPageDef JsonPageDefs_Report[] = {
@@ -45,11 +45,11 @@
45 /*
46 ** Implementation of the /json/report page.
47 **
48 **
49 */
50 cson_value * json_page_report(void){
51 if(!g.perm.RdTkt && !g.perm.NewTkt ){
52 json_set_err(FSL_JSON_E_DENIED,
53 "Requires 'r' or 'n' permissions.");
54 return NULL;
55 }
@@ -77,16 +77,16 @@
77 }
78 }
79 return nReport;
80 }
81
82 static cson_value * json_report_create(void){
83 json_set_err(FSL_JSON_E_NYI, NULL);
84 return NULL;
85 }
86
87 static cson_value * json_report_get(void){
88 int nReport;
89 Stmt q = empty_Stmt;
90 cson_value * pay = NULL;
91
92 if(!g.perm.TktFmt){
@@ -122,11 +122,11 @@
122 }
123
124 /*
125 ** Impl of /json/report/list.
126 */
127 static cson_value * json_report_list(void){
128 Blob sql = empty_blob;
129 cson_value * pay = NULL;
130 if(!g.perm.RdTkt){
131 json_set_err(FSL_JSON_E_DENIED,
132 "Requires 'r' privileges.");
@@ -158,11 +158,11 @@
158 ** limit=int (CLI: -limit # or -n #) -n is for compat. with other commands.
159 **
160 ** format=a|o Specifies result format: a=each row is an arry, o=each
161 ** row is an object. Default=o.
162 */
163 static cson_value * json_report_run(void){
164 int nReport;
165 Stmt q = empty_Stmt;
166 cson_object * pay = NULL;
167 cson_array * tktList = NULL;
168 char const * zFmt;
@@ -255,9 +255,9 @@
255
256 return pay ? cson_object_value(pay) : NULL;
257
258 }
259
260 static cson_value * json_report_save(void){
261 return NULL;
262 }
263 #endif /* FOSSIL_ENABLE_JSON */
264
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -22,13 +22,13 @@
2222
2323
#if INTERFACE
2424
#include "json_detail.h"
2525
#endif
2626
27
-static cson_value * json_timeline_branch();
28
-static cson_value * json_timeline_ci();
29
-static cson_value * json_timeline_ticket();
27
+static cson_value * json_timeline_branch(void);
28
+static cson_value * json_timeline_ci(void);
29
+static cson_value * json_timeline_ticket(void);
3030
/*
3131
** Mapping of /json/timeline/XXX commands/paths to callbacks.
3232
*/
3333
static const JsonPageDef JsonPageDefs_Timeline[] = {
3434
/* the short forms are only enabled in CLI mode, to avoid
@@ -49,11 +49,11 @@
4949
/*
5050
** Implements the /json/timeline family of pages/commands. Far from
5151
** complete.
5252
**
5353
*/
54
-cson_value * json_page_timeline(){
54
+cson_value * json_page_timeline(void){
5555
#if 0
5656
/* The original timeline code does not require 'h' access,
5757
but it arguably should. For JSON mode i think one could argue
5858
that History permissions are required.
5959
*/
@@ -364,11 +364,11 @@
364364
}
365365
db_finalize(&q);
366366
return rowsV;
367367
}
368368
369
-static cson_value * json_timeline_branch(){
369
+static cson_value * json_timeline_branch(void){
370370
cson_value * pay = NULL;
371371
Blob sql = empty_blob;
372372
Stmt q = empty_Stmt;
373373
int limit = 0;
374374
if(!g.perm.Read){
@@ -445,11 +445,11 @@
445445
** Implementation of /json/timeline/ci.
446446
**
447447
** Still a few TODOs (like figuring out how to structure
448448
** inheritance info).
449449
*/
450
-static cson_value * json_timeline_ci(){
450
+static cson_value * json_timeline_ci(void){
451451
cson_value * payV = NULL;
452452
cson_object * pay = NULL;
453453
cson_value * tmp = NULL;
454454
cson_value * listV = NULL;
455455
cson_array * list = NULL;
@@ -526,11 +526,11 @@
526526
527527
/*
528528
** Implementation of /json/timeline/event.
529529
**
530530
*/
531
-cson_value * json_timeline_event(){
531
+cson_value * json_timeline_event(void){
532532
/* This code is 95% the same as json_timeline_ci(), by the way. */
533533
cson_value * payV = NULL;
534534
cson_object * pay = NULL;
535535
cson_array * list = NULL;
536536
int check = 0;
@@ -582,11 +582,11 @@
582582
583583
/*
584584
** Implementation of /json/timeline/wiki.
585585
**
586586
*/
587
-cson_value * json_timeline_wiki(){
587
+cson_value * json_timeline_wiki(void){
588588
/* This code is 95% the same as json_timeline_ci(), by the way. */
589589
cson_value * payV = NULL;
590590
cson_object * pay = NULL;
591591
cson_array * list = NULL;
592592
int check = 0;
@@ -643,11 +643,11 @@
643643
644644
/*
645645
** Implementation of /json/timeline/ticket.
646646
**
647647
*/
648
-static cson_value * json_timeline_ticket(){
648
+static cson_value * json_timeline_ticket(void){
649649
/* This code is 95% the same as json_timeline_ci(), by the way. */
650650
cson_value * payV = NULL;
651651
cson_object * pay = NULL;
652652
cson_value * tmp = NULL;
653653
cson_value * listV = NULL;
654654
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -22,13 +22,13 @@
22
23 #if INTERFACE
24 #include "json_detail.h"
25 #endif
26
27 static cson_value * json_timeline_branch();
28 static cson_value * json_timeline_ci();
29 static cson_value * json_timeline_ticket();
30 /*
31 ** Mapping of /json/timeline/XXX commands/paths to callbacks.
32 */
33 static const JsonPageDef JsonPageDefs_Timeline[] = {
34 /* the short forms are only enabled in CLI mode, to avoid
@@ -49,11 +49,11 @@
49 /*
50 ** Implements the /json/timeline family of pages/commands. Far from
51 ** complete.
52 **
53 */
54 cson_value * json_page_timeline(){
55 #if 0
56 /* The original timeline code does not require 'h' access,
57 but it arguably should. For JSON mode i think one could argue
58 that History permissions are required.
59 */
@@ -364,11 +364,11 @@
364 }
365 db_finalize(&q);
366 return rowsV;
367 }
368
369 static cson_value * json_timeline_branch(){
370 cson_value * pay = NULL;
371 Blob sql = empty_blob;
372 Stmt q = empty_Stmt;
373 int limit = 0;
374 if(!g.perm.Read){
@@ -445,11 +445,11 @@
445 ** Implementation of /json/timeline/ci.
446 **
447 ** Still a few TODOs (like figuring out how to structure
448 ** inheritance info).
449 */
450 static cson_value * json_timeline_ci(){
451 cson_value * payV = NULL;
452 cson_object * pay = NULL;
453 cson_value * tmp = NULL;
454 cson_value * listV = NULL;
455 cson_array * list = NULL;
@@ -526,11 +526,11 @@
526
527 /*
528 ** Implementation of /json/timeline/event.
529 **
530 */
531 cson_value * json_timeline_event(){
532 /* This code is 95% the same as json_timeline_ci(), by the way. */
533 cson_value * payV = NULL;
534 cson_object * pay = NULL;
535 cson_array * list = NULL;
536 int check = 0;
@@ -582,11 +582,11 @@
582
583 /*
584 ** Implementation of /json/timeline/wiki.
585 **
586 */
587 cson_value * json_timeline_wiki(){
588 /* This code is 95% the same as json_timeline_ci(), by the way. */
589 cson_value * payV = NULL;
590 cson_object * pay = NULL;
591 cson_array * list = NULL;
592 int check = 0;
@@ -643,11 +643,11 @@
643
644 /*
645 ** Implementation of /json/timeline/ticket.
646 **
647 */
648 static cson_value * json_timeline_ticket(){
649 /* This code is 95% the same as json_timeline_ci(), by the way. */
650 cson_value * payV = NULL;
651 cson_object * pay = NULL;
652 cson_value * tmp = NULL;
653 cson_value * listV = NULL;
654
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -22,13 +22,13 @@
22
23 #if INTERFACE
24 #include "json_detail.h"
25 #endif
26
27 static cson_value * json_timeline_branch(void);
28 static cson_value * json_timeline_ci(void);
29 static cson_value * json_timeline_ticket(void);
30 /*
31 ** Mapping of /json/timeline/XXX commands/paths to callbacks.
32 */
33 static const JsonPageDef JsonPageDefs_Timeline[] = {
34 /* the short forms are only enabled in CLI mode, to avoid
@@ -49,11 +49,11 @@
49 /*
50 ** Implements the /json/timeline family of pages/commands. Far from
51 ** complete.
52 **
53 */
54 cson_value * json_page_timeline(void){
55 #if 0
56 /* The original timeline code does not require 'h' access,
57 but it arguably should. For JSON mode i think one could argue
58 that History permissions are required.
59 */
@@ -364,11 +364,11 @@
364 }
365 db_finalize(&q);
366 return rowsV;
367 }
368
369 static cson_value * json_timeline_branch(void){
370 cson_value * pay = NULL;
371 Blob sql = empty_blob;
372 Stmt q = empty_Stmt;
373 int limit = 0;
374 if(!g.perm.Read){
@@ -445,11 +445,11 @@
445 ** Implementation of /json/timeline/ci.
446 **
447 ** Still a few TODOs (like figuring out how to structure
448 ** inheritance info).
449 */
450 static cson_value * json_timeline_ci(void){
451 cson_value * payV = NULL;
452 cson_object * pay = NULL;
453 cson_value * tmp = NULL;
454 cson_value * listV = NULL;
455 cson_array * list = NULL;
@@ -526,11 +526,11 @@
526
527 /*
528 ** Implementation of /json/timeline/event.
529 **
530 */
531 cson_value * json_timeline_event(void){
532 /* This code is 95% the same as json_timeline_ci(), by the way. */
533 cson_value * payV = NULL;
534 cson_object * pay = NULL;
535 cson_array * list = NULL;
536 int check = 0;
@@ -582,11 +582,11 @@
582
583 /*
584 ** Implementation of /json/timeline/wiki.
585 **
586 */
587 cson_value * json_timeline_wiki(void){
588 /* This code is 95% the same as json_timeline_ci(), by the way. */
589 cson_value * payV = NULL;
590 cson_object * pay = NULL;
591 cson_array * list = NULL;
592 int check = 0;
@@ -643,11 +643,11 @@
643
644 /*
645 ** Implementation of /json/timeline/ticket.
646 **
647 */
648 static cson_value * json_timeline_ticket(void){
649 /* This code is 95% the same as json_timeline_ci(), by the way. */
650 cson_value * payV = NULL;
651 cson_object * pay = NULL;
652 cson_value * tmp = NULL;
653 cson_value * listV = NULL;
654
+7 -7
--- src/json_user.c
+++ src/json_user.c
@@ -21,13 +21,13 @@
2121
2222
#if INTERFACE
2323
#include "json_detail.h"
2424
#endif
2525
26
-static cson_value * json_user_get();
27
-static cson_value * json_user_list();
28
-static cson_value * json_user_save();
26
+static cson_value * json_user_get(void);
27
+static cson_value * json_user_list(void);
28
+static cson_value * json_user_save(void);
2929
3030
/*
3131
** Mapping of /json/user/XXX commands/paths to callbacks.
3232
*/
3333
static const JsonPageDef JsonPageDefs_User[] = {
@@ -41,19 +41,19 @@
4141
4242
/*
4343
** Implements the /json/user family of pages/commands.
4444
**
4545
*/
46
-cson_value * json_page_user(){
46
+cson_value * json_page_user(void){
4747
return json_page_dispatch_helper(&JsonPageDefs_User[0]);
4848
}
4949
5050
5151
/*
5252
** Impl of /json/user/list. Requires admin/setup rights.
5353
*/
54
-static cson_value * json_user_list(){
54
+static cson_value * json_user_list(void){
5555
cson_value * payV = NULL;
5656
Stmt q;
5757
if(!g.perm.Admin && !g.perm.Setup){
5858
json_set_err(FSL_JSON_E_DENIED,
5959
"Requires 'a' or 's' privileges.");
@@ -122,11 +122,11 @@
122122
123123
124124
/*
125125
** Impl of /json/user/get. Requires admin or setup rights.
126126
*/
127
-static cson_value * json_user_get(){
127
+static cson_value * json_user_get(void){
128128
cson_value * payV = NULL;
129129
char const * pUser = NULL;
130130
if(!g.perm.Admin && !g.perm.Setup){
131131
json_set_err(FSL_JSON_E_DENIED,
132132
"Requires 'a' or 's' privileges.");
@@ -393,11 +393,11 @@
393393
394394
395395
/*
396396
** Impl of /json/user/save.
397397
*/
398
-static cson_value * json_user_save(){
398
+static cson_value * json_user_save(void){
399399
/* try to get user info from GET/CLI args and construct
400400
a JSON form of it... */
401401
cson_object * u = cson_new_object();
402402
char const * str = NULL;
403403
int b = -1;
404404
--- src/json_user.c
+++ src/json_user.c
@@ -21,13 +21,13 @@
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 static cson_value * json_user_get();
27 static cson_value * json_user_list();
28 static cson_value * json_user_save();
29
30 /*
31 ** Mapping of /json/user/XXX commands/paths to callbacks.
32 */
33 static const JsonPageDef JsonPageDefs_User[] = {
@@ -41,19 +41,19 @@
41
42 /*
43 ** Implements the /json/user family of pages/commands.
44 **
45 */
46 cson_value * json_page_user(){
47 return json_page_dispatch_helper(&JsonPageDefs_User[0]);
48 }
49
50
51 /*
52 ** Impl of /json/user/list. Requires admin/setup rights.
53 */
54 static cson_value * json_user_list(){
55 cson_value * payV = NULL;
56 Stmt q;
57 if(!g.perm.Admin && !g.perm.Setup){
58 json_set_err(FSL_JSON_E_DENIED,
59 "Requires 'a' or 's' privileges.");
@@ -122,11 +122,11 @@
122
123
124 /*
125 ** Impl of /json/user/get. Requires admin or setup rights.
126 */
127 static cson_value * json_user_get(){
128 cson_value * payV = NULL;
129 char const * pUser = NULL;
130 if(!g.perm.Admin && !g.perm.Setup){
131 json_set_err(FSL_JSON_E_DENIED,
132 "Requires 'a' or 's' privileges.");
@@ -393,11 +393,11 @@
393
394
395 /*
396 ** Impl of /json/user/save.
397 */
398 static cson_value * json_user_save(){
399 /* try to get user info from GET/CLI args and construct
400 a JSON form of it... */
401 cson_object * u = cson_new_object();
402 char const * str = NULL;
403 int b = -1;
404
--- src/json_user.c
+++ src/json_user.c
@@ -21,13 +21,13 @@
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 static cson_value * json_user_get(void);
27 static cson_value * json_user_list(void);
28 static cson_value * json_user_save(void);
29
30 /*
31 ** Mapping of /json/user/XXX commands/paths to callbacks.
32 */
33 static const JsonPageDef JsonPageDefs_User[] = {
@@ -41,19 +41,19 @@
41
42 /*
43 ** Implements the /json/user family of pages/commands.
44 **
45 */
46 cson_value * json_page_user(void){
47 return json_page_dispatch_helper(&JsonPageDefs_User[0]);
48 }
49
50
51 /*
52 ** Impl of /json/user/list. Requires admin/setup rights.
53 */
54 static cson_value * json_user_list(void){
55 cson_value * payV = NULL;
56 Stmt q;
57 if(!g.perm.Admin && !g.perm.Setup){
58 json_set_err(FSL_JSON_E_DENIED,
59 "Requires 'a' or 's' privileges.");
@@ -122,11 +122,11 @@
122
123
124 /*
125 ** Impl of /json/user/get. Requires admin or setup rights.
126 */
127 static cson_value * json_user_get(void){
128 cson_value * payV = NULL;
129 char const * pUser = NULL;
130 if(!g.perm.Admin && !g.perm.Setup){
131 json_set_err(FSL_JSON_E_DENIED,
132 "Requires 'a' or 's' privileges.");
@@ -393,11 +393,11 @@
393
394
395 /*
396 ** Impl of /json/user/save.
397 */
398 static cson_value * json_user_save(void){
399 /* try to get user info from GET/CLI args and construct
400 a JSON form of it... */
401 cson_object * u = cson_new_object();
402 char const * str = NULL;
403 int b = -1;
404
+13 -13
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -21,16 +21,16 @@
2121
2222
#if INTERFACE
2323
#include "json_detail.h"
2424
#endif
2525
26
-static cson_value * json_wiki_create();
27
-static cson_value * json_wiki_get();
28
-static cson_value * json_wiki_list();
29
-static cson_value * json_wiki_preview();
30
-static cson_value * json_wiki_save();
31
-static cson_value * json_wiki_diff();
26
+static cson_value * json_wiki_create(void);
27
+static cson_value * json_wiki_get(void);
28
+static cson_value * json_wiki_list(void);
29
+static cson_value * json_wiki_preview(void);
30
+static cson_value * json_wiki_save(void);
31
+static cson_value * json_wiki_diff(void);
3232
/*
3333
** Mapping of /json/wiki/XXX commands/paths to callbacks.
3434
*/
3535
static const JsonPageDef JsonPageDefs_Wiki[] = {
3636
{"create", json_wiki_create, 0},
@@ -47,11 +47,11 @@
4747
4848
/*
4949
** Implements the /json/wiki family of pages/commands.
5050
**
5151
*/
52
-cson_value * json_page_wiki(){
52
+cson_value * json_page_wiki(void){
5353
return json_page_dispatch_helper(JsonPageDefs_Wiki);
5454
}
5555
5656
/*
5757
** Returns the UUID for the given wiki blob RID, or NULL if not
@@ -244,11 +244,11 @@
244244
245245
/*
246246
** Implementation of /json/wiki/get.
247247
**
248248
*/
249
-static cson_value * json_wiki_get(){
249
+static cson_value * json_wiki_get(void){
250250
char const * zPageName;
251251
char const * zSymName = NULL;
252252
int contentFormat = -1;
253253
if( !g.perm.RdWiki && !g.perm.Read ){
254254
json_set_err(FSL_JSON_E_DENIED,
@@ -274,11 +274,11 @@
274274
}
275275
276276
/*
277277
** Implementation of /json/wiki/preview.
278278
*/
279
-static cson_value * json_wiki_preview(){
279
+static cson_value * json_wiki_preview(void){
280280
char const * zContent = NULL;
281281
char const * zMime = NULL;
282282
cson_string * sContent = NULL;
283283
cson_value * pay = NULL;
284284
Blob contentOrig = empty_blob;
@@ -449,26 +449,26 @@
449449
}
450450
451451
/*
452452
** Implementation of /json/wiki/create.
453453
*/
454
-static cson_value * json_wiki_create(){
454
+static cson_value * json_wiki_create(void){
455455
return json_wiki_create_or_save(1,0);
456456
}
457457
458458
/*
459459
** Implementation of /json/wiki/save.
460460
*/
461
-static cson_value * json_wiki_save(){
461
+static cson_value * json_wiki_save(void){
462462
char const createIfNotExists = json_getenv_bool("createIfNotExists",0);
463463
return json_wiki_create_or_save(0,createIfNotExists);
464464
}
465465
466466
/*
467467
** Implementation of /json/wiki/list.
468468
*/
469
-static cson_value * json_wiki_list(){
469
+static cson_value * json_wiki_list(void){
470470
cson_value * listV = NULL;
471471
cson_array * list = NULL;
472472
char const * zGlob = NULL;
473473
Stmt q = empty_Stmt;
474474
Blob sql = empty_blob;
@@ -531,11 +531,11 @@
531531
end:
532532
db_finalize(&q);
533533
return listV;
534534
}
535535
536
-static cson_value * json_wiki_diff(){
536
+static cson_value * json_wiki_diff(void){
537537
char const * zV1 = NULL;
538538
char const * zV2 = NULL;
539539
cson_object * pay = NULL;
540540
int argPos = g.json.dispatchDepth;
541541
int r1 = 0, r2 = 0;
542542
543543
ADDED www/json-api/api-settings.md
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -21,16 +21,16 @@
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 static cson_value * json_wiki_create();
27 static cson_value * json_wiki_get();
28 static cson_value * json_wiki_list();
29 static cson_value * json_wiki_preview();
30 static cson_value * json_wiki_save();
31 static cson_value * json_wiki_diff();
32 /*
33 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
34 */
35 static const JsonPageDef JsonPageDefs_Wiki[] = {
36 {"create", json_wiki_create, 0},
@@ -47,11 +47,11 @@
47
48 /*
49 ** Implements the /json/wiki family of pages/commands.
50 **
51 */
52 cson_value * json_page_wiki(){
53 return json_page_dispatch_helper(JsonPageDefs_Wiki);
54 }
55
56 /*
57 ** Returns the UUID for the given wiki blob RID, or NULL if not
@@ -244,11 +244,11 @@
244
245 /*
246 ** Implementation of /json/wiki/get.
247 **
248 */
249 static cson_value * json_wiki_get(){
250 char const * zPageName;
251 char const * zSymName = NULL;
252 int contentFormat = -1;
253 if( !g.perm.RdWiki && !g.perm.Read ){
254 json_set_err(FSL_JSON_E_DENIED,
@@ -274,11 +274,11 @@
274 }
275
276 /*
277 ** Implementation of /json/wiki/preview.
278 */
279 static cson_value * json_wiki_preview(){
280 char const * zContent = NULL;
281 char const * zMime = NULL;
282 cson_string * sContent = NULL;
283 cson_value * pay = NULL;
284 Blob contentOrig = empty_blob;
@@ -449,26 +449,26 @@
449 }
450
451 /*
452 ** Implementation of /json/wiki/create.
453 */
454 static cson_value * json_wiki_create(){
455 return json_wiki_create_or_save(1,0);
456 }
457
458 /*
459 ** Implementation of /json/wiki/save.
460 */
461 static cson_value * json_wiki_save(){
462 char const createIfNotExists = json_getenv_bool("createIfNotExists",0);
463 return json_wiki_create_or_save(0,createIfNotExists);
464 }
465
466 /*
467 ** Implementation of /json/wiki/list.
468 */
469 static cson_value * json_wiki_list(){
470 cson_value * listV = NULL;
471 cson_array * list = NULL;
472 char const * zGlob = NULL;
473 Stmt q = empty_Stmt;
474 Blob sql = empty_blob;
@@ -531,11 +531,11 @@
531 end:
532 db_finalize(&q);
533 return listV;
534 }
535
536 static cson_value * json_wiki_diff(){
537 char const * zV1 = NULL;
538 char const * zV2 = NULL;
539 cson_object * pay = NULL;
540 int argPos = g.json.dispatchDepth;
541 int r1 = 0, r2 = 0;
542
543 DDED www/json-api/api-settings.md
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -21,16 +21,16 @@
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 static cson_value * json_wiki_create(void);
27 static cson_value * json_wiki_get(void);
28 static cson_value * json_wiki_list(void);
29 static cson_value * json_wiki_preview(void);
30 static cson_value * json_wiki_save(void);
31 static cson_value * json_wiki_diff(void);
32 /*
33 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
34 */
35 static const JsonPageDef JsonPageDefs_Wiki[] = {
36 {"create", json_wiki_create, 0},
@@ -47,11 +47,11 @@
47
48 /*
49 ** Implements the /json/wiki family of pages/commands.
50 **
51 */
52 cson_value * json_page_wiki(void){
53 return json_page_dispatch_helper(JsonPageDefs_Wiki);
54 }
55
56 /*
57 ** Returns the UUID for the given wiki blob RID, or NULL if not
@@ -244,11 +244,11 @@
244
245 /*
246 ** Implementation of /json/wiki/get.
247 **
248 */
249 static cson_value * json_wiki_get(void){
250 char const * zPageName;
251 char const * zSymName = NULL;
252 int contentFormat = -1;
253 if( !g.perm.RdWiki && !g.perm.Read ){
254 json_set_err(FSL_JSON_E_DENIED,
@@ -274,11 +274,11 @@
274 }
275
276 /*
277 ** Implementation of /json/wiki/preview.
278 */
279 static cson_value * json_wiki_preview(void){
280 char const * zContent = NULL;
281 char const * zMime = NULL;
282 cson_string * sContent = NULL;
283 cson_value * pay = NULL;
284 Blob contentOrig = empty_blob;
@@ -449,26 +449,26 @@
449 }
450
451 /*
452 ** Implementation of /json/wiki/create.
453 */
454 static cson_value * json_wiki_create(void){
455 return json_wiki_create_or_save(1,0);
456 }
457
458 /*
459 ** Implementation of /json/wiki/save.
460 */
461 static cson_value * json_wiki_save(void){
462 char const createIfNotExists = json_getenv_bool("createIfNotExists",0);
463 return json_wiki_create_or_save(0,createIfNotExists);
464 }
465
466 /*
467 ** Implementation of /json/wiki/list.
468 */
469 static cson_value * json_wiki_list(void){
470 cson_value * listV = NULL;
471 cson_array * list = NULL;
472 char const * zGlob = NULL;
473 Stmt q = empty_Stmt;
474 Blob sql = empty_blob;
@@ -531,11 +531,11 @@
531 end:
532 db_finalize(&q);
533 return listV;
534 }
535
536 static cson_value * json_wiki_diff(void){
537 char const * zV1 = NULL;
538 char const * zV2 = NULL;
539 cson_object * pay = NULL;
540 int argPos = g.json.dispatchDepth;
541 int r1 = 0, r2 = 0;
542
543 DDED www/json-api/api-settings.md
--- a/www/json-api/api-settings.md
+++ b/www/json-api/api-settings.md
@@ -0,0 +1,127 @@
1
+# JSON API: /settings
2
+([&#x2b11;JSON API Index](index.md))
3
+
4
+Jump to:
5
+
6
+* [Fetch Settings](#get)
7
+* [Set Settings](#set)
8
+
9
+---
10
+
11
+<a id="get"></a>
12
+# Fetch Settings
13
+
14
+**Status:** Implemented 20230120
15
+
16
+**Required permissions:** "o"
17
+
18
+**Request:** `/json/settings/get[?version=X]`
19
+
20
+**Response payload example:**
21
+
22
+```json
23
+{
24
+ "access-log":{
25
+ "versionable":false,
26
+ "sensitive":false,
27
+ "defaultValue":"off",
28
+ "valueSource":null,
29
+ "value":null
30
+ },
31
+...
32
+ "binary-glob":{
33
+ "versionable":true,
34
+ "sensitive":false,
35
+ "defaultValue":null,
36
+ "valueSource":"versioned",
37
+ "value":"*.gif\n*.ico\n*.jpg\n*.odp\n*.dia\n*.pdf\n*.png\n*.wav..."
38
+ },
39
+...
40
+ "web-browser":{
41
+ "versionable":false,
42
+ "sensitive":true,
43
+ "defaultValue":null,
44
+ "valueSource":"repo",
45
+ "value":"firefox"
46
+ }
47
+}
48
+```
49
+
50
+Each key in the payload is the name of a fossil-recognized setting,
51
+modeled as an object. The keys of that are:
52
+
53
+
54
+- `defaultValue`: the setting's default value, or `null` if no default
55
+ is defined.
56
+- `value`: The current value of that setting.
57
+- `valueSource`: one of (`"repo"`, `"checkout"`, `"versioned"`, or
58
+ `null`), specifying the data source where the setting was found. The
59
+ settings sources are checked in this order and the first one found
60
+ is the result:
61
+ - If `version=X` is provided, check-in `X` is searched for a
62
+ versionable-settings file. If found, its value is used and
63
+ `valueSource` will be `"versioned"`. If `X` is not a checkin, an
64
+ error response is produced with code `FOSSIL-3006`.
65
+ - If a versionable setting is found in the current checkout, its
66
+ value is used and `valueSource` will be `"versioned"`
67
+ - If the setting is found in checkout database's `vvar` table, its
68
+ value is used and `valueSource` will be `"checkout"`.
69
+ - If the setting is found in repository's `config` table, its
70
+ value is used and `valueSource` will be `"repo"`.
71
+ - If no value is found, `null` is used for both the `value` and
72
+ `valueSource` results. Note that _global settings are never
73
+ checked_ because they can leak information which have nothing
74
+ specifically to do with the given repository.
75
+- `sensitive`: a value which fossil has flagged as sensitive can only
76
+ be fetched by a Setup user. For other users, they will always have
77
+ a `value` and `valueSource` of `null`.
78
+- `versionable`: `true` if the setting is tagged as versionable, else
79
+ `false`.
80
+
81
+Note that settings are internally stored as strings, even if they're
82
+semantically treated as numbers. The way settings are stored and
83
+handled does not give us enough information to recognize their exact
84
+data type here so they are passed on as-is.
85
+
86
+
87
+<a id="set"></a>
88
+# Set Settings
89
+
90
+**Status:** Implemented 20230120
91
+
92
+**Required permissions:** "s"
93
+
94
+**Request:** `/json/settings/set`
95
+
96
+This call requires that the input payload be an object containing a
97
+mapping of fossil-known configuration keys (case-sensitive) to
98
+values. For example:
99
+
100
+```json
101
+{
102
+ "editor": "emacs",
103
+ "admin-log": true,
104
+ "auto-captcha": false
105
+}
106
+```
107
+
108
+It iterates through each property, which must have a data type of
109
+`null`, boolean, number, or string. A value of `null` _unsets_
110
+(deletes) the setting. Boolean values are stored as integer 0
111
+or 1. All other types are stored as-is. It only updates the
112
+`repository.config` database and never updates a checkout or global
113
+config database, nor is it capable of updating versioned settings
114
+(^Updating versioned settings requires creating a full check-in.).
115
+
116
+It has no result payload but this may be changed in the future it
117
+practice shows that it should return something specific.
118
+
119
+Error responses include:
120
+
121
+- `FOSSIL-2002`: called without "setup" permissions.
122
+- `FOSSIL-3002`: called without a payload object.
123
+- `FOSSIL-3001`: passed an unknown config option.
124
+- `FOSSIL-3000`: a value has an unsupported data type.
125
+
126
+If an error is triggered, any settings made by this call up until that
127
+point are discarded.
--- a/www/json-api/api-settings.md
+++ b/www/json-api/api-settings.md
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/www/json-api/api-settings.md
+++ b/www/json-api/api-settings.md
@@ -0,0 +1,127 @@
1 # JSON API: /settings
2 ([&#x2b11;JSON API Index](index.md))
3
4 Jump to:
5
6 * [Fetch Settings](#get)
7 * [Set Settings](#set)
8
9 ---
10
11 <a id="get"></a>
12 # Fetch Settings
13
14 **Status:** Implemented 20230120
15
16 **Required permissions:** "o"
17
18 **Request:** `/json/settings/get[?version=X]`
19
20 **Response payload example:**
21
22 ```json
23 {
24 "access-log":{
25 "versionable":false,
26 "sensitive":false,
27 "defaultValue":"off",
28 "valueSource":null,
29 "value":null
30 },
31 ...
32 "binary-glob":{
33 "versionable":true,
34 "sensitive":false,
35 "defaultValue":null,
36 "valueSource":"versioned",
37 "value":"*.gif\n*.ico\n*.jpg\n*.odp\n*.dia\n*.pdf\n*.png\n*.wav..."
38 },
39 ...
40 "web-browser":{
41 "versionable":false,
42 "sensitive":true,
43 "defaultValue":null,
44 "valueSource":"repo",
45 "value":"firefox"
46 }
47 }
48 ```
49
50 Each key in the payload is the name of a fossil-recognized setting,
51 modeled as an object. The keys of that are:
52
53
54 - `defaultValue`: the setting's default value, or `null` if no default
55 is defined.
56 - `value`: The current value of that setting.
57 - `valueSource`: one of (`"repo"`, `"checkout"`, `"versioned"`, or
58 `null`), specifying the data source where the setting was found. The
59 settings sources are checked in this order and the first one found
60 is the result:
61 - If `version=X` is provided, check-in `X` is searched for a
62 versionable-settings file. If found, its value is used and
63 `valueSource` will be `"versioned"`. If `X` is not a checkin, an
64 error response is produced with code `FOSSIL-3006`.
65 - If a versionable setting is found in the current checkout, its
66 value is used and `valueSource` will be `"versioned"`
67 - If the setting is found in checkout database's `vvar` table, its
68 value is used and `valueSource` will be `"checkout"`.
69 - If the setting is found in repository's `config` table, its
70 value is used and `valueSource` will be `"repo"`.
71 - If no value is found, `null` is used for both the `value` and
72 `valueSource` results. Note that _global settings are never
73 checked_ because they can leak information which have nothing
74 specifically to do with the given repository.
75 - `sensitive`: a value which fossil has flagged as sensitive can only
76 be fetched by a Setup user. For other users, they will always have
77 a `value` and `valueSource` of `null`.
78 - `versionable`: `true` if the setting is tagged as versionable, else
79 `false`.
80
81 Note that settings are internally stored as strings, even if they're
82 semantically treated as numbers. The way settings are stored and
83 handled does not give us enough information to recognize their exact
84 data type here so they are passed on as-is.
85
86
87 <a id="set"></a>
88 # Set Settings
89
90 **Status:** Implemented 20230120
91
92 **Required permissions:** "s"
93
94 **Request:** `/json/settings/set`
95
96 This call requires that the input payload be an object containing a
97 mapping of fossil-known configuration keys (case-sensitive) to
98 values. For example:
99
100 ```json
101 {
102 "editor": "emacs",
103 "admin-log": true,
104 "auto-captcha": false
105 }
106 ```
107
108 It iterates through each property, which must have a data type of
109 `null`, boolean, number, or string. A value of `null` _unsets_
110 (deletes) the setting. Boolean values are stored as integer 0
111 or 1. All other types are stored as-is. It only updates the
112 `repository.config` database and never updates a checkout or global
113 config database, nor is it capable of updating versioned settings
114 (^Updating versioned settings requires creating a full check-in.).
115
116 It has no result payload but this may be changed in the future it
117 practice shows that it should return something specific.
118
119 Error responses include:
120
121 - `FOSSIL-2002`: called without "setup" permissions.
122 - `FOSSIL-3002`: called without a payload object.
123 - `FOSSIL-3001`: passed an unknown config option.
124 - `FOSSIL-3000`: a value has an unsupported data type.
125
126 If an error is triggered, any settings made by this call up until that
127 point are discarded.
--- www/json-api/index.md
+++ www/json-api/index.md
@@ -28,10 +28,11 @@
2828
* [Diffs](api-diff.md)
2929
* [Directory Listing](api-dir.md)
3030
* [File Info](api-finfo.md)
3131
* [The Obligatory Misc. Category](api-misc.md)
3232
* [Repository Stats](api-stat.md)
33
+* [Settings](api-settings.md)
3334
* [SQL Query](api-query.md)
3435
* [Tags](api-tag.md)
3536
* [Tickets](api-ticket.md)
3637
* [Timeline](api-timeline.md)
3738
* [User Management](api-user.md)
3839
--- www/json-api/index.md
+++ www/json-api/index.md
@@ -28,10 +28,11 @@
28 * [Diffs](api-diff.md)
29 * [Directory Listing](api-dir.md)
30 * [File Info](api-finfo.md)
31 * [The Obligatory Misc. Category](api-misc.md)
32 * [Repository Stats](api-stat.md)
 
33 * [SQL Query](api-query.md)
34 * [Tags](api-tag.md)
35 * [Tickets](api-ticket.md)
36 * [Timeline](api-timeline.md)
37 * [User Management](api-user.md)
38
--- www/json-api/index.md
+++ www/json-api/index.md
@@ -28,10 +28,11 @@
28 * [Diffs](api-diff.md)
29 * [Directory Listing](api-dir.md)
30 * [File Info](api-finfo.md)
31 * [The Obligatory Misc. Category](api-misc.md)
32 * [Repository Stats](api-stat.md)
33 * [Settings](api-settings.md)
34 * [SQL Query](api-query.md)
35 * [Tags](api-tag.md)
36 * [Tickets](api-ticket.md)
37 * [Timeline](api-timeline.md)
38 * [User Management](api-user.md)
39

Keyboard Shortcuts

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