Пример #1
0
			LEX_SINGLE('{', TOK_LBRACE)
			LEX_SINGLE('}', TOK_RBRACE)
			LEX_SINGLE('[', TOK_LBRACKET)
			LEX_SINGLE(']', TOK_RBRACKET)
			LEX_SINGLE(',', TOK_COMMA)
			LEX_SINGLE(';', TOK_SEMICOLON)
			LEX_SINGLE('=', TOK_EQ)
			else {
				LONInputRead(state->input);
			}
			break;
		case LEX_NAME:
			if (isalpha(c)) {
				LEX_EAT_ONE()
			} else {
				if (strcmp(BUF_STR(t->buf), "true") == 0) {
					t->type = TOK_TRUE;
				} else if (strcmp(BUF_STR(t->buf), "false") == 0) {
					t->type = TOK_FALSE;
				} else if (strcmp(BUF_STR(t->buf), "nil") == 0) {
					t->type = TOK_NULL;
				} else {
					t->type = TOK_NAME;
				}
				state->type = LEX_DEFAULT;
			}
			break;
		case LEX_STRING:
			if (c != '"') {
				LEX_EAT_ONE()
			} else {
Пример #2
0
static handler_t proxy_http_parse_chunked_stream(server *srv, proxy_session *sess, chunkqueue *in, chunkqueue *out) {
	protocol_state_data *data = (protocol_state_data *)sess->proxy_con->protocol_data;
	char *err = NULL;
	off_t we_have = 0, we_want = 0;
	off_t chunk_len = 0;
	off_t offset = 0;
	buffer *b;
	chunk *c;
	char ch = '\0';
	int finished = 0;

	UNUSED(srv);

	for (c = in->first; c && !finished;) {
		if(c->mem->used == 0) {
			c = c->next;
			continue;
		}
		switch(data->chunk_parse_state) {
		case HTTP_CHUNK_LEN:
			/* parse chunk len. */
			for(offset = c->offset; (size_t)(offset) < (c->mem->used - 1) ; offset++) {
				ch = c->mem->ptr[offset];
				if(!light_isxdigit(ch)) break;
			}
			if(offset > c->offset) {
				buffer_append_string_len(data->buf, (c->mem->ptr + c->offset), offset - c->offset);
				in->bytes_out += (offset - c->offset);
				c->offset = offset;
			}
			if (!(ch == ' ' || ch == '\r' || ch == ';')) {
				if (ch == '\0') {
					/* get next chunk from queue */
					break;
				}
				/* protocol error.  bad http-chunk len */
				return HANDLER_ERROR;
			}
			data->chunk_len = strtol(BUF_STR(data->buf), &err, 16);
			data->chunk_offset = 0;
			buffer_reset(data->buf);
			data->chunk_parse_state = HTTP_CHUNK_EXTENSION;
		case HTTP_CHUNK_EXTENSION:
			/* find CRLF.  discard chunk-extension */
			for(ch = 0; (size_t)(c->offset) < (c->mem->used - 1) && ch != '\n' ;) {
				ch = c->mem->ptr[c->offset];
				c->offset++;
				in->bytes_out++;
			}
			if(ch != '\n') {
				/* get next chunk from queue */
				break;
			}
			if(data->chunk_len > 0) {
				data->chunk_parse_state = HTTP_CHUNK_DATA;
			} else {
				data->chunk_parse_state = HTTP_CHUNK_END;
			}
		case HTTP_CHUNK_DATA:
			chunk_len = data->chunk_len - data->chunk_offset;
			/* copy chunk_len bytes from in queue to out queue. */
			we_have = c->mem->used - c->offset - 1;
			we_want = chunk_len > we_have ? we_have : chunk_len;

			if (c->offset == 0 && we_want == we_have) {
				/* we are copying the whole buffer, just steal it */
				chunkqueue_steal_chunk(out, c);
				/* c is an empty chunk now */
			} else {
				b = chunkqueue_get_append_buffer(out);
				buffer_copy_string_len(b, c->mem->ptr + c->offset, we_want);
				c->offset += we_want;
			}

			chunk_len -= we_want;
			out->bytes_in += we_want;
			in->bytes_out += we_want;
			data->chunk_offset += we_want;
			if(chunk_len > 0) {
				/* get next chunk from queue */
				break;
			}
			data->chunk_offset = 0;
			data->chunk_parse_state = HTTP_CHUNK_END;
		case HTTP_CHUNK_END:
			/* discard CRLF.*/
			for(ch = 0; c->mem->used > 0 && (size_t)(c->offset) < (c->mem->used - 1) && ch != '\n' ;) {
				ch = c->mem->ptr[c->offset];
				c->offset++;
				in->bytes_out++;
			}
			if(ch != '\n') {
				/* get next chunk from queue */
				break;
			}
			/* final chunk */
			if(data->chunk_len == 0) {
				finished = 1;
			}
			/* finished http-chunk.  reset and parse next chunk. */
			protocol_state_data_reset(data);
			break;
		}
		if((size_t)(c->offset) == c->mem->used - 1) {
			c = c->next;
		}
	}
	chunkqueue_remove_finished_chunks(in);
	if (finished) {
		sess->is_request_finished = 1;
		return HANDLER_FINISHED;
	}
	/* ran out of data. */
	return HANDLER_GO_ON;
}
Пример #3
0
int http_response_handle_cachable(server *srv, connection *con, buffer *mtime, buffer *etag) {
	data_string *http_if_none_match;
	data_string *http_if_modified_since;

	UNUSED(srv);

	/*
	 * 14.26 If-None-Match
	 *    [...]
	 *    If none of the entity tags match, then the server MAY perform the
	 *    requested method as if the If-None-Match header field did not exist,
	 *    but MUST also ignore any If-Modified-Since header field(s) in the
	 *    request. That is, if no entity tags match, then the server MUST NOT
	 *    return a 304 (Not Modified) response.
	 */

	http_if_none_match = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("if-none-match"));
	http_if_modified_since = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("if-modified-since"));

	/* last-modified handling */
	if (http_if_none_match) {
		if (etag_is_equal(etag, BUF_STR(http_if_none_match->value))) {
			if (con->request.http_method == HTTP_METHOD_GET ||
			    con->request.http_method == HTTP_METHOD_HEAD) {

				/* check if etag + last-modified */
				if (http_if_modified_since) {
					size_t used_len;
					char *semicolon;

					if (NULL == (semicolon = strchr(BUF_STR(http_if_modified_since->value), ';'))) {
						used_len = http_if_modified_since->value->used - 1;
					} else {
						used_len = semicolon - BUF_STR(http_if_modified_since->value);
					}

					if (0 == strncmp(BUF_STR(http_if_modified_since->value), mtime->ptr, used_len)) {
						if ('\0' == mtime->ptr[used_len]) con->http_status = 304;
						return HANDLER_FINISHED;
					} else {
#ifdef HAVE_STRPTIME
						char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
						time_t t_header, t_file;
						struct tm tm;

						/* check if we can safely copy the string */
						if (used_len >= sizeof(buf)) {
							TRACE("last-mod check failed as timestamp was too long: %s: %zu, %zu",
									SAFE_BUF_STR(http_if_modified_since->value),
									used_len, sizeof(buf) - 1);

							con->http_status = 412;
							return HANDLER_FINISHED;
						}


						strncpy(buf, BUF_STR(http_if_modified_since->value), used_len);
						buf[used_len] = '\0';

						if (NULL == strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm)) {
							con->http_status = 412;
							return HANDLER_FINISHED;
						}
						tm.tm_isdst = 0;
						t_header = mktime(&tm);

						strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
						tm.tm_isdst = 0;
						t_file = mktime(&tm);

						if (t_file > t_header) return HANDLER_GO_ON;

						con->http_status = 304;
						return HANDLER_FINISHED;
#else
						return HANDLER_GO_ON;
#endif
					}
				} else {
					con->http_status = 304;
					return HANDLER_FINISHED;
				}
			} else {
				con->http_status = 412;
				return HANDLER_FINISHED;
			}
		}
	} else if (http_if_modified_since) {
		size_t used_len;
		char *semicolon;

		if (NULL == (semicolon = strchr(BUF_STR(http_if_modified_since->value), ';'))) {
			used_len = http_if_modified_since->value->used - 1;
		} else {
			used_len = semicolon - BUF_STR(http_if_modified_since->value);
		}

		if (0 == strncmp(BUF_STR(http_if_modified_since->value), mtime->ptr, used_len)) {
			if ('\0' == mtime->ptr[used_len]) con->http_status = 304;
			return HANDLER_FINISHED;
		} else {
#ifdef HAVE_STRPTIME
			char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
			time_t t_header, t_file;
			struct tm tm;

			/* convert to timestamp */
			if (used_len >= sizeof(buf)) return HANDLER_GO_ON;

			strncpy(buf, BUF_STR(http_if_modified_since->value), used_len);
			buf[used_len] = '\0';

			if (NULL == strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm)) {
				return HANDLER_GO_ON;
			}
			tm.tm_isdst = 0;
			t_header = mktime(&tm);

			strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
			tm.tm_isdst = 0;
			t_file = mktime(&tm);

			if (t_file > t_header) return HANDLER_GO_ON;

			con->http_status = 304;
			return HANDLER_FINISHED;
#else
            return HANDLER_GO_ON;
#endif
		}
	}

	return HANDLER_GO_ON;
}