-const char cgi_rcs[] = "$Id: cgi.c,v 1.17 2001/08/05 15:57:38 oes Exp $";
+const char cgi_rcs[] = "$Id: cgi.c,v 1.20 2001/09/13 23:40:36 jongfoster Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/cgi.c,v $
*
* Revisions :
* $Log: cgi.c,v $
+ * Revision 1.20 2001/09/13 23:40:36 jongfoster
+ * (Cosmetic only) Indentation correction
+ *
+ * Revision 1.19 2001/09/13 23:31:25 jongfoster
+ * Moving image data to cgi.c rather than cgi.h.
+ *
+ * Revision 1.18 2001/08/05 16:06:20 jongfoster
+ * Modifiying "struct map" so that there are now separate header and
+ * "map_entry" structures. This means that functions which modify a
+ * map no longer need to return a pointer to the modified map.
+ * Also, it no longer reverses the order of the entries (which may be
+ * important with some advanced template substitutions).
+ *
* Revision 1.17 2001/08/05 15:57:38 oes
* Adapted finish_http_response to new list_to_text
*
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
+#include <assert.h>
#ifdef _WIN32
#define snprintf _snprintf
};
+/*
+ * Some images
+ *
+ * Hint: You can encode your own GIFs like that:
+ * perl -e 'while (read STDIN, $c, 1) { printf("\\%.3o,", unpack("C", $c)); }'
+ */
+
+const char image_junkbuster_gif_data[] =
+ "GIF89aD\000\013\000\360\000\000\000\000\000\377\377\377!"
+ "\371\004\001\000\000\001\000,\000\000\000\000D\000\013\000"
+ "\000\002a\214\217\251\313\355\277\000\200G&K\025\316hC\037"
+ "\200\234\230Y\2309\235S\230\266\206\372J\253<\3131\253\271"
+ "\270\215\342\254\013\203\371\202\264\334P\207\332\020o\266"
+ "N\215I\332=\211\312\3513\266:\026AK)\364\370\365aobr\305"
+ "\372\003S\275\274k2\354\254z\347?\335\274x\306^9\374\276"
+ "\037Q\000\000;";
+
+const int image_junkbuster_gif_length = sizeof(image_junkbuster_gif_data) - 1;
+
+
+const char image_blank_gif_data[] =
+ "GIF89a\001\000\001\000\200\000\000\377\377\377\000\000"
+ "\000!\371\004\001\000\000\000\000,\000\000\000\000\001"
+ "\000\001\000\000\002\002D\001\000;";
+
+const int image_blank_gif_length = sizeof(image_blank_gif_data) - 1;
+
+
/*********************************************************************
*
* Function : dispatch_cgi
{
if(strcmp(lookup(parameters, "type"), "trans"))
{
- rsp->body = bindup(JBGIF, sizeof(JBGIF) - 1);
- rsp->content_length = sizeof(JBGIF) - 1;
+ rsp->body = bindup(image_junkbuster_gif_data, image_junkbuster_gif_length);
+ rsp->content_length = image_junkbuster_gif_length;
}
else
{
- rsp->body = bindup(BLANKGIF, sizeof(BLANKGIF) - 1);
- rsp->content_length = sizeof(BLANKGIF) - 1;
+ rsp->body = bindup(image_blank_gif_data, image_blank_gif_length);
+ rsp->content_length = image_blank_gif_length;
}
enlist(rsp->headers, "Content-Type: image/gif");
+ rsp->is_static = 1;
return(0);
return NULL;
}
- map(exports, "host-html", 1, html_encode(csp->http->host), 0);
- map(exports, "hostport", 1, csp->http->hostport, 1);
- map(exports, "hostport-html", 1, html_encode(csp->http->hostport), 0);
- map(exports, "path", 1, csp->http->path, 1);
- map(exports, "path-html", 1, html_encode(csp->http->path), 0);
- map(exports, "error", 1, safe_strerror(err), 0);
- map(exports, "host-ip", 1, csp->http->host_ip_addr_str, 1);
+ map(exports, "host-html", 1, html_encode(csp->http->host), 0);
+ map(exports, "hostport", 1, csp->http->hostport, 1);
+ map(exports, "hostport-html", 1, html_encode(csp->http->hostport), 0);
+ map(exports, "path", 1, csp->http->path, 1);
+ map(exports, "path-html", 1, html_encode(csp->http->path), 0);
+ map(exports, "error", 1, safe_strerror(err), 0);
+ map(exports, "host-ip", 1, csp->http->host_ip_addr_str, 1);
- rsp->body = fill_template(csp, templatename, exports);
- free_map(exports);
-
- if (!strcmp(templatename, "no-such-domain"))
- {
- rsp->status = strdup("404 No such domain");
- }
- else if (!strcmp(templatename, "connect-failed"))
- {
- rsp->status = strdup("503 Connect failed");
- }
+ rsp->body = fill_template(csp, templatename, exports);
+ free_map(exports);
+
+ if (!strcmp(templatename, "no-such-domain"))
+ {
+ rsp->status = strdup("404 No such domain");
+ }
+ else if (!strcmp(templatename, "connect-failed"))
+ {
+ rsp->status = strdup("503 Connect failed");
+ }
+
+ return(finish_http_response(rsp));
+}
+
+
+/*********************************************************************
+ *
+ * Function : get_http_time
+ *
+ * Description : Get the time in a format suitable for use in a
+ * HTTP header - e.g.:
+ * "Sun, 06 Nov 1994 08:49:37 GMT"
+ *
+ * Parameters :
+ * 1 : time_offset = Time returned will be current time
+ * plus this number of seconds.
+ * 2 : buf = Destination for result. Must be long enough
+ * to hold 29 characters plus a trailing zero.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void get_http_time(int time_offset, char * buf)
+{
+ static const char day_names[7][4] =
+ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+ static const char month_names[12][4] =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+ struct tm *t;
+ time_t current_time;
+
+ assert(buf);
+
+ time(¤t_time); /* get current time */
- return(finish_http_response(rsp));
+/* FIXME: is this needed? time() can't fail on Win32. What about Linux?
+ if(current_time <= 0)
+ {
+ return NULL;
+ }
+*/
+
+ current_time += time_offset;
+
+ /* get and save the gmt */
+ t = gmtime(¤t_time);
+
+ /* Format: "Sun, 06 Nov 1994 08:49:37 GMT" */
+ snprintf(buf, 30,
+ "%s, %02d %s %4d %02d:%02d:%02d GMT",
+ day_names[t->tm_wday],
+ t->tm_mday,
+ month_names[t->tm_mon],
+ t->tm_year + 1900,
+ t->tm_hour,
+ t->tm_min,
+ t->tm_sec
+ );
+ buf[32] = '\0';
}
enlist(rsp->headers, buf);
/*
- * Fill in the default headers FIXME: Are these correct? sequence OK? check rfc!
- * FIXME: Should have:
- * "JunkBuster" GIF: Last-Modified: any *fixed* date in the past (as now).
- * Expires: 5 minutes after the time when reply sent
- * CGI, "blocked", & all other requests:
- * Last-Modified: Time when reply sent
- * Expires: Time when reply sent
- * "Cache-Control: no-cache"
- *
+ * Fill in the default headers:
+ *
+ * Content-Type: default to text/html if not already specified.
+ * Date: set to current date/time.
+ * Last-Modified: set to date/time the page was last changed.
+ * Expires: set to date/time page next needs reloading.
+ * Cache-Control: set to "no-cache" if applicable.
+ *
* See http://www.w3.org/Protocols/rfc2068/rfc2068
*/
- enlist_unique(rsp->headers, "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT", 14);
- enlist_unique(rsp->headers, "Expires: Thu Jul 31, 1997 07:42:22 pm GMT", 8);
enlist_unique(rsp->headers, "Content-Type: text/html", 13);
+ if (rsp->is_static)
+ {
+ /*
+ * Set Expires to about 10 min into the future so it'll get reloaded
+ * occasionally, e.g. if IJB gets upgraded.
+ */
+
+ get_http_time(0, buf);
+ enlist_unique_header(rsp->headers, "Date", buf);
+
+ /* Some date in the past. */
+ enlist_unique_header(rsp->headers, "Last-Modified", "Sat, 17 Jun 2000 12:00:00 GMT");
+
+ get_http_time(10 * 60, buf); /* 10 * 60sec = 10 minutes */
+ enlist_unique_header(rsp->headers, "Expires", buf);
+ }
+ else
+ {
+ /*
+ * Compliant browsers should not cache this due to the "Cache-Control"
+ * setting. However, to be certain, we also set both "Last-Modified"
+ * and "Expires" to the current time.
+ */
+ enlist_unique_header(rsp->headers, "Cache-Control", "no-cache");
+ get_http_time(0, buf);
+ enlist_unique_header(rsp->headers, "Date", buf);
+ enlist_unique_header(rsp->headers, "Last-Modified", buf);
+ enlist_unique_header(rsp->headers, "Expires", buf);
+ }
+
/*
* Write the head
return(rsp);
}
-
+
/*********************************************************************
*