#if !defined(FOSSIL_JSON_DETAIL_H_INCLUDED)
#define FOSSIL_JSON_DETAIL_H_INCLUDED
/*
** Copyright (c) 2011 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*/
#include "cson_amalgamation.h"
/*
** Impl details for the JSON API which need to be shared
** across multiple C files.
*/
/*
** The "official" list of Fossil/JSON error codes. Their values might
** very well change during initial development but after their first
** public release they must stay stable.
**
** Values must be in the range 1000..9999 for error codes and 1..999
** for warning codes.
**
** Numbers evenly dividable by 100 are "categories", and error codes
** for a given category have their high bits set to the category
** value.
**
*/
enum FossilJsonCodes {
FSL_JSON_W_START = 0,
FSL_JSON_W_UNKNOWN /*+1*/,
FSL_JSON_W_ROW_TO_JSON_FAILED /*+2*/,
FSL_JSON_W_COL_TO_JSON_FAILED /*+3*/,
FSL_JSON_W_STRING_TO_ARRAY_FAILED /*+4*/,
FSL_JSON_W_TAG_NOT_FOUND /*+5*/,
FSL_JSON_W_END = 1000,
FSL_JSON_E_GENERIC = 1000,
FSL_JSON_E_GENERIC_SUB1 = FSL_JSON_E_GENERIC + 100,
FSL_JSON_E_INVALID_REQUEST /*+1*/,
FSL_JSON_E_UNKNOWN_COMMAND /*+2*/,
FSL_JSON_E_UNKNOWN /*+3*/,
/*REUSE: +4*/
FSL_JSON_E_TIMEOUT /*+5*/,
FSL_JSON_E_ASSERT /*+6*/,
FSL_JSON_E_ALLOC /*+7*/,
FSL_JSON_E_NYI /*+8*/,
FSL_JSON_E_PANIC /*+9*/,
FSL_JSON_E_MANIFEST_READ_FAILED /*+10*/,
FSL_JSON_E_FILE_OPEN_FAILED /*+11*/,
FSL_JSON_E_AUTH = 2000,
FSL_JSON_E_MISSING_AUTH /*+1*/,
FSL_JSON_E_DENIED /*+2*/,
FSL_JSON_E_WRONG_MODE /*+3*/,
FSL_JSON_E_LOGIN_FAILED = FSL_JSON_E_AUTH +100,
FSL_JSON_E_LOGIN_FAILED_NOSEED /*+1*/,
FSL_JSON_E_LOGIN_FAILED_NONAME /*+2*/,
FSL_JSON_E_LOGIN_FAILED_NOPW /*+3*/,
FSL_JSON_E_LOGIN_FAILED_NOTFOUND /*+4*/,
FSL_JSON_E_USAGE = 3000,
FSL_JSON_E_INVALID_ARGS /*+1*/,
FSL_JSON_E_MISSING_ARGS /*+2*/,
FSL_JSON_E_AMBIGUOUS_UUID /*+3*/,
FSL_JSON_E_UNRESOLVED_UUID /*+4*/,
FSL_JSON_E_RESOURCE_ALREADY_EXISTS /*+5*/,
FSL_JSON_E_RESOURCE_NOT_FOUND /*+6*/,
FSL_JSON_E_DB = 4000,
FSL_JSON_E_STMT_PREP /*+1*/,
FSL_JSON_E_STMT_BIND /*+2*/,
FSL_JSON_E_STMT_EXEC /*+3*/,
FSL_JSON_E_DB_LOCKED /*+4*/,
FSL_JSON_E_DB_NEEDS_REBUILD = FSL_JSON_E_DB + 101,
FSL_JSON_E_DB_NOT_FOUND = FSL_JSON_E_DB + 102,
FSL_JSON_E_DB_NOT_VALID = FSL_JSON_E_DB + 103
};
/*
** Signature for JSON page/command callbacks. Each callback is
** responsible for handling one JSON request/command and/or
** dispatching to sub-commands.
**
** By the time the callback is called, json_page_top() (HTTP mode) or
** json_cmd_top() (CLI mode) will have set up the JSON-related
** environment. Implementations may generate a "result payload" of any
** JSON type by returning its value from this function (ownership is
** tranferred to the caller). On error they should set
** g.json.resultCode to one of the FossilJsonCodes values and return
** either their payload object or NULL. Note that NULL is a legal
** success value - it simply means the response will contain no
** payload. If g.json.resultCode is non-zero when this function
** returns then the top-level dispatcher will destroy any payload
** returned by this function and will output a JSON error response
** instead.
**
** All of the setup/response code is handled by the top dispatcher
** functions and the callbacks concern themselves only with:
**
** a) Permissions checking (inspecting g.perm).
** b) generating a response payload (if applicable)
** c) Setting g.json's error state (if applicable). See json_set_err().
**
** It is imperitive that NO callback functions EVER output ANYTHING to
** stdout, as that will effectively corrupt any JSON output, and
** almost certainly will corrupt any HTTP response headers. Output
** sent to stderr ends up in my apache log, so that might be useful
** for debuggering in some cases, but no such code should be left
** enabled for non-debuggering builds.
*/
typedef cson_value * (*fossil_json_f)();
/*
** Holds name-to-function mappings for JSON page/command dispatching.
**
** Internally we model page dispatching lists as arrays of these
** objects, where the final entry in the array has a NULL name value
** to act as the end-of-list sentinel.
**
*/
typedef struct JsonPageDef{
/*
** The commmand/page's name (path, not including leading /json/).
**
** Reminder to self: we cannot use sub-paths with commands this way
** without additional string-splitting downstream. e.g. foo/bar.
** Alternately, we can create different JsonPageDef arrays for each
** subset.
*/
char const * name;
/*
** Returns a payload object for the response. If it returns a
** non-NULL value, the caller owns it. To trigger an error this
** function should set g.json.resultCode to a value from the
** FossilJsonCodes enum. If it sets an error value and returns
** a payload, the payload will be destroyed (not sent with the
** response).
*/
fossil_json_f func;
/*
** Which mode(s) of execution does func() support:
**
** <0 = CLI only, >0 = HTTP only, 0==both
*/
char runMode;
} JsonPageDef;
/*
** Holds common keys used for various JSON API properties.
*/
typedef struct FossilJsonKeys_{
/** maintainers: please keep alpha sorted (case-insensitive) */
char const * anonymousSeed;
char const * authToken;
char const * commandPath;
char const * mtime;
char const * payload;
char const * requestId;
char const * resultCode;
char const * resultText;
char const * timestamp;
} FossilJsonKeys_;
const FossilJsonKeys_ FossilJsonKeys;
/*
** A page/command dispatch helper for fossil_json_f() implementations.
** pages must be an array of JsonPageDef commands which we can
** dispatch. The final item in the array MUST have a NULL name
** element.
**
** This function takes the command specified in
** json_comand_arg(1+g.json.dispatchDepth) and searches pages for a
** matching name. If found then that page's func() is called to fetch
** the payload, which is returned to the caller.
**
** On error, g.json.resultCode is set to one of the FossilJsonCodes
** values and NULL is returned. If non-NULL is returned, ownership is
** transfered to the caller (but the g.json error state might still be
** set in that case, so the caller must check that or pass it on up
** the dispatch chain).
*/
cson_value * json_page_dispatch_helper(JsonPageDef const * pages);
/*
** Implements the /json/wiki family of pages/commands.
**
*/
cson_value * json_page_wiki();
/*
** Implements /json/timeline/wiki and /json/wiki/timeline.
*/
cson_value * json_timeline_wiki();
/*
** Implements /json/timeline family of functions.
*/
cson_value * json_page_timeline();
/*
** Convenience wrapper around cson_value_new_string().
** Returns NULL if str is NULL or on allocation error.
*/
cson_value * json_new_string( char const * str );
/*
** Similar to json_new_string(), but takes a printf()-style format
** specifiers. Supports the printf extensions supported by fossil's
** mprintf(). Returns NULL if str is NULL or on allocation error.
**
** Maintenance note: json_new_string() is NOT variadic because by the
** time the variadic form was introduced we already had use cases
** which segfaulted via json_new_string() because they contain printf
** markup (e.g. wiki content). Been there, debugged that.
*/
cson_value * json_new_string_f( char const * fmt, ... );
#endif/*FOSSIL_JSON_DETAIL_H_INCLUDED*/