diff options
| author | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
| commit | 4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch) | |
| tree | c296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /src/json_report.c | |
| download | relic-4f49b16079b27d7ce633619e4cddfdf2bffbc952.tar.gz | |
Diffstat (limited to 'src/json_report.c')
| -rw-r--r-- | src/json_report.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/src/json_report.c b/src/json_report.c new file mode 100644 index 0000000..e3fb8ad --- /dev/null +++ b/src/json_report.c @@ -0,0 +1,263 @@ +#ifdef FOSSIL_ENABLE_JSON +/* +** 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 "config.h" +#include "json_report.h" + +#if INTERFACE +#include "json_detail.h" +#endif + + +static cson_value * json_report_create(void); +static cson_value * json_report_get(void); +static cson_value * json_report_list(void); +static cson_value * json_report_run(void); +static cson_value * json_report_save(void); + +/* +** Mapping of /json/report/XXX commands/paths to callbacks. +*/ +static const JsonPageDef JsonPageDefs_Report[] = { +{"create", json_report_create, 0}, +{"get", json_report_get, 0}, +{"list", json_report_list, 0}, +{"run", json_report_run, 0}, +{"save", json_report_save, 0}, +/* Last entry MUST have a NULL name. */ +{NULL,NULL,0} +}; +/* +** Implementation of the /json/report page. +** +** +*/ +cson_value * json_page_report(void){ + if(!g.perm.RdTkt && !g.perm.NewTkt ){ + json_set_err(FSL_JSON_E_DENIED, + "Requires 'r' or 'n' permissions."); + return NULL; + } + return json_page_dispatch_helper(JsonPageDefs_Report); +} + +/* +** Searches the environment for a "report" parameter +** (CLI: -report/-r #). +** +** If one is not found and argPos is >0 then json_command_arg() +** is checked. +** +** Returns >0 (the report number) on success . +*/ +static int json_report_get_number(int argPos){ + int nReport = json_find_option_int("report",NULL,"r",-1); + if( (nReport<=0) && cson_value_is_integer(g.json.reqPayload.v)){ + nReport = cson_value_get_integer(g.json.reqPayload.v); + } + if( (nReport <= 0) && (argPos>0) ){ + char const * arg = json_command_arg(argPos); + if(arg && fossil_isdigit(*arg)) { + nReport = atoi(arg); + } + } + return nReport; +} + +static cson_value * json_report_create(void){ + json_set_err(FSL_JSON_E_NYI, NULL); + return NULL; +} + +static cson_value * json_report_get(void){ + int nReport; + Stmt q = empty_Stmt; + cson_value * pay = NULL; + + if(!g.perm.TktFmt){ + json_set_err(FSL_JSON_E_DENIED, + "Requires 't' privileges."); + return NULL; + } + nReport = json_report_get_number(3); + if(nReport <=0){ + json_set_err(FSL_JSON_E_MISSING_ARGS, + "Missing or invalid 'report' (-r) parameter."); + return NULL; + } + + db_prepare(&q,"SELECT rn AS report," + " owner AS owner," + " title AS title," + " cast(strftime('%%s',mtime) as int) as timestamp," + " cols as columns," + " sqlcode as sqlCode" + " FROM reportfmt" + " WHERE rn=%d", + nReport); + if( SQLITE_ROW != db_step(&q) ){ + db_finalize(&q); + json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, + "Report #%d not found.", nReport); + return NULL; + } + pay = cson_sqlite3_row_to_object(q.pStmt); + db_finalize(&q); + return pay; +} + +/* +** Impl of /json/report/list. +*/ +static cson_value * json_report_list(void){ + Blob sql = empty_blob; + cson_value * pay = NULL; + if(!g.perm.RdTkt){ + json_set_err(FSL_JSON_E_DENIED, + "Requires 'r' privileges."); + return NULL; + } + blob_append(&sql, "SELECT" + " rn AS report," + " title as title," + " owner as owner" + " FROM reportfmt" + " WHERE 1" + " ORDER BY title", + -1); + pay = json_sql_to_array_of_obj(&sql, NULL, 1); + if(!pay){ + json_set_err(FSL_JSON_E_UNKNOWN, + "Quite unexpected: no ticket reports found."); + } + return pay; +} + +/* +** Impl for /json/report/run +** +** Options/arguments: +** +** report=int (CLI: -report # or -r #) is the report number to run. +** +** limit=int (CLI: -limit # or -n #) -n is for compat. with other commands. +** +** format=a|o Specifies result format: a=each row is an array, o=each +** row is an object. Default=o. +*/ +static cson_value * json_report_run(void){ + int nReport; + Stmt q = empty_Stmt; + cson_object * pay = NULL; + cson_array * tktList = NULL; + char const * zFmt; + char * zTitle = NULL; + Blob sql = empty_blob; + int limit = 0; + cson_value * colNames = NULL; + int i; + + if(!g.perm.RdTkt){ + json_set_err(FSL_JSON_E_DENIED, + "Requires 'r' privileges."); + return NULL; + } + nReport = json_report_get_number(3); + if(nReport <=0){ + json_set_err(FSL_JSON_E_MISSING_ARGS, + "Missing or invalid 'number' (-n) parameter."); + goto error; + } + zFmt = json_find_option_cstr2("format",NULL,"f",3); + if(!zFmt) zFmt = "o"; + db_prepare(&q, + "SELECT sqlcode, " + " title" + " FROM reportfmt" + " WHERE rn=%d", + nReport); + if(SQLITE_ROW != db_step(&q)){ + json_set_err(FSL_JSON_E_INVALID_ARGS, + "Report number %d not found.", + nReport); + db_finalize(&q); + goto error; + } + + limit = json_find_option_int("limit",NULL,"n",-1); + + + /* Copy over report's SQL...*/ + blob_append(&sql, db_column_text(&q,0), -1); + zTitle = fossil_strdup(db_column_text(&q,1)); + db_finalize(&q); + db_prepare(&q, "%s", blob_sql_text(&sql)); + + /** Build the response... */ + pay = cson_new_object(); + + cson_object_set(pay, "report", json_new_int(nReport)); + cson_object_set(pay, "title", json_new_string(zTitle)); + if(limit>0){ + cson_object_set(pay, "limit", json_new_int((limit<0) ? 0 : limit)); + } + free(zTitle); + zTitle = NULL; + + if(g.perm.TktFmt){ + cson_object_set(pay, "sqlcode", + cson_value_new_string(blob_str(&sql), + (unsigned int)blob_size(&sql))); + } + blob_reset(&sql); + + colNames = cson_sqlite3_column_names(q.pStmt); + cson_object_set( pay, "columnNames", colNames); + for( i = 0 ; ((limit>0) ?(i < limit) : 1) + && (SQLITE_ROW == db_step(&q)); + ++i){ + cson_value * row = ('a'==*zFmt) + ? cson_sqlite3_row_to_array(q.pStmt) + : cson_sqlite3_row_to_object2(q.pStmt, + cson_value_get_array(colNames)); + ; + if(row && !tktList){ + tktList = cson_new_array(); + } + cson_array_append(tktList, row); + } + db_finalize(&q); + cson_object_set(pay, "tickets", + tktList ? cson_array_value(tktList) : cson_value_null()); + + goto end; + + error: + assert(0 != g.json.resultCode); + cson_value_free( cson_object_value(pay) ); + pay = NULL; + end: + + return pay ? cson_object_value(pay) : NULL; + +} + +static cson_value * json_report_save(void){ + return NULL; +} +#endif /* FOSSIL_ENABLE_JSON */ |
