|
1
|
#ifdef FOSSIL_ENABLE_JSON |
|
2
|
#if !defined(FOSSIL_JSON_DETAIL_H_INCLUDED) |
|
3
|
#define FOSSIL_JSON_DETAIL_H_INCLUDED |
|
4
|
/* |
|
5
|
** Copyright (c) 2011 D. Richard Hipp |
|
6
|
** |
|
7
|
** This program is free software; you can redistribute it and/or |
|
8
|
** modify it under the terms of the Simplified BSD License (also |
|
9
|
** known as the "2-Clause License" or "FreeBSD License".) |
|
10
|
** |
|
11
|
** This program is distributed in the hope that it will be useful, |
|
12
|
** but without any warranty; without even the implied warranty of |
|
13
|
** merchantability or fitness for a particular purpose. |
|
14
|
** |
|
15
|
** Author contact information: |
|
16
|
** [email protected] |
|
17
|
** http://www.hwaci.com/drh/ |
|
18
|
** |
|
19
|
*/ |
|
20
|
|
|
21
|
#if !defined(_RC_COMPILE_) |
|
22
|
#include "cson_amalgamation.h" |
|
23
|
#endif /* !defined(_RC_COMPILE_) */ |
|
24
|
|
|
25
|
/** |
|
26
|
FOSSIL_JSON_API_VERSION holds the date (YYYYMMDD) of the latest |
|
27
|
"significant" change to the JSON API (a change in an interface or |
|
28
|
new functionality). It is sent as part of the /json/version |
|
29
|
request. We could arguably add it to each response or even add a |
|
30
|
version number to each response type, allowing very fine (too |
|
31
|
fine?) granularity in compatibility change notification. The |
|
32
|
version number could be included in part of the command dispatching |
|
33
|
framework, allowing the top-level dispatching code to deal with it |
|
34
|
(for the most part). |
|
35
|
*/ |
|
36
|
#define FOSSIL_JSON_API_VERSION "20120713" |
|
37
|
|
|
38
|
/* |
|
39
|
** Impl details for the JSON API which need to be shared |
|
40
|
** across multiple C files. |
|
41
|
*/ |
|
42
|
|
|
43
|
/* |
|
44
|
** The "official" list of Fossil/JSON error codes. Their values might |
|
45
|
** very well change during initial development but after their first |
|
46
|
** public release they must stay stable. |
|
47
|
** |
|
48
|
** Values must be in the range 1000..9999 for error codes and 1..999 |
|
49
|
** for warning codes. |
|
50
|
** |
|
51
|
** Numbers evenly dividable by 100 are "categories", and error codes |
|
52
|
** for a given category have their high bits set to the category |
|
53
|
** value. |
|
54
|
** |
|
55
|
** Maintenance reminder: when entries are added to this list, update |
|
56
|
** the code in json_page_resultCodes() and json_err_cstr() (both in |
|
57
|
** json.c)! |
|
58
|
** |
|
59
|
*/ |
|
60
|
#if !defined(_RC_COMPILE_) |
|
61
|
enum FossilJsonCodes { |
|
62
|
FSL_JSON_W_START = 0, |
|
63
|
FSL_JSON_W_UNKNOWN /*+1*/, |
|
64
|
FSL_JSON_W_ROW_TO_JSON_FAILED /*+2*/, |
|
65
|
FSL_JSON_W_COL_TO_JSON_FAILED /*+3*/, |
|
66
|
FSL_JSON_W_STRING_TO_ARRAY_FAILED /*+4*/, |
|
67
|
FSL_JSON_W_TAG_NOT_FOUND /*+5*/, |
|
68
|
|
|
69
|
FSL_JSON_W_END = 1000, |
|
70
|
FSL_JSON_E_GENERIC = 1000, |
|
71
|
FSL_JSON_E_GENERIC_SUB1 = FSL_JSON_E_GENERIC + 100, |
|
72
|
FSL_JSON_E_INVALID_REQUEST /*+1*/, |
|
73
|
FSL_JSON_E_UNKNOWN_COMMAND /*+2*/, |
|
74
|
FSL_JSON_E_UNKNOWN /*+3*/, |
|
75
|
/*REUSE: +4*/ |
|
76
|
FSL_JSON_E_TIMEOUT /*+5*/, |
|
77
|
FSL_JSON_E_ASSERT /*+6*/, |
|
78
|
FSL_JSON_E_ALLOC /*+7*/, |
|
79
|
FSL_JSON_E_NYI /*+8*/, |
|
80
|
FSL_JSON_E_PANIC /*+9*/, |
|
81
|
FSL_JSON_E_MANIFEST_READ_FAILED /*+10*/, |
|
82
|
FSL_JSON_E_FILE_OPEN_FAILED /*+11*/, |
|
83
|
|
|
84
|
FSL_JSON_E_AUTH = 2000, |
|
85
|
FSL_JSON_E_MISSING_AUTH /*+1*/, |
|
86
|
FSL_JSON_E_DENIED /*+2*/, |
|
87
|
FSL_JSON_E_WRONG_MODE /*+3*/, |
|
88
|
|
|
89
|
FSL_JSON_E_LOGIN_FAILED = FSL_JSON_E_AUTH +100, |
|
90
|
FSL_JSON_E_LOGIN_FAILED_NOSEED /*+1*/, |
|
91
|
FSL_JSON_E_LOGIN_FAILED_NONAME /*+2*/, |
|
92
|
FSL_JSON_E_LOGIN_FAILED_NOPW /*+3*/, |
|
93
|
FSL_JSON_E_LOGIN_FAILED_NOTFOUND /*+4*/, |
|
94
|
|
|
95
|
FSL_JSON_E_USAGE = 3000, |
|
96
|
FSL_JSON_E_INVALID_ARGS /*+1*/, |
|
97
|
FSL_JSON_E_MISSING_ARGS /*+2*/, |
|
98
|
FSL_JSON_E_AMBIGUOUS_UUID /*+3*/, |
|
99
|
FSL_JSON_E_UNRESOLVED_UUID /*+4*/, |
|
100
|
FSL_JSON_E_RESOURCE_ALREADY_EXISTS /*+5*/, |
|
101
|
FSL_JSON_E_RESOURCE_NOT_FOUND /*+6*/, |
|
102
|
|
|
103
|
FSL_JSON_E_DB = 4000, |
|
104
|
FSL_JSON_E_STMT_PREP /*+1*/, |
|
105
|
FSL_JSON_E_STMT_BIND /*+2*/, |
|
106
|
FSL_JSON_E_STMT_EXEC /*+3*/, |
|
107
|
FSL_JSON_E_DB_LOCKED /*+4*/, |
|
108
|
|
|
109
|
FSL_JSON_E_DB_NEEDS_REBUILD = FSL_JSON_E_DB + 101, |
|
110
|
FSL_JSON_E_DB_NOT_FOUND = FSL_JSON_E_DB + 102, |
|
111
|
FSL_JSON_E_DB_NOT_VALID = FSL_JSON_E_DB + 103, |
|
112
|
/* |
|
113
|
** Maintenance reminder: FSL_JSON_E_DB_NOT_FOUND gets triggered in the |
|
114
|
** bootstrapping process before we know whether we need to check for |
|
115
|
** FSL_JSON_E_DB_NEEDS_CHECKOUT. Thus the former error trumps the |
|
116
|
** latter. |
|
117
|
*/ |
|
118
|
FSL_JSON_E_DB_NEEDS_CHECKOUT = FSL_JSON_E_DB + 104 |
|
119
|
}; |
|
120
|
|
|
121
|
|
|
122
|
/* |
|
123
|
** Signature for JSON page/command callbacks. Each callback is |
|
124
|
** responsible for handling one JSON request/command and/or |
|
125
|
** dispatching to sub-commands. |
|
126
|
** |
|
127
|
** By the time the callback is called, json_page_top() (HTTP mode) or |
|
128
|
** json_cmd_top() (CLI mode) will have set up the JSON-related |
|
129
|
** environment. Implementations may generate a "result payload" of any |
|
130
|
** JSON type by returning its value from this function (ownership is |
|
131
|
** transferred to the caller). On error they should set |
|
132
|
** g.json.resultCode to one of the FossilJsonCodes values and return |
|
133
|
** either their payload object or NULL. Note that NULL is a legal |
|
134
|
** success value - it simply means the response will contain no |
|
135
|
** payload. If g.json.resultCode is non-zero when this function |
|
136
|
** returns then the top-level dispatcher will destroy any payload |
|
137
|
** returned by this function and will output a JSON error response |
|
138
|
** instead. |
|
139
|
** |
|
140
|
** All of the setup/response code is handled by the top dispatcher |
|
141
|
** functions and the callbacks concern themselves only with: |
|
142
|
** |
|
143
|
** a) Permissions checking (inspecting g.perm). |
|
144
|
** b) generating a response payload (if applicable) |
|
145
|
** c) Setting g.json's error state (if applicable). See json_set_err(). |
|
146
|
** |
|
147
|
** It is imperative that NO callback functions EVER output ANYTHING to |
|
148
|
** stdout, as that will effectively corrupt any JSON output, and |
|
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 |
|
160
|
** objects, where the final entry in the array has a NULL name value |
|
161
|
** to act as the end-of-list sentinel. |
|
162
|
** |
|
163
|
*/ |
|
164
|
typedef struct JsonPageDef{ |
|
165
|
/* |
|
166
|
** The commmand/page's name (path, not including leading /json/). |
|
167
|
** |
|
168
|
** Reminder to self: we cannot use sub-paths with commands this way |
|
169
|
** without additional string-splitting downstream. e.g. foo/bar. |
|
170
|
** Alternately, we can create different JsonPageDef arrays for each |
|
171
|
** subset. |
|
172
|
*/ |
|
173
|
char const * name; |
|
174
|
/* |
|
175
|
** Returns a payload object for the response. If it returns a |
|
176
|
** non-NULL value, the caller owns it. To trigger an error this |
|
177
|
** function should set g.json.resultCode to a value from the |
|
178
|
** FossilJsonCodes enum. If it sets an error value and returns |
|
179
|
** a payload, the payload will be destroyed (not sent with the |
|
180
|
** response). |
|
181
|
*/ |
|
182
|
fossil_json_f func; |
|
183
|
/* |
|
184
|
** Which mode(s) of execution does func() support: |
|
185
|
** |
|
186
|
** <0 = CLI only, >0 = HTTP only, 0==both |
|
187
|
** |
|
188
|
** Now that we can simulate POST in CLI mode, the distinction |
|
189
|
** between them has disappeared in most (or all) cases, so 0 is |
|
190
|
** the standard value. |
|
191
|
*/ |
|
192
|
int runMode; |
|
193
|
} JsonPageDef; |
|
194
|
|
|
195
|
/* |
|
196
|
** Holds common keys used for various JSON API properties. |
|
197
|
*/ |
|
198
|
typedef struct FossilJsonKeys_{ |
|
199
|
/** maintainers: please keep alpha sorted (case-insensitive) */ |
|
200
|
char const * anonymousSeed; |
|
201
|
char const * authToken; |
|
202
|
char const * commandPath; |
|
203
|
char const * mtime; |
|
204
|
char const * payload; |
|
205
|
char const * requestId; |
|
206
|
char const * resultCode; |
|
207
|
char const * resultText; |
|
208
|
char const * timestamp; |
|
209
|
} FossilJsonKeys_; |
|
210
|
extern const FossilJsonKeys_ FossilJsonKeys; |
|
211
|
|
|
212
|
/* |
|
213
|
** A page/command dispatch helper for fossil_json_f() implementations. |
|
214
|
** pages must be an array of JsonPageDef commands which we can |
|
215
|
** dispatch. The final item in the array MUST have a NULL name |
|
216
|
** element. |
|
217
|
** |
|
218
|
** This function takes the command specified in |
|
219
|
** json_command_arg(1+g.json.dispatchDepth) and searches pages for a |
|
220
|
** matching name. If found then that page's func() is called to fetch |
|
221
|
** the payload, which is returned to the caller. |
|
222
|
** |
|
223
|
** On error, g.json.resultCode is set to one of the FossilJsonCodes |
|
224
|
** values and NULL is returned. If non-NULL is returned, ownership is |
|
225
|
** transfered to the caller (but the g.json error state might still be |
|
226
|
** set in that case, so the caller must check that or pass it on up |
|
227
|
** the dispatch chain). |
|
228
|
*/ |
|
229
|
cson_value * json_page_dispatch_helper(JsonPageDef const * pages); |
|
230
|
|
|
231
|
/* |
|
232
|
** Convenience wrapper around cson_value_new_string(). |
|
233
|
** Returns NULL if str is NULL or on allocation error. |
|
234
|
*/ |
|
235
|
cson_value * json_new_string( char const * str ); |
|
236
|
|
|
237
|
/* |
|
238
|
** Similar to json_new_string(), but takes a printf()-style format |
|
239
|
** specifiers. Supports the printf extensions supported by fossil's |
|
240
|
** mprintf(). Returns NULL if str is NULL or on allocation error. |
|
241
|
** |
|
242
|
** Maintenance note: json_new_string() is NOT variadic because by the |
|
243
|
** time the variadic form was introduced we already had use cases |
|
244
|
** which segfaulted via json_new_string() because they contain printf |
|
245
|
** markup (e.g. wiki content). Been there, debugged that. |
|
246
|
*/ |
|
247
|
cson_value * json_new_string_f( char const * fmt, ... ); |
|
248
|
|
|
249
|
/* |
|
250
|
** Returns true if fossil is running in JSON mode and we are either |
|
251
|
** running in HTTP mode OR g.json.post.o is not NULL (meaning POST |
|
252
|
** data was fed in from CLI mode). |
|
253
|
** |
|
254
|
** Specifically, it will return false when any of these apply: |
|
255
|
** |
|
256
|
** a) Not running in JSON mode (via json command or /json path). |
|
257
|
** |
|
258
|
** b) We are running in JSON CLI mode, but no POST data has been fed |
|
259
|
** in. |
|
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
|
|