📄 parse.c
字号:
/*Copyright (c) 2002-2003 Nicolas Jombart - HSCRedistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditionsare met:1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ORIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIESOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUTNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANYTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OFTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*//* * parsing functions : * - decode WSP packet (almost only interesting fields * for us) * - make the HTTP reply * * $Id: parse.c,v 1.22 2004/09/08 09:33:56 jombart Exp $ * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "wspp.h"/* * Parse proxy request */int parse_req (request *req, char *line) {int i, k;char tmp[16]; /* houuu */ if(req->parse_state == PARSE_TODO) { /* init */ req->content_length = 0; req->data_length = 0; req->headers = NULL; req->data = NULL; /* extract METHOD */ if( !strncmp(line, "GET ", 4) ) { req->method = WSP_GET; k = 4; } else if( !strncmp(line, "DELETE ", 7) ) { req->method = WSP_DELETE; k = 7; } else if( !strncmp(line, "OPTIONS ", 8) ) { req->method = WSP_OPTIONS; k = 8; } else if( !strncmp(line, "PUT ", 4) ) { req->method = WSP_PUT; k = 4; } else if( !strncmp(line, "HEAD ", 5) ) { req->method = WSP_HEAD; k = 5; } else if( !strncmp(line, "POST ", 5) ) { req->method = WSP_POST; k = 5; } else if( !strncmp(line, "TRACE ", 6) ) { req->method = WSP_TRACE; k = 6; } else { req->parse_state = PARSE_ERROR; return -1; } /* extract URI */ for(i = k; line[i] != '\x20' && i < strlen(line); i++); req->uri = (char *) malloc(i-k+1); memset(req->uri, 0, i-k+1); memcpy(req->uri, line + k, i - k); /* FIXME: We ignore HTTP Version */ req->parse_state = PARSE_HEADER_TODO; return 1; } if(req->parse_state == PARSE_HEADER_TODO) { /* Skip hardcoded ignored headers */ if( !strncasecmp(line, "User-Agent:", 11) ) {#ifdef DEBUG printf("Ignored header (replaced) : %s \n", line);#endif return 1; } if( !strncasecmp(line, "Content-Length:", 15) ) { k = 0; for(i = 16; line[i] && isdigit(line[i]) && k<16; tmp[k++] = line[i++]); tmp[k] = '\0'; req->content_length = atoi(tmp); return 1; } /* header to transmit to gateway */ req->headers = restrcat(req->headers, line); return 1; } return 0;}/* * Parse WSP reply packet and fill in structure */int parse_wsp (wsp_reply *reply, unsigned char *packet, int size) {int p, e, offset, i, head, textual, ctype_length, c;char header_tmp[256];char header_name[256];char header_value[256]; memset((void *)reply, 0, sizeof(reply)); head = 0; offset = 0; reply->headers = NULL; /* reply ? */ if(packet[1] != PDU_REPLY) { reply->status = HTTP_ERROR_CODE; reply->header_length = 0; reply->data_length = 0; reply->contenttype = 0x02; return -1; } ++head; /* status code */ reply->status = http_code(packet[2]);/* if(packet[2] != WSP_OK) { return 0; }*/ ++head; reply->header_length = from_uintvar(packet, 3, 8);#ifdef DEBUG printf("Header length from packet : %d\n", reply->header_length);#endif /* Content-Type code */ offset = uintvar_len(reply->header_length); head += offset; c = packet[offset+3]; if((c > 40) && (c < 0x7f)) { //printf("Textual content-type\n"); reply->contenttype = 0xFF; /* internal value because conversion is done later */ reply->contenttype_string = strdup(packet + offset + 3); for(i = offset+3; packet[i]; i++) /*{ printf("%c", packet[i])*/;/* }*/ head += i - (offset + 3) + 1/*- 1*/ ; ctype_length= strlen(reply->contenttype_string) + 1; } else if (c >= 0x80) { //printf("one char content-type\n"); reply->contenttype = c & 0x7f; ctype_length = 1; head += 1; } else if (c<= 40) { /* first byte = len */ //printf("content-type coded with %d bytes\n", c); ctype_length = c; head += c + 1; reply->contenttype = packet[offset+4] & 0x7f; if((c == 3) && (packet[offset+5] == 0x81)) { /* charset */ reply->charset = packet[offset+6] & 0x7f; } } else { /* should never occur */ ctype_length = 0; }#ifdef DEBUG printf("Content-type : 0x%x (%s)", reply->contenttype, contentt(reply->contenttype)); if(reply->contenttype == 0xFF) { printf(" (%s) \n", reply->contenttype_string); } else { printf("\n"); }#endif i = head + 1; //printf("limite = %d\n", head + (reply->header_length - ctype_length)); while(i < head + (reply->header_length - ctype_length)) { e = packet[i] & 0x7f; /* field name */ textual = 0; if((e >= 0x42) && (e <= 0x7f)) { /* XXX */ /* textual name */ strlcpy(header_name, packet + i, 256); offset = strlen(packet+i) + 1; textual = 1; /* textual names MUST be followed by textual value */ } else { strlcpy(header_name, header(e), 256); offset = 1; }#ifdef DEBUG printf("parsing header %s\n", header_name);#endif i += offset; p = (int) packet[i]; /* first octet of field value */ //printf("First octet of value : 0x%x ... ", p); /* endodings */ if((textual == 1) || ((p >= 32) && (p <= 127))) { /* Null terminated text string */ //printf("textual\n"); strlcpy(header_value, packet+i, 256); i += 1 + strlen(packet+i); } if(p <= 30) { /* followed by indicated number of data octets */ //printf("followed by indicated number of data octets \n"); if((e == 0x12) || (e == 0x1d) || (e == 0x14)) { /* date */ snprintf(header_value, 256, "%s", extime(packet + i + 1, p)); } else if (e == 0x0d) { /* Content-Length : we recompute it later */ i += 1 + p; continue; } else { strlcpy(header_value, packet+i, p); /* always < 256 */ } i += 1 + p; } if(p == 31) { /* uintvar */ //printf("unintvar\n"); snprintf(header_value, 256, "%d", from_uintvar(packet, i+1, 8)); i += 1 + (from_uintvar(packet, i+1, 8) / 0x7f) + 1; } if(p > 127) { /* encoded 7bit value, no more data*/ //printf("Encoded 7-bit value\n"); /* Ignore Content-Length */ if(e == 0x0d) { i += 1; continue; } /* common headers which spec gives specific encoding info (8.4.2.X) */ switch(e) { /* common headers */ case 0x04: /* Accept-Range */ switch(p) { case 128: strlcpy(header_value, "None", 256); break; case 129: strlcpy(header_value, "bytes", 256); break; default: strlcpy(header_value, "Unknown", 256); } break; case 0x08: /* Cache-Control */ switch(p) { case 128: strlcpy(header_value, "no-cache", 256); break; case 129: strlcpy(header_value, "no-store", 256); break; case 130: strlcpy(header_value, "max-age", 256); break; case 131: strlcpy(header_value, "max-stale", 256); break; case 132: strlcpy(header_value, "min-fresh", 256); break; case 133: strlcpy(header_value, "only-if-cached", 256); break; case 134: strlcpy(header_value, "public", 256); break; case 135: strlcpy(header_value, "private", 256); break; case 136: strlcpy(header_value, "no-transform", 256); break; case 137: strlcpy(header_value, "must-revalidate", 256); break; case 138: strlcpy(header_value, "proxy-revalidate", 256); break; case 139: strlcpy(header_value, "s-maxage", 256); break; default: strlcpy(header_value, "Unknown", 256); } break; case 0x0c: /* Content-Language */ switch(p) { /* FIXME : arbitrary langages, should implement ISO 639 */ case 0x19: strlcpy(header_value, "en", 256); break; case 0x1B: strlcpy(header_value, "es", 256); break; case 0x22: strlcpy(header_value, "fr", 256); break; case 0x5F: strlcpy(header_value, "ru", 256); break; case 0x16: strlcpy(header_value, "de", 256); break; case 0x36: strlcpy(header_value, "ja", 256); break; case 0x70: strlcpy(header_value, "sv", 256); break; case 0x12: strlcpy(header_value, "co", 256); break; default: strlcpy(header_value, "en", 256); } break; case 0x2a: /* Vary */ switch(p) { case 0xa9: strlcpy(header_value, "User-Agent", 256); break; default: strlcpy(header_value, "Unknown", 256); } break; default: /* fall-back */ snprintf(header_value, 256, "%d", p & 0x7f); } i += 1; } /* store Name: Value */ snprintf(header_tmp, 256, "%s: %s", header_name, header_value); reply->headers = restrcat(reply->headers, header_tmp);} /* datas */ reply->data_length = size - i; reply->data = (char *) malloc(reply->data_length); memcpy(reply->data, packet + i, reply->data_length); return 0;}/* * WSP to HTTP structure */void wsp_to_http (http *body, const wsp_reply *wsp_packet) { char tmp[69]; body->headers = NULL; strlcpy(tmp, expand_http_code(wsp_packet->status), 69); body->headers = restrcat(body->headers, tmp); /* Content-Type */ sprintf(tmp, "Content-Type: %s", wsp_packet->contenttype == 0xFF ? wsp_packet->contenttype_string : contentt(wsp_packet->contenttype)); body->headers = restrcat(body->headers, tmp); /* Content-Length */ sprintf(tmp, "Content-Length: %d", wsp_packet->data_length); body->headers = restrcat(body->headers, tmp); /* Our Via: */ body->headers = restrcat(body->headers, HEADER_VIA); /* headers from gateway */ body->headers = restrcat(body->headers, wsp_packet->headers); /* \n */ body->headers = restrcat(body->headers, "\n"); /* Body */ body->data_length = wsp_packet->data_length; body->data = (char *) malloc(wsp_packet->data_length * sizeof(char)); memcpy(body->data, wsp_packet->data, wsp_packet->data_length);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -