Fossil

Diff
Login

Differences From Artifact [2bc2c40803]:

To Artifact [6b1a464fb2]:


25
26
27
28
29
30
31
32
33
34
35




36
37
38
39
40
41
42
43







44
45
46

47
48
49
50
51
52
53
25
26
27
28
29
30
31




32
33
34
35
36







37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
+







** services to CGI programs.  There are procedures for parsing and
** dispensing QUERY_STRING parameters and cookies, the "mprintf()"
** formatting function and its cousins, and routines to encode and
** decode strings in HTML or HTTP.
*/
#include "config.h"
#ifdef __MINGW32__
#  include <windows.h>           /* for Sleep once server works again */
#  include <winsock2.h>          /* socket operations */
#  define sleep Sleep            /* windows does not have sleep, but Sleep */
#  include <ws2tcpip.h>          
# include <windows.h>           /* for Sleep once server works again */
# include <winsock2.h>          /* socket operations */
# define sleep Sleep            /* windows does not have sleep, but Sleep */
# include <ws2tcpip.h>          
#else
#  include <sys/socket.h>
#  include <netinet/in.h>
#  include <arpa/inet.h>
#  include <sys/times.h>
#  include <sys/time.h>
#  include <sys/wait.h>
#  include <sys/select.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/times.h>
# include <sys/time.h>
# include <sys/wait.h>
# include <sys/select.h>
#endif
#ifdef __EMX__
   typedef int socklen_t;
  typedef int socklen_t;
#endif
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "cgi.h"

193
194
195
196
197
198
199
200
201
202
203
204
205


206
207
208
209
210
211
212
213
193
194
195
196
197
198
199

200

201


202
203

204
205
206
207
208
209
210







-

-

-
-
+
+
-







  const char *zName,    /* Name of the cookie */
  const char *zValue,   /* Value of the cookie.  Automatically escaped */
  const char *zPath,    /* Path cookie applies to.  NULL means "/" */
  int lifetime          /* Expiration of the cookie in seconds from now */
){
  if( zPath==0 ) zPath = g.zTop;
  if( lifetime>0 ){
    char *zDate;
    lifetime += (int)time(0);
    zDate = cgi_rfc822_datestamp(lifetime);
    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; expires=%s; Version=1\r\n",
        zName, zValue, zPath, zDate);
       "Set-Cookie: %s=%t; Path=%s; expires=%z; Version=1\r\n",
        zName, zValue, zPath, cgi_rfc822_datestamp(lifetime));
    if( zDate[0] ) free( zDate );
  }else{
    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; Version=1\r\n",
       zName, zValue, zPath);
  }
}

264
265
266
267
268
269
270
271

272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330


331
332
333
334
335
336
337
261
262
263
264
265
266
267

268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

286

287

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307


308

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332







-
+

















-

-
+
-




















-
-
+
-















+
+







}
#endif

/*
** Do a normal HTTP reply
*/
void cgi_reply(void){
  int total_size = 0;
  int total_size;
  if( iReplyStatus<=0 ){
    iReplyStatus = 200;
    zReplyStatus = "OK";
  }

#if 0
  if( iReplyStatus==200 && check_cache_control() ) {
    /* change the status to "unchanged" and we can skip sending the
    ** actual response body. Obviously we only do this when we _have_ a
    ** body (code 200).
    */
    iReplyStatus = 304;
    zReplyStatus = "Not Modified";
  }
#endif

  if( g.fullHttpReply ){
    char *zDate = cgi_rfc822_datestamp(time(0));
    fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
    fprintf(g.httpOut, "Date: %s\r\n", zDate );
    fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
    if( zDate[0] ) free( zDate );
    fprintf(g.httpOut, "Connection: close\r\n");
  }else{
    fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
  }

  if( blob_size(&extraHeader)>0 ){
    fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
  }

  if( g.isConst ){
    /* constant means that the input URL will _never_ generate anything
    ** else. In the case of attachments, the contents won't change because
    ** an attempt to change them generates a new attachment number. In the
    ** case of most /getfile calls for specific versions, the only way the
    ** content changes is if someone breaks the SCM. And if that happens, a
    ** stale cache is the least of the problem. So we provide an Expires
    ** header set to a reasonable period (default: one week).
    */
    /*time_t expires = time(0) + atoi(db_config("constant_expires","604800"));*/
    time_t expires = time(0) + 604800;
    char * zDate = cgi_rfc822_datestamp(expires);
    fprintf(g.httpOut, "Expires: %s\r\n", zDate );
    fprintf(g.httpOut, "Expires: %s\r\n", cgi_rfc822_datestamp(expires));
    if( zDate[0] ) free( zDate );
  }

  /* Content intended for logged in users should only be cached in
  ** the browser, not some shared location.
  */
  fprintf(g.httpOut, "Cache-control: no-cache, no-store\r\n");
  fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
  if( strcmp(zContentType,"application/x-fossil")==0 ){
    cgi_combine_header_and_body();
    blob_compress(&cgiContent[0], &cgiContent[0]);
  }

  if( iReplyStatus != 304 ) {
    total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
    fprintf(g.httpOut, "Content-Length: %d\r\n", total_size);
  }else{
    total_size = 0;
  }
  fprintf(g.httpOut, "\r\n");
  if( total_size>0 && iReplyStatus != 304 ){
    int i, size;
    for(i=0; i<2; i++){
      size = blob_size(&cgiContent[i]);
      if( size>0 ){
1285
1286
1287
1288
1289
1290
1291
1292

1293
1294
1295
1296



1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307







1308
1309
1310
1311
1312
1313
1314
1280
1281
1282
1283
1284
1285
1286

1287




1288
1289
1290
1291
1292
1293
1294
1295
1296
1297




1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311







-
+
-
-
-
-
+
+
+







-
-
-
-
+
+
+
+
+
+
+







    {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0};
static const char *azMonths[] =
    {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};


/*
** Returns an RFC822-formatted time string suitable for HTTP headers, among
** Returns an RFC822-formatted time string suitable for HTTP headers.
** other things.
** Returned timezone is always GMT as required by HTTP/1.1 specification.
** The returned string is allocated with malloc() and must be freed
** with free().
** The timezone is always GMT.  The value returned is always a
** string obtained from mprintf() and must be freed using free() to
** avoid a memory leak.
**
** See http://www.faqs.org/rfcs/rfc822.html, section 5
** and http://www.faqs.org/rfcs/rfc2616.html, section 3.3.
*/
char *cgi_rfc822_datestamp(time_t now){
  struct tm *pTm;
  pTm = gmtime(&now);
  if( pTm==0 ) return "";
  return mprintf("%s, %d %s %02d %02d:%02d:%02d GMT",
                 azDays[pTm->tm_wday], pTm->tm_mday, azMonths[pTm->tm_mon],
                 pTm->tm_year+1900, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
  if( pTm==0 ){
    return mprintf("");
  }else{
    return mprintf("%s, %d %s %02d %02d:%02d:%02d GMT",
                   azDays[pTm->tm_wday], pTm->tm_mday, azMonths[pTm->tm_mon],
                   pTm->tm_year+1900, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
  }
}

/*
** Parse an RFC822-formatted timestamp as we'd expect from HTTP and return
** a Unix epoch time. <= zero is returned on failure.
**
** Note that this won't handle all the _allowed_ HTTP formats, just the