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