-const char parsers_rcs[] = "$Id: parsers.c,v 1.200 2009/07/19 09:24:17 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.209 2009/09/06 14:11:06 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/parsers.c,v $
static jb_err server_keep_alive(struct client_state *csp, char **header);
static jb_err server_proxy_connection(struct client_state *csp, char **header);
static jb_err client_keep_alive(struct client_state *csp, char **header);
+static jb_err client_save_content_length(struct client_state *csp, char **header);
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
static jb_err client_host_adder (struct client_state *csp);
{ "if-modified-since:", 18, client_if_modified_since },
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
{ "Keep-Alive:", 11, client_keep_alive },
+ { "Content-Length:", 15, client_save_content_length },
#else
{ "Keep-Alive:", 11, crumble },
#endif
assert(bufsize >= skip_size);
memcpy(buf, csp->iob->buf, skip_size);
- zstr.avail_out = bufsize - skip_size;
+ zstr.avail_out = (uInt)(bufsize - skip_size);
zstr.next_out = (Bytef *)buf + skip_size;
/* Try to decompress the whole stream in one shot. */
* buffer, which may be in a location different from
* the old one.
*/
- zstr.avail_out += bufsize - oldbufsize;
+ zstr.avail_out += (uInt)(bufsize - oldbufsize);
zstr.next_out = (Bytef *)tmpbuf + bufsize - zstr.avail_out;
/*
*/
assert(zstr.avail_out == tmpbuf + bufsize - (char *)zstr.next_out);
assert((char *)zstr.next_out == tmpbuf + ((char *)oldnext_out - buf));
- assert(zstr.avail_out > 0U);
buf = tmpbuf;
}
return JB_ERR_OK;
}
+
+
+/*********************************************************************
+ *
+ * Function : get_content_length
+ *
+ * Description : Gets the content length specified in a
+ * Content-Length header.
+ *
+ * Parameters :
+ * 1 : header = The Content-Length header.
+ * 2 : length = Storage to return the value.
+ *
+ * Returns : JB_ERR_OK on success, or
+ * JB_ERR_PARSE if no value is recognized.
+ *
+ *********************************************************************/
+static jb_err get_content_length(const char *header, unsigned long long *length)
+{
+ assert(header[14] == ':');
+
+#ifdef _WIN32
+ assert(sizeof(unsigned long long) > 4);
+ if (1 != sscanf(header+14, ": %I64u", length))
+#else
+ if (1 != sscanf(header+14, ": %llu", length))
+#endif
+ {
+ return JB_ERR_PARSE;
+ }
+
+ return JB_ERR_OK;
+}
+
+
+/*********************************************************************
+ *
+ * Function : client_save_content_length
+ *
+ * Description : Save the Content-Length sent by the client.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : header = On input, pointer to header to modify.
+ * On output, pointer to the modified header, or NULL
+ * to remove the header. This function frees the
+ * original string if necessary.
+ *
+ * Returns : JB_ERR_OK on success, or
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+static jb_err client_save_content_length(struct client_state *csp, char **header)
+{
+ unsigned long long content_length = 0;
+
+ assert(*(*header+14) == ':');
+
+ if (JB_ERR_OK != get_content_length(*header, &content_length))
+ {
+ log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
+ freez(*header);
+ }
+ else
+ {
+ csp->expected_client_content_length = content_length;
+ }
+
+ return JB_ERR_OK;
+}
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
*header);
csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
}
-#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
}
- else
+ else if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE))
{
-#ifdef FEATURE_CONNECTION_KEEP_ALIVE
log_error(LOG_LEVEL_HEADER,
"Keeping the client header '%s' around. "
"The server connection will be kept alive if possible.",
*header);
csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
-#else
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+ }
+ else
+ {
char *old_header = *header;
*header = strdup(connection_close);
log_error(LOG_LEVEL_HEADER,
"Replaced: \'%s\' with \'%s\'", old_header, *header);
freez(old_header);
-#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
}
/* Signal client_connection_adder() to return early. */
assert(*(*header+14) == ':');
-#ifdef _WIN32
- if (1 != sscanf(*header+14, ": %I64u", &content_length))
-#else
- if (1 != sscanf(*header+14, ": %llu", &content_length))
-#endif
+ if (JB_ERR_OK != get_content_length(*header, &content_length))
{
log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
freez(*header);
* Function : server_set_cookie
*
* Description : Handle the server "cookie" header properly.
- * Log cookie to the jar file. Then "crunch",
- * accept or rewrite it to a session cookie.
+ * Crunch, accept or rewrite it to a session cookie.
* Called from `sed'.
*
* TODO: Allow the user to specify a new expiration
{
char *expiration_date = cur_tag + 8; /* Skip "[Ee]xpires=" */
+ if ((expiration_date[0] == '"')
+ && (expiration_date[1] != '\0'))
+ {
+ /*
+ * Skip quotation mark. RFC 2109 10.1.2 seems to hint
+ * that the expiration date isn't supposed to be quoted,
+ * but some servers do it anyway.
+ */
+ expiration_date++;
+ }
+
/* Did we detect the date properly? */
if (JB_ERR_OK != parse_header_time(expiration_date, &cookie_time))
{