Fossil SCM

initial code for reading POST data from a file/stdin in CLI mode.

stephan 2011-10-02 12:31 UTC json-multitag-test
Commit 8145cdbf3b167efcf304e4ec924aaf85fdfa072d
3 files changed +9 -6 +49 -15 +2 -2
+9 -6
--- src/cgi.c
+++ src/cgi.c
@@ -725,22 +725,25 @@
725725
}
726726
727727
/*
728728
** Reads a JSON object from the first contentLen bytes of zIn. On
729729
** g.json.post is updated to hold the content. On error a
730
-** FSL_JSON_E_INVALID_REQUEST response is output and fossil_exit(0) is
731
-** called.
730
+** FSL_JSON_E_INVALID_REQUEST response is output and fossil_exit() is
731
+** called (in HTTP mode exit code 0 is used).
732
+**
733
+** If contentLen is 0 then the whole file is read.
732734
*/
733
-static void cgi_parse_POST_JSON( FILE * zIn, unsigned int contentLen ){
735
+void cgi_parse_POST_JSON( FILE * zIn, unsigned int contentLen ){
734736
cson_value * jv = NULL;
735737
int rc;
736738
CgiPostReadState state;
737
- assert( 0 != contentLen );
738739
state.fh = zIn;
739740
state.len = contentLen;
740741
state.pos = 0;
741
- rc = cson_parse( &jv, cson_data_source_FILE_n, &state, NULL, NULL );
742
+ rc = cson_parse( &jv,
743
+ contentLen ? cson_data_source_FILE_n : cson_data_source_FILE,
744
+ contentLen ? (void *)&state : (void *)zIn, NULL, NULL );
742745
if(rc){
743746
goto invalidRequest;
744747
}else{
745748
json_gc_add( "POST.JSON", jv, 1 );
746749
g.json.post.v = jv;
@@ -751,11 +754,11 @@
751754
}
752755
return;
753756
invalidRequest:
754757
cgi_set_content_type(json_guess_content_type());
755758
json_err( FSL_JSON_E_INVALID_REQUEST, NULL, 1 );
756
- fossil_exit(0);
759
+ fossil_exit( g.isHTTP ? 0 : 1);
757760
}
758761
759762
760763
/*
761764
** Initialize the query parameter database. Information is pulled from
762765
--- src/cgi.c
+++ src/cgi.c
@@ -725,22 +725,25 @@
725 }
726
727 /*
728 ** Reads a JSON object from the first contentLen bytes of zIn. On
729 ** g.json.post is updated to hold the content. On error a
730 ** FSL_JSON_E_INVALID_REQUEST response is output and fossil_exit(0) is
731 ** called.
 
 
732 */
733 static void cgi_parse_POST_JSON( FILE * zIn, unsigned int contentLen ){
734 cson_value * jv = NULL;
735 int rc;
736 CgiPostReadState state;
737 assert( 0 != contentLen );
738 state.fh = zIn;
739 state.len = contentLen;
740 state.pos = 0;
741 rc = cson_parse( &jv, cson_data_source_FILE_n, &state, NULL, NULL );
 
 
742 if(rc){
743 goto invalidRequest;
744 }else{
745 json_gc_add( "POST.JSON", jv, 1 );
746 g.json.post.v = jv;
@@ -751,11 +754,11 @@
751 }
752 return;
753 invalidRequest:
754 cgi_set_content_type(json_guess_content_type());
755 json_err( FSL_JSON_E_INVALID_REQUEST, NULL, 1 );
756 fossil_exit(0);
757 }
758
759
760 /*
761 ** Initialize the query parameter database. Information is pulled from
762
--- src/cgi.c
+++ src/cgi.c
@@ -725,22 +725,25 @@
725 }
726
727 /*
728 ** Reads a JSON object from the first contentLen bytes of zIn. On
729 ** g.json.post is updated to hold the content. On error a
730 ** FSL_JSON_E_INVALID_REQUEST response is output and fossil_exit() is
731 ** called (in HTTP mode exit code 0 is used).
732 **
733 ** If contentLen is 0 then the whole file is read.
734 */
735 void cgi_parse_POST_JSON( FILE * zIn, unsigned int contentLen ){
736 cson_value * jv = NULL;
737 int rc;
738 CgiPostReadState state;
 
739 state.fh = zIn;
740 state.len = contentLen;
741 state.pos = 0;
742 rc = cson_parse( &jv,
743 contentLen ? cson_data_source_FILE_n : cson_data_source_FILE,
744 contentLen ? (void *)&state : (void *)zIn, NULL, NULL );
745 if(rc){
746 goto invalidRequest;
747 }else{
748 json_gc_add( "POST.JSON", jv, 1 );
749 g.json.post.v = jv;
@@ -751,11 +754,11 @@
754 }
755 return;
756 invalidRequest:
757 cgi_set_content_type(json_guess_content_type());
758 json_err( FSL_JSON_E_INVALID_REQUEST, NULL, 1 );
759 fossil_exit( g.isHTTP ? 0 : 1);
760 }
761
762
763 /*
764 ** Initialize the query parameter database. Information is pulled from
765
+49 -15
--- src/json.c
+++ src/json.c
@@ -887,30 +887,30 @@
887887
if( once ){
888888
return;
889889
}else{
890890
once = 1;
891891
}
892
- g.json.jsonp = PD("jsonp",NULL);
892
+ g.json.jsonp = PD("jsonp",NULL)
893
+ /* FIXME: do some sanity checking on g.json.jsonp and ignore it
894
+ if it is not halfway reasonable.
895
+ */
896
+ ;
893897
g.json.isJsonMode = 1;
894898
g.json.resultCode = 0;
895899
g.json.cmd.offset = -1;
896900
if( !g.isHTTP && g.fullHttpReply ){
897901
/* workaround for server mode, so we see it as CGI mode. */
898902
g.isHTTP = 1;
899903
}
900904
901
- /* FIXME: do some sanity checking on g.json.jsonp and ignore it
902
- if it is not halfway reasonable.
903
- */
904
- cgi_set_content_type(json_guess_content_type())
905
- /* reminder: must be done after g.json.jsonp is initialized */
906
- ;
907
-
908
-#if defined(NDEBUG)
909
- /* avoids debug messages on stderr in JSON mode */
910
- sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);
911
-#endif
905
+ if(g.isHTTP){
906
+ cgi_set_content_type(json_guess_content_type())
907
+ /* reminder: must be done after g.json.jsonp is initialized */
908
+ ;
909
+ /* avoids debug messages on stderr in JSON mode */
910
+ sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);
911
+ }
912912
913913
g.json.cmd.v = cson_value_new_array();
914914
g.json.cmd.a = cson_value_get_array(g.json.cmd.v);
915915
json_gc_add( FossilJsonKeys.commandPath, g.json.cmd.v, 1 );
916916
/*
@@ -931,15 +931,43 @@
931931
cson_value * part;
932932
for(i = 1/*skip argv[0]*/; i < g.argc; ++i ){
933933
arg = g.argv[i];
934934
if( !arg || !*arg ){
935935
continue;
936
+ }
937
+ if('-' == *arg){
938
+ /* workaround to skip CLI args so that
939
+ json_command_arg() does not see them.
940
+ This assumes that all arguments come LAST
941
+ on the command line.
942
+ */
943
+ break;
936944
}
937945
part = cson_value_new_string(arg,strlen(arg));
938946
cson_array_append(g.json.cmd.a, part);
939947
}
940948
}
949
+
950
+ while(!g.isHTTP){ /* simulate JSON POST data via input file. */
951
+ FILE * inFile = NULL;
952
+ char const * jfile = find_option("json-input",NULL,1);
953
+ if(!jfile || !*jfile){
954
+ break;
955
+ }
956
+ inFile = (0==strcmp("-",jfile))
957
+ ? stdin
958
+ : fopen(jfile,"rb");
959
+ if(!inFile){
960
+ json_err(FSL_JSON_E_UNKNOWN,"Could not open JSON file.",1);
961
+ fossil_exit(1);
962
+ }
963
+ cgi_parse_POST_JSON(inFile, 0);
964
+ if( stdin != inFile ){
965
+ fclose(inFile);
966
+ }
967
+ break;
968
+ }
941969
942970
/* g.json.reqPayload exists only to simplify some of our access to
943971
the request payload. We currently only use this in the context of
944972
Object payloads, not Arrays, strings, etc.
945973
*/
@@ -969,13 +997,19 @@
969997
}
970998
971999
{/* set up JSON output formatting options. */
9721000
unsigned char indent = g.isHTTP ? 0 : 1;
9731001
char const * indentStr = NULL;
974
- if( g.isHTTP ){
975
- indent = (unsigned char)json_getenv_int("indent",(int)indent);
976
- }else{/*CLI mode*/
1002
+ char checkAgain = 1;
1003
+ if( g.json.post.v ){
1004
+ cson_value const * check = json_getenv("indent");
1005
+ if(check){
1006
+ checkAgain = 0;
1007
+ indent = (unsigned char)json_getenv_int("indent",(int)indent);
1008
+ }
1009
+ }
1010
+ if(!g.isHTTP && checkAgain){/*CLI mode*/
9771011
indentStr = find_option("indent","I",1);
9781012
if(indentStr){
9791013
int const n = atoi(indentStr);
9801014
indent = (n>0)
9811015
? (unsigned char)n
9821016
--- src/json.c
+++ src/json.c
@@ -887,30 +887,30 @@
887 if( once ){
888 return;
889 }else{
890 once = 1;
891 }
892 g.json.jsonp = PD("jsonp",NULL);
 
 
 
 
893 g.json.isJsonMode = 1;
894 g.json.resultCode = 0;
895 g.json.cmd.offset = -1;
896 if( !g.isHTTP && g.fullHttpReply ){
897 /* workaround for server mode, so we see it as CGI mode. */
898 g.isHTTP = 1;
899 }
900
901 /* FIXME: do some sanity checking on g.json.jsonp and ignore it
902 if it is not halfway reasonable.
903 */
904 cgi_set_content_type(json_guess_content_type())
905 /* reminder: must be done after g.json.jsonp is initialized */
906 ;
907
908 #if defined(NDEBUG)
909 /* avoids debug messages on stderr in JSON mode */
910 sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);
911 #endif
912
913 g.json.cmd.v = cson_value_new_array();
914 g.json.cmd.a = cson_value_get_array(g.json.cmd.v);
915 json_gc_add( FossilJsonKeys.commandPath, g.json.cmd.v, 1 );
916 /*
@@ -931,15 +931,43 @@
931 cson_value * part;
932 for(i = 1/*skip argv[0]*/; i < g.argc; ++i ){
933 arg = g.argv[i];
934 if( !arg || !*arg ){
935 continue;
 
 
 
 
 
 
 
 
936 }
937 part = cson_value_new_string(arg,strlen(arg));
938 cson_array_append(g.json.cmd.a, part);
939 }
940 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
941
942 /* g.json.reqPayload exists only to simplify some of our access to
943 the request payload. We currently only use this in the context of
944 Object payloads, not Arrays, strings, etc.
945 */
@@ -969,13 +997,19 @@
969 }
970
971 {/* set up JSON output formatting options. */
972 unsigned char indent = g.isHTTP ? 0 : 1;
973 char const * indentStr = NULL;
974 if( g.isHTTP ){
975 indent = (unsigned char)json_getenv_int("indent",(int)indent);
976 }else{/*CLI mode*/
 
 
 
 
 
 
977 indentStr = find_option("indent","I",1);
978 if(indentStr){
979 int const n = atoi(indentStr);
980 indent = (n>0)
981 ? (unsigned char)n
982
--- src/json.c
+++ src/json.c
@@ -887,30 +887,30 @@
887 if( once ){
888 return;
889 }else{
890 once = 1;
891 }
892 g.json.jsonp = PD("jsonp",NULL)
893 /* FIXME: do some sanity checking on g.json.jsonp and ignore it
894 if it is not halfway reasonable.
895 */
896 ;
897 g.json.isJsonMode = 1;
898 g.json.resultCode = 0;
899 g.json.cmd.offset = -1;
900 if( !g.isHTTP && g.fullHttpReply ){
901 /* workaround for server mode, so we see it as CGI mode. */
902 g.isHTTP = 1;
903 }
904
905 if(g.isHTTP){
906 cgi_set_content_type(json_guess_content_type())
907 /* reminder: must be done after g.json.jsonp is initialized */
908 ;
909 /* avoids debug messages on stderr in JSON mode */
910 sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0);
911 }
 
 
 
 
912
913 g.json.cmd.v = cson_value_new_array();
914 g.json.cmd.a = cson_value_get_array(g.json.cmd.v);
915 json_gc_add( FossilJsonKeys.commandPath, g.json.cmd.v, 1 );
916 /*
@@ -931,15 +931,43 @@
931 cson_value * part;
932 for(i = 1/*skip argv[0]*/; i < g.argc; ++i ){
933 arg = g.argv[i];
934 if( !arg || !*arg ){
935 continue;
936 }
937 if('-' == *arg){
938 /* workaround to skip CLI args so that
939 json_command_arg() does not see them.
940 This assumes that all arguments come LAST
941 on the command line.
942 */
943 break;
944 }
945 part = cson_value_new_string(arg,strlen(arg));
946 cson_array_append(g.json.cmd.a, part);
947 }
948 }
949
950 while(!g.isHTTP){ /* simulate JSON POST data via input file. */
951 FILE * inFile = NULL;
952 char const * jfile = find_option("json-input",NULL,1);
953 if(!jfile || !*jfile){
954 break;
955 }
956 inFile = (0==strcmp("-",jfile))
957 ? stdin
958 : fopen(jfile,"rb");
959 if(!inFile){
960 json_err(FSL_JSON_E_UNKNOWN,"Could not open JSON file.",1);
961 fossil_exit(1);
962 }
963 cgi_parse_POST_JSON(inFile, 0);
964 if( stdin != inFile ){
965 fclose(inFile);
966 }
967 break;
968 }
969
970 /* g.json.reqPayload exists only to simplify some of our access to
971 the request payload. We currently only use this in the context of
972 Object payloads, not Arrays, strings, etc.
973 */
@@ -969,13 +997,19 @@
997 }
998
999 {/* set up JSON output formatting options. */
1000 unsigned char indent = g.isHTTP ? 0 : 1;
1001 char const * indentStr = NULL;
1002 char checkAgain = 1;
1003 if( g.json.post.v ){
1004 cson_value const * check = json_getenv("indent");
1005 if(check){
1006 checkAgain = 0;
1007 indent = (unsigned char)json_getenv_int("indent",(int)indent);
1008 }
1009 }
1010 if(!g.isHTTP && checkAgain){/*CLI mode*/
1011 indentStr = find_option("indent","I",1);
1012 if(indentStr){
1013 int const n = atoi(indentStr);
1014 indent = (n>0)
1015 ? (unsigned char)n
1016
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -167,16 +167,16 @@
167167
** Never returns a negative value. 0 means no limit.
168168
*/
169169
static int json_timeline_limit(){
170170
static const int defaultLimit = 20;
171171
int limit = -1;
172
- if( g.isHTTP ){
172
+ if( g.json.post.v ){
173173
limit = json_getenv_int("limit",-1);
174174
if(limit<0){
175175
limit = json_getenv_int("n",-1);
176176
}
177
- }else{/* CLI mode */
177
+ }else if(!g.isHTTP){/* CLI mode */
178178
char const * arg = find_option("limit","n",1);
179179
if(arg && *arg){
180180
limit = atoi(arg);
181181
}
182182
}
183183
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -167,16 +167,16 @@
167 ** Never returns a negative value. 0 means no limit.
168 */
169 static int json_timeline_limit(){
170 static const int defaultLimit = 20;
171 int limit = -1;
172 if( g.isHTTP ){
173 limit = json_getenv_int("limit",-1);
174 if(limit<0){
175 limit = json_getenv_int("n",-1);
176 }
177 }else{/* CLI mode */
178 char const * arg = find_option("limit","n",1);
179 if(arg && *arg){
180 limit = atoi(arg);
181 }
182 }
183
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -167,16 +167,16 @@
167 ** Never returns a negative value. 0 means no limit.
168 */
169 static int json_timeline_limit(){
170 static const int defaultLimit = 20;
171 int limit = -1;
172 if( g.json.post.v ){
173 limit = json_getenv_int("limit",-1);
174 if(limit<0){
175 limit = json_getenv_int("n",-1);
176 }
177 }else if(!g.isHTTP){/* CLI mode */
178 char const * arg = find_option("limit","n",1);
179 if(arg && *arg){
180 limit = atoi(arg);
181 }
182 }
183

Keyboard Shortcuts

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