Fossil SCM

Implemented /json/timeline/wiki. Fixed --limit/-n handling of timeline/ci.

stephan 2011-09-22 20:07 UTC json
Commit 12545465e98da0733d6240b7cfdb9b85e9ccb00e
2 files changed +2 +146 -9
--- ajax/index.html
+++ ajax/index.html
@@ -203,10 +203,12 @@
203203
<input type='button' value='version' onclick='TheApp.cgi.sendCommand("/json/version")' />
204204
<input type='button' value='stat' onclick='TheApp.cgi.sendCommand("/json/stat")' />
205205
<input type='button' value='whoami' onclick='TheApp.cgi.sendCommand("/json/whoami")' />
206206
<input type='button' value='cap' onclick='TheApp.cgi.sendCommand("/json/cap")' />
207207
<input type='button' value='branch/list' onclick='TheApp.cgi.sendCommand("/json/branch/list")' />
208
+<input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci")' />
209
+<input type='button' value='timeline/wiki' onclick='TheApp.cgi.sendCommand("/json/timeline/wiki")' />
208210
<input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
209211
<input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{"page":"Fossil"})' />
210212
211213
<!--
212214
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
213215
--- ajax/index.html
+++ ajax/index.html
@@ -203,10 +203,12 @@
203 <input type='button' value='version' onclick='TheApp.cgi.sendCommand("/json/version")' />
204 <input type='button' value='stat' onclick='TheApp.cgi.sendCommand("/json/stat")' />
205 <input type='button' value='whoami' onclick='TheApp.cgi.sendCommand("/json/whoami")' />
206 <input type='button' value='cap' onclick='TheApp.cgi.sendCommand("/json/cap")' />
207 <input type='button' value='branch/list' onclick='TheApp.cgi.sendCommand("/json/branch/list")' />
 
 
208 <input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
209 <input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{"page":"Fossil"})' />
210
211 <!--
212 <input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
213
--- ajax/index.html
+++ ajax/index.html
@@ -203,10 +203,12 @@
203 <input type='button' value='version' onclick='TheApp.cgi.sendCommand("/json/version")' />
204 <input type='button' value='stat' onclick='TheApp.cgi.sendCommand("/json/stat")' />
205 <input type='button' value='whoami' onclick='TheApp.cgi.sendCommand("/json/whoami")' />
206 <input type='button' value='cap' onclick='TheApp.cgi.sendCommand("/json/cap")' />
207 <input type='button' value='branch/list' onclick='TheApp.cgi.sendCommand("/json/branch/list")' />
208 <input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci")' />
209 <input type='button' value='timeline/wiki' onclick='TheApp.cgi.sendCommand("/json/timeline/wiki")' />
210 <input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
211 <input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{"page":"Fossil"})' />
212
213 <!--
214 <input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
215
+146 -9
--- src/json.c
+++ src/json.c
@@ -721,10 +721,14 @@
721721
g.json.cmd.offset = -1;
722722
if( !g.isHTTP && g.fullHttpReply ){
723723
/* workaround for server mode, so we see it as CGI mode. */
724724
g.isHTTP = 1;
725725
}
726
+ if( !g.isHTTP ){
727
+ g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/;
728
+ }
729
+
726730
if(! g.json.post.v ){
727731
/* If cgi_init() reads POSTed JSON then it sets the content type.
728732
If it did not then we need to set it.
729733
*/
730734
cgi_set_content_type(json_guess_content_type());
@@ -1865,15 +1869,17 @@
18651869
}
18661870
return payV;
18671871
}
18681872
18691873
static cson_value * json_timeline_ci(unsigned int depth);
1874
+static cson_value * json_timeline_wiki(unsigned int depth);
18701875
/*
18711876
** Mapping of /json/timeline/XXX commands/paths to callbacks.
18721877
*/
18731878
static const JsonPageDef JsonPageDefs_Timeline[] = {
18741879
{"ci", json_timeline_ci, 0},
1880
+{"wiki", json_timeline_wiki, 0},
18751881
/* Last entry MUST have a NULL name. */
18761882
{NULL,NULL,0}
18771883
};
18781884
18791885
/*
@@ -1909,13 +1915,13 @@
19091915
db_multi_exec(zSql);
19101916
}
19111917
19121918
/*
19131919
** Return a pointer to a constant string that forms the basis
1914
-** for a timeline query for the JSON "checkin" interface.
1920
+** for a timeline query for the JSON interface.
19151921
*/
1916
-const char const * json_timeline_query_ci(void){
1922
+const char const * json_timeline_query(void){
19171923
/* Field order MUST match that from json_timeline_temp_table()!!! */
19181924
static const char zBaseSql[] =
19191925
@ SELECT
19201926
@ blob.rid,
19211927
@ uuid,
@@ -1935,37 +1941,59 @@
19351941
@ WHERE blob.rid=event.objid
19361942
;
19371943
return zBaseSql;
19381944
}
19391945
1940
-
19411946
/*
1942
-** /json/timeline/ci
1947
+** Tries to figure out a timeline query length limit base on
1948
+** environment parameters. If it can it returns that value,
1949
+** else it returns some statically defined default value.
19431950
**
1944
-** Far from complete.
1951
+** Never returns a negative value. 0 means no limit.
19451952
*/
1946
-static cson_value * json_timeline_ci(unsigned int depth){
1953
+static int json_timeline_limit(){
19471954
static const int defaultLimit = 20;
1955
+ int limit = -1;
1956
+ if( g.isHTTP ){
1957
+ limit = json_getenv_int("limit",-1);
1958
+ if(limit<0){
1959
+ limit = json_getenv_int("n",-1);
1960
+ }
1961
+ }else{/* CLI mode */
1962
+ char const * arg = find_option("limit","n",1);
1963
+ if(arg && *arg){
1964
+ limit = atoi(arg);
1965
+ }
1966
+ }
1967
+ return (limit<0) ? defaultLimit : limit;
1968
+}
1969
+/*
1970
+** Implementation of /json/timeline/ci.
1971
+**
1972
+** Still a few TODOs (like figuring out how to structure
1973
+** inheritance info).
1974
+*/
1975
+static cson_value * json_timeline_ci(unsigned int depth){
19481976
cson_value * payV = NULL;
19491977
cson_object * pay = NULL;
19501978
cson_value * tmp = NULL;
19511979
cson_value * listV = NULL;
19521980
cson_array * list = NULL;
1953
- int limit = json_getenv_int("n",defaultLimit);
1981
+ int limit;
19541982
int check = 0;
19551983
Stmt q;
19561984
Blob sql = empty_blob;
19571985
if( !g.perm.Read/* && !g.perm.RdTkt && !g.perm.RdWiki*/ ){
19581986
g.json.resultCode = FSL_JSON_E_DENIED;
19591987
return NULL;
19601988
}
1989
+ limit = json_timeline_limit();
19611990
payV = cson_value_new_object();
19621991
pay = cson_value_get_object(payV);
1963
- if( limit < 0 ) limit = defaultLimit;
19641992
json_timeline_temp_table();
19651993
blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1);
1966
- blob_append(&sql, json_timeline_query_ci(), -1 );
1994
+ blob_append(&sql, json_timeline_query(), -1 );
19671995
blob_append(&sql, "AND event.type IN('ci') ", -1);
19681996
blob_append(&sql, "ORDER BY mtime DESC ", -1);
19691997
#define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \
19701998
g.json.resultCode = (cson_rc.AllocError==check) \
19711999
? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \
@@ -2052,10 +2080,119 @@
20522080
cson_value_free(payV);
20532081
payV = NULL;
20542082
ok:
20552083
return payV;
20562084
}
2085
+
2086
+/*
2087
+** Implementation of /json/timeline/wiki.
2088
+**
2089
+*/
2090
+static cson_value * json_timeline_wiki(unsigned int depth){
2091
+ /* This code is 95% the same as json_timeline_ci(), by the way. */
2092
+ cson_value * payV = NULL;
2093
+ cson_object * pay = NULL;
2094
+ cson_value * tmp = NULL;
2095
+ cson_value * listV = NULL;
2096
+ cson_array * list = NULL;
2097
+ int limit;
2098
+ int check = 0;
2099
+ Stmt q;
2100
+ Blob sql = empty_blob;
2101
+ if( !g.perm.Read || !g.perm.RdWiki ){
2102
+ g.json.resultCode = FSL_JSON_E_DENIED;
2103
+ return NULL;
2104
+ }
2105
+ limit = json_timeline_limit();
2106
+ payV = cson_value_new_object();
2107
+ pay = cson_value_get_object(payV);
2108
+ json_timeline_temp_table();
2109
+ blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1);
2110
+ blob_append(&sql, json_timeline_query(), -1 );
2111
+ blob_append(&sql, "AND event.type IN('w') ", -1);
2112
+ blob_append(&sql, "ORDER BY mtime DESC ", -1);
2113
+#define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \
2114
+ g.json.resultCode = (cson_rc.AllocError==check) \
2115
+ ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \
2116
+ goto error;\
2117
+ }
2118
+ if(limit){
2119
+ blob_appendf(&sql,"LIMIT %d ",limit);
2120
+ tmp = cson_value_new_integer(limit);
2121
+ SET("limit");
2122
+ }
2123
+ db_multi_exec(blob_buffer(&sql));
2124
+
2125
+#if 0
2126
+ /* only for testing! */
2127
+ tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
2128
+ SET("timelineSql");
2129
+#endif
2130
+
2131
+ blob_reset(&sql);
2132
+ blob_append(&sql, "SELECT rid AS rid,"
2133
+ " uuid AS uuid,"
2134
+ " mtime AS timestamp,"
2135
+ " timestampString AS timestampString,"
2136
+ " comment AS comment, "
2137
+ " user AS user,"
2138
+ " eventType AS eventType"
2139
+#if 0
2140
+ /* can wiki pages have tags? */
2141
+ " tags AS tags," /*FIXME: split this into
2142
+ a JSON array*/
2143
+ " tagId AS tagId,"
2144
+#endif
2145
+ " FROM json_timeline"
2146
+ " ORDER BY mtime DESC",
2147
+ -1);
2148
+ db_prepare(&q,blob_buffer(&sql));
2149
+ listV = cson_value_new_array();
2150
+ list = cson_value_get_array(listV);
2151
+ tmp = listV;
2152
+ SET("timeline");
2153
+ while( (SQLITE_ROW == db_step(&q) )){
2154
+ /* convert each row into a JSON object...*/
2155
+ cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt);
2156
+ cson_object * row = cson_value_get_object(rowV);
2157
+ cson_string const * tagsStr = NULL;
2158
+ if(!row){
2159
+ json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
2160
+ "Could not convert at least one timeline result row to JSON." );
2161
+ continue;
2162
+ }
2163
+ /* Split tags string field into JSON Array... */
2164
+ cson_array_append(list, rowV);
2165
+#if 0
2166
+ tagsStr = cson_value_get_string(cson_object_get(row,"tags"));
2167
+ if(tagsStr){
2168
+ cson_value * tags = json_string_split2( cson_string_cstr(tagsStr),
2169
+ ',', 0);
2170
+ if( tags ){
2171
+ if(0 != cson_object_set(row,"tags",tags)){
2172
+ cson_value_free(tags);
2173
+ }else{
2174
+ /*replaced/deleted old tags value, invalidating tagsStr*/;
2175
+ tagsStr = NULL;
2176
+ }
2177
+ }else{
2178
+ json_warn(FSL_JSON_W_STRING_TO_ARRAY_FAILED,
2179
+ "Could not convert tags string to array.");
2180
+ }
2181
+ }
2182
+#endif
2183
+ }
2184
+ db_finalize(&q);
2185
+#undef SET
2186
+ goto ok;
2187
+ error:
2188
+ cson_value_free(payV);
2189
+ payV = NULL;
2190
+ ok:
2191
+ return payV;
2192
+}
2193
+
20572194
20582195
/*
20592196
** Implements the /json/whoami page/command.
20602197
*/
20612198
static cson_value * json_page_whoami(unsigned int depth){
20622199
--- src/json.c
+++ src/json.c
@@ -721,10 +721,14 @@
721 g.json.cmd.offset = -1;
722 if( !g.isHTTP && g.fullHttpReply ){
723 /* workaround for server mode, so we see it as CGI mode. */
724 g.isHTTP = 1;
725 }
 
 
 
 
726 if(! g.json.post.v ){
727 /* If cgi_init() reads POSTed JSON then it sets the content type.
728 If it did not then we need to set it.
729 */
730 cgi_set_content_type(json_guess_content_type());
@@ -1865,15 +1869,17 @@
1865 }
1866 return payV;
1867 }
1868
1869 static cson_value * json_timeline_ci(unsigned int depth);
 
1870 /*
1871 ** Mapping of /json/timeline/XXX commands/paths to callbacks.
1872 */
1873 static const JsonPageDef JsonPageDefs_Timeline[] = {
1874 {"ci", json_timeline_ci, 0},
 
1875 /* Last entry MUST have a NULL name. */
1876 {NULL,NULL,0}
1877 };
1878
1879 /*
@@ -1909,13 +1915,13 @@
1909 db_multi_exec(zSql);
1910 }
1911
1912 /*
1913 ** Return a pointer to a constant string that forms the basis
1914 ** for a timeline query for the JSON "checkin" interface.
1915 */
1916 const char const * json_timeline_query_ci(void){
1917 /* Field order MUST match that from json_timeline_temp_table()!!! */
1918 static const char zBaseSql[] =
1919 @ SELECT
1920 @ blob.rid,
1921 @ uuid,
@@ -1935,37 +1941,59 @@
1935 @ WHERE blob.rid=event.objid
1936 ;
1937 return zBaseSql;
1938 }
1939
1940
1941 /*
1942 ** /json/timeline/ci
 
 
1943 **
1944 ** Far from complete.
1945 */
1946 static cson_value * json_timeline_ci(unsigned int depth){
1947 static const int defaultLimit = 20;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1948 cson_value * payV = NULL;
1949 cson_object * pay = NULL;
1950 cson_value * tmp = NULL;
1951 cson_value * listV = NULL;
1952 cson_array * list = NULL;
1953 int limit = json_getenv_int("n",defaultLimit);
1954 int check = 0;
1955 Stmt q;
1956 Blob sql = empty_blob;
1957 if( !g.perm.Read/* && !g.perm.RdTkt && !g.perm.RdWiki*/ ){
1958 g.json.resultCode = FSL_JSON_E_DENIED;
1959 return NULL;
1960 }
 
1961 payV = cson_value_new_object();
1962 pay = cson_value_get_object(payV);
1963 if( limit < 0 ) limit = defaultLimit;
1964 json_timeline_temp_table();
1965 blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1);
1966 blob_append(&sql, json_timeline_query_ci(), -1 );
1967 blob_append(&sql, "AND event.type IN('ci') ", -1);
1968 blob_append(&sql, "ORDER BY mtime DESC ", -1);
1969 #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \
1970 g.json.resultCode = (cson_rc.AllocError==check) \
1971 ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \
@@ -2052,10 +2080,119 @@
2052 cson_value_free(payV);
2053 payV = NULL;
2054 ok:
2055 return payV;
2056 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2057
2058 /*
2059 ** Implements the /json/whoami page/command.
2060 */
2061 static cson_value * json_page_whoami(unsigned int depth){
2062
--- src/json.c
+++ src/json.c
@@ -721,10 +721,14 @@
721 g.json.cmd.offset = -1;
722 if( !g.isHTTP && g.fullHttpReply ){
723 /* workaround for server mode, so we see it as CGI mode. */
724 g.isHTTP = 1;
725 }
726 if( !g.isHTTP ){
727 g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/;
728 }
729
730 if(! g.json.post.v ){
731 /* If cgi_init() reads POSTed JSON then it sets the content type.
732 If it did not then we need to set it.
733 */
734 cgi_set_content_type(json_guess_content_type());
@@ -1865,15 +1869,17 @@
1869 }
1870 return payV;
1871 }
1872
1873 static cson_value * json_timeline_ci(unsigned int depth);
1874 static cson_value * json_timeline_wiki(unsigned int depth);
1875 /*
1876 ** Mapping of /json/timeline/XXX commands/paths to callbacks.
1877 */
1878 static const JsonPageDef JsonPageDefs_Timeline[] = {
1879 {"ci", json_timeline_ci, 0},
1880 {"wiki", json_timeline_wiki, 0},
1881 /* Last entry MUST have a NULL name. */
1882 {NULL,NULL,0}
1883 };
1884
1885 /*
@@ -1909,13 +1915,13 @@
1915 db_multi_exec(zSql);
1916 }
1917
1918 /*
1919 ** Return a pointer to a constant string that forms the basis
1920 ** for a timeline query for the JSON interface.
1921 */
1922 const char const * json_timeline_query(void){
1923 /* Field order MUST match that from json_timeline_temp_table()!!! */
1924 static const char zBaseSql[] =
1925 @ SELECT
1926 @ blob.rid,
1927 @ uuid,
@@ -1935,37 +1941,59 @@
1941 @ WHERE blob.rid=event.objid
1942 ;
1943 return zBaseSql;
1944 }
1945
 
1946 /*
1947 ** Tries to figure out a timeline query length limit base on
1948 ** environment parameters. If it can it returns that value,
1949 ** else it returns some statically defined default value.
1950 **
1951 ** Never returns a negative value. 0 means no limit.
1952 */
1953 static int json_timeline_limit(){
1954 static const int defaultLimit = 20;
1955 int limit = -1;
1956 if( g.isHTTP ){
1957 limit = json_getenv_int("limit",-1);
1958 if(limit<0){
1959 limit = json_getenv_int("n",-1);
1960 }
1961 }else{/* CLI mode */
1962 char const * arg = find_option("limit","n",1);
1963 if(arg && *arg){
1964 limit = atoi(arg);
1965 }
1966 }
1967 return (limit<0) ? defaultLimit : limit;
1968 }
1969 /*
1970 ** Implementation of /json/timeline/ci.
1971 **
1972 ** Still a few TODOs (like figuring out how to structure
1973 ** inheritance info).
1974 */
1975 static cson_value * json_timeline_ci(unsigned int depth){
1976 cson_value * payV = NULL;
1977 cson_object * pay = NULL;
1978 cson_value * tmp = NULL;
1979 cson_value * listV = NULL;
1980 cson_array * list = NULL;
1981 int limit;
1982 int check = 0;
1983 Stmt q;
1984 Blob sql = empty_blob;
1985 if( !g.perm.Read/* && !g.perm.RdTkt && !g.perm.RdWiki*/ ){
1986 g.json.resultCode = FSL_JSON_E_DENIED;
1987 return NULL;
1988 }
1989 limit = json_timeline_limit();
1990 payV = cson_value_new_object();
1991 pay = cson_value_get_object(payV);
 
1992 json_timeline_temp_table();
1993 blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1);
1994 blob_append(&sql, json_timeline_query(), -1 );
1995 blob_append(&sql, "AND event.type IN('ci') ", -1);
1996 blob_append(&sql, "ORDER BY mtime DESC ", -1);
1997 #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \
1998 g.json.resultCode = (cson_rc.AllocError==check) \
1999 ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \
@@ -2052,10 +2080,119 @@
2080 cson_value_free(payV);
2081 payV = NULL;
2082 ok:
2083 return payV;
2084 }
2085
2086 /*
2087 ** Implementation of /json/timeline/wiki.
2088 **
2089 */
2090 static cson_value * json_timeline_wiki(unsigned int depth){
2091 /* This code is 95% the same as json_timeline_ci(), by the way. */
2092 cson_value * payV = NULL;
2093 cson_object * pay = NULL;
2094 cson_value * tmp = NULL;
2095 cson_value * listV = NULL;
2096 cson_array * list = NULL;
2097 int limit;
2098 int check = 0;
2099 Stmt q;
2100 Blob sql = empty_blob;
2101 if( !g.perm.Read || !g.perm.RdWiki ){
2102 g.json.resultCode = FSL_JSON_E_DENIED;
2103 return NULL;
2104 }
2105 limit = json_timeline_limit();
2106 payV = cson_value_new_object();
2107 pay = cson_value_get_object(payV);
2108 json_timeline_temp_table();
2109 blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1);
2110 blob_append(&sql, json_timeline_query(), -1 );
2111 blob_append(&sql, "AND event.type IN('w') ", -1);
2112 blob_append(&sql, "ORDER BY mtime DESC ", -1);
2113 #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \
2114 g.json.resultCode = (cson_rc.AllocError==check) \
2115 ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \
2116 goto error;\
2117 }
2118 if(limit){
2119 blob_appendf(&sql,"LIMIT %d ",limit);
2120 tmp = cson_value_new_integer(limit);
2121 SET("limit");
2122 }
2123 db_multi_exec(blob_buffer(&sql));
2124
2125 #if 0
2126 /* only for testing! */
2127 tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
2128 SET("timelineSql");
2129 #endif
2130
2131 blob_reset(&sql);
2132 blob_append(&sql, "SELECT rid AS rid,"
2133 " uuid AS uuid,"
2134 " mtime AS timestamp,"
2135 " timestampString AS timestampString,"
2136 " comment AS comment, "
2137 " user AS user,"
2138 " eventType AS eventType"
2139 #if 0
2140 /* can wiki pages have tags? */
2141 " tags AS tags," /*FIXME: split this into
2142 a JSON array*/
2143 " tagId AS tagId,"
2144 #endif
2145 " FROM json_timeline"
2146 " ORDER BY mtime DESC",
2147 -1);
2148 db_prepare(&q,blob_buffer(&sql));
2149 listV = cson_value_new_array();
2150 list = cson_value_get_array(listV);
2151 tmp = listV;
2152 SET("timeline");
2153 while( (SQLITE_ROW == db_step(&q) )){
2154 /* convert each row into a JSON object...*/
2155 cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt);
2156 cson_object * row = cson_value_get_object(rowV);
2157 cson_string const * tagsStr = NULL;
2158 if(!row){
2159 json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
2160 "Could not convert at least one timeline result row to JSON." );
2161 continue;
2162 }
2163 /* Split tags string field into JSON Array... */
2164 cson_array_append(list, rowV);
2165 #if 0
2166 tagsStr = cson_value_get_string(cson_object_get(row,"tags"));
2167 if(tagsStr){
2168 cson_value * tags = json_string_split2( cson_string_cstr(tagsStr),
2169 ',', 0);
2170 if( tags ){
2171 if(0 != cson_object_set(row,"tags",tags)){
2172 cson_value_free(tags);
2173 }else{
2174 /*replaced/deleted old tags value, invalidating tagsStr*/;
2175 tagsStr = NULL;
2176 }
2177 }else{
2178 json_warn(FSL_JSON_W_STRING_TO_ARRAY_FAILED,
2179 "Could not convert tags string to array.");
2180 }
2181 }
2182 #endif
2183 }
2184 db_finalize(&q);
2185 #undef SET
2186 goto ok;
2187 error:
2188 cson_value_free(payV);
2189 payV = NULL;
2190 ok:
2191 return payV;
2192 }
2193
2194
2195 /*
2196 ** Implements the /json/whoami page/command.
2197 */
2198 static cson_value * json_page_whoami(unsigned int depth){
2199

Keyboard Shortcuts

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