1 #ifdef FOSSIL_ENABLE_JSON
2 /*
3 ** Copyright (c) 2011 D. Richard Hipp
4 **
5 ** This program is free software; you can redistribute it and/or
6 ** modify it under the terms of the Simplified BSD License (also
7 ** known as the "2-Clause License" or "FreeBSD License".)
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but without any warranty; without even the implied warranty of
11 ** merchantability or fitness for a particular purpose.
12 **
13 ** Author contact information:
14 ** drh@hwaci.com
15 ** http://www.hwaci.com/drh/
16 **
17 */
18 #include "VERSION.h"
19 #include "config.h"
20 #include "json_config.h"
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[] = {
33 {"get", json_config_get, 0},
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 */
json_page_config()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
52 ** is private and cannot be re-used directly here.
53 */
54 static const struct JsonConfigProperty {
55 char const * name;
56 int groupMask;
57 } JsonConfigProperties[] = {
58 { "css", CONFIGSET_CSS },
59 { "header", CONFIGSET_SKIN },
60 { "footer", CONFIGSET_SKIN },
61 { "details", CONFIGSET_SKIN },
62 { "logo-mimetype", CONFIGSET_SKIN },
63 { "logo-image", CONFIGSET_SKIN },
64 { "background-mimetype", CONFIGSET_SKIN },
65 { "background-image", CONFIGSET_SKIN },
66 { "icon-mimetype", CONFIGSET_SKIN },
67 { "icon-image", CONFIGSET_SKIN },
68 { "timeline-block-markup", CONFIGSET_SKIN },
69 { "timeline-max-comment", CONFIGSET_SKIN },
70 { "timeline-plaintext", CONFIGSET_SKIN },
71 { "adunit", CONFIGSET_SKIN },
72 { "adunit-omit-if-admin", CONFIGSET_SKIN },
73 { "adunit-omit-if-user", CONFIGSET_SKIN },
74
75 { "project-name", CONFIGSET_PROJ },
76 { "short-project-name", CONFIGSET_PROJ },
77 { "project-description", CONFIGSET_PROJ },
78 { "index-page", CONFIGSET_PROJ },
79 { "manifest", CONFIGSET_PROJ },
80 { "binary-glob", CONFIGSET_PROJ },
81 { "clean-glob", CONFIGSET_PROJ },
82 { "ignore-glob", CONFIGSET_PROJ },
83 { "keep-glob", CONFIGSET_PROJ },
84 { "crlf-glob", CONFIGSET_PROJ },
85 { "crnl-glob", CONFIGSET_PROJ },
86 { "encoding-glob", CONFIGSET_PROJ },
87 { "empty-dirs", CONFIGSET_PROJ },
88 { "dotfiles", CONFIGSET_PROJ },
89
90 { "ticket-table", CONFIGSET_TKT },
91 { "ticket-common", CONFIGSET_TKT },
92 { "ticket-change", CONFIGSET_TKT },
93 { "ticket-newpage", CONFIGSET_TKT },
94 { "ticket-viewpage", CONFIGSET_TKT },
95 { "ticket-editpage", CONFIGSET_TKT },
96 { "ticket-reportlist", CONFIGSET_TKT },
97 { "ticket-report-template", CONFIGSET_TKT },
98 { "ticket-key-template", CONFIGSET_TKT },
99 { "ticket-title-expr", CONFIGSET_TKT },
100 { "ticket-closed-expr", CONFIGSET_TKT },
101
102 {NULL, 0}
103 };
104
105
106 /*
107 ** Impl of /json/config/get. Requires setup rights.
108 **
109 */
json_config_get()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;
116 char optSkinBackups = 0;
117 unsigned int i;
118 if(!g.perm.Setup){
119 json_set_err(FSL_JSON_E_DENIED, "Requires 's' permissions.");
120 return NULL;
121 }
122
123 i = g.json.dispatchDepth + 1;
124 zName = json_command_arg(i);
125 for( ; zName; zName = json_command_arg(++i) ){
126 if(0==(strcmp("all", zName))){
127 confMask = CONFIGSET_ALL;
128 }else if(0==(strcmp("project", zName))){
129 confMask |= CONFIGSET_PROJ;
130 }else if(0==(strcmp("skin", zName))){
131 confMask |= (CONFIGSET_CSS|CONFIGSET_SKIN);
132 }else if(0==(strcmp("ticket", zName))){
133 confMask |= CONFIGSET_TKT;
134 }else if(0==(strcmp("skin-backup", zName))){
135 optSkinBackups = 1;
136 }else{
137 json_set_err( FSL_JSON_E_INVALID_ARGS,
138 "Unknown config area: %s", zName);
139 return NULL;
140 }
141 }
142
143 if(!confMask && !optSkinBackups){
144 json_set_err(FSL_JSON_E_MISSING_ARGS, "No configuration area(s) selected.");
145 }
146 blob_append(&sql,
147 "SELECT name, value"
148 " FROM config "
149 " WHERE 0 ", -1);
150 {
151 const struct JsonConfigProperty * prop = &JsonConfigProperties[0];
152 blob_append(&sql," OR name IN (",-1);
153 for( i = 0; prop->name; ++prop ){
154 if(prop->groupMask & confMask){
155 if( i++ ){
156 blob_append(&sql,",",1);
157 }
158 blob_append_sql(&sql, "%Q", prop->name);
159 }
160 }
161 blob_append(&sql,") ", -1);
162 }
163
164
165 if( optSkinBackups ){
166 blob_append(&sql, " OR name GLOB 'skin:*'", -1);
167 }
168 blob_append(&sql," ORDER BY name", -1);
169 db_prepare(&q, "%s", blob_sql_text(&sql));
170 blob_reset(&sql);
171 pay = cson_new_object();
172 while( (SQLITE_ROW==db_step(&q)) ){
173 cson_object_set(pay,
174 db_column_text(&q,0),
175 json_new_string(db_column_text(&q,1)));
176 }
177 db_finalize(&q);
178 return cson_object_value(pay);
179 }
180
181 /*
182 ** Impl of /json/config/save.
183 **
184 ** TODOs:
185 */
json_config_save()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