| | @@ -1320,16 +1320,21 @@ |
| 1320 | 1320 | if(!part){ |
| 1321 | 1321 | fossil_warning("Iterating further than expected in %s.", |
| 1322 | 1322 | __FILE__); |
| 1323 | 1323 | break; |
| 1324 | 1324 | } |
| 1325 | | - blob_append(&path,part,-1); |
| 1326 | | - if(i < (aLen-1)){ |
| 1327 | | - blob_append(&path,"/",1); |
| 1328 | | - } |
| 1325 | + blob_appendf(&path,"%s%s", (i>1 ? "/": ""), part); |
| 1329 | 1326 | } |
| 1330 | | - rc = json_new_string(blob_buffer(&path)); |
| 1327 | + rc = json_new_string((blob_size(&path)>0) |
| 1328 | + ? blob_buffer(&path) |
| 1329 | + : "") |
| 1330 | + /* reminder; we need an empty string instead of NULL |
| 1331 | + in this case, to avoid what outwardly looks like |
| 1332 | + (but is not) an allocation error in |
| 1333 | + json_create_response(). |
| 1334 | + */ |
| 1335 | + ; |
| 1331 | 1336 | blob_reset(&path); |
| 1332 | 1337 | return rc; |
| 1333 | 1338 | } |
| 1334 | 1339 | } |
| 1335 | 1340 | |
| | @@ -1953,10 +1958,33 @@ |
| 1953 | 1958 | static cson_value * json_user_get(); |
| 1954 | 1959 | #if 0 |
| 1955 | 1960 | static cson_value * json_user_create(); |
| 1956 | 1961 | static cson_value * json_user_edit(); |
| 1957 | 1962 | #endif |
| 1963 | + |
| 1964 | +/* |
| 1965 | +** Creates a comma-separated list of command names |
| 1966 | +** taken from zPages. zPages must be an array of objects |
| 1967 | +** whose final entry MUST have a NULL name value or results |
| 1968 | +** are undefined. |
| 1969 | +** |
| 1970 | +** The list is appended to pOut. The number of items (not bytes) |
| 1971 | +** appended are returned. |
| 1972 | +*/ |
| 1973 | +static int json_pagedefs_to_string(JsonPageDef const * zPages, |
| 1974 | + Blob * pOut){ |
| 1975 | + int i = 0; |
| 1976 | + for( ; zPages->name; ++zPages, ++i ){ |
| 1977 | + if(g.isHTTP && zPages->runMode < 0) continue; |
| 1978 | + else if(zPages->runMode > 0) continue; |
| 1979 | + blob_appendf(pOut, zPages->name, -1); |
| 1980 | + if((zPages+1)->name){ |
| 1981 | + blob_append(pOut, ", ",2); |
| 1982 | + } |
| 1983 | + } |
| 1984 | + return i; |
| 1985 | +} |
| 1958 | 1986 | |
| 1959 | 1987 | /* |
| 1960 | 1988 | ** Mapping of /json/user/XXX commands/paths to callbacks. |
| 1961 | 1989 | */ |
| 1962 | 1990 | static const JsonPageDef JsonPageDefs_User[] = { |
| | @@ -1972,11 +2000,16 @@ |
| 1972 | 2000 | cson_value * json_page_dispatch_helper(JsonPageDef const * pages){ |
| 1973 | 2001 | JsonPageDef const * def; |
| 1974 | 2002 | char const * cmd = json_command_arg(1+g.json.dispatchDepth); |
| 1975 | 2003 | assert( NULL != pages ); |
| 1976 | 2004 | if( ! cmd ){ |
| 1977 | | - json_set_err(FSL_JSON_E_MISSING_ARGS, "No subcommand specified."); |
| 2005 | + Blob cmdNames = empty_blob; |
| 2006 | + json_pagedefs_to_string(pages, &cmdNames); |
| 2007 | + json_set_err(FSL_JSON_E_MISSING_ARGS, |
| 2008 | + "No subcommand specified. Try one of (%s).", |
| 2009 | + blob_str(&cmdNames)); |
| 2010 | + blob_reset(&cmdNames); |
| 1978 | 2011 | return NULL; |
| 1979 | 2012 | } |
| 1980 | 2013 | def = json_handler_for_name( cmd, pages ); |
| 1981 | 2014 | if(!def){ |
| 1982 | 2015 | g.json.resultCode = FSL_JSON_E_UNKNOWN_COMMAND; |
| | @@ -2188,10 +2221,13 @@ |
| 2188 | 2221 | cson_value * payload = NULL; |
| 2189 | 2222 | JsonPageDef const * pageDef = NULL; |
| 2190 | 2223 | BEGIN_TIMER; |
| 2191 | 2224 | json_mode_bootstrap(); |
| 2192 | 2225 | cmd = json_command_arg(1); |
| 2226 | + if(!cmd || !*cmd){ |
| 2227 | + goto usage; |
| 2228 | + } |
| 2193 | 2229 | /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/ |
| 2194 | 2230 | pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]); |
| 2195 | 2231 | if( ! pageDef ){ |
| 2196 | 2232 | json_err( FSL_JSON_E_UNKNOWN_COMMAND, NULL, 0 ); |
| 2197 | 2233 | return; |
| | @@ -2207,10 +2243,24 @@ |
| 2207 | 2243 | }else{ |
| 2208 | 2244 | cson_value * root = json_create_response(rc, NULL, payload); |
| 2209 | 2245 | json_send_response(root); |
| 2210 | 2246 | cson_value_free(root); |
| 2211 | 2247 | } |
| 2248 | + |
| 2249 | + return; |
| 2250 | + usage: |
| 2251 | + { |
| 2252 | + Blob cmdNames = empty_blob; |
| 2253 | + blob_init(&cmdNames, |
| 2254 | + "No command (sub-path) specified. Try one of: ", |
| 2255 | + -1); |
| 2256 | + json_pagedefs_to_string(&JsonPageDefs[0], &cmdNames); |
| 2257 | + json_err(FSL_JSON_E_MISSING_ARGS, |
| 2258 | + blob_str(&cmdNames), 0); |
| 2259 | + blob_reset(&cmdNames); |
| 2260 | + } |
| 2261 | + |
| 2212 | 2262 | } |
| 2213 | 2263 | |
| 2214 | 2264 | /* |
| 2215 | 2265 | ** This function dispatches json commands and is the CLI equivalent of |
| 2216 | 2266 | ** json_page_top(). |
| | @@ -2290,13 +2340,22 @@ |
| 2290 | 2340 | fossil_exit(1); |
| 2291 | 2341 | } |
| 2292 | 2342 | } |
| 2293 | 2343 | return; |
| 2294 | 2344 | usage: |
| 2295 | | - usage("subcommand"); |
| 2345 | + { |
| 2346 | + Blob cmdNames = empty_blob; |
| 2347 | + blob_init(&cmdNames, |
| 2348 | + "No subcommand specified. Try one of: ", -1); |
| 2349 | + json_pagedefs_to_string(&JsonPageDefs[0], &cmdNames); |
| 2350 | + json_err(FSL_JSON_E_MISSING_ARGS, |
| 2351 | + blob_str(&cmdNames), 1); |
| 2352 | + blob_reset(&cmdNames); |
| 2353 | + fossil_exit(1); |
| 2354 | + } |
| 2296 | 2355 | } |
| 2297 | 2356 | |
| 2298 | 2357 | #undef BITSET_BYTEFOR |
| 2299 | 2358 | #undef BITSET_SET |
| 2300 | 2359 | #undef BITSET_UNSET |
| 2301 | 2360 | #undef BITSET_GET |
| 2302 | 2361 | #undef BITSET_TOGGLE |
| 2303 | 2362 | |