Fossil

Check-in [79294bb8]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Remove dead code from cgi.c. Attempt better error handling.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1: 79294bb81b45107a973efc509a7d82d949352818
User & Date: drh 2010-08-26 12:10:03
Context
2010-08-26
13:17
Untested implementation of popen2() for windows. Closed-Leaf check-in: 34ea1e4a user: drh tags: experimental
12:10
Remove dead code from cgi.c. Attempt better error handling. check-in: 79294bb8 user: drh tags: experimental
11:27
Fix buffering issues with ssh://. The ssh:// sync method now works with older, unmodified servers. Added the "?fossil=exe" option to URL processing. check-in: af977263 user: drh tags: experimental
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/cgi.c.

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
  cgi_parameter("","");  /* Force the parameters into sorted order */
  for(i=0; i<nUsedQP; i++){
    cgi_printf("%s = %s  <br />\n",
       htmlize(aParamQP[i].zName, -1), htmlize(aParamQP[i].zValue, -1));
  }
}

/*
** Write HTML text for an option menu to standard output.  zParam
** is the query parameter that the option menu sets.  zDflt is the
** initial value of the option menu.  Addition arguments are name/value
** pairs that define values on the menu.  The list is terminated with
** a single NULL argument.
*/
void cgi_optionmenu(int in, const char *zP, const char *zD, ...){
  va_list ap;
  char *zName, *zVal;
  int dfltSeen = 0;
  cgi_printf("%*s<select size=1 name=\"%s\">\n", in, "", zP);
  va_start(ap, zD);
  while( (zName = va_arg(ap, char*))!=0 && (zVal = va_arg(ap, char*))!=0 ){
    if( strcmp(zVal,zD)==0 ){ dfltSeen = 1; break; }
  }
  va_end(ap);
  if( !dfltSeen ){
    if( zD[0] ){
      cgi_printf("%*s<option value=\"%h\" selected>%h</option>\n",
        in+2, "", zD, zD);
    }else{
      cgi_printf("%*s<option value=\"\" selected>&nbsp;</option>\n", in+2, "");
    }
  }
  va_start(ap, zD);
  while( (zName = va_arg(ap, char*))!=0 && (zVal = va_arg(ap, char*))!=0 ){
    if( zName[0] ){
      cgi_printf("%*s<option value=\"%h\"%s>%h</option>\n",
        in+2, "",
        zVal,
        strcmp(zVal, zD) ? "" : " selected",
        zName
      );
    }else{
      cgi_printf("%*s<option value=\"\"%s>&nbsp;</option>\n",
        in+2, "",
        strcmp(zVal, zD) ? "" : " selected"
      );
    }
  }
  va_end(ap);
  cgi_printf("%*s</select>\n", in, "");
}

/*
** This routine works a lot like cgi_optionmenu() except that the list of
** values is contained in an array.  Also, the values are just values, not
** name/value pairs as in cgi_optionmenu.
*/
void cgi_v_optionmenu(
  int in,              /* Indent by this amount */
  const char *zP,      /* The query parameter name */
  const char *zD,      /* Default value */
  const char **az      /* NULL-terminated list of allowed values */
){
  const char *zVal;
  int i;
  cgi_printf("%*s<select size=1 name=\"%s\">\n", in, "", zP);
  for(i=0; az[i]; i++){
    if( strcmp(az[i],zD)==0 ) break;
  }
  if( az[i]==0 ){
    if( zD[0]==0 ){
      cgi_printf("%*s<option value=\"\" selected>&nbsp;</option>\n",
       in+2, "");
    }else{
      cgi_printf("%*s<option value=\"%h\" selected>%h</option>\n",
       in+2, "", zD, zD);
    }
  }
  while( (zVal = *(az++))!=0  ){
    if( zVal[0] ){
      cgi_printf("%*s<option value=\"%h\"%s>%h</option>\n",
        in+2, "",
        zVal,
        strcmp(zVal, zD) ? "" : " selected",
        zVal
      );
    }else{
      cgi_printf("%*s<option value=\"\"%s>&nbsp;</option>\n",
        in+2, "",
        strcmp(zVal, zD) ? "" : " selected"
      );
    }
  }
  cgi_printf("%*s</select>\n", in, "");
}

/*
** This routine works a lot like cgi_v_optionmenu() except that the list
** is a list of pairs.  The first element of each pair is the value used
** internally and the second element is the value displayed to the user.
*/
void cgi_v_optionmenu2(
  int in,              /* Indent by this amount */
  const char *zP,      /* The query parameter name */
  const char *zD,      /* Default value */
  const char **az      /* NULL-terminated list of allowed values */
){
  const char *zVal;
  int i;
  cgi_printf("%*s<select size=1 name=\"%s\">\n", in, "", zP);
  for(i=0; az[i]; i+=2){
    if( strcmp(az[i],zD)==0 ) break;
  }
  if( az[i]==0 ){
    if( zD[0]==0 ){
      cgi_printf("%*s<option value=\"\" selected>&nbsp;</option>\n",
       in+2, "");
    }else{
      cgi_printf("%*s<option value=\"%h\" selected>%h</option>\n",
       in+2, "", zD, zD);
    }
  }
  while( (zVal = *(az++))!=0  ){
    const char *zName = *(az++);
    if( zName[0] ){
      cgi_printf("%*s<option value=\"%h\"%s>%h</option>\n",
        in+2, "",
        zVal,
        strcmp(zVal, zD) ? "" : " selected",
        zName
      );
    }else{
      cgi_printf("%*s<option value=\"%h\"%s>&nbsp;</option>\n",
        in+2, "",
        zVal,
        strcmp(zVal, zD) ? "" : " selected"
      );
    }
  }
  cgi_printf("%*s</select>\n", in, "");
}

/*
** This routine works like "printf" except that it has the
** extra formatting capabilities such as %h and %t.
*/
void cgi_printf(const char *zFormat, ...){
  va_list ap;
  va_start(ap,zFormat);







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







849
850
851
852
853
854
855







































































































































856
857
858
859
860
861
862
  cgi_parameter("","");  /* Force the parameters into sorted order */
  for(i=0; i<nUsedQP; i++){
    cgi_printf("%s = %s  <br />\n",
       htmlize(aParamQP[i].zName, -1), htmlize(aParamQP[i].zValue, -1));
  }
}








































































































































/*
** This routine works like "printf" except that it has the
** extra formatting capabilities such as %h and %t.
*/
void cgi_printf(const char *zFormat, ...){
  va_list ap;
  va_start(ap,zFormat);

Changes to src/http.c.

135
136
137
138
139
140
141

142
143
144
145
146
147
148
...
191
192
193
194
195
196
197

198
199
200
201
202
203
204
...
228
229
230
231
232
233
234


235
236
237
238
239
240
241
...
246
247
248
249
250
251
252














253
254
255
256
257
258
259
  Blob hdr;             /* The HTTP request header */
  int closeConnection;  /* True to close the connection when done */
  int iLength;          /* Length of the reply payload */
  int rc;               /* Result code */
  int iHttpVersion;     /* Which version of HTTP protocol server uses */
  char *zLine;          /* A single line of the reply header */
  int i;                /* Loop counter */


  if( transport_open() ){
    fossil_fatal(transport_errmsg());
  }

  /* Construct the login card and prepare the complete payload */
  blob_zero(&login);
................................................................................
  
  /*
  ** Read and interpret the server reply
  */
  closeConnection = 1;
  iLength = -1;
  while( (zLine = transport_receive_line())!=0 && zLine[0]!=0 ){

    if( strncasecmp(zLine, "http/1.", 7)==0 ){
      if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
      if( rc!=200 && rc!=302 ){
        int ii;
        for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
        while( zLine[ii]==' ' ) ii++;
        fossil_fatal("server says: %s\n", &zLine[ii]);
................................................................................
      j = strlen(zLine) - 1; 
      if( j>4 && strcmp(&zLine[j-4],"/xfer")==0 ) zLine[j-4] = 0;
      fossil_print("redirect to %s\n", &zLine[i]);
      url_parse(&zLine[i]);
      transport_close();
      http_exchange(pSend, pReply, useLogin);
      return;


    }
  }
  if( rc!=200 ){
    fossil_fatal("\"location:\" missing from 302 redirect reply");
    goto write_err;
  }

................................................................................
    fossil_fatal("server did not reply");
    goto write_err;
  }
  blob_zero(pReply);
  blob_resize(pReply, iLength);
  iLength = transport_receive(blob_buffer(pReply), iLength);
  blob_resize(pReply, iLength);














  if( g.fHttpTrace ){
    printf("HTTP RECEIVE:\n%s\n=======================\n", blob_str(pReply));
  }else{
    blob_uncompress(pReply, pReply);
  }

  /*







>







 







>







 







>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  Blob hdr;             /* The HTTP request header */
  int closeConnection;  /* True to close the connection when done */
  int iLength;          /* Length of the reply payload */
  int rc;               /* Result code */
  int iHttpVersion;     /* Which version of HTTP protocol server uses */
  char *zLine;          /* A single line of the reply header */
  int i;                /* Loop counter */
  int isError = 0;      /* True if the reply is an error message */

  if( transport_open() ){
    fossil_fatal(transport_errmsg());
  }

  /* Construct the login card and prepare the complete payload */
  blob_zero(&login);
................................................................................
  
  /*
  ** Read and interpret the server reply
  */
  closeConnection = 1;
  iLength = -1;
  while( (zLine = transport_receive_line())!=0 && zLine[0]!=0 ){
    /* printf("[%s]\n", zLine); fflush(stdout); */
    if( strncasecmp(zLine, "http/1.", 7)==0 ){
      if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
      if( rc!=200 && rc!=302 ){
        int ii;
        for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
        while( zLine[ii]==' ' ) ii++;
        fossil_fatal("server says: %s\n", &zLine[ii]);
................................................................................
      j = strlen(zLine) - 1; 
      if( j>4 && strcmp(&zLine[j-4],"/xfer")==0 ) zLine[j-4] = 0;
      fossil_print("redirect to %s\n", &zLine[i]);
      url_parse(&zLine[i]);
      transport_close();
      http_exchange(pSend, pReply, useLogin);
      return;
    }else if( strncasecmp(zLine, "content-type: text/html", 23)==0 ){
      isError = 1;
    }
  }
  if( rc!=200 ){
    fossil_fatal("\"location:\" missing from 302 redirect reply");
    goto write_err;
  }

................................................................................
    fossil_fatal("server did not reply");
    goto write_err;
  }
  blob_zero(pReply);
  blob_resize(pReply, iLength);
  iLength = transport_receive(blob_buffer(pReply), iLength);
  blob_resize(pReply, iLength);
  if( isError ){
    char *z;
    int i, j;
    z = blob_str(pReply);
    for(i=j=0; z[i]; i++, j++){
      if( z[i]=='<' ){
        while( z[i] && z[i]!='>' ) i++;
        if( z[i]==0 ) break;
      }
      z[j] = z[i];
    }
    z[j] = 0;
    fossil_fatal("server sends error: %s", z);
  }
  if( g.fHttpTrace ){
    printf("HTTP RECEIVE:\n%s\n=======================\n", blob_str(pReply));
  }else{
    blob_uncompress(pReply, pReply);
  }

  /*

Changes to src/main.c.

914
915
916
917
918
919
920

921
922
923
924
925
926
927
928
929
930
931
...
935
936
937
938
939
940
941


942
943
944
945
946
947






948
949
950
951
952
953
954
** not select a valid repository and the --notfound option is available,
** then the server redirects (HTTP code 302) to the URL of --notfound.
*/
void cmd_http(void){
  const char *zIpAddr;
  const char *zNotFound;
  zNotFound = find_option("notfound", 0, 1);

  if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
    cgi_panic("no repository specified");
  }
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  if( g.argc==6 ){
    g.httpIn = fopen(g.argv[3], "rb");
    g.httpOut = fopen(g.argv[4], "wb");
    zIpAddr = g.argv[5];
  }else{
    g.httpIn = stdin;
................................................................................
  find_server_repository(0);
  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  cgi_handle_http_request(zIpAddr);
  process_one_web_page(zNotFound);
}

/*


** COMMAND: test-http
** Works like the http command but gives setup permission to all users.
*/
void cmd_test_http(void){
  login_set_capabilities("s");
  cmd_http();






}

#ifndef __MINGW32__
#if !defined(__DARWIN__) && !defined(__APPLE__)
/*
** Search for an executable on the PATH environment variable.
** Return true (1) if found and false (0) if not found.







>

|

<







 







>
>





|
>
>
>
>
>
>







914
915
916
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
...
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
** not select a valid repository and the --notfound option is available,
** then the server redirects (HTTP code 302) to the URL of --notfound.
*/
void cmd_http(void){
  const char *zIpAddr;
  const char *zNotFound;
  zNotFound = find_option("notfound", 0, 1);
  g.cgiOutput = 1;
  if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
    fossil_fatal("no repository specified");
  }

  g.fullHttpReply = 1;
  if( g.argc==6 ){
    g.httpIn = fopen(g.argv[3], "rb");
    g.httpOut = fopen(g.argv[4], "wb");
    zIpAddr = g.argv[5];
  }else{
    g.httpIn = stdin;
................................................................................
  find_server_repository(0);
  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  cgi_handle_http_request(zIpAddr);
  process_one_web_page(zNotFound);
}

/*
** Note that the following command is used by ssh:// processing.
**
** COMMAND: test-http
** Works like the http command but gives setup permission to all users.
*/
void cmd_test_http(void){
  login_set_capabilities("s");
  g.httpIn = stdin;
  g.httpOut = stdout;
  find_server_repository(0);
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  cgi_handle_http_request(0);
  process_one_web_page(0);
}

#ifndef __MINGW32__
#if !defined(__DARWIN__) && !defined(__APPLE__)
/*
** Search for an executable on the PATH environment variable.
** Return true (1) if found and false (0) if not found.