2
0
Эх сурвалжийг харах

functions for parsing content_type and content_length added.

Bogdan-Andrei Iancu 23 жил өмнө
parent
commit
ec147e2e5c

+ 5 - 1
parser/hf.c

@@ -59,7 +59,7 @@ void clean_hdr_field(struct hdr_field* hf)
 			free_cseq(hf->parsed);
 			break;
 
-                case HDR_AUTHORIZATION:
+		case HDR_AUTHORIZATION:
 		case HDR_PROXYAUTH:
 			free_credentials((auth_body_t**)(&(hf->parsed)));
 			break;
@@ -80,6 +80,10 @@ void clean_hdr_field(struct hdr_field* hf)
 			free_contact((contact_body_t**)(&(hf->parsed)));
 			break;
 
+		case HDR_CONTENTLENGTH:
+		case HDR_CONTENTTYPE:
+			break;
+
 		default:
 			LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",
 			    hf->type);

+ 44 - 22
parser/msg_parser.c

@@ -43,6 +43,7 @@
 #include "../globals.h"
 #include "parse_hname2.h"
 #include "parse_uri.h"
+#include "parse_content.h"
 
 #ifdef DEBUG_DMALLOC
 #include <mem/dmalloc.h>
@@ -64,6 +65,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 	struct via_body *vb;
 	struct cseq_body* cseq_b;
 	struct to_body* to_b;
+	int integer;
 
 	if ((*buf)=='\n' || (*buf)=='\r'){
 		/* double crlf or lflf or crcr */
@@ -139,24 +141,44 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 				hdr->name.s, hdr->body.len, to_b->uri.len,to_b->uri.s);
 			DBG("DEBUG: to body [%.*s]\n",to_b->body.len,to_b->body.s);
 			break;
+		case HDR_CONTENTLENGTH:
+			hdr->body.s=tmp;
+			tmp=parse_content_length(tmp,end, &integer);
+			if (tmp==0){
+				LOG(L_ERR, "ERROR:get_hdr_field: bad content_length header\n");
+				goto error;
+			}
+			hdr->parsed=(void*)integer;
+			hdr->body.len=tmp-hdr->body.s;
+			DBG("DEBUG: get_hdr_body : content_length=%d\n",(int)hdr->parsed);
+			break;
+		case HDR_CONTENTTYPE:
+			hdr->body.s=tmp;
+			tmp=parse_content_type(tmp,end, &integer);
+			if (tmp==0){
+				LOG(L_ERR, "ERROR:get_hdr_field: bad content_type header\n");
+				goto error;
+			}
+			hdr->parsed=(void*)integer;
+			hdr->body.len=tmp-hdr->body.s;
+			DBG("DEBUG: get_hdr_body : content_type=%d\n",(int)hdr->parsed);
+			break;
 		case HDR_FROM:
 		case HDR_CALLID:
 		case HDR_CONTACT:
 		case HDR_ROUTE:
 		case HDR_RECORDROUTE:
 		case HDR_MAXFORWARDS:
-		case HDR_CONTENTTYPE:
-		case HDR_CONTENTLENGTH:
-	        case HDR_AUTHORIZATION:
-	        case HDR_EXPIRES:
-	        case HDR_PROXYAUTH:
-	        case HDR_WWWAUTH:
-	        case HDR_SUPPORTED:
-	        case HDR_REQUIRE:
-	        case HDR_PROXYREQUIRE:
-	        case HDR_UNSUPPORTED:
-	        case HDR_ALLOW:
-	        case HDR_EVENT:
+		case HDR_AUTHORIZATION:
+		case HDR_EXPIRES:
+		case HDR_PROXYAUTH:
+		case HDR_WWWAUTH:
+		case HDR_SUPPORTED:
+		case HDR_REQUIRE:
+		case HDR_PROXYREQUIRE:
+		case HDR_UNSUPPORTED:
+		case HDR_ALLOW:
+		case HDR_EVENT:
 		case HDR_OTHER:
 			/* just skip over it */
 			hdr->body.s=tmp;
@@ -286,39 +308,39 @@ int parse_headers(struct sip_msg* msg, int flags, int next)
 				if (msg->content_length==0) msg->content_length = hf;
 				msg->parsed_flag|=HDR_CONTENTLENGTH;
 				break;
-		        case HDR_AUTHORIZATION:
-			        if (msg->authorization==0) msg->authorization = hf;
+			case HDR_AUTHORIZATION:
+				if (msg->authorization==0) msg->authorization = hf;
 				msg->parsed_flag|=HDR_AUTHORIZATION;
 				break;
-        		case HDR_EXPIRES:
+			case HDR_EXPIRES:
 				if (msg->expires==0) msg->expires = hf;
 				msg->parsed_flag|=HDR_EXPIRES;
 				break;
-		        case HDR_PROXYAUTH:
+			case HDR_PROXYAUTH:
 				if (msg->proxy_auth==0) msg->proxy_auth = hf;
 				msg->parsed_flag|=HDR_PROXYAUTH;
 				break;
-		        case HDR_WWWAUTH:
+			case HDR_WWWAUTH:
 				if (msg->www_auth==0) msg->www_auth = hf;
 				msg->parsed_flag|=HDR_WWWAUTH;
 				break;
-		        case HDR_SUPPORTED:
+			case HDR_SUPPORTED:
 				if (msg->supported==0) msg->supported = hf;
 				msg->parsed_flag|=HDR_SUPPORTED;
 				break;
-		        case HDR_REQUIRE:
+			case HDR_REQUIRE:
 				if (msg->require==0) msg->require = hf;
 				msg->parsed_flag|=HDR_REQUIRE;
 				break;
-		        case HDR_PROXYREQUIRE:
+			case HDR_PROXYREQUIRE:
 				if (msg->proxy_require==0) msg->proxy_require = hf;
 				msg->parsed_flag|=HDR_PROXYREQUIRE;
 				break;
-		        case HDR_UNSUPPORTED:
+			case HDR_UNSUPPORTED:
 				if (msg->unsupported==0) msg->unsupported=hf;
 				msg->parsed_flag|=HDR_UNSUPPORTED;
 				break;
-		        case HDR_ALLOW:
+			case HDR_ALLOW:
 				if (msg->allow==0) msg->allow = hf;
 				msg->parsed_flag|=HDR_ALLOW;
 				break;

+ 20 - 0
parser/msg_parser.h

@@ -208,4 +208,24 @@ inline static int char_msg_val( struct sip_msg *msg, char *cv )
 	return 1;
 }
 
+
+/* returns a pointer to the begining of the msg's body
+ */
+inline static char* get_body(struct sip_msg *msg)
+{
+	int offset;
+
+	if ( parse_headers(msg,HDR_EOH, 0)==-1 )
+		return 0;
+
+	if ( strncmp(CRLF,msg->unparsed,CRLF_LEN)==0 )
+		offset = CRLF_LEN;
+	else if (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' )
+		offset = 1;
+	else
+		return 0;
+
+	return msg->unparsed + offset;
+}
+
 #endif

+ 194 - 0
parser/parse_content.c

@@ -0,0 +1,194 @@
+/*
+ * $Id$
+ *
+ *
+ * Copyright (C) 2001-2003 Fhg Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "../dprint.h"
+#include "../str.h"
+#include "../ut.h"
+#include "parse_content.h"
+
+
+typedef struct type_node_s {
+	char c;
+	unsigned char final;
+	unsigned char nr_sons;
+	int next;
+}type_node_t;
+
+
+char* parse_content_length( char* buffer, char* end, int* length)
+{
+	int number;
+	char *p;
+	int  size;
+
+	p = buffer;
+	/* search the begining of the number */
+	while ( p<end && (*p==' ' || *p=='\t' ||
+	(*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
+		p++;
+	if (p==end)
+		goto error;
+	/* parse the number */
+	size = 0;
+	number = 0;
+	while (p<end && *p>='0' && *p<='9') {
+		number = number*10 + (*p)-'0';
+		size ++;
+		p++;
+	}
+	if (p==end || size==0)
+		goto error;
+	/* now we should have only spaces at the end */
+	while ( p<end && (*p==' ' || *p=='\t' ||
+	(*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
+		p++;
+	if (p==end)
+		goto error;
+	/* the header ends proper? */
+	if ( (*(p++)!='\n') && (*(p-1)!='\r' || *(p++)!='\n' ) )
+		goto error;
+
+	*length = number;
+	return p;
+error:
+	LOG(L_ERR,"ERROR:parse_content_length: parse error near char [%d][%c]\n",
+		*p,*p);
+	return 0;
+}
+
+
+
+
+char* parse_content_type( char* buffer, char* end, int* type)
+{
+	static type_node_t type_tree[] = {
+		{'t',-1,1,4}, {'e',-1,1,-1}, {'x',-1,1,-1}, {'t',0,0,-1},
+		{'m',-1,1,11}, {'e',-1,1,-1}, {'s',-1,1,-1}, {'s',-1,1,-1},
+			{'a',-1,1,-1},{'g',-1,1,-1}, {'e',5,0,-1},
+		{'a',-1,1,-1}, {'p',-1,1,-1}, {'p',-1,1,-1}, {'l',-1,1,-1},
+			{'i',-1,1,-1},{'c',-1,1,-1},{'a',-1,1,-1},{'t',-1,1,-1},
+			{'i',-1,1,-1},{'o',-1,1,-1},{'n',9,0,-1}
+	};
+	static type_node_t subtype_tree[] = {
+		{'p',0,1,5}, {'l',0,1,-1}, {'a',0,1,-1}, {'i',0,1,-1},
+			{'n',CONTENT_TYPE_TEXT_PLAIN,0,-1},
+		{'c',0,1,9}, {'p',0,1,-1}, {'i',0,1,-1},
+			{'m',CONTENT_TYPE_MESSAGE_CPIM,0,-1},
+		{'s',0,1,-1}, {'d',0,1,-1},
+			{'p',CONTENT_TYPE_APPLICATION_SDP,0,-1},
+	};
+	int node;
+	int mime;
+	char *p;
+
+	p = buffer;
+	mime = CONTENT_TYPE_UNKNOWN;
+
+	/* search the begining of the type */
+	while ( p<end && (*p==' ' || *p=='\t' ||
+	(*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
+		p++;
+	if (p==end)
+		goto error;
+
+	/* parse the type */
+	node = 0;
+	while (p<end && ((*p>='a' && *p<='z') || (*p>='A' && *p<='Z')) ) {
+		while ( node!=-1 && type_tree[node].c!=*p && type_tree[node].c+32!=*p){
+			node = type_tree[node].next;
+		}
+		if (node!=-1 && type_tree[node].nr_sons)
+			node++;
+		p++;
+	}
+	if (p==end || node==0)
+		goto error;
+	if (node!=-1)
+		node = type_tree[node].final;
+
+	/* search the '/' separator */
+	while ( p<end && (*p==' ' || *p=='\t' ||
+	(*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
+		p++;
+	if ( p==end || *(p++)!='/')
+		goto error;
+
+	/* search the begining of the sub-type */
+	while ( p<end && (*p==' ' || *p=='\t' ||
+	(*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
+		p++;
+	if (p==end)
+		goto error;
+
+	/* parse the sub-type */
+	while (p<end && ((*p>='a' && *p<='z') || (*p>='A' && *p<='Z')) ) {
+		while(node!=-1&&subtype_tree[node].c!=*p&&subtype_tree[node].c+32!=*p)
+			node = subtype_tree[node].next;
+		if (node!=-1 && subtype_tree[node].nr_sons)
+			node++;
+		p++;
+	}
+	if (p==end || node==0)
+		goto error;
+	if (node!=-1)
+		mime = subtype_tree[node].final;
+
+	/* now its possible to have some spaces */
+	while ( p<end && (*p==' ' || *p=='\t' ||
+	(*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
+		p++;
+	if (p==end)
+		goto error;
+
+	/* if there are params, eat everything to the end */
+	if (*p==';') {
+		while ( p<end && (*p!='\n' || (*(p+1)==' '||*(p+1)=='\t')) )
+			p++;
+		if (p==end)
+			goto error;
+	}
+
+	/* the header ends proper? */
+	if ( (*(p++)!='\n') && (*(p-1)!='\r' || *(p++)!='\n' ) )
+		goto error;
+
+	*type = mime;
+	return p;
+error:
+	LOG(L_ERR,"ERROR:parse_content_length: parse error near char [%d][%c]\n",
+		*p,*p);
+	return 0;
+}
+
+
+

+ 41 - 0
parser/parse_content.h

@@ -0,0 +1,41 @@
+/*
+ * $Id$
+ *
+ *
+ * Copyright (C) 2001-2003 Fhg Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _PARSE_CONTENT_H
+#define _PARSE_CONTENT_H
+
+#define CONTENT_TYPE_UNKNOWN         0
+#define CONTENT_TYPE_TEXT_PLAIN      1
+#define CONTENT_TYPE_MESSAGE_CPIM    2
+#define CONTENT_TYPE_APPLICATION_SDP 3
+
+
+char* parse_content_type( char* buffer, char* end, int* type);
+char* parse_content_length( char* buffer, char* end, int* len);
+
+#endif