浏览代码

- patch from Jan (for recognizing some extra headers) applyed.
- interface for parse_content_type_hdr changed (separation between type and
subtype inside a mime)
- parse_accept_hdr added

Bogdan-Andrei Iancu 22 年之前
父节点
当前提交
2f43c7326f
共有 15 个文件被更改,包括 744 次插入146 次删除
  1. 0 6
      modules/tm/sip_msg.c
  2. 38 1
      parser/case_acce.h
  3. 74 4
      parser/case_cont.h
  4. 60 0
      parser/case_orga.h
  5. 50 0
      parser/case_prio.h
  6. 56 0
      parser/case_subj.h
  7. 57 0
      parser/case_user.h
  8. 5 0
      parser/hf.c
  9. 33 27
      parser/hf.h
  10. 28 0
      parser/keys.h
  11. 46 16
      parser/msg_parser.c
  12. 8 2
      parser/msg_parser.h
  13. 233 73
      parser/parse_content.c
  14. 41 7
      parser/parse_content.h
  15. 15 10
      parser/parse_hname2.c

+ 0 - 6
modules/tm/sip_msg.c

@@ -563,15 +563,9 @@ struct sip_msg*  sip_msg_cloner( struct sip_msg *org_msg )
 					new_hdr->parsed = auth_body_cloner(new_msg->buf , org_msg->buf , (struct auth_body*)hdr->parsed , &p);
 				}
 				break;
-			case HDR_WWWAUTH :
-				new_msg->www_auth = new_hdr;
-				break;
 			case HDR_SUPPORTED :
 				new_msg->supported = new_hdr;
 				break;
-			case HDR_REQUIRE :
-				new_msg->require = new_hdr;
-				break;
 			case HDR_PROXYREQUIRE :
 				new_msg->proxy_require = new_hdr;
 				break;

+ 38 - 1
parser/case_acce.h

@@ -1,7 +1,7 @@
 /* 
  * $Id$ 
  *
- * Accept Header Field Name Parsing Macros
+ * Accept and Accept-Language Header Field Name Parsing Macros
  *
  * Copyright (C) 2001-2003 Fhg Fokus
  *
@@ -31,8 +31,45 @@
 #define CASE_ACCE_H
 
 
+#define age_CASE                                \
+        switch(LOWER_DWORD(val)) {              \
+        case _age1_:                            \
+	        hdr->type = HDR_ACCEPTLANGUAGE; \
+	        hdr->name.len = 15;             \
+	        return (p + 4);                 \
+                                                \
+        case _age2_:                            \
+                hdr->type = HDR_ACCEPTLANGUAGE; \
+                p += 4;                         \
+	        goto dc_end;                    \
+        }
+
+
+#define angu_CASE                  \
+        switch(LOWER_DWORD(val)) { \
+        case _angu_:               \
+		p += 4;            \
+		val = READ(p);     \
+		age_CASE;          \
+		goto other;        \
+	}
+
+
+#define ptl_CASE                   \
+        switch(LOWER_DWORD(val)) { \
+        case _pt_l_:               \
+		p += 4;            \
+		val = READ(p);     \
+		angu_CASE;         \
+		goto other;        \
+	}
+
+
 #define acce_CASE                           \
     p += 4;                                 \
+    val = READ(p);                          \
+    ptl_CASE;                               \
+                                            \
     if (LOWER_BYTE(*p) == 'p') {            \
             p++;                            \
             if (LOWER_BYTE(*p) == 't') {    \

+ 74 - 4
parser/case_cont.h

@@ -1,7 +1,8 @@
 /* 
  * $Id$ 
  *
- * Contact, Content-Type, Content-Length Header Field Name Parsing Macros
+ * Contact, Content-Type, Content-Length, Content-Purpose,
+ * Content-Action, Content-Disposition  Header Field Name Parsing Macros
  *
  * Copyright (C) 2001-2003 Fhg Fokus
  *
@@ -56,8 +57,59 @@
         }
 
 
-#define LENG_TYPE_CASE                       \
-        switch(LOWER_DWORD(val)) {            \
+#define PURP_CASE                               \
+        switch(LOWER_DWORD(val)) {              \
+        case _ose1_:                            \
+	        hdr->type = HDR_CONTENTPURPOSE; \
+	        hdr->name.len = 15;             \
+	        return (p + 4);                 \
+                                                \
+        case _ose2_:                            \
+                hdr->type = HDR_CONTENTPURPOSE; \
+                p += 4;                         \
+	        goto dc_end;                    \
+        }
+
+
+#define ACTION_CASE                                \
+    p += 4;                                        \
+    if (LOWER_BYTE(*p) == 'o') {                   \
+            p++;                                   \
+            if (LOWER_BYTE(*p) == 'n') {           \
+                    hdr->type = HDR_CONTENTACTION; \
+                    p++;                           \
+                    goto dc_end;                   \
+            }                                      \
+    }                                              \
+    goto other;
+
+
+#define ion_CASE                                    \
+        switch(LOWER_DWORD(val)) {                  \
+        case _ion1_:                                \
+	        hdr->type = HDR_CONTENTDISPOSITION; \
+	        hdr->name.len = 19;                 \
+	        return (p + 4);                     \
+                                                    \
+        case _ion2_:                                \
+                hdr->type = HDR_CONTENTDISPOSITION; \
+                p += 4;                             \
+	        goto dc_end;                        \
+        }
+
+
+#define DISPOSITION_CASE           \
+        switch(LOWER_DWORD(val)) { \
+        case _osit_:               \
+		p += 4;            \
+		val = READ(p);     \
+		ion_CASE;          \
+		goto other;        \
+	}
+
+
+#define CONTENT_CASE                         \
+        switch(LOWER_DWORD(val)) {           \
         case _leng_:                         \
                 p += 4;                      \
                 val = READ(p);               \
@@ -68,6 +120,24 @@
                 hdr->type = HDR_CONTENTTYPE; \
                 p += 4;                      \
                 goto dc_end;                 \
+                                             \
+        case _purp_:                         \
+		p += 4;                      \
+		val = READ(p);               \
+		PURP_CASE;                   \
+		goto other;                  \
+                                             \
+        case _acti_:                         \
+                p += 4;                      \
+                val = READ(p);               \
+                ACTION_CASE;                 \
+                goto other;                  \
+                                             \
+        case _disp_:                         \
+                p += 4;                      \
+		val = READ(p);               \
+		DISPOSITION_CASE;            \
+                goto other;                  \
         }
 
 
@@ -86,7 +156,7 @@
         case _ent__:                     \
                 p += 4;                  \
                 val = READ(p);           \
-                LENG_TYPE_CASE;          \
+                CONTENT_CASE;            \
                 goto other;              \
         }                         
 

+ 60 - 0
parser/case_orga.h

@@ -0,0 +1,60 @@
+/* 
+ * $Id$ 
+ *
+ * Organization Header Field Name Parsing Macros
+ *
+ * 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 CASE_ORGA_H
+#define CASE_ORGA_H
+
+
+#define tion_CASE                             \
+        if (LOWER_DWORD(val) == _tion_) {     \
+	        hdr->type = HDR_ORGANIZATION; \
+		p += 4;                       \
+		goto dc_end;                  \
+	}                                     \
+
+
+#define niza_CASE                  \
+        switch(LOWER_DWORD(val)) { \
+        case _niza_:               \
+	        p += 4;            \
+	        val = READ(p);     \
+		tion_CASE;         \
+	        goto other;        \
+        }
+
+
+#define orga_CASE         \
+        p += 4;           \
+        val = READ(p);    \
+        niza_CASE;        \
+        goto other;
+
+
+#endif /* CASE_ORGA_H */

+ 50 - 0
parser/case_prio.h

@@ -0,0 +1,50 @@
+/* 
+ * $Id$ 
+ *
+ * Priority Header Field Name Parsing Macros
+ *
+ * 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 CASE_PRIO_H
+#define CASE_PRIO_H
+
+
+#define rity_CASE                             \
+        if (LOWER_DWORD(val) == _rity_) {     \
+	        hdr->type = HDR_PRIORITY;     \
+		p += 4;                       \
+		goto dc_end;                  \
+	}                                     \
+
+
+#define prio_CASE         \
+        p += 4;           \
+        val = READ(p);    \
+        rity_CASE;        \
+        goto other;
+
+
+#endif /* CASE_PRIO_H */

+ 56 - 0
parser/case_subj.h

@@ -0,0 +1,56 @@
+/* 
+ * $Id$ 
+ *
+ * Subject Header Field Name Parsing Macros
+ *
+ * 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 CASE_SUBJ_H
+#define CASE_SUBJ_H
+
+
+#define ect_CASE                         \
+        switch(LOWER_DWORD(val)) {       \
+        case _ect1_:                     \
+	        hdr->type = HDR_SUBJECT; \
+	        hdr->name.len = 7;       \
+	        return (p + 4);          \
+                                         \
+        case _ect2_:                     \
+                hdr->type = HDR_SUBJECT; \
+                p += 4;                  \
+	        goto dc_end;             \
+        }
+
+
+#define subj_CASE        \
+        p += 4;          \
+        val = READ(p);   \
+        ect_CASE;        \
+        goto other;
+
+
+#endif /* CASE_SUBJ_H */

+ 57 - 0
parser/case_user.h

@@ -0,0 +1,57 @@
+/* 
+ * $Id$ 
+ *
+ * User-Agent Header Field Name Parsing Macros
+ *
+ * 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 CASE_USER_H
+#define CASE_USER_H
+
+
+#define nt_CASE                                \
+    if (LOWER_BYTE(*p) == 'n') {               \
+            p++;                               \
+            if (LOWER_BYTE(*p) == 't') {       \
+                    hdr->type = HDR_USERAGENT; \
+                    p++;                       \
+                    goto dc_end;               \
+            }                                  \
+    }                                          \
+    goto other;
+
+
+#define user_CASE              \
+    p += 4;                    \
+    val = READ(p);             \
+    switch(LOWER_DWORD(val)) { \
+    case __age_:               \
+	p += 4;                \
+	nt_CASE;               \
+    }                          \
+    goto other;
+
+
+#endif /* CASE_USER_H */

+ 5 - 0
parser/hf.c

@@ -28,6 +28,7 @@
  * -------
  * 2003-03-26 Frees also hdr->parsed for Route & Record-Route (janakj)
  * 2003-04-26 ZSW (jiri)
+ * 2003-08-05 free the parsed part of Accept header (bogdan)
  */
 
 
@@ -96,6 +97,10 @@ void clean_hdr_field(struct hdr_field* hf)
 		case HDR_CONTENTTYPE:
 			break;
 
+		case HDR_ACCEPT:
+			pkg_free(hf->parsed);
+			break;
+
 		default:
 			LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",
 			    hf->type);

+ 33 - 27
parser/hf.h

@@ -40,33 +40,39 @@
 
 
 /* Header types and flags */
-#define HDR_EOH         		-1   /* End of header found */
-#define HDR_ERROR                0   /* Error while parsing */
-#define HDR_VIA                  1   /* Via header field */
-#define HDR_VIA1                 1   /* First Via header field */
-#define HDR_VIA2          (1 <<  1)  /* only used as flag*/
-#define HDR_TO            (1 <<  2)  /* To header field */
-#define HDR_FROM          (1 <<  3)  /* From header field */
-#define HDR_CSEQ          (1 <<  4)  /* CSeq header field */
-#define HDR_CALLID        (1 <<  5)  /* Call-Id header field */
-#define HDR_CONTACT       (1 <<  6)  /* Contact header field */
-#define HDR_MAXFORWARDS   (1 <<  7)  /* MaxForwards header field */
-#define HDR_ROUTE         (1 <<  8)  /* Route header field */
-#define HDR_RECORDROUTE   (1 <<  9)  /* Record-Route header field */
-#define HDR_CONTENTTYPE   (1 << 10)  /* Content-Type header field */
-#define HDR_CONTENTLENGTH (1 << 11)  /* Content-Length header field */
-#define HDR_AUTHORIZATION (1 << 12)  /* Authorization header field */
-#define HDR_EXPIRES       (1 << 13)  /* Expires header field */
-#define HDR_PROXYAUTH     (1 << 14)  /* Proxy-Authorization header field */
-#define HDR_WWWAUTH       (1 << 15)  /* WWW-Authorization header field */
-#define HDR_SUPPORTED     (1 << 16)  /* Supported header field */
-#define HDR_REQUIRE       (1 << 17)  /* Require header field */
-#define HDR_PROXYREQUIRE  (1 << 18)  /* Proxy-Require header field */
-#define HDR_UNSUPPORTED   (1 << 19)  /* Unsupported header field */
-#define HDR_ALLOW         (1 << 20)  /* Allow header field */
-#define HDR_EVENT         (1 << 21)  /* Event header field */
-#define HDR_ACCEPT        (1 << 22)  /* Accept header field */
-#define HDR_OTHER         (1 << 23)  /* Some other header field */
+#define HDR_EOH         	     -1   /* End of header found */
+#define HDR_ERROR                     0   /* Error while parsing */
+#define HDR_VIA                       1   /* Via header field */
+#define HDR_VIA1                      1   /* First Via header field */
+#define HDR_VIA2               (1 <<  1)  /* only used as flag*/
+#define HDR_TO                 (1 <<  2)  /* To header field */
+#define HDR_FROM               (1 <<  3)  /* From header field */
+#define HDR_CSEQ               (1 <<  4)  /* CSeq header field */
+#define HDR_CALLID             (1 <<  5)  /* Call-Id header field */
+#define HDR_CONTACT            (1 <<  6)  /* Contact header field */
+#define HDR_MAXFORWARDS        (1 <<  7)  /* MaxForwards header field */
+#define HDR_ROUTE              (1 <<  8)  /* Route header field */
+#define HDR_RECORDROUTE        (1 <<  9)  /* Record-Route header field */
+#define HDR_CONTENTTYPE        (1 << 10)  /* Content-Type header field */
+#define HDR_CONTENTLENGTH      (1 << 11)  /* Content-Length header field */
+#define HDR_AUTHORIZATION      (1 << 12)  /* Authorization header field */
+#define HDR_EXPIRES            (1 << 13)  /* Expires header field */
+#define HDR_PROXYAUTH          (1 << 14)  /* Proxy-Authorization header field */
+#define HDR_SUPPORTED          (1 << 15)  /* Supported  header field */
+#define HDR_PROXYREQUIRE       (1 << 16)  /* Proxy-Require header field */
+#define HDR_UNSUPPORTED        (1 << 17)  /* Unsupported header field */
+#define HDR_ALLOW              (1 << 18)  /* Allow header field */
+#define HDR_EVENT              (1 << 19)  /* Event header field */
+#define HDR_ACCEPT             (1 << 20)  /* Accept header field */
+#define HDR_ACCEPTLANGUAGE     (1 << 21)  /* Accept-Language header field */
+#define HDR_ORGANIZATION       (1 << 22)  /* Organization header field */
+#define HDR_PRIORITY           (1 << 23)  /* Priority header field */
+#define HDR_SUBJECT            (1 << 24)  /* Subject header field */
+#define HDR_USERAGENT          (1 << 25)  /* User-Agent header field */
+#define HDR_CONTENTPURPOSE     (1 << 26)  /* Content-Purpose header field */
+#define HDR_CONTENTACTION      (1 << 27)  /* Content-Action header field */
+#define HDR_CONTENTDISPOSITION (1 << 28)  /* Content-Disposition header field */
+#define HDR_OTHER              (1 << 29)  /* Some other header field */
 
 
 /* 

+ 28 - 0
parser/keys.h

@@ -34,6 +34,11 @@
 #ifndef KEYS_H
 #define KEYS_H
 
+/*
+ * a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z  :  ' ' -
+ * 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 3a 20  2d
+ */
+
 #define _acce_ 0x65636361   /* "acce" */
 #define _allo_ 0x6f6c6c61   /* "allo" */
 #define _auth_ 0x68747561   /* "auth" */
@@ -86,4 +91,27 @@
 #define _cate_ 0x65746163   /* "cate" */
 #define _even_ 0x6e657665   /* "even" */
 
+#define _pt_l_ 0x6c2d7470   /* "pt-l" */
+#define _angu_ 0x75676e61   /* "angu" */
+#define _age2_ 0x20656761   /* "age " */
+#define _age1_ 0x3a656761   /* "age:" */
+#define _orga_ 0x6167726f   /* "orga" */
+#define _niza_ 0x617a696e   /* "niza" */
+#define _tion_ 0x6e6f6974   /* "tion" */
+#define _prio_ 0x6f697270   /* "prio" */
+#define _rity_ 0x79746972   /* "rity" */
+#define _subj_ 0x6a627573   /* "subj" */
+#define _ect2_ 0x20746365   /* "ect " */
+#define _ect1_ 0x3a746365   /* "ect:" */
+#define _user_ 0x72657375   /* "user" */
+#define __age_ 0x6567612d   /* "-age" */
+#define _purp_ 0x70727570   /* "purp" */
+#define _ose2_ 0x2065736f   /* "ose " */
+#define _ose1_ 0x3a65736f   /* "ose:" */
+#define _acti_ 0x69746361   /* "acti" */
+#define _disp_ 0x70736964   /* "disp" */
+#define _osit_ 0x7469736f   /* "osit" */
+#define _ion2_ 0x206e6f69   /* "ion " */
+#define _ion1_ 0x3a6e6f69   /* "ion:" */
+
 #endif /* KEYS_H */

+ 46 - 16
parser/msg_parser.c

@@ -179,6 +179,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 			DBG("DEBUG: get_hdr_body : content_length=%d\n",
 					(int)(long)hdr->parsed);
 			break;
+		case HDR_SUPPORTED:
 		case HDR_CONTENTTYPE:
 		case HDR_FROM:
 		case HDR_CALLID:
@@ -189,14 +190,19 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 		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_ACCEPT:
+	        case HDR_ACCEPTLANGUAGE:
+	        case HDR_ORGANIZATION:
+	        case HDR_PRIORITY:
+	        case HDR_SUBJECT:
+	        case HDR_USERAGENT:
+	        case HDR_CONTENTPURPOSE:
+	        case HDR_CONTENTACTION:
+	        case HDR_CONTENTDISPOSITION:
 		case HDR_OTHER:
 			/* just skip over it */
 			hdr->body.s=tmp;
@@ -340,22 +346,14 @@ int parse_headers(struct sip_msg* msg, int flags, int next)
 				if (msg->proxy_auth==0) msg->proxy_auth = hf;
 				msg->parsed_flag|=HDR_PROXYAUTH;
 				break;
-			case HDR_WWWAUTH:
-				if (msg->www_auth==0) msg->www_auth = hf;
-				msg->parsed_flag|=HDR_WWWAUTH;
-				break;
-			case HDR_SUPPORTED:
-				if (msg->supported==0) msg->supported = hf;
-				msg->parsed_flag|=HDR_SUPPORTED;
-				break;
-			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_SUPPORTED:
+				if (msg->supported==0) msg->supported=hf;
+				msg->parsed_flag|=HDR_SUPPORTED;
+				break;
 			case HDR_UNSUPPORTED:
 				if (msg->unsupported==0) msg->unsupported=hf;
 				msg->parsed_flag|=HDR_UNSUPPORTED;
@@ -372,6 +370,38 @@ int parse_headers(struct sip_msg* msg, int flags, int next)
 				if (msg->accept==0) msg->accept = hf;
 				msg->parsed_flag|=HDR_ACCEPT;
 				break;
+		        case HDR_ACCEPTLANGUAGE:
+				if (msg->accept_language==0) msg->accept_language = hf;
+				msg->parsed_flag|=HDR_ACCEPTLANGUAGE;
+				break;
+		        case HDR_ORGANIZATION:
+				if (msg->organization==0) msg->organization = hf;
+				msg->parsed_flag|=HDR_ORGANIZATION;
+				break;
+		        case HDR_PRIORITY:
+				if (msg->priority==0) msg->priority = hf;
+				msg->parsed_flag|=HDR_PRIORITY;
+				break;
+		        case HDR_SUBJECT:
+				if (msg->subject==0) msg->subject = hf;
+				msg->parsed_flag|=HDR_SUBJECT;
+				break;
+		        case HDR_USERAGENT:
+				if (msg->user_agent==0) msg->user_agent = hf;
+				msg->parsed_flag|=HDR_USERAGENT;
+				break;
+		        case HDR_CONTENTPURPOSE:
+				if (msg->content_purpose==0) msg->content_purpose = hf;
+				msg->parsed_flag|=HDR_CONTENTPURPOSE;
+				break;
+		        case HDR_CONTENTACTION:
+				if (msg->content_action==0) msg->content_action = hf;
+				msg->parsed_flag|=HDR_CONTENTACTION;
+				break;
+		        case HDR_CONTENTDISPOSITION:
+				if (msg->content_disposition==0) msg->content_disposition = hf;
+				msg->parsed_flag|=HDR_CONTENTDISPOSITION;
+				break;
 			case HDR_VIA:
 				msg->parsed_flag|=HDR_VIA;
 				DBG("parse_headers: Via found, flags=%d\n", flags);

+ 8 - 2
parser/msg_parser.h

@@ -173,14 +173,20 @@ struct sip_msg {
 	struct hdr_field* authorization;
 	struct hdr_field* expires;
 	struct hdr_field* proxy_auth;
-	struct hdr_field* www_auth;
 	struct hdr_field* supported;
-	struct hdr_field* require;
 	struct hdr_field* proxy_require;
 	struct hdr_field* unsupported;
 	struct hdr_field* allow;
 	struct hdr_field* event;
 	struct hdr_field* accept;
+	struct hdr_field* accept_language;
+	struct hdr_field* organization;
+	struct hdr_field* priority;
+	struct hdr_field* subject;
+	struct hdr_field* user_agent;
+	struct hdr_field* content_purpose;
+	struct hdr_field* content_action;
+	struct hdr_field* content_disposition;
 
 	char* eoh;        /* pointer to the end of header (if found) or null */
 	char* unparsed;   /* here we stopped parsing*/

+ 233 - 73
parser/parse_content.c

@@ -24,6 +24,12 @@
  * 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
+ *
+ * History:
+ * 2003-08-04 parse_content_type_hdr separates type from subtype inside
+ * the mime type (bogdan)
+ * 2003-08-04 CPL subtype added (bogdan)
+ * 2003-08-05 parse_accept_hdr function added (bogdan)
  */
 
 
@@ -31,26 +37,72 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include "../mem/mem.h"
 #include "../dprint.h"
 #include "../str.h"
 #include "../ut.h"
 #include "parse_content.h"
 
+
+#define is_mime_char(_c_) \
+	(isalpha(_c_) || (_c_)=='-' || (_c_)=='+')
+#define is_char_equal(_c_,_cs_) \
+	( (isalpha(_c_)?(((_c_)|0x20)==(_cs_)):((_c_)==(_cs_)))==1 )
+
+
 /*
  * Node of the type's tree; this tree contains all the known types;
  */
 typedef struct type_node_s {
 	char c;                      /* char contained by this node */
-	char final;                 /* says what to be done if the matched string
-	                              * ends at this node: -1-> dead end (unknown
-	                              * type) or the index of the sub-type that
-	                              * follows (for types) or the  final type 
-	                              * (for sub-types)*/
+	unsigned char final;         /* says what mime type/subtype was detected
+	                              * if string ends at this node */
 	unsigned char nr_sons;       /* the number of sub-nodes */
 	int next;                    /* the next sibling node */
 }type_node_t;
 
 
+static type_node_t type_tree[] = {
+	{'t',TYPE_UNKNOWN,1,4},
+		{'e',TYPE_UNKNOWN,1,-1},
+			{'x',TYPE_UNKNOWN,1,-1},
+				{'t',TYPE_TEXT,0,-1},
+	{'m',TYPE_UNKNOWN,1,11},
+		{'e',TYPE_UNKNOWN,1,-1},
+			{'s',TYPE_UNKNOWN,1,-1},
+				{'s',TYPE_UNKNOWN,1,-1},
+					{'a',TYPE_UNKNOWN,1,-1},
+						{'g',TYPE_UNKNOWN,1,-1},
+							{'e',TYPE_MESSAGE,0,-1},
+	{'a',TYPE_UNKNOWN,1,-1},
+		{'p',TYPE_UNKNOWN,1,-1},
+			{'p',TYPE_UNKNOWN,1,-1},
+				{'l',TYPE_UNKNOWN,1,-1},
+					{'i',TYPE_UNKNOWN,1,-1},
+						{'c',TYPE_UNKNOWN,1,-1},
+							{'a',TYPE_UNKNOWN,1,-1},
+								{'t',TYPE_UNKNOWN,1,-1},
+									{'i',TYPE_UNKNOWN,1,-1},
+										{'o',TYPE_UNKNOWN,1,-1},
+											{'n',TYPE_APPLICATION,0,-1}
+	};
+
+static type_node_t subtype_tree[] = {
+		{'p',SUBTYPE_UNKNOWN,1,5},
+			{'l',SUBTYPE_UNKNOWN,1,-1},
+				{'a',SUBTYPE_UNKNOWN,1,-1},
+					{'i',SUBTYPE_UNKNOWN,1,-1},
+						{'n',SUBTYPE_PLAIN,0,-1},
+		{'c',SUBTYPE_UNKNOWN,1,10},
+			{'p',SUBTYPE_UNKNOWN,2,-1},
+				{'i',SUBTYPE_UNKNOWN,1,9},
+					{'m',SUBTYPE_CPIM,0,-1},
+				{'l',SUBTYPE_CPL,0,-1},
+		{'s',SUBTYPE_UNKNOWN,1,-1},
+			{'d',SUBTYPE_UNKNOWN,1,-1},
+				{'p',SUBTYPE_SDP,0,-1},
+	};
+
 
 
 char* parse_content_length( char* buffer, char* end, int* length)
@@ -96,51 +148,13 @@ error:
 
 
 
-
-
-int parse_content_type_hdr( struct sip_msg *msg )
+char* decode_mime_type(char *start, char *end, unsigned int *mime_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;
-	long mime;
 	char *mark;
-	char *p, *end;
-
-	/* is the header already found? */
-	if ( msg->content_type==0 ) {
-		/* if not, found it */
-		if ( parse_headers(msg,HDR_CONTENTTYPE,0)==-1)
-			return -1;
-		if ( msg->content_type==0 ) {
-			LOG(L_ERR,"ERROR:parse_content_type_header: missing Content-Type"
-					"header\n");
-			return -1;
-		}
-	}
-
-	/* maybe the header is already parsed! */
-	if ( get_content_type(msg)!=CONTENT_TYPE_UNPARSED)
-		return get_content_type(msg);
+	char *p;
 
-	/* it seams we have to parse it! :-( */
-	p = msg->content_type->body.s;
-	end = p + msg->content_type->body.len;
-	mime = CONTENT_TYPE_UNKNOWN;
+	p = start;
 
 	/* search the begining of the type */
 	while ( p<end && (*p==' ' || *p=='\t' ||
@@ -150,20 +164,27 @@ int parse_content_type_hdr( struct sip_msg *msg )
 		goto error;
 
 	/* parse the type */
-	node = 0;
-	mark = p;
-	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++;
+	if (*p=='*') {
+		*mime_type = TYPE_ALL<<16;
 		p++;
+	} else {
+		node = 0;
+		mark = p;
+		while (p<end && is_mime_char(*p)  ) {
+			while ( node!=-1 && !is_char_equal(*p,type_tree[node].c) ){
+				node = type_tree[node].next;
+			}
+			if (node!=-1 && type_tree[node].nr_sons)
+				node++;
+			p++;
+		}
+		if (p==end || mark==p)
+			goto error;
+		if (node!=-1)
+			*mime_type = type_tree[node].final<<16;
+		else
+			*mime_type = TYPE_UNKNOWN<<16;
 	}
-	if (p==end || mark==p)
-		goto error;
-	if (node!=-1)
-		node = type_tree[node].final;
 
 	/* search the '/' separator */
 	while ( p<end && (*p==' ' || *p=='\t' ||
@@ -180,36 +201,175 @@ int parse_content_type_hdr( struct sip_msg *msg )
 		goto error;
 
 	/* parse the sub-type */
-	mark = p;
-	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++;
+	if (*p=='*') {
+		*mime_type |= SUBTYPE_ALL;
 		p++;
+	} else {
+		node = 0;
+		mark = p;
+		while (p<end && is_mime_char(*p) ) {
+			while(node!=-1 && !is_char_equal(*p,subtype_tree[node].c) )
+				node = subtype_tree[node].next;
+			if (node!=-1 && subtype_tree[node].nr_sons)
+				node++;
+			p++;
+		}
+		if (p==mark)
+			goto error;
+		if (node!=-1)
+			*mime_type |= subtype_tree[node].final;
+		else
+			*mime_type |= SUBTYPE_UNKNOWN;
 	}
-	if (p==mark)
-		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++;
 
-	/* is this the end? if there are params, ignore them!! */
-	if ( *p!=';' && p!=end )
+	/* if there are params, ignore them!! -> eat everything to
+	 * the end or to the first ',' */
+	if ( p<end && *p==';' )
+		for(p++; p<end && *p!=','; p++);
+
+	/* is this the correct end? */
+	if (p!=end && *p!=',' )
+		goto error;
+
+	/* check the format of the decoded mime */
+	if ((*mime_type)>>16==TYPE_ALL && ((*mime_type)&0x00ff)!=SUBTYPE_ALL) {
+		LOG(L_ERR,"ERROR:decode_mine_type: invalid mime format found "
+			" <*/submime> in [%.*s]!!\n", end-start,start);
+		return 0;
+	}
+
+	return p;
+error:
+	LOG(L_ERR,"ERROR:decode_mine_type: parse error near in [%.*s] char"
+		"[%d][%c] offset=%d\n", end-start,start,*p,*p,(int)(p-start));
+	return 0;
+}
+
+
+
+/* returns: > 0 mime found
+ *          = 0 hdr not found
+ *          =-1 error */
+int parse_content_type_hdr( struct sip_msg *msg )
+{
+	char *end;
+	char *ret;
+	int  mime;
+
+	/* is the header already found? */
+	if ( msg->content_type==0 ) {
+		/* if not, found it */
+		if ( parse_headers(msg,HDR_CONTENTTYPE,0)==-1)
+			goto error;
+		if ( msg->content_type==0 ) {
+			DBG("DEBUG:parse_content_type_hdr: missing Content-Type"
+				"header\n");
+			return 0;
+		}
+	}
+
+	/* maybe the header is already parsed! */
+	if ( msg->content_type->parsed!=0)
+		return get_content_type(msg);
+
+	/* it seams we have to parse it! :-( */
+	end = msg->content_type->body.s + msg->content_type->body.len;
+	ret = decode_mime_type(msg->content_type->body.s, end , &mime);
+	if (ret==0)
 		goto error;
+	if (ret!=end) {
+		LOG(L_ERR,"ERROR:parse_content_type_hdr: CONTENT_TYPE hdr containes "
+			"more then one mime type :-(!\n");
+		goto error;
+	}
+	if ((mime&0x00ff)==SUBTYPE_ALL || (mime>>16)==TYPE_ALL) {
+		LOG(L_ERR,"ERROR:parse_content_type_hdr: invalid mime with wildcard "
+			"'*' in Content-Type hdr!\n");
+		goto error;
+	}
 
-	mime = ((mime==-1)?CONTENT_TYPE_UNKNOWN:mime);
 	msg->content_type->parsed = (void*)mime;
 	return mime;
+
 error:
-	LOG(L_ERR,"ERROR:parse_content_type: parse error near char [%d][%c] "
-		"offset=%d\n",*p,*p,(int)(p-msg->content_type->body.s));
 	return -1;
 }
 
 
 
+/* returns: > 0 ok
+ *          = 0 hdr not found
+ *          = -1 error */
+int parse_accept_hdr( struct sip_msg *msg )
+{
+	static int mimes[MAX_MIMES_NR];
+	int nr_mimes;
+	int mime;
+	char *end;
+	char *ret;
+
+	/* is the header already found? */
+	if ( msg->accept==0 ) {
+		/* if not, found it */
+		if ( parse_headers(msg,HDR_ACCEPT,0)==-1)
+			goto error;
+		if ( msg->accept==0 ) {
+			DBG("DEBUG:parse_accept_hdr: missing Accept header\n");
+			return 0;
+		}
+	}
+
+	/* maybe the header is already parsed! */
+	if ( msg->accept->parsed!=0)
+		return 1;
+
+	/* it seams we have to parse it! :-( */
+	ret = msg->accept->body.s;
+	end = ret + msg->accept->body.len;
+	nr_mimes = 0;
+	while (1){
+		ret = decode_mime_type(ret, end , &mime);
+		if (ret==0)
+			goto error;
+		/* a new mime was found  -> put it into array */
+		if (nr_mimes==MAX_MIMES_NR) {
+			LOG(L_ERR,"ERROR:parse_accept_hdr: Accept hdr contains more than"
+				" %d mime type -> buffer ovrflow!!\n",MAX_MIMES_NR);
+			goto error;
+		}
+		mimes[nr_mimes++] = mime;
+		/* is another mime following? */
+		if (ret==end )
+			break;
+		/* parse the mime separator ',' */
+		if (*ret!=',' || ret+1==end) {
+			LOG(L_ERR,"ERROR:parse_accept_hdr: parse error between mimes at "
+				"char <%x> (offset=%d) in <%.*s>!\n",
+				*ret,ret-msg->accept->body.s,
+				msg->accept->body.len,msg->accept->body.s);
+			goto error;
+		}
+		/* skip the ',' */
+		ret++;
+	}
+
+	/* copy and link the mime buffer into the message */
+	msg->accept->parsed = (void*)pkg_malloc((nr_mimes+1)*sizeof(int));
+	if (msg->accept->parsed==0) {
+		LOG(L_ERR,"ERROR:parse_accept_hdr: no more pkg memory\n");
+		goto error;
+	}
+	memcpy(msg->accept->parsed,mimes,nr_mimes*sizeof(int));
+	/* make the buffer null terminated */
+	((int*)msg->accept->parsed)[nr_mimes] = 0;
+
+	return 1;
+error:
+	return -1;
+}
+

+ 41 - 7
parser/parse_content.h

@@ -31,16 +31,35 @@
 
 #include "msg_parser.h"
 
+
+struct mime_type {
+	unsigned short type;
+	unsigned short subtype;
+};
+
+
+
 /*
- * Types for Content-Type header that are recognize
+ * Mimes types/subtypes that are recognize
  */
-#define CONTENT_TYPE_UNPARSED        0
-#define CONTENT_TYPE_TEXT_PLAIN      1
-#define CONTENT_TYPE_MESSAGE_CPIM    2
-#define CONTENT_TYPE_APPLICATION_SDP 3
-#define CONTENT_TYPE_UNKNOWN         0x7fff
+#define TYPE_TEXT            1
+#define TYPE_MESSAGE         2
+#define TYPE_APPLICATION     3
+#define TYPE_ALL             0xfe
+#define TYPE_UNKNOWN         0xff
+
+#define SUBTYPE_PLAIN        1
+#define SUBTYPE_CPIM         2
+#define SUBTYPE_SDP          3
+#define SUBTYPE_CPL          4
+#define SUBTYPE_ALL          0xfe
+#define SUBTYPE_UNKNOWN      0xff
 
 
+/*
+ * Maximum number of mimes allowed in Accept header 
+ */
+#define MAX_MIMES_NR         128
 
 /*
  * returns the content-length value of a sip_msg as an integer
@@ -54,15 +73,30 @@
 #define get_content_type(_msg_)   ((int)(long)((_msg_)->content_type->parsed))
 
 
+/*
+ * returns the accept values of a sip_msg as an null-terminated array
+ * of integer
+ */
+#define get_accept(_msg_) ((int*)((_msg_)->accept->parsed))
 
 /*
  * parse the the body of the Content-Type header. It's value is also converted
  * as int.
  * Returns:   n (n>0)  : the found type
- *           -1        : error (parse error or hdr not found)
+ *            0        : hdr not found
+ *           -1        : error (parse error )
  */
 int parse_content_type_hdr( struct sip_msg *msg);
 
+/*
+ * parse the the body of the Accept header. It's values are also converted
+ * as an null-terminated array of ints.
+ * Returns:   1 : OK
+ *            0 : hdr not found
+ *           -1 : error (parse error)
+ */
+int parse_accept_hdr( struct sip_msg *msg );
+
 
 /*
  *  parse the body of a Content_-Length header. Also tryes to recognize the

+ 15 - 10
parser/parse_hname2.c

@@ -65,7 +65,8 @@ static inline char* skip_ws(char* p, unsigned int size)
 #include "case_to.h"       /* To */
 #include "case_cseq.h"     /* CSeq */
 #include "case_call.h"     /* Call-ID */
-#include "case_cont.h"     /* Contact, Content-Type, Content-Length */
+#include "case_cont.h"     /* Contact, Content-Type, Content-Length, Content-Purpose, 
+			    * Content-Action, Content-Disposition */
 #include "case_rout.h"     /* Route */
 #include "case_max.h"      /* Max-Forwards */
 #include "case_reco.h"     /* Record-Route */
@@ -74,11 +75,13 @@ static inline char* skip_ws(char* p, unsigned int size)
 #include "case_prox.h"     /* Proxy-Authorization, Proxy-Require */
 #include "case_allo.h"     /* Allow */
 #include "case_unsu.h"     /* Unsupported */
-#include "case_requ.h"     /* Require */
-#include "case_supp.h"     /* Supported */
-#include "case_www.h"      /* WWW-Authenticate */
 #include "case_even.h"     /* Event */
-#include "case_acce.h"     /* Accept */
+#include "case_acce.h"     /* Accept, Accept-Language */
+#include "case_orga.h"     /* Organization */
+#include "case_prio.h"     /* Priority */
+#include "case_subj.h"     /* Subject */
+#include "case_user.h"     /* User-Agent */
+#include "case_supp.h"     /* Supported */
 
 
 #define READ(val) \
@@ -97,15 +100,17 @@ static inline char* skip_ws(char* p, unsigned int size)
 	case _reco_: reco_CASE; \
 	case _via2_: via2_CASE; \
 	case _auth_: auth_CASE; \
+	case _supp_: supp_CASE; \
 	case _expi_: expi_CASE; \
 	case _prox_: prox_CASE; \
 	case _allo_: allo_CASE; \
 	case _unsu_: unsu_CASE; \
-	case _requ_: requ_CASE; \
-	case _supp_: supp_CASE; \
-        case _www__: www_CASE;  \
         case _even_: even_CASE; \
-        case _acce_: acce_CASE;
+        case _acce_: acce_CASE; \
+        case _orga_: orga_CASE; \
+        case _prio_: prio_CASE; \
+        case _subj_: subj_CASE; \
+        case _user_: user_CASE;
 
 
 #define PARSE_COMPACT(id)          \
@@ -162,8 +167,8 @@ char* parse_hname2(char* begin, char* end, struct hdr_field* hdr)
 		case 'i': PARSE_COMPACT(HDR_CALLID);        break;
 		case 'm': PARSE_COMPACT(HDR_CONTACT);       break;
 		case 'l': PARSE_COMPACT(HDR_CONTENTLENGTH); break;
-		case 'c': PARSE_COMPACT(HDR_CONTENTTYPE);   break;
 		case 'k': PARSE_COMPACT(HDR_SUPPORTED);     break;
+		case 'c': PARSE_COMPACT(HDR_CONTENTTYPE);   break;
 		case 'o': PARSE_COMPACT(HDR_EVENT);         break;
 		}
 		goto other;