Fossil SCM

fossil-scm / src / json_detail.h
Blame History Raw 274 lines
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

Keyboard Shortcuts

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