summaryrefslogtreecommitdiffstats
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/Makefile.am195
-rw-r--r--src/parser/challenge.cpp178
-rw-r--r--src/parser/challenge.h66
-rw-r--r--src/parser/coding.cpp42
-rw-r--r--src/parser/coding.h39
-rw-r--r--src/parser/credentials.cpp158
-rw-r--r--src/parser/credentials.h69
-rw-r--r--src/parser/definitions.cpp59
-rw-r--r--src/parser/definitions.h81
-rw-r--r--src/parser/hdr_accept.cpp47
-rw-r--r--src/parser/hdr_accept.h44
-rw-r--r--src/parser/hdr_accept_encoding.cpp42
-rw-r--r--src/parser/hdr_accept_encoding.h43
-rw-r--r--src/parser/hdr_accept_language.cpp66
-rw-r--r--src/parser/hdr_accept_language.h52
-rw-r--r--src/parser/hdr_alert_info.cpp56
-rw-r--r--src/parser/hdr_alert_info.h53
-rw-r--r--src/parser/hdr_allow.cpp75
-rw-r--r--src/parser/hdr_allow.h45
-rw-r--r--src/parser/hdr_allow_events.cpp42
-rw-r--r--src/parser/hdr_allow_events.h41
-rw-r--r--src/parser/hdr_auth_info.cpp99
-rw-r--r--src/parser/hdr_auth_info.h47
-rw-r--r--src/parser/hdr_authorization.cpp92
-rw-r--r--src/parser/hdr_authorization.h51
-rw-r--r--src/parser/hdr_call_id.cpp33
-rw-r--r--src/parser/hdr_call_id.h38
-rw-r--r--src/parser/hdr_call_info.cpp56
-rw-r--r--src/parser/hdr_call_info.h53
-rw-r--r--src/parser/hdr_contact.cpp178
-rw-r--r--src/parser/hdr_contact.h100
-rw-r--r--src/parser/hdr_content_disp.cpp60
-rw-r--r--src/parser/hdr_content_disp.h51
-rw-r--r--src/parser/hdr_content_encoding.cpp43
-rw-r--r--src/parser/hdr_content_encoding.h43
-rw-r--r--src/parser/hdr_content_language.cpp43
-rw-r--r--src/parser/hdr_content_language.h43
-rw-r--r--src/parser/hdr_content_length.cpp40
-rw-r--r--src/parser/hdr_content_length.h39
-rw-r--r--src/parser/hdr_content_type.cpp37
-rw-r--r--src/parser/hdr_content_type.h36
-rw-r--r--src/parser/hdr_cseq.cpp64
-rw-r--r--src/parser/hdr_cseq.h46
-rw-r--r--src/parser/hdr_date.cpp64
-rw-r--r--src/parser/hdr_date.h40
-rw-r--r--src/parser/hdr_error_info.cpp56
-rw-r--r--src/parser/hdr_error_info.h53
-rw-r--r--src/parser/hdr_event.cpp54
-rw-r--r--src/parser/hdr_event.h52
-rw-r--r--src/parser/hdr_expires.cpp36
-rw-r--r--src/parser/hdr_expires.h39
-rw-r--r--src/parser/hdr_from.cpp88
-rw-r--r--src/parser/hdr_from.h58
-rw-r--r--src/parser/hdr_in_reply_to.cpp42
-rw-r--r--src/parser/hdr_in_reply_to.h39
-rw-r--r--src/parser/hdr_max_forwards.cpp36
-rw-r--r--src/parser/hdr_max_forwards.h39
-rw-r--r--src/parser/hdr_mime_version.cpp33
-rw-r--r--src/parser/hdr_mime_version.h37
-rw-r--r--src/parser/hdr_min_expires.cpp36
-rw-r--r--src/parser/hdr_min_expires.h39
-rw-r--r--src/parser/hdr_organization.cpp33
-rw-r--r--src/parser/hdr_organization.h37
-rw-r--r--src/parser/hdr_p_asserted_identity.cpp43
-rw-r--r--src/parser/hdr_p_asserted_identity.h41
-rw-r--r--src/parser/hdr_p_preferred_identity.cpp43
-rw-r--r--src/parser/hdr_p_preferred_identity.h41
-rw-r--r--src/parser/hdr_priority.cpp33
-rw-r--r--src/parser/hdr_priority.h37
-rw-r--r--src/parser/hdr_privacy.cpp51
-rw-r--r--src/parser/hdr_privacy.h48
-rw-r--r--src/parser/hdr_proxy_authenticate.cpp33
-rw-r--r--src/parser/hdr_proxy_authenticate.h41
-rw-r--r--src/parser/hdr_proxy_authorization.cpp92
-rw-r--r--src/parser/hdr_proxy_authorization.h50
-rw-r--r--src/parser/hdr_proxy_require.cpp42
-rw-r--r--src/parser/hdr_proxy_require.h37
-rw-r--r--src/parser/hdr_rack.cpp64
-rw-r--r--src/parser/hdr_rack.h47
-rw-r--r--src/parser/hdr_record_route.cpp66
-rw-r--r--src/parser/hdr_record_route.h44
-rw-r--r--src/parser/hdr_refer_sub.cpp49
-rw-r--r--src/parser/hdr_refer_sub.h46
-rw-r--r--src/parser/hdr_refer_to.cpp70
-rw-r--r--src/parser/hdr_refer_to.h47
-rw-r--r--src/parser/hdr_referred_by.cpp80
-rw-r--r--src/parser/hdr_referred_by.h49
-rw-r--r--src/parser/hdr_replaces.cpp77
-rw-r--r--src/parser/hdr_replaces.h51
-rw-r--r--src/parser/hdr_reply_to.cpp68
-rw-r--r--src/parser/hdr_reply_to.h46
-rw-r--r--src/parser/hdr_request_disposition.cpp213
-rw-r--r--src/parser/hdr_request_disposition.h111
-rw-r--r--src/parser/hdr_require.cpp75
-rw-r--r--src/parser/hdr_require.h41
-rw-r--r--src/parser/hdr_retry_after.cpp69
-rw-r--r--src/parser/hdr_retry_after.h46
-rw-r--r--src/parser/hdr_route.cpp67
-rw-r--r--src/parser/hdr_route.h47
-rw-r--r--src/parser/hdr_rseq.cpp40
-rw-r--r--src/parser/hdr_rseq.h43
-rw-r--r--src/parser/hdr_server.cpp77
-rw-r--r--src/parser/hdr_server.h55
-rw-r--r--src/parser/hdr_service_route.cpp66
-rw-r--r--src/parser/hdr_service_route.h44
-rw-r--r--src/parser/hdr_sip_etag.cpp31
-rw-r--r--src/parser/hdr_sip_etag.h49
-rw-r--r--src/parser/hdr_sip_if_match.cpp36
-rw-r--r--src/parser/hdr_sip_if_match.h52
-rw-r--r--src/parser/hdr_subject.cpp34
-rw-r--r--src/parser/hdr_subject.h37
-rw-r--r--src/parser/hdr_subscription_state.cpp78
-rw-r--r--src/parser/hdr_subscription_state.h63
-rw-r--r--src/parser/hdr_supported.cpp72
-rw-r--r--src/parser/hdr_supported.h49
-rw-r--r--src/parser/hdr_timestamp.cpp51
-rw-r--r--src/parser/hdr_timestamp.h40
-rw-r--r--src/parser/hdr_to.cpp80
-rw-r--r--src/parser/hdr_to.h48
-rw-r--r--src/parser/hdr_unsupported.cpp59
-rw-r--r--src/parser/hdr_unsupported.h39
-rw-r--r--src/parser/hdr_user_agent.cpp47
-rw-r--r--src/parser/hdr_user_agent.h44
-rw-r--r--src/parser/hdr_via.cpp211
-rw-r--r--src/parser/hdr_via.h73
-rw-r--r--src/parser/hdr_warning.cpp89
-rw-r--r--src/parser/hdr_warning.h83
-rw-r--r--src/parser/hdr_www_authenticate.cpp33
-rw-r--r--src/parser/hdr_www_authenticate.h41
-rw-r--r--src/parser/header.cpp82
-rw-r--r--src/parser/header.h66
-rw-r--r--src/parser/identity.cpp51
-rw-r--r--src/parser/identity.h40
-rw-r--r--src/parser/media_type.cpp100
-rw-r--r--src/parser/media_type.h84
-rw-r--r--src/parser/milenage.cpp284
-rw-r--r--src/parser/milenage.h35
-rw-r--r--src/parser/parameter.cpp90
-rw-r--r--src/parser/parameter.h60
-rw-r--r--src/parser/parse_ctrl.cpp136
-rw-r--r--src/parser/parse_ctrl.h131
-rw-r--r--src/parser/parser.cxx5106
-rw-r--r--src/parser/parser.h252
-rw-r--r--src/parser/parser.yxx1594
-rw-r--r--src/parser/request.cpp769
-rw-r--r--src/parser/request.h218
-rwxr-xr-xsrc/parser/response.cpp237
-rw-r--r--src/parser/response.h214
-rw-r--r--src/parser/rijndael.cpp440
-rw-r--r--src/parser/rijndael.h26
-rw-r--r--src/parser/route.cpp48
-rw-r--r--src/parser/route.h41
-rw-r--r--src/parser/scanner.cxx3485
-rw-r--r--src/parser/scanner.lxx333
-rw-r--r--src/parser/sip_body.cpp326
-rw-r--r--src/parser/sip_body.h260
-rw-r--r--src/parser/sip_message.cpp476
-rw-r--r--src/parser/sip_message.h270
158 files changed, 22819 insertions, 0 deletions
diff --git a/src/parser/Makefile.am b/src/parser/Makefile.am
new file mode 100644
index 0000000..67bf122
--- /dev/null
+++ b/src/parser/Makefile.am
@@ -0,0 +1,195 @@
+AM_CPPFLAGS = -Wall $(XML2_CFLAGS) -I$(top_srcdir)/src
+
+# bison flags
+AM_YFLAGS = -d
+
+# flex flags
+# The -s flag is not used on purpose. As it is better to have
+# some unmatched symbols echoed to stdout then a jammed flex
+# causing the process to die.
+AM_LFLAGS = -i
+
+# The output of bison cannot be compiled with the -O2 flag.
+# With the -O2 flag g++ crashes. The -O2 flag is stripped from
+# CXXFLAGS by configure.
+# rumen:
+# Above don't work.
+# It is enought to drop -funit-at-a-time set when -O2 flag is set.
+# The error is:
+# "cc1plus: out of memory allocating 336746144 bytes after a total of 10846208 bytes."
+# Note user can specify -O2 in CXXFLAGS at configure time !
+# Also note that unit-at-a-time if new for gcc 3.4 !
+# See http://lists.debian.org/debian-gcc/2006/07/msg00281.html
+# that claim to be fixed in gcc-4.1+ .
+
+AM_CXXFLAGS = -fno-unit-at-a-time
+
+
+# This target is only for testing the parser in isolation
+#noinst_PROGRAMS = sipparse
+#
+#sipparse_SOURCES = main.cpp
+#
+#sipparse_LDADD = $(top_builddir)/src/util.o\
+# $(top_builddir)/src/parser/libsipparser.a\
+# $(top_builddir)/src/sdp/libsdpparser.a\
+# $(top_builddir)/src/sockets/libsocket.a\
+# -lresolv
+
+noinst_LIBRARIES = libsipparser.a
+
+libsipparser_a_SOURCES =\
+ challenge.cpp\
+ coding.cpp\
+ credentials.cpp\
+ definitions.cpp\
+ hdr_accept.cpp\
+ hdr_accept_encoding.cpp\
+ hdr_accept_language.cpp\
+ hdr_alert_info.cpp\
+ hdr_allow.cpp\
+ hdr_allow_events.cpp\
+ hdr_auth_info.cpp\
+ hdr_authorization.cpp\
+ hdr_call_id.cpp\
+ hdr_call_info.cpp\
+ hdr_contact.cpp\
+ hdr_content_disp.cpp\
+ hdr_content_encoding.cpp\
+ hdr_content_language.cpp\
+ hdr_content_length.cpp\
+ hdr_content_type.cpp\
+ hdr_cseq.cpp\
+ hdr_date.cpp\
+ hdr_error_info.cpp\
+ hdr_event.cpp\
+ hdr_expires.cpp\
+ hdr_from.cpp\
+ hdr_in_reply_to.cpp\
+ hdr_max_forwards.cpp\
+ hdr_min_expires.cpp\
+ hdr_mime_version.cpp\
+ hdr_organization.cpp\
+ hdr_priority.cpp\
+ hdr_privacy.cpp\
+ hdr_p_asserted_identity.cpp\
+ hdr_p_preferred_identity.cpp\
+ hdr_proxy_authenticate.cpp\
+ hdr_proxy_authorization.cpp\
+ hdr_proxy_require.cpp\
+ hdr_rack.cpp\
+ hdr_record_route.cpp\
+ hdr_refer_sub.cpp\
+ hdr_refer_to.cpp\
+ hdr_referred_by.cpp\
+ hdr_replaces.cpp\
+ hdr_reply_to.cpp\
+ hdr_require.cpp\
+ hdr_request_disposition.cpp\
+ hdr_retry_after.cpp\
+ hdr_route.cpp\
+ hdr_rseq.cpp\
+ hdr_server.cpp\
+ hdr_service_route.cpp\
+ hdr_sip_etag.cpp\
+ hdr_sip_if_match.cpp\
+ hdr_subject.cpp\
+ hdr_subscription_state.cpp\
+ hdr_supported.cpp\
+ hdr_timestamp.cpp\
+ hdr_to.cpp\
+ hdr_unsupported.cpp\
+ hdr_user_agent.cpp\
+ hdr_via.cpp\
+ hdr_warning.cpp\
+ hdr_www_authenticate.cpp\
+ header.cpp\
+ identity.cpp\
+ media_type.cpp\
+ milenage.cpp\
+ parameter.cpp\
+ parse_ctrl.cpp\
+ parser.yxx\
+ request.cpp\
+ response.cpp\
+ rijndael.cpp\
+ route.cpp\
+ scanner.lxx\
+ sip_body.cpp\
+ sip_message.cpp\
+ challenge.h\
+ coding.h\
+ credentials.h\
+ definitions.h\
+ hdr_accept.h\
+ hdr_accept_encoding.h\
+ hdr_accept_language.h\
+ hdr_alert_info.h\
+ hdr_allow.h\
+ hdr_allow_events.h\
+ hdr_auth_info.h\
+ hdr_authorization.h\
+ hdr_call_id.h\
+ hdr_call_info.h\
+ hdr_contact.h\
+ hdr_content_disp.h\
+ hdr_content_encoding.h\
+ hdr_content_language.h\
+ hdr_content_length.h\
+ hdr_content_type.h\
+ hdr_cseq.h\
+ hdr_date.h\
+ hdr_error_info.h\
+ hdr_event.h\
+ hdr_expires.h\
+ hdr_from.h\
+ hdr_in_reply_to.h\
+ hdr_max_forwards.h\
+ hdr_min_expires.h\
+ hdr_mime_version.h\
+ hdr_organization.h\
+ hdr_p_asserted_identity.h\
+ hdr_p_preferred_identity.h\
+ hdr_priority.h\
+ hdr_privacy.h\
+ hdr_proxy_authenticate.h\
+ hdr_proxy_authorization.h\
+ hdr_proxy_require.h\
+ hdr_rack.h\
+ hdr_record_route.h\
+ hdr_refer_sub.h\
+ hdr_refer_to.h\
+ hdr_referred_by.h\
+ hdr_replaces.h\
+ hdr_reply_to.h\
+ hdr_require.h\
+ hdr_request_disposition.h\
+ hdr_retry_after.h\
+ hdr_route.h\
+ hdr_rseq.h\
+ hdr_server.h\
+ hdr_service_route.h\
+ hdr_sip_etag.h\
+ hdr_sip_if_match.h\
+ hdr_subject.h\
+ hdr_subscription_state.h\
+ hdr_supported.h\
+ hdr_timestamp.h\
+ hdr_to.h\
+ hdr_unsupported.h\
+ hdr_user_agent.h\
+ hdr_via.h\
+ hdr_warning.h\
+ hdr_www_authenticate.h\
+ header.h\
+ identity.h\
+ media_type.h\
+ milenage.h\
+ parameter.h\
+ parse_ctrl.h\
+ request.h\
+ response.h\
+ rijndael.h\
+ route.h\
+ sip_body.h\
+ sip_message.h
diff --git a/src/parser/challenge.cpp b/src/parser/challenge.cpp
new file mode 100644
index 0000000..9c365a5
--- /dev/null
+++ b/src/parser/challenge.cpp
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <iostream>
+#include "challenge.h"
+#include "definitions.h"
+#include "log.h"
+#include "util.h"
+
+t_digest_challenge::t_digest_challenge() {
+ stale = false;
+
+ // The default algorithm is MD5.
+ algorithm = ALG_MD5;
+}
+
+string t_digest_challenge::encode(void) const {
+ string s;
+
+ if (realm.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "realm=";
+ s += '"';
+ s += realm;
+ s += '"';
+ }
+
+ if (domain.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "domain=";
+ s += '"';
+
+ for (list<t_url>::const_iterator i = domain.begin();
+ i != domain.end(); i++)
+ {
+ if (i != domain.begin()) s += ' ';
+ s += i->encode();
+ }
+
+ s += '"';
+ }
+
+ if (nonce.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "nonce=";
+ s += '"';
+ s += nonce;
+ s += '"';
+ }
+
+ if (opaque.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "opaque=";
+ s += '"';
+ s += opaque;
+ s += '"';
+ }
+
+ // RFC 2617 3.2.1
+ // If the stale flag is absent it means stale=false.
+ if (stale) {
+ if (s.size() > 0) s += ',';
+ s += "stale=true";
+ }
+
+ if (algorithm.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "algorithm=";
+ s += algorithm;
+ }
+
+ if (qop_options.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "qop=";
+ s += '"';
+
+ for (list<string>::const_iterator i = qop_options.begin();
+ i != qop_options.end(); i++)
+ {
+ if (i != qop_options.begin()) s += ',';
+ s += *i;
+ }
+
+ s += '"';
+ }
+
+ for (list<t_parameter>::const_iterator i = auth_params.begin();
+ i != auth_params.end(); i++)
+ {
+ if (s.size() > 0) s += ',';
+ s += i->encode();
+ }
+
+ return s;
+}
+
+bool t_digest_challenge::set_attr(const t_parameter &p) {
+ if (p.name == "realm")
+ realm = p.value;
+ else if (p.name == "nonce")
+ nonce = p.value;
+ else if (p.name == "opaque")
+ opaque = p.value;
+ else if (p.name == "algorithm")
+ algorithm = p.value;
+ else if (p.name == "domain") {
+ vector<string> l = split_ws(p.value);
+ for (vector<string>::iterator i = l.begin();
+ i != l.end(); i++)
+ {
+ t_url u(*i);
+ if (u.is_valid()) {
+ domain.push_back(u);
+ } else {
+ log_file->write_header("t_digest_challenge::set_attr",
+ LOG_SIP, LOG_WARNING);
+ log_file->write_raw("Invalid domain in digest challenge: ");
+ log_file->write_raw(*i);
+ log_file->write_endl();
+ log_file->write_footer();
+ }
+ }
+ }
+ else if (p.name == "qop") {
+ vector<string> l = split(p.value, ',');
+ for (vector<string>::iterator i = l.begin();
+ i != l.end(); i++)
+ {
+ qop_options.push_back(trim(*i));
+ }
+ }
+ else if (p.name == "stale") {
+ if (cmp_nocase(p.value, "true") == 0)
+ stale = true;
+ else
+ // RFC 2617 3.2.1
+ // Any value other than false should be interpreted
+ // as false.
+ stale = false;
+ }
+ else
+ auth_params.push_back(p);
+
+ return true;
+}
+
+string t_challenge::encode(void) const {
+ string s = auth_scheme;
+ s += ' ';
+
+ if (auth_scheme == AUTH_DIGEST) {
+ s += digest_challenge.encode();
+ } else {
+ for (list<t_parameter>::const_iterator i = auth_params.begin();
+ i != auth_params.end(); i++)
+ {
+ if (i != auth_params.begin()) s += ',';
+ s += i->encode();
+ }
+ }
+
+ return s;
+}
diff --git a/src/parser/challenge.h b/src/parser/challenge.h
new file mode 100644
index 0000000..cc0c3bd
--- /dev/null
+++ b/src/parser/challenge.h
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Challenges are used in Proxy-Authenticate and
+// WWW-Authenticate headers
+
+#ifndef _CHALLENGE_H
+#define _CHALLENGE_H
+
+#include <list>
+#include <string>
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_digest_challenge {
+public:
+ string realm;
+ list<t_url> domain;
+ string nonce;
+ string opaque;
+ bool stale;
+ string algorithm;
+ list<string> qop_options;
+ list<t_parameter> auth_params;
+
+ t_digest_challenge();
+
+ // Set one of the attributes to a value. The parameter p
+ // indicated wich attribute (p.name) should be set to
+ // which value (p.value).
+ // Returns false if p does not contain a valid attribute
+ // setting.
+ bool set_attr(const t_parameter &p);
+
+ string encode(void) const;
+};
+
+class t_challenge {
+public:
+ string auth_scheme;
+ t_digest_challenge digest_challenge;
+
+ // auth_params is used when auth_scheme is not Digest.
+ list<t_parameter> auth_params;
+
+ string encode(void) const;
+};
+
+#endif
diff --git a/src/parser/coding.cpp b/src/parser/coding.cpp
new file mode 100644
index 0000000..83f8e8f
--- /dev/null
+++ b/src/parser/coding.cpp
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "coding.h"
+#include "util.h"
+
+t_coding::t_coding() {
+ q = 1.0;
+}
+
+t_coding::t_coding(const string &s) {
+ q = 1.0;
+ content_coding = s;
+}
+
+string t_coding::encode(void) const {
+ string s;
+
+ s = content_coding;
+
+ if (q != 1.0) {
+ s += ";q=";
+ s += float2str(q, 1);
+ }
+
+ return s;
+}
diff --git a/src/parser/coding.h b/src/parser/coding.h
new file mode 100644
index 0000000..7169845
--- /dev/null
+++ b/src/parser/coding.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Content coding type
+
+#ifndef _CODING_H
+#define _CODING_H
+
+#include <string>
+
+using namespace std;
+
+class t_coding {
+public:
+ string content_coding;
+ float q; // quality factor;
+
+ t_coding();
+ t_coding(const string &s);
+
+ string encode(void) const;
+};
+
+#endif
diff --git a/src/parser/credentials.cpp b/src/parser/credentials.cpp
new file mode 100644
index 0000000..067744c
--- /dev/null
+++ b/src/parser/credentials.cpp
@@ -0,0 +1,158 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "credentials.h"
+#include "definitions.h"
+#include "util.h"
+
+t_digest_response::t_digest_response() {
+ nonce_count = 0;
+}
+
+string t_digest_response::encode(void) const {
+ string s;
+
+ if (username.size() > 0) {
+ s += "username=";
+ s += '"';
+ s += username;
+ s += '"';
+ }
+
+ if (realm.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "realm=";
+ s += '"';
+ s += realm;
+ s += '"';
+ }
+
+ if (nonce.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "nonce=";
+ s += '"';
+ s += nonce;
+ s += '"';
+ }
+
+ if (digest_uri.is_valid()) {
+ if (s.size() > 0) s += ',';
+ s += "uri=";
+ s += '"';
+ s += digest_uri.encode();
+ s += '"';
+ }
+
+ if (dresponse.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "response=";
+ s += '"';
+ s += dresponse;
+ s += '"';
+ }
+
+ if (algorithm.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "algorithm=";
+ s += algorithm;
+ }
+
+ if (cnonce.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "cnonce=";
+ s += '"';
+ s += cnonce;
+ s += '"';
+ }
+
+ if (opaque.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "opaque=";
+ s += '"';
+ s += opaque;
+ s += '"';
+ }
+
+ if (message_qop.size() > 0) {
+ if (s.size() > 0) s += ',';
+ s += "qop=";
+ s += message_qop;
+ }
+
+ if (nonce_count > 0) {
+ if (s.size() > 0) s += ',';
+ s += "nc=";
+ s += ulong2str(nonce_count, "%08x");
+ }
+
+ for (list<t_parameter>::const_iterator i = auth_params.begin();
+ i != auth_params.end(); i++)
+ {
+ if (s.size() > 0) s += ',';
+ s += i->encode();
+ }
+
+ return s;
+}
+
+bool t_digest_response::set_attr(const t_parameter &p) {
+ if (p.name == "username")
+ username = p.value;
+ else if (p.name == "realm")
+ realm = p.value;
+ else if (p.name == "nonce")
+ nonce = p.value;
+ else if (p.name == "digest_uri") {
+ digest_uri.set_url(p.value);
+ if (!digest_uri.is_valid()) return false;
+ }
+ else if (p.name == "response")
+ dresponse = p.value;
+ else if (p.name == "cnonce")
+ cnonce = p.value;
+ else if (p.name == "opaque")
+ opaque = p.value;
+ else if (p.name == "algorithm")
+ algorithm = p.value;
+ else if (p.name == "qop")
+ message_qop = p.value;
+ else if (p.name == "nc")
+ nonce_count = hex2int(p.value);
+ else
+ auth_params.push_back(p);
+
+ return true;
+}
+
+string t_credentials::encode(void) const {
+ string s = auth_scheme;
+ s += ' ';
+
+ if (auth_scheme == AUTH_DIGEST) {
+ s += digest_response.encode();
+ } else {
+ for (list<t_parameter>::const_iterator i = auth_params.begin();
+ i != auth_params.end(); i++)
+ {
+ if (i != auth_params.begin()) s += ',';
+ s += i->encode();
+ }
+ }
+
+ return s;
+}
diff --git a/src/parser/credentials.h b/src/parser/credentials.h
new file mode 100644
index 0000000..15fa881
--- /dev/null
+++ b/src/parser/credentials.h
@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Credentials are used in Proxy-Authorization and
+// Authorization headers
+
+#ifndef _CREDENTIALS_H
+#define _CREDENTIALS_H
+
+#include <list>
+#include <string>
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_digest_response {
+public:
+ string username;
+ string realm;
+ string nonce;
+ t_url digest_uri;
+ string dresponse;
+ string algorithm;
+ string cnonce;
+ string opaque;
+ string message_qop;
+ unsigned long nonce_count;
+ list<t_parameter> auth_params;
+
+ t_digest_response();
+
+ // Set one of the attributes to a value. The parameter p
+ // indicated wich attribute (p.name) should be set to
+ // which value (p.value).
+ // Returns false if p does not contain a valid attribute
+ // setting.
+ bool set_attr(const t_parameter &p);
+
+ string encode(void) const;
+};
+
+class t_credentials {
+public:
+ string auth_scheme;
+ t_digest_response digest_response;
+
+ // auth_params is used when auth_scheme is not Digest.
+ list<t_parameter> auth_params;
+
+ string encode(void) const;
+};
+
+#endif
diff --git a/src/parser/definitions.cpp b/src/parser/definitions.cpp
new file mode 100644
index 0000000..c849553
--- /dev/null
+++ b/src/parser/definitions.cpp
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <assert.h>
+#include "definitions.h"
+#include "parse_ctrl.h"
+
+string method2str(const t_method &m, const string &unknown) {
+ switch (m) {
+ case INVITE: return "INVITE";
+ case ACK: return "ACK";
+ case OPTIONS: return "OPTIONS";
+ case BYE: return "BYE";
+ case CANCEL: return "CANCEL";
+ case REGISTER: return "REGISTER";
+ case PRACK: return "PRACK";
+ case SUBSCRIBE: return "SUBSCRIBE";
+ case NOTIFY: return "NOTIFY";
+ case REFER: return "REFER";
+ case INFO: return "INFO";
+ case MESSAGE: return "MESSAGE";
+ case PUBLISH: return "PUBLISH";
+ case METHOD_UNKNOWN: return unknown;
+ default: assert(false);
+ }
+}
+
+t_method str2method(const string &s) {
+ if (s == "INVITE") return INVITE;
+ if (s == "ACK") return ACK;
+ if (s == "OPTIONS") return OPTIONS;
+ if (s == "BYE") return BYE;
+ if (s == "CANCEL") return CANCEL;
+ if (s == "REGISTER") return REGISTER;
+ if (s == "PRACK") return PRACK;
+ if (s == "SUBSCRIBE") return SUBSCRIBE;
+ if (s == "NOTIFY") return NOTIFY;
+ if (s == "REFER") return REFER;
+ if (s == "INFO") return INFO;
+ if (s == "MESSAGE") return MESSAGE;
+ if (s == "PUBLISH") return PUBLISH;
+
+ return METHOD_UNKNOWN;
+}
diff --git a/src/parser/definitions.h b/src/parser/definitions.h
new file mode 100644
index 0000000..af7a55a
--- /dev/null
+++ b/src/parser/definitions.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 _DEFINITIONS_H
+#define _DEFINITIONS_H
+
+#include <string>
+#include "protocol.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+#define SIP_VERSION "2.0"
+
+// RFC 3261
+#ifndef RFC3261_COOKIE
+#define RFC3261_COOKIE "z9hG4bK"
+#endif
+
+// Authentication schemes
+#define AUTH_DIGEST "Digest"
+
+// Authentication algorithms
+#define ALG_MD5 "MD5"
+#define ALG_AKAV1_MD5 "AKAV1-MD5"
+#define ALG_MD5_SESS "MD5-sess"
+
+// Authentication QOP
+#define QOP_AUTH "auth"
+#define QOP_AUTH_INT "auth-int"
+
+/** SIP request methods. */
+enum t_method {
+ INVITE,
+ ACK,
+ OPTIONS,
+ BYE,
+ CANCEL,
+ REGISTER,
+ PRACK,
+ SUBSCRIBE,
+ NOTIFY,
+ REFER,
+ INFO,
+ MESSAGE,
+ PUBLISH,
+ METHOD_UNKNOWN
+};
+
+/**
+ * Convert a method to a string.
+ * @param m The method.
+ * @param unknown Method name if m is @ref METHOD_UNKNOWN.
+ * @return The name of the method.
+ */
+string method2str(const t_method &m, const string &unknown = "");
+
+/**
+ * Convert a string to a method.
+ * @param s The string.
+ * @return The method having s as name. If s is an unknown name,
+ * then @ref METHOD_UNKNOWN is returned.
+ */
+t_method str2method(const string &s);
+
+#endif
diff --git a/src/parser/hdr_accept.cpp b/src/parser/hdr_accept.cpp
new file mode 100644
index 0000000..31bf80e
--- /dev/null
+++ b/src/parser/hdr_accept.cpp
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_accept.h"
+#include "definitions.h"
+
+t_hdr_accept::t_hdr_accept() : t_header("Accept") {};
+
+void t_hdr_accept::add_media(const t_media &media) {
+ populated = true;
+ media_list.push_back(media);
+}
+
+void t_hdr_accept::set_empty(void) {
+ populated = true;
+ media_list.clear();
+}
+
+string t_hdr_accept::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_media>::const_iterator i = media_list.begin();
+ i != media_list.end(); i++)
+ {
+ if (i != media_list.begin()) s += ",";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_accept.h b/src/parser/hdr_accept.h
new file mode 100644
index 0000000..feb90af
--- /dev/null
+++ b/src/parser/hdr_accept.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Accept header
+
+#ifndef _HDR_ACCEPT_H
+#define _HDR_ACCEPT_H
+
+#include <list>
+#include "header.h"
+#include "media_type.h"
+
+class t_hdr_accept : public t_header {
+public:
+ list<t_media> media_list; // list of accepted media
+
+ t_hdr_accept();
+
+ // Add a media to the list of accepted media
+ void add_media(const t_media &media);
+
+ // Clear the list of features, but make the header 'populated'.
+ // An empty header will be in the message.
+ void set_empty(void);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_accept_encoding.cpp b/src/parser/hdr_accept_encoding.cpp
new file mode 100644
index 0000000..bd44104
--- /dev/null
+++ b/src/parser/hdr_accept_encoding.cpp
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_accept_encoding.h"
+#include "definitions.h"
+
+t_hdr_accept_encoding::t_hdr_accept_encoding() : t_header("Accept-Encoding") {};
+
+void t_hdr_accept_encoding::add_coding(const t_coding &coding) {
+ populated = true;
+ coding_list.push_back(coding);
+}
+
+string t_hdr_accept_encoding::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_coding>::const_iterator i = coding_list.begin();
+ i != coding_list.end(); i++)
+ {
+ if (i != coding_list.begin()) s += ",";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_accept_encoding.h b/src/parser/hdr_accept_encoding.h
new file mode 100644
index 0000000..9c05d3c
--- /dev/null
+++ b/src/parser/hdr_accept_encoding.h
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Accept-Encoding header
+
+#ifndef _HDR_ACCEPT_ENCODING_H
+#define _HDR_ACCEPT_ENCODING_H
+
+#include <list>
+#include <string>
+#include "coding.h"
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_accept_encoding : public t_header {
+public:
+ list<t_coding> coding_list; // list of content codings;
+
+ t_hdr_accept_encoding();
+
+ // Add a coding to the list of content codings
+ void add_coding(const t_coding &coding);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_accept_language.cpp b/src/parser/hdr_accept_language.cpp
new file mode 100644
index 0000000..2f38bb4
--- /dev/null
+++ b/src/parser/hdr_accept_language.cpp
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_accept_language.h"
+#include "util.h"
+
+t_language::t_language() {
+ language = "en";
+ q = 1.0;
+}
+
+t_language::t_language(const string &l) {
+ language = l;
+ q = 1.0;
+}
+
+string t_language::encode(void) const {
+ string s;
+
+ s = language;
+ if (q != 1.0) {
+ s += ";q=";
+ s += float2str(q, 1);
+ }
+
+ return s;
+}
+
+
+t_hdr_accept_language::t_hdr_accept_language() : t_header("Accept-Language") {};
+
+void t_hdr_accept_language::add_language(const t_language &language) {
+ populated = true;
+ language_list.push_back(language);
+}
+
+string t_hdr_accept_language::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_language>::const_iterator i = language_list.begin();
+ i != language_list.end(); i++)
+ {
+ if (i != language_list.begin()) s += ",";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_accept_language.h b/src/parser/hdr_accept_language.h
new file mode 100644
index 0000000..e1cc85b
--- /dev/null
+++ b/src/parser/hdr_accept_language.h
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Accept_Language header
+
+#ifndef _HDR_ACCEPT_LANGUAGE_H
+#define _HDR_ACCEPT_LANGUAGE_H
+
+#include <list>
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_language {
+public:
+ string language;
+ float q; // quality factor
+
+ t_language();
+ t_language(const string &l);
+ string encode(void) const;
+};
+
+class t_hdr_accept_language : public t_header {
+public:
+ list<t_language> language_list; // list of accepted languages
+
+ t_hdr_accept_language();
+
+ // Add a language to the list of accepted media
+ void add_language(const t_language &language);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_alert_info.cpp b/src/parser/hdr_alert_info.cpp
new file mode 100644
index 0000000..310d08b
--- /dev/null
+++ b/src/parser/hdr_alert_info.cpp
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_alert_info.h"
+
+void t_alert_param::add_param(const t_parameter &p) {
+ parameter_list.push_back(p);
+}
+
+string t_alert_param::encode(void) const {
+ string s;
+
+ s = '<' + uri.encode() + '>';
+ s += param_list2str(parameter_list);
+
+ return s;
+}
+
+
+t_hdr_alert_info::t_hdr_alert_info() : t_header("Alert-Info") {};
+
+void t_hdr_alert_info::add_param(const t_alert_param &p) {
+ populated = true;
+ alert_param_list.push_back(p);
+}
+
+string t_hdr_alert_info::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_alert_param>::const_iterator i = alert_param_list.begin();
+ i != alert_param_list.end(); i++)
+ {
+ if (i != alert_param_list.begin()) s += ", ";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_alert_info.h b/src/parser/hdr_alert_info.h
new file mode 100644
index 0000000..d9f72ab
--- /dev/null
+++ b/src/parser/hdr_alert_info.h
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Alert-Info header
+
+#ifndef _HDR_ALERT_INFO_H
+#define _HDR_ALERT_INFO_H
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_alert_param {
+public:
+ t_url uri;
+ list<t_parameter> parameter_list;
+
+ void add_param(const t_parameter &p);
+ string encode(void) const;
+};
+
+class t_hdr_alert_info : public t_header {
+public:
+ list<t_alert_param> alert_param_list;
+
+ t_hdr_alert_info();
+
+ // Add a paramter to the list of alert parameters
+ void add_param(const t_alert_param &p);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_allow.cpp b/src/parser/hdr_allow.cpp
new file mode 100644
index 0000000..8031f50
--- /dev/null
+++ b/src/parser/hdr_allow.cpp
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <algorithm>
+
+#include "definitions.h"
+#include "hdr_allow.h"
+
+using namespace std;
+
+t_hdr_allow::t_hdr_allow() : t_header("Allow") {}
+
+void t_hdr_allow::add_method(const t_method &m, const string &unknown) {
+ populated = true;
+
+ if (m != METHOD_UNKNOWN) {
+ method_list.push_back(m);
+ } else {
+ unknown_methods.push_back(unknown);
+ }
+}
+
+void t_hdr_allow::add_method(const string &s) {
+ populated = true;
+
+ t_method m = str2method(s);
+ if (m != METHOD_UNKNOWN) {
+ method_list.push_back(m);
+ } else {
+ unknown_methods.push_back(s);
+ }
+}
+
+bool t_hdr_allow::contains_method(const t_method &m) const {
+ return (find(method_list.begin(), method_list.end(), m) != method_list.end());
+}
+
+string t_hdr_allow::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_method>::const_iterator i = method_list.begin();
+ i != method_list.end(); i++)
+ {
+ if (i != method_list.begin()) s += ",";
+ s += method2str(*i);
+ }
+
+ for (list<string>::const_iterator i = unknown_methods.begin();
+ i != unknown_methods.end(); i++)
+ {
+ if (i != unknown_methods.begin() || method_list.size() != 0) {
+ s += ",";
+ }
+ s += *i;
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_allow.h b/src/parser/hdr_allow.h
new file mode 100644
index 0000000..2aafbc9
--- /dev/null
+++ b/src/parser/hdr_allow.h
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Allow header
+
+#ifndef _HDR_ALLOW_H
+#define _HDR_ALLOW_H
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "definitions.h"
+
+using namespace std;
+
+class t_hdr_allow : public t_header {
+public:
+ list<t_method> method_list;
+
+ // Unknown methods are represented as strings
+ list<string> unknown_methods;
+
+ t_hdr_allow();
+ void add_method(const t_method &m, const string &unknown = "");
+ void add_method(const string &s);
+ bool contains_method(const t_method &m) const;
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_allow_events.cpp b/src/parser/hdr_allow_events.cpp
new file mode 100644
index 0000000..f88c42c
--- /dev/null
+++ b/src/parser/hdr_allow_events.cpp
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_allow_events.h"
+#include "parse_ctrl.h"
+
+t_hdr_allow_events::t_hdr_allow_events() : t_header("Allow-Events", "u") {}
+
+void t_hdr_allow_events::add_event_type(const string &t) {
+ populated = true;
+ event_types.push_back(t);
+}
+
+string t_hdr_allow_events::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<string>::const_iterator i = event_types.begin();
+ i != event_types.end(); i++)
+ {
+ if (i != event_types.begin()) s += ",";
+ s += *i;
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_allow_events.h b/src/parser/hdr_allow_events.h
new file mode 100644
index 0000000..c0ee9a8
--- /dev/null
+++ b/src/parser/hdr_allow_events.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Allow-Events header
+// RFC 3265
+
+#ifndef _HDR_ALLOW_EVENTS
+#define _HDR_ALLOW_EVENTS
+
+#include <list>
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_allow_events : public t_header {
+public:
+ list<string> event_types;
+
+ t_hdr_allow_events();
+ void add_event_type(const string &t);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_auth_info.cpp b/src/parser/hdr_auth_info.cpp
new file mode 100644
index 0000000..7962432
--- /dev/null
+++ b/src/parser/hdr_auth_info.cpp
@@ -0,0 +1,99 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_auth_info.h"
+#include "definitions.h"
+#include "util.h"
+
+t_hdr_auth_info::t_hdr_auth_info() : t_header("Authentication-Info") {
+ nonce_count = 0;
+}
+
+void t_hdr_auth_info::set_next_nonce(const string &nn) {
+ populated = true;
+ next_nonce = nn;
+}
+
+void t_hdr_auth_info::set_message_qop(const string &mq) {
+ populated = true;
+ message_qop = mq;
+}
+
+void t_hdr_auth_info::set_response_auth(const string &ra) {
+ populated = true;
+ response_auth = ra;
+}
+
+void t_hdr_auth_info::set_cnonce(const string &cn) {
+ populated = true;
+ cnonce = cn;
+}
+
+void t_hdr_auth_info::set_nonce_count(const unsigned long &nc) {
+ populated = true;
+ nonce_count = nc;
+}
+
+string t_hdr_auth_info::encode_value(void) const {
+ string s;
+ bool add_comma = false;
+
+ if (!populated) return s;
+
+ if (next_nonce.size() > 0) {
+ s += "nextnonce=";
+ s += '"';
+ s += next_nonce;
+ s += '"';
+ add_comma = true;
+ }
+
+ if (message_qop.size() > 0) {
+ if (add_comma) s += ',';
+ s += "qop=";
+ s += message_qop;
+ add_comma = true;
+ }
+
+ if (response_auth.size() > 0) {
+ if (add_comma) s += ',';
+ s += "rspauth=";
+ s += '"';
+ s += response_auth;
+ s += '"';
+ add_comma = true;
+ }
+
+ if (cnonce.size() > 0) {
+ if (add_comma) s += ',';
+ s += "cnonce=";
+ s += '"';
+ s += cnonce;
+ s += '"';
+ add_comma = true;
+ }
+
+ if (nonce_count > 0) {
+ if (add_comma) s += ',';
+ s += "nc=";
+ s += ulong2str(nonce_count, "%08x");
+ add_comma = true;
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_auth_info.h b/src/parser/hdr_auth_info.h
new file mode 100644
index 0000000..16fe87d
--- /dev/null
+++ b/src/parser/hdr_auth_info.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Authentication-Info header
+
+#ifndef _HDR_AUTH_INFO_H
+#define _HDR_AUTH_INFO_H
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_auth_info : public t_header {
+public:
+ string next_nonce;
+ string message_qop;
+ string response_auth;
+ string cnonce;
+ unsigned long nonce_count;
+
+ t_hdr_auth_info();
+
+ void set_next_nonce(const string &nn);
+ void set_message_qop(const string &mq);
+ void set_response_auth(const string &ra);
+ void set_cnonce(const string &cn);
+ void set_nonce_count(const unsigned long &nc);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_authorization.cpp b/src/parser/hdr_authorization.cpp
new file mode 100644
index 0000000..61ae723
--- /dev/null
+++ b/src/parser/hdr_authorization.cpp
@@ -0,0 +1,92 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_authorization.h"
+#include "definitions.h"
+
+t_hdr_authorization::t_hdr_authorization() : t_header("Authorization") {}
+
+void t_hdr_authorization::add_credentials(const t_credentials &c) {
+ populated = true;
+ credentials_list.push_back(c);
+}
+
+string t_hdr_authorization::encode(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ // RFC 3261 20.7
+ // Each authorization should appear as a separate header
+ for (list<t_credentials>::const_iterator i = credentials_list.begin();
+ i != credentials_list.end(); i++)
+ {
+ s += header_name;
+ s += ": ";
+ s += i->encode();
+ s += CRLF;
+ }
+
+ return s;
+}
+
+string t_hdr_authorization::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_credentials>::const_iterator i = credentials_list.begin();
+ i != credentials_list.end(); i++)
+ {
+ if (i != credentials_list.begin()) s += ", ";
+ s += i->encode();
+ }
+
+ return s;
+}
+
+bool t_hdr_authorization::contains(const string &realm,
+ const t_url &uri) const
+{
+ for (list<t_credentials>::const_iterator i = credentials_list.begin();
+ i != credentials_list.end(); i++)
+ {
+ if (i->digest_response.realm == realm &&
+ i->digest_response.digest_uri == uri)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void t_hdr_authorization::remove_credentials(const string &realm,
+ const t_url &uri)
+{
+ for (list<t_credentials>::iterator i = credentials_list.begin();
+ i != credentials_list.end(); i++)
+ {
+ if (i->digest_response.realm == realm &&
+ i->digest_response.digest_uri == uri)
+ {
+ credentials_list.erase(i);
+ return;
+ }
+ }
+}
diff --git a/src/parser/hdr_authorization.h b/src/parser/hdr_authorization.h
new file mode 100644
index 0000000..a3065bb
--- /dev/null
+++ b/src/parser/hdr_authorization.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Authorization header
+
+#ifndef _HDR_AUTHORIZATION_H
+#define _HDR_AUTHORIZATION_H
+
+#include <list>
+#include <string>
+#include "credentials.h"
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_hdr_authorization : public t_header {
+public:
+ list<t_credentials> credentials_list;
+
+ t_hdr_authorization();
+
+ void add_credentials(const t_credentials &c);
+ string encode(void) const;
+ string encode_value(void) const;
+
+ // Return true if the header contains credentials for a realm/dest
+ bool contains(const string &realm, const t_url &uri) const;
+
+ // Remove credentials for a realm/dest
+ void remove_credentials(const string &realm, const t_url &uri);
+};
+
+#endif
+
diff --git a/src/parser/hdr_call_id.cpp b/src/parser/hdr_call_id.cpp
new file mode 100644
index 0000000..8763f76
--- /dev/null
+++ b/src/parser/hdr_call_id.cpp
@@ -0,0 +1,33 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_call_id.h"
+#include "definitions.h"
+#include "parse_ctrl.h"
+
+t_hdr_call_id::t_hdr_call_id() : t_header("Call-ID", "i") {};
+
+void t_hdr_call_id::set_call_id(const string &id) {
+ populated = true;
+ call_id = id;
+}
+
+string t_hdr_call_id::encode_value(void) const {
+ if (!populated) return "";
+ return call_id;
+}
diff --git a/src/parser/hdr_call_id.h b/src/parser/hdr_call_id.h
new file mode 100644
index 0000000..997d88f
--- /dev/null
+++ b/src/parser/hdr_call_id.h
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Call-ID header
+
+#ifndef _HDR_CALL_ID_H
+#define _HDR_CALL_ID_H
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_call_id : public t_header {
+public:
+ string call_id;
+
+ t_hdr_call_id();
+ void set_call_id(const string &id);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_call_info.cpp b/src/parser/hdr_call_info.cpp
new file mode 100644
index 0000000..3646472
--- /dev/null
+++ b/src/parser/hdr_call_info.cpp
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_call_info.h"
+
+void t_info_param::add_param(const t_parameter &p) {
+ parameter_list.push_back(p);
+}
+
+string t_info_param::encode(void) const {
+ string s;
+
+ s = '<' + uri.encode() + '>';
+ s += param_list2str(parameter_list);
+
+ return s;
+}
+
+
+t_hdr_call_info::t_hdr_call_info() : t_header("Call-Info") {};
+
+void t_hdr_call_info::add_param(const t_info_param &p) {
+ populated = true;
+ info_param_list.push_back(p);
+}
+
+string t_hdr_call_info::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_info_param>::const_iterator i = info_param_list.begin();
+ i != info_param_list.end(); i++)
+ {
+ if (i != info_param_list.begin()) s += ", ";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_call_info.h b/src/parser/hdr_call_info.h
new file mode 100644
index 0000000..a6fd6cb
--- /dev/null
+++ b/src/parser/hdr_call_info.h
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Call-Info header
+
+#ifndef _HDR_CALL_INFO_H
+#define _HDR_CALL_INFO_H
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_info_param {
+public:
+ t_url uri;
+ list<t_parameter> parameter_list;
+
+ void add_param(const t_parameter &p);
+ string encode(void) const;
+};
+
+class t_hdr_call_info : public t_header {
+public:
+ list<t_info_param> info_param_list;
+
+ t_hdr_call_info();
+
+ // Add a paramter to the list of alert parameters
+ void add_param(const t_info_param &p);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_contact.cpp b/src/parser/hdr_contact.cpp
new file mode 100644
index 0000000..00e8d5d
--- /dev/null
+++ b/src/parser/hdr_contact.cpp
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_contact.h"
+#include "parse_ctrl.h"
+#include "util.h"
+
+t_contact_param::t_contact_param() {
+ qvalue = 1.0;
+ qvalue_present = false;
+ expires = 0;
+ expires_present = false;
+}
+
+void t_contact_param::add_extension(const t_parameter &p) {
+ extensions.push_back(p);
+}
+
+string t_contact_param::encode(void) const {
+ string s;
+
+ if (display.size() > 0) {
+ s += '"';
+ s += escape(display, '"');
+ s += '"';
+ s += ' ';
+ }
+
+ s += '<';
+ s += uri.encode();
+ s += '>';
+
+ if (qvalue_present) {
+ s += ";q=";
+ s += float2str(qvalue, 3);
+ }
+
+ if (expires_present) s += ulong2str(expires, ";expires=%u");
+ s += param_list2str(extensions);
+
+ return s;
+}
+
+bool t_contact_param::operator<(const t_contact_param &c) const {
+ return (qvalue > c.qvalue);
+}
+
+
+t_hdr_contact::t_hdr_contact() : t_header("Contact", "m") {
+ any_flag = false;
+}
+
+void t_hdr_contact::add_contact(const t_contact_param &contact) {
+ populated = true;
+ contact_list.push_back(contact);
+}
+
+void t_hdr_contact::add_contacts(const list<t_contact_param> &l) {
+ populated = true;
+
+ for (list<t_contact_param>::const_iterator i = l.begin(); i != l.end();
+ i++)
+ {
+ contact_list.push_back(*i);
+ }
+}
+
+void t_hdr_contact::set_contacts(const list<t_contact_param> &l) {
+ populated = true;
+ contact_list = l;
+}
+
+void t_hdr_contact::set_contacts(const list<t_url> &l) {
+ t_contact_param c;
+ float q = 0.9;
+
+ populated = true;
+
+ contact_list.clear();
+ for (list<t_url>::const_iterator i = l.begin(); i != l.end(); i++) {
+ c.uri = *i;
+ c.set_qvalue(q);
+ contact_list.push_back(c);
+ q = q - 0.1;
+ if (q < 0.1) q = 0.1;
+ }
+}
+
+void t_hdr_contact::set_contacts(const list<t_display_url> &l) {
+ t_contact_param c;
+ float q = 0.9;
+
+ populated = true;
+
+ contact_list.clear();
+ for (list<t_display_url>::const_iterator i = l.begin(); i != l.end(); i++) {
+ c.uri = i->url;
+ c.display = i->display;
+ c.set_qvalue(q);
+ contact_list.push_back(c);
+ q = q - 0.1;
+ if (q < 0.1) q = 0.1;
+ }
+}
+
+void t_hdr_contact::set_any(void) {
+ populated = true;
+ any_flag = true;
+ contact_list.clear();
+}
+
+t_contact_param *t_hdr_contact::find_contact(const t_url &u) {
+ for (list<t_contact_param>::iterator i = contact_list.begin();
+ i != contact_list.end(); i++)
+ {
+ if (u.sip_match(i->uri)) return &(*i);
+ }
+
+ return NULL;
+}
+
+bool t_contact_param::is_expires_present(void) const {
+ return expires_present;
+}
+
+unsigned long t_contact_param::get_expires(void) const {
+ return expires;
+}
+
+void t_contact_param::set_expires(unsigned long e) {
+ expires_present = true;
+ expires = e;
+}
+
+float t_contact_param::get_qvalue(void) const {
+ return qvalue;
+}
+
+void t_contact_param::set_qvalue(float q) {
+ qvalue_present = true;
+ qvalue = q;
+}
+
+string t_hdr_contact::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ if (any_flag) {
+ s += '*';
+ return s;
+ }
+
+ for (list<t_contact_param>::const_iterator i = contact_list.begin();
+ i != contact_list.end(); i++)
+ {
+ if (i != contact_list.begin()) s += ", ";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_contact.h b/src/parser/hdr_contact.h
new file mode 100644
index 0000000..f1b74db
--- /dev/null
+++ b/src/parser/hdr_contact.h
@@ -0,0 +1,100 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Contact header
+
+#ifndef _HDR_CONTACT
+#define _HDR_CONTACT
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_contact_param {
+private:
+ bool expires_present;
+ unsigned long expires;
+ bool qvalue_present;
+ float qvalue;
+
+public:
+ string display; // display name
+ t_url uri;
+ list<t_parameter> extensions;
+
+ t_contact_param();
+ void add_extension(const t_parameter &p);
+ string encode(void) const;
+ bool is_expires_present(void) const;
+ unsigned long get_expires(void) const;
+ void set_expires(unsigned long e);
+ float get_qvalue(void) const;
+ void set_qvalue(float q);
+
+ // Compare contacts on q-value.
+ // The contacts with the highest q-value comes first in the order
+ bool operator<(const t_contact_param &c) const;
+};
+
+class t_hdr_contact : public t_header {
+public:
+ bool any_flag; // true if Contact: *
+ list<t_contact_param> contact_list;
+
+ t_hdr_contact();
+ void add_contact(const t_contact_param &contact);
+ void add_contacts(const list<t_contact_param> &l);
+ void set_contacts(const list<t_contact_param> &l);
+
+ /**
+ * Set the contact list to a sequence of URI's with display names.
+ * The URI's are give a descending q-value starting at 0.9
+ * Each subsequent URI gets a q-value 0.1 less than the previous
+ * URI. If more than 9 URI's are passed then the tail of URI's all
+ * get a q-value of 0.1.
+ *
+ * @param l [in] The list of URI's to be put in the contact list.
+ */
+ void set_contacts(const list<t_url> &l);
+
+ /**
+ * Set the contact list to a sequence of URI's with display names.
+ * The URI's are give a descending q-value starting at 0.9
+ * Each subsequent URI gets a q-value 0.1 less than the previous
+ * URI. If more than 9 URI's are passed then the tail of URI's all
+ * get a q-value of 0.1.
+ *
+ * @param l [in] The list of URI's to be put in the contact list.
+ */
+ void set_contacts(const list<t_display_url> &l);
+
+ // Set contact to any, eg. Contact: *
+ void set_any(void);
+
+ // Find contact with uri u. If no contact is found, then
+ // NULL is returned.
+ t_contact_param *find_contact(const t_url &u);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_content_disp.cpp b/src/parser/hdr_content_disp.cpp
new file mode 100644
index 0000000..d74525d
--- /dev/null
+++ b/src/parser/hdr_content_disp.cpp
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_content_disp.h"
+
+t_hdr_content_disp::t_hdr_content_disp() : t_header("Content-Disposition") {};
+
+void t_hdr_content_disp::set_type(const string &t) {
+ populated = true;
+ type = t;
+}
+
+void t_hdr_content_disp::set_filename(const string &name) {
+ populated = true;
+ filename = name;
+}
+
+void t_hdr_content_disp::add_param(const t_parameter &p) {
+ populated = true;
+ params.push_back(p);
+}
+
+void t_hdr_content_disp::set_params(const list<t_parameter> &l) {
+ populated = true;
+ params = l;
+}
+
+string t_hdr_content_disp::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s = type;
+
+ if (!filename.empty()) {
+ s += ";filename=\"";
+ s += filename;
+ s += "\"";
+ }
+
+ s += param_list2str(params);
+
+ return s;
+}
diff --git a/src/parser/hdr_content_disp.h b/src/parser/hdr_content_disp.h
new file mode 100644
index 0000000..81a8c34
--- /dev/null
+++ b/src/parser/hdr_content_disp.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Content-Disposition header
+
+#ifndef _HDR_CONTENT_DISP
+#define _HDR_CONTENT_DISP
+
+#include <string>
+#include <list>
+#include "header.h"
+#include "parameter.h"
+
+using namespace std;
+
+//@{
+/** @name Disposition types */
+#define DISPOSITION_ATTACHMENT "attachment"
+//@}
+
+class t_hdr_content_disp : public t_header {
+public:
+ string type;
+ string filename;
+ list<t_parameter> params;
+
+ t_hdr_content_disp();
+
+ void set_type(const string &t);
+ void set_filename(const string &name);
+ void add_param(const t_parameter &p);
+ void set_params(const list<t_parameter> &l);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_content_encoding.cpp b/src/parser/hdr_content_encoding.cpp
new file mode 100644
index 0000000..0c99854
--- /dev/null
+++ b/src/parser/hdr_content_encoding.cpp
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_content_encoding.h"
+#include "definitions.h"
+#include "parse_ctrl.h"
+
+t_hdr_content_encoding::t_hdr_content_encoding() : t_header("Content-Encoding", "e") {};
+
+void t_hdr_content_encoding::add_coding(const t_coding &coding) {
+ populated = true;
+ coding_list.push_back(coding);
+}
+
+string t_hdr_content_encoding::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_coding>::const_iterator i = coding_list.begin();
+ i != coding_list.end(); i++)
+ {
+ if (i != coding_list.begin()) s += ", ";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_content_encoding.h b/src/parser/hdr_content_encoding.h
new file mode 100644
index 0000000..2f6d726
--- /dev/null
+++ b/src/parser/hdr_content_encoding.h
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Content-Encoding header
+
+#ifndef _HDR_CONTENT_ENCODING_H
+#define _HDR_CONTENT_ENCODING_H
+
+#include <list>
+#include <string>
+#include "coding.h"
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_content_encoding : public t_header {
+public:
+ list<t_coding> coding_list; // list of content codings;
+
+ t_hdr_content_encoding();
+
+ // Add a coding to the list of content codings
+ void add_coding(const t_coding &coding);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_content_language.cpp b/src/parser/hdr_content_language.cpp
new file mode 100644
index 0000000..6e0f23e
--- /dev/null
+++ b/src/parser/hdr_content_language.cpp
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_content_language.h"
+#include "util.h"
+
+t_hdr_content_language::t_hdr_content_language() : t_header("Content-Language") {};
+
+void t_hdr_content_language::add_language(const t_language &language) {
+ populated = true;
+ language_list.push_back(language);
+}
+
+string t_hdr_content_language::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_language>::const_iterator i = language_list.begin();
+ i != language_list.end(); i++)
+ {
+ if (i != language_list.begin()) s += ", ";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_content_language.h b/src/parser/hdr_content_language.h
new file mode 100644
index 0000000..738ab98
--- /dev/null
+++ b/src/parser/hdr_content_language.h
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Content_Language header
+
+#ifndef _HDR_CONTENT_LANGUAGE_H
+#define _HDR_CONTENT_LANGUAGE_H
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "hdr_accept_language.h"
+
+using namespace std;
+
+class t_hdr_content_language : public t_header {
+public:
+ list<t_language> language_list; // list of languages
+
+ t_hdr_content_language();
+
+ // Add a language to the list of languages
+ void add_language(const t_language &language);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_content_length.cpp b/src/parser/hdr_content_length.cpp
new file mode 100644
index 0000000..b1c952d
--- /dev/null
+++ b/src/parser/hdr_content_length.cpp
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_content_length.h"
+#include "parse_ctrl.h"
+#include "util.h"
+
+t_hdr_content_length::t_hdr_content_length() : t_header("Content-Length", "l") {
+ length = 0;
+}
+
+void t_hdr_content_length::set_length(unsigned long l) {
+ populated = true;
+ length = l;
+}
+
+string t_hdr_content_length::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s = ulong2str(length);
+ return s;
+}
diff --git a/src/parser/hdr_content_length.h b/src/parser/hdr_content_length.h
new file mode 100644
index 0000000..accf8ca
--- /dev/null
+++ b/src/parser/hdr_content_length.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Content-Length header
+
+#ifndef _HDR_CONTENT_LENGTH
+#define _HDR_CONTENT_LENGTH
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_content_length : public t_header {
+public:
+ unsigned long length;
+
+ t_hdr_content_length();
+ void set_length(unsigned long l);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_content_type.cpp b/src/parser/hdr_content_type.cpp
new file mode 100644
index 0000000..ba4fcfe
--- /dev/null
+++ b/src/parser/hdr_content_type.cpp
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_content_type.h"
+#include "definitions.h"
+#include "parse_ctrl.h"
+
+t_hdr_content_type::t_hdr_content_type() : t_header("Content-Type", "c") {};
+
+void t_hdr_content_type::set_media(const t_media &m) {
+ populated = true;
+ media = m;
+}
+
+string t_hdr_content_type::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s = media.encode();
+ return s;
+}
diff --git a/src/parser/hdr_content_type.h b/src/parser/hdr_content_type.h
new file mode 100644
index 0000000..059dcc8
--- /dev/null
+++ b/src/parser/hdr_content_type.h
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Content-Type header
+
+#ifndef _HDR_CONTENT_TYPE_H
+#define _HDR_CONTENT_TYPE_H
+
+#include "header.h"
+#include "media_type.h"
+
+class t_hdr_content_type : public t_header {
+public:
+ t_media media;
+
+ t_hdr_content_type();
+ void set_media(const t_media &m);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_cseq.cpp b/src/parser/hdr_cseq.cpp
new file mode 100644
index 0000000..06d096b
--- /dev/null
+++ b/src/parser/hdr_cseq.cpp
@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_cseq.h"
+#include "util.h"
+
+t_hdr_cseq::t_hdr_cseq() : t_header("CSeq") {
+ seqnr = 0;
+ method = INVITE;
+}
+
+void t_hdr_cseq::set_seqnr(unsigned long l) {
+ populated = true;
+ seqnr = l;
+}
+
+void t_hdr_cseq::set_method(t_method m, const string &unknown) {
+ populated = true;
+ method = m;
+ unknown_method = unknown;
+}
+
+void t_hdr_cseq::set_method(const string &s) {
+ populated = true;
+ method = str2method(s);
+ if (method == METHOD_UNKNOWN) {
+ unknown_method = s;
+ }
+}
+
+string t_hdr_cseq::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s = ulong2str(seqnr) + ' ';
+ s += method2str(method, unknown_method);
+
+ return s;
+}
+
+bool t_hdr_cseq::operator==(const t_hdr_cseq &h) const {
+ if (method != METHOD_UNKNOWN) {
+ return (seqnr == h.seqnr && method == h.method);
+ }
+
+ return (seqnr == h.seqnr && unknown_method == h.unknown_method);
+}
diff --git a/src/parser/hdr_cseq.h b/src/parser/hdr_cseq.h
new file mode 100644
index 0000000..87147a3
--- /dev/null
+++ b/src/parser/hdr_cseq.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// CSeq header
+
+#ifndef _HDR_CSEQ
+#define _HDR_CSEQ
+
+#include <string>
+#include "header.h"
+#include "definitions.h"
+
+using namespace std;
+
+class t_hdr_cseq : public t_header {
+public:
+ unsigned long seqnr;
+ t_method method;
+ string unknown_method; // set if method is UNKNOWN
+
+ t_hdr_cseq();
+ void set_seqnr(unsigned long l);
+ void set_method(t_method m, const string &unknown = "");
+ void set_method(const string &s);
+
+ string encode_value(void) const;
+
+ bool operator==(const t_hdr_cseq &h) const;
+};
+
+#endif
diff --git a/src/parser/hdr_date.cpp b/src/parser/hdr_date.cpp
new file mode 100644
index 0000000..0ae5343
--- /dev/null
+++ b/src/parser/hdr_date.cpp
@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// NOTE: the date functions are not thread safe
+
+#include <sys/time.h>
+#include "hdr_date.h"
+#include "definitions.h"
+#include "util.h"
+
+t_hdr_date::t_hdr_date() : t_header("Date") {}
+
+void t_hdr_date::set_date_gm(struct tm *tm) {
+ populated = true;
+ date = timegm(tm);
+}
+
+void t_hdr_date::set_now(void) {
+ struct timeval t;
+
+ populated = true;
+ gettimeofday(&t, NULL);
+ date = t.tv_sec;
+}
+
+string t_hdr_date::encode_value(void) const {
+ string s;
+ struct tm tm;
+
+ if (!populated) return s;
+
+ gmtime_r(&date, &tm);
+ s = weekday2str(tm.tm_wday);
+ s += ", ";
+ s += int2str(tm.tm_mday, "%02d");
+ s += ' ';
+ s += month2str(tm.tm_mon);
+ s += ' ';
+ s += int2str(tm.tm_year + 1900, "%04d");
+ s += ' ';
+ s += int2str(tm.tm_hour, "%02d");
+ s += ':';
+ s += int2str(tm.tm_min, "%02d");
+ s += ':';
+ s += int2str(tm.tm_sec, "%02d");
+ s += " GMT";
+
+ return s;
+}
diff --git a/src/parser/hdr_date.h b/src/parser/hdr_date.h
new file mode 100644
index 0000000..6d78009
--- /dev/null
+++ b/src/parser/hdr_date.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Date header
+
+#ifndef _HDR_DATE_H
+#define _HDR_DATE_H
+
+#include <ctime>
+#include <string>
+#include "header.h"
+
+class t_hdr_date : public t_header {
+public:
+ time_t date;
+
+ t_hdr_date();
+ void set_date_gm(struct tm *tm); // set date, tm is GMT
+ void set_now(void); // Set date/time to current date/time
+ string encode_value(void) const;
+};
+
+using namespace std;
+
+#endif
diff --git a/src/parser/hdr_error_info.cpp b/src/parser/hdr_error_info.cpp
new file mode 100644
index 0000000..3bd8be4
--- /dev/null
+++ b/src/parser/hdr_error_info.cpp
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_error_info.h"
+
+void t_error_param::add_param(const t_parameter &p) {
+ parameter_list.push_back(p);
+}
+
+string t_error_param::encode(void) const {
+ string s;
+
+ s = '<' + uri.encode() + '>';
+ s += param_list2str(parameter_list);
+
+ return s;
+}
+
+
+t_hdr_error_info::t_hdr_error_info() : t_header("Error-Info") {};
+
+void t_hdr_error_info::add_param(const t_error_param &p) {
+ populated = true;
+ error_param_list.push_back(p);
+}
+
+string t_hdr_error_info::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_error_param>::const_iterator i = error_param_list.begin();
+ i != error_param_list.end(); i++)
+ {
+ if (i != error_param_list.begin()) s += ", ";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_error_info.h b/src/parser/hdr_error_info.h
new file mode 100644
index 0000000..c0eb7a3
--- /dev/null
+++ b/src/parser/hdr_error_info.h
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Error-Info header
+
+#ifndef _HDR_ERROR_INFO_H
+#define _HDR_ERROR_INFO_H
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_error_param {
+public:
+ t_url uri;
+ list<t_parameter> parameter_list;
+
+ void add_param(const t_parameter &p);
+ string encode(void) const;
+};
+
+class t_hdr_error_info : public t_header {
+public:
+ list<t_error_param> error_param_list;
+
+ t_hdr_error_info();
+
+ // Add a paramter to the list of error parameters
+ void add_param(const t_error_param &p);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_event.cpp b/src/parser/hdr_event.cpp
new file mode 100644
index 0000000..d0fe1a1
--- /dev/null
+++ b/src/parser/hdr_event.cpp
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_event.h"
+#include "parse_ctrl.h"
+
+t_hdr_event::t_hdr_event() : t_header("Event", "o") {}
+
+void t_hdr_event::set_event_type(const string &t) {
+ populated = true;
+ event_type = t;
+}
+
+void t_hdr_event::set_id(const string &s) {
+ populated = true;
+ id = s;
+}
+
+void t_hdr_event::add_event_param(const t_parameter &p) {
+ populated = true;
+ event_params.push_back(p);
+}
+
+string t_hdr_event::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s += event_type;
+
+ if (id.size() > 0) {
+ s += ";id=";
+ s += id;
+ }
+
+ s += param_list2str(event_params);
+
+ return s;
+}
diff --git a/src/parser/hdr_event.h b/src/parser/hdr_event.h
new file mode 100644
index 0000000..09c0ab9
--- /dev/null
+++ b/src/parser/hdr_event.h
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Event header
+// RFC 3265
+
+#ifndef _HDR_EVENT
+#define _HDR_EVENT
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "parameter.h"
+
+#define SIP_EVENT_REFER "refer" // RFC 3515
+#define SIP_EVENT_MSG_SUMMARY "message-summary" // RFC 3842
+#define SIP_EVENT_PRESENCE "presence" // RFC 3856
+
+using namespace std;
+
+class t_hdr_event : public t_header {
+public:
+ // The event_type attribute contains the event-template as well
+ // if present, e.g. event.template
+ string event_type;
+ string id;
+ list<t_parameter> event_params;
+
+ t_hdr_event();
+ void set_event_type(const string &t);
+ void set_id(const string &s);
+ void add_event_param(const t_parameter &p);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_expires.cpp b/src/parser/hdr_expires.cpp
new file mode 100644
index 0000000..0caeb04
--- /dev/null
+++ b/src/parser/hdr_expires.cpp
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_expires.h"
+#include "util.h"
+
+t_hdr_expires::t_hdr_expires() : t_header("Expires") {
+ time = 0;
+}
+
+void t_hdr_expires::set_time(unsigned long t) {
+ populated = true;
+ time = t;
+}
+
+string t_hdr_expires::encode_value(void) const {
+ if (!populated) return "";
+
+ return ulong2str(time);
+}
diff --git a/src/parser/hdr_expires.h b/src/parser/hdr_expires.h
new file mode 100644
index 0000000..5ca589a
--- /dev/null
+++ b/src/parser/hdr_expires.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Expires header
+
+#ifndef _HDR_EXPIRES_LENGTH
+#define _HDR_EXPIRES_LENGTH
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_expires : public t_header {
+public:
+ unsigned long time; // expiry time in seconds
+
+ t_hdr_expires();
+ void set_time(unsigned long t);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_from.cpp b/src/parser/hdr_from.cpp
new file mode 100644
index 0000000..fa83456
--- /dev/null
+++ b/src/parser/hdr_from.cpp
@@ -0,0 +1,88 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_from.h"
+#include "definitions.h"
+#include "parse_ctrl.h"
+#include "util.h"
+
+t_hdr_from::t_hdr_from() : t_header("From", "f") {}
+
+void t_hdr_from::set_display(const string &d) {
+ populated = true;
+ display = d;
+}
+
+void t_hdr_from::set_uri(const string &u) {
+ populated = true;
+ uri.set_url(u);
+}
+
+void t_hdr_from::set_uri(const t_url &u) {
+ populated = true;
+ uri = u;
+}
+
+void t_hdr_from::set_tag(const string &t) {
+ populated = true;
+ tag = t;
+}
+
+void t_hdr_from::set_params(const list<t_parameter> &l) {
+ populated = true;
+ params = l;
+}
+
+void t_hdr_from::add_param(const t_parameter &p) {
+ populated = true;
+ params.push_back(p);
+}
+
+string t_hdr_from::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ if (display.size() > 0) {
+ s += '"';
+ s += escape(display, '"');
+ s += '"';
+ s += ' ';
+ }
+
+ s += '<';
+ s += uri.encode();
+ s += '>';
+
+ if (tag != "") {
+ s += ";tag=";
+ s += tag;
+ }
+
+ s += param_list2str(params);
+
+ return s;
+}
+
+string t_hdr_from::get_display_presentation(void) const {
+ if (display_override.empty()) {
+ return display;
+ } else {
+ return display_override;
+ }
+}
diff --git a/src/parser/hdr_from.h b/src/parser/hdr_from.h
new file mode 100644
index 0000000..23fb7cf
--- /dev/null
+++ b/src/parser/hdr_from.h
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// From header
+
+#ifndef _H_HDR_FROM
+#define _H_HDR_FROM
+
+#include <string>
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_hdr_from : public t_header {
+public:
+ string display; // display name
+
+ // The display_override may be set by the UA to display another
+ // name to the user, then the display name received in the
+ // signalling, e.g. a lookup from an address book. This value
+ // does NOT appear in the SIP message.
+ string display_override;
+
+ t_url uri;
+ string tag;
+ list<t_parameter> params;
+
+ t_hdr_from();
+ void set_display(const string &d);
+ void set_uri(const string &u);
+ void set_uri(const t_url &u);
+ void set_tag(const string &t);
+ void set_params(const list<t_parameter> &l);
+ void add_param(const t_parameter &p);
+ string encode_value(void) const;
+
+ // Get the display name to show to the user.
+ string get_display_presentation(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_in_reply_to.cpp b/src/parser/hdr_in_reply_to.cpp
new file mode 100644
index 0000000..0383eed
--- /dev/null
+++ b/src/parser/hdr_in_reply_to.cpp
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_in_reply_to.h"
+#include "definitions.h"
+
+t_hdr_in_reply_to::t_hdr_in_reply_to() : t_header("In-Reply-To") {};
+
+void t_hdr_in_reply_to::add_call_id(const string &id) {
+ populated = true;
+ call_ids.push_back(id);
+}
+
+string t_hdr_in_reply_to::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<string>::const_iterator i = call_ids.begin();
+ i != call_ids.end(); i++)
+ {
+ if (i != call_ids.begin()) s += ", ";
+ s += *i;
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_in_reply_to.h b/src/parser/hdr_in_reply_to.h
new file mode 100644
index 0000000..774f0a1
--- /dev/null
+++ b/src/parser/hdr_in_reply_to.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// In-Reply-To header
+
+#ifndef _H_HDR_IN_REPLY_TO
+#define _H_HDR_IN_REPLY_TO
+
+#include <string>
+#include <list>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_in_reply_to : public t_header {
+public:
+ list<string> call_ids;
+
+ t_hdr_in_reply_to();
+ void add_call_id(const string &id);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_max_forwards.cpp b/src/parser/hdr_max_forwards.cpp
new file mode 100644
index 0000000..e4fd081
--- /dev/null
+++ b/src/parser/hdr_max_forwards.cpp
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_max_forwards.h"
+#include "util.h"
+
+t_hdr_max_forwards::t_hdr_max_forwards() : t_header("Max-Forwards") {
+ max_forwards = 0;
+}
+
+void t_hdr_max_forwards::set_max_forwards(int m) {
+ populated = true;
+ max_forwards = m;
+}
+
+string t_hdr_max_forwards::encode_value(void) const {
+ if (!populated) return "";
+
+ return int2str(max_forwards);
+}
diff --git a/src/parser/hdr_max_forwards.h b/src/parser/hdr_max_forwards.h
new file mode 100644
index 0000000..508309d
--- /dev/null
+++ b/src/parser/hdr_max_forwards.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Max-Forwards header
+
+#ifndef _HDR_MAX_FORWARDS_LENGTH
+#define _HDR_MAX_FORWARDS_LENGTH
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_max_forwards : public t_header {
+public:
+ int max_forwards;
+
+ t_hdr_max_forwards();
+ void set_max_forwards(int m);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_mime_version.cpp b/src/parser/hdr_mime_version.cpp
new file mode 100644
index 0000000..48c5e50
--- /dev/null
+++ b/src/parser/hdr_mime_version.cpp
@@ -0,0 +1,33 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_mime_version.h"
+
+t_hdr_mime_version::t_hdr_mime_version() : t_header("MIME-Version") {};
+
+void t_hdr_mime_version::set_version(const string &v) {
+ populated = true;
+ version = v;
+}
+
+string t_hdr_mime_version::encode_value(void) const {
+ if (!populated) return "";
+
+ return version;
+}
diff --git a/src/parser/hdr_mime_version.h b/src/parser/hdr_mime_version.h
new file mode 100644
index 0000000..c25b9fc
--- /dev/null
+++ b/src/parser/hdr_mime_version.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// MIME-Version header
+#ifndef _H_HDR_MIME_VERSION
+#define _H_HDR_MIME_VERSION
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_mime_version : public t_header {
+public:
+ string version;
+
+ t_hdr_mime_version();
+ void set_version(const string &v);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_min_expires.cpp b/src/parser/hdr_min_expires.cpp
new file mode 100644
index 0000000..7895c47
--- /dev/null
+++ b/src/parser/hdr_min_expires.cpp
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_min_expires.h"
+#include "util.h"
+
+t_hdr_min_expires::t_hdr_min_expires() : t_header("Min-Expires") {
+ time = 0;
+}
+
+void t_hdr_min_expires::set_time(unsigned long t) {
+ populated = true;
+ time = t;
+}
+
+string t_hdr_min_expires::encode_value(void) const {
+ if (!populated) return "";
+
+ return ulong2str(time);
+}
diff --git a/src/parser/hdr_min_expires.h b/src/parser/hdr_min_expires.h
new file mode 100644
index 0000000..ef82bc1
--- /dev/null
+++ b/src/parser/hdr_min_expires.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Expires header
+
+#ifndef _HDR_MIN_EXPIRES_LENGTH
+#define _HDR_MIN_EXPIRES_LENGTH
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_min_expires : public t_header {
+public:
+ unsigned long time; // expiry time in seconds
+
+ t_hdr_min_expires();
+ void set_time(unsigned long t);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_organization.cpp b/src/parser/hdr_organization.cpp
new file mode 100644
index 0000000..fe32a72
--- /dev/null
+++ b/src/parser/hdr_organization.cpp
@@ -0,0 +1,33 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_organization.h"
+
+t_hdr_organization::t_hdr_organization() : t_header("Organization") {};
+
+void t_hdr_organization::set_name(const string &n) {
+ populated = true;
+ name = n;
+}
+
+string t_hdr_organization::encode_value(void) const {
+ if (!populated) return "";
+
+ return name;
+}
diff --git a/src/parser/hdr_organization.h b/src/parser/hdr_organization.h
new file mode 100644
index 0000000..bfa788c
--- /dev/null
+++ b/src/parser/hdr_organization.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Organization header
+#ifndef _H_HDR_ORGANIZATION
+#define _H_HDR_ORGANIZATION
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_organization : public t_header {
+public:
+ string name;
+
+ t_hdr_organization();
+ void set_name(const string &n);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_p_asserted_identity.cpp b/src/parser/hdr_p_asserted_identity.cpp
new file mode 100644
index 0000000..ac1847c
--- /dev/null
+++ b/src/parser/hdr_p_asserted_identity.cpp
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_p_asserted_identity.h"
+
+t_hdr_p_asserted_identity::t_hdr_p_asserted_identity() :
+ t_header("P-Asserted-Identity")
+{}
+
+void t_hdr_p_asserted_identity::add_identity(const t_identity &identity) {
+ populated = true;
+ identity_list.push_back(identity);
+}
+
+string t_hdr_p_asserted_identity::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_identity>::const_iterator i = identity_list.begin();
+ i != identity_list.end(); i++)
+ {
+ if (i != identity_list.begin()) s += ',';
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_p_asserted_identity.h b/src/parser/hdr_p_asserted_identity.h
new file mode 100644
index 0000000..6148fac
--- /dev/null
+++ b/src/parser/hdr_p_asserted_identity.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// RFC 3325 9.1
+// P-Asserted-Identity header
+
+#ifndef _H_HDR_P_ASSERTED_IDENTITY
+#define _H_HDR_P_ASSERTED_IDENTITY
+
+#include <string>
+#include "header.h"
+#include "identity.h"
+
+using namespace std;
+
+class t_hdr_p_asserted_identity : public t_header {
+public:
+ list<t_identity> identity_list;
+
+ t_hdr_p_asserted_identity();
+ void add_identity(const t_identity &identity);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_p_preferred_identity.cpp b/src/parser/hdr_p_preferred_identity.cpp
new file mode 100644
index 0000000..0009fb6
--- /dev/null
+++ b/src/parser/hdr_p_preferred_identity.cpp
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_p_preferred_identity.h"
+
+t_hdr_p_preferred_identity::t_hdr_p_preferred_identity() :
+ t_header("P-Preferred-Identity")
+{}
+
+void t_hdr_p_preferred_identity::add_identity(const t_identity &identity) {
+ populated = true;
+ identity_list.push_back(identity);
+}
+
+string t_hdr_p_preferred_identity::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_identity>::const_iterator i = identity_list.begin();
+ i != identity_list.end(); i++)
+ {
+ if (i != identity_list.begin()) s += ',';
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_p_preferred_identity.h b/src/parser/hdr_p_preferred_identity.h
new file mode 100644
index 0000000..5449b61
--- /dev/null
+++ b/src/parser/hdr_p_preferred_identity.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// RFC 3325 9.2
+// P-Preferred-Identity header
+
+#ifndef _H_HDR_P_PREFERRED_IDENTITY
+#define _H_HDR_P_PREFERRED_IDENTITY
+
+#include <string>
+#include "header.h"
+#include "identity.h"
+
+using namespace std;
+
+class t_hdr_p_preferred_identity : public t_header {
+public:
+ list<t_identity> identity_list;
+
+ t_hdr_p_preferred_identity();
+ void add_identity(const t_identity &identity);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_priority.cpp b/src/parser/hdr_priority.cpp
new file mode 100644
index 0000000..470ffac
--- /dev/null
+++ b/src/parser/hdr_priority.cpp
@@ -0,0 +1,33 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_priority.h"
+
+t_hdr_priority::t_hdr_priority() : t_header("Priority") {};
+
+void t_hdr_priority::set_priority(const string &p) {
+ populated = true;
+ priority = p;
+}
+
+string t_hdr_priority::encode_value(void) const {
+ if (!populated) return "";
+
+ return priority;
+}
diff --git a/src/parser/hdr_priority.h b/src/parser/hdr_priority.h
new file mode 100644
index 0000000..5ba2128
--- /dev/null
+++ b/src/parser/hdr_priority.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Priority header
+#ifndef _H_HDR_PRIORITY_VERSION
+#define _H_HDR_PRIORITY_VERSION
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_priority : public t_header {
+public:
+ string priority;
+
+ t_hdr_priority();
+ void set_priority(const string &p);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_privacy.cpp b/src/parser/hdr_privacy.cpp
new file mode 100644
index 0000000..7c0cbca
--- /dev/null
+++ b/src/parser/hdr_privacy.cpp
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <algorithm>
+
+#include "definitions.h"
+#include "hdr_privacy.h"
+
+using namespace std;
+
+t_hdr_privacy::t_hdr_privacy() : t_header("Privacy") {};
+
+void t_hdr_privacy::add_privacy(const string &privacy) {
+ populated = true;
+ privacy_list.push_back(privacy);
+}
+
+bool t_hdr_privacy::contains_privacy(const string &privacy) const {
+ return (find(privacy_list.begin(), privacy_list.end(), privacy) !=
+ privacy_list.end());
+}
+
+string t_hdr_privacy::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<string>::const_iterator i = privacy_list.begin();
+ i != privacy_list.end(); i++)
+ {
+ if (i != privacy_list.begin()) s += ";";
+ s += *i;
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_privacy.h b/src/parser/hdr_privacy.h
new file mode 100644
index 0000000..e7d33e2
--- /dev/null
+++ b/src/parser/hdr_privacy.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// RFC 3323
+// Privacy header
+
+#ifndef _H_HDR_PRIVACY
+#define _H_HDR_PRICACY
+
+#include <list>
+#include <string>
+#include "header.h"
+
+#define PRIVACY_HEADER "header"
+#define PRIVACY_SESSION "session"
+#define PRIVACY_USER "user"
+#define PRIVACY_NONE "none"
+#define PRIVACY_CRITICAL "critical"
+
+// RFC 3325 9.3 defines id privacy
+#define PRIVACY_ID "id"
+
+class t_hdr_privacy : public t_header {
+public:
+ list<string> privacy_list;
+
+ t_hdr_privacy();
+ void add_privacy(const string &privacy);
+ bool contains_privacy(const string &privacy) const;
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_proxy_authenticate.cpp b/src/parser/hdr_proxy_authenticate.cpp
new file mode 100644
index 0000000..da1f0bd
--- /dev/null
+++ b/src/parser/hdr_proxy_authenticate.cpp
@@ -0,0 +1,33 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_proxy_authenticate.h"
+#include "definitions.h"
+
+t_hdr_proxy_authenticate::t_hdr_proxy_authenticate() : t_header("Proxy-Authenticate") {}
+
+void t_hdr_proxy_authenticate::set_challenge(const t_challenge &c) {
+ populated = true;
+ challenge = c;
+}
+
+string t_hdr_proxy_authenticate::encode_value(void) const {
+ if (!populated) return "";
+
+ return challenge.encode();
+}
diff --git a/src/parser/hdr_proxy_authenticate.h b/src/parser/hdr_proxy_authenticate.h
new file mode 100644
index 0000000..964c804
--- /dev/null
+++ b/src/parser/hdr_proxy_authenticate.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Proxy-Authenticate header
+
+#ifndef _HDR_PROXY_AUTHENTICATE_H
+#define _HDR_PROXY_AUTHENTICATE_H
+
+#include <list>
+#include <string>
+#include "challenge.h"
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_proxy_authenticate : public t_header {
+public:
+ t_challenge challenge;
+
+ t_hdr_proxy_authenticate();
+
+ void set_challenge(const t_challenge &c);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_proxy_authorization.cpp b/src/parser/hdr_proxy_authorization.cpp
new file mode 100644
index 0000000..2f73911
--- /dev/null
+++ b/src/parser/hdr_proxy_authorization.cpp
@@ -0,0 +1,92 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_proxy_authorization.h"
+#include "definitions.h"
+
+t_hdr_proxy_authorization::t_hdr_proxy_authorization() : t_header("Proxy-Authorization") {}
+
+void t_hdr_proxy_authorization::add_credentials(const t_credentials &c) {
+ populated = true;
+ credentials_list.push_back(c);
+}
+
+string t_hdr_proxy_authorization::encode(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ // RFC 3261 20.28
+ // Each authorization should appear as a separate header
+ for (list<t_credentials>::const_iterator i = credentials_list.begin();
+ i != credentials_list.end(); i++)
+ {
+ s += header_name;
+ s += ": ";
+ s += i->encode();
+ s += CRLF;
+ }
+
+ return s;
+}
+
+string t_hdr_proxy_authorization::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_credentials>::const_iterator i = credentials_list.begin();
+ i != credentials_list.end(); i++)
+ {
+ if (i != credentials_list.begin()) s += ", ";
+ s += i->encode();
+ }
+
+ return s;
+}
+
+bool t_hdr_proxy_authorization::contains(const string &realm,
+ const t_url &uri) const
+{
+ for (list<t_credentials>::const_iterator i = credentials_list.begin();
+ i != credentials_list.end(); i++)
+ {
+ if (i->digest_response.realm == realm &&
+ i->digest_response.digest_uri == uri)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void t_hdr_proxy_authorization::remove_credentials(const string &realm,
+ const t_url &uri)
+{
+ for (list<t_credentials>::iterator i = credentials_list.begin();
+ i != credentials_list.end(); i++)
+ {
+ if (i->digest_response.realm == realm &&
+ i->digest_response.digest_uri == uri)
+ {
+ credentials_list.erase(i);
+ return;
+ }
+ }
+}
diff --git a/src/parser/hdr_proxy_authorization.h b/src/parser/hdr_proxy_authorization.h
new file mode 100644
index 0000000..b68849a
--- /dev/null
+++ b/src/parser/hdr_proxy_authorization.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Proxy-Authorization header
+
+#ifndef _HDR_PROXY_AUTHORIZATION
+#define _HDR_PROXY_AUTHORIZATION
+
+#include <list>
+#include <string>
+#include "credentials.h"
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_hdr_proxy_authorization : public t_header {
+public:
+ list<t_credentials> credentials_list;
+
+ t_hdr_proxy_authorization();
+
+ void add_credentials(const t_credentials &c);
+ string encode(void) const;
+ string encode_value(void) const;
+
+ // Return true if the header contains credentials for a realm/dest
+ bool contains(const string &realm, const t_url &uri) const;
+
+ // Remove credentials for a realm/dest
+ void remove_credentials(const string &realm, const t_url &uri);
+};
+
+#endif
diff --git a/src/parser/hdr_proxy_require.cpp b/src/parser/hdr_proxy_require.cpp
new file mode 100644
index 0000000..70696fb
--- /dev/null
+++ b/src/parser/hdr_proxy_require.cpp
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_proxy_require.h"
+
+t_hdr_proxy_require::t_hdr_proxy_require() : t_header("Proxy-Require") {};
+
+void t_hdr_proxy_require::add_feature(const string &f) {
+ populated = true;
+ features.push_back(f);
+}
+
+string t_hdr_proxy_require::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<string>::const_iterator i = features.begin();
+ i != features.end(); i++)
+ {
+ if (i != features.begin()) s += ", ";
+ s += *i;
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_proxy_require.h b/src/parser/hdr_proxy_require.h
new file mode 100644
index 0000000..a3bc594
--- /dev/null
+++ b/src/parser/hdr_proxy_require.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Proxy-Require header
+
+#ifndef _H_HDR_PROXY_REQUIRE
+#define _H_HDR_PROXY_REQUIRE
+
+#include <list>
+#include <string>
+#include "header.h"
+
+class t_hdr_proxy_require : public t_header {
+public:
+ list<string> features;
+
+ t_hdr_proxy_require();
+ void add_feature(const string &f);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_rack.cpp b/src/parser/hdr_rack.cpp
new file mode 100644
index 0000000..24a8f15
--- /dev/null
+++ b/src/parser/hdr_rack.cpp
@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_rack.h"
+#include "util.h"
+
+t_hdr_rack::t_hdr_rack() : t_header("RAck") {
+ cseq_nr = 0;
+ resp_nr = 0;
+ method = INVITE;
+}
+
+void t_hdr_rack::set_cseq_nr(unsigned long l) {
+ populated = true;
+ cseq_nr = l;
+}
+
+void t_hdr_rack::set_resp_nr(unsigned long l) {
+ populated = true;
+ resp_nr = l;
+}
+
+void t_hdr_rack::set_method(t_method m, const string &unknown) {
+ populated = true;
+ method = m;
+ unknown_method = unknown;
+}
+
+void t_hdr_rack::set_method(const string &s) {
+ populated = true;
+ method = str2method(s);
+ if (method == METHOD_UNKNOWN) {
+ unknown_method = s;
+ }
+}
+
+string t_hdr_rack::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s = ulong2str(resp_nr) + ' ';
+ s += ulong2str(cseq_nr);
+ s += ' ';
+ s += method2str(method, unknown_method);
+
+ return s;
+}
diff --git a/src/parser/hdr_rack.h b/src/parser/hdr_rack.h
new file mode 100644
index 0000000..dbfb4ec
--- /dev/null
+++ b/src/parser/hdr_rack.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// RAck header
+// RFC 3262
+
+#ifndef _HDR_RACK
+#define _HDR_RACK
+
+#include <string>
+#include "header.h"
+#include "definitions.h"
+
+using namespace std;
+
+class t_hdr_rack : public t_header {
+public:
+ unsigned long cseq_nr;
+ unsigned long resp_nr;
+ t_method method;
+ string unknown_method; // set if method is UNKNOWN
+
+ t_hdr_rack();
+ void set_cseq_nr(unsigned long l);
+ void set_resp_nr(unsigned long l);
+ void set_method(t_method m, const string &unknown = "");
+ void set_method(const string &s);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_record_route.cpp b/src/parser/hdr_record_route.cpp
new file mode 100644
index 0000000..dc9f14d
--- /dev/null
+++ b/src/parser/hdr_record_route.cpp
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_record_route.h"
+#include "parse_ctrl.h"
+#include "util.h"
+
+t_hdr_record_route::t_hdr_record_route() : t_header("Record-Route") {}
+
+void t_hdr_record_route::add_route(const t_route &r) {
+ populated = true;
+ route_list.push_back(r);
+}
+
+string t_hdr_record_route::encode(void) const {
+ return (t_parser::multi_values_as_list ?
+ t_header::encode() : encode_multi_header());
+}
+
+string t_hdr_record_route::encode_multi_header(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_route>::const_iterator i = route_list.begin();
+ i != route_list.end(); i++)
+ {
+ s += header_name;
+ s += ": ";
+ s += i->encode();
+ s += CRLF;
+ }
+
+ return s;
+}
+
+string t_hdr_record_route::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_route>::const_iterator i = route_list.begin();
+ i != route_list.end(); i++)
+ {
+ if (i != route_list.begin()) s += ",";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_record_route.h b/src/parser/hdr_record_route.h
new file mode 100644
index 0000000..7123e83
--- /dev/null
+++ b/src/parser/hdr_record_route.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Record-Route header
+
+#ifndef _H_HDR_RECORD_ROUTE
+#define _H_HDR_RECORD_ROUTE
+
+#include <list>
+#include <string>
+#include "route.h"
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_hdr_record_route : public t_header {
+public:
+ list<t_route> route_list;
+
+ t_hdr_record_route();
+ void add_route(const t_route &r);
+ string encode(void) const;
+ string encode_multi_header(void) const;
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_refer_sub.cpp b/src/parser/hdr_refer_sub.cpp
new file mode 100644
index 0000000..9e3cad2
--- /dev/null
+++ b/src/parser/hdr_refer_sub.cpp
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_refer_sub.h"
+
+t_hdr_refer_sub::t_hdr_refer_sub() : t_header("Refer-Sub"),
+ create_refer_sub(true)
+{}
+
+void t_hdr_refer_sub::set_create_refer_sub(bool on) {
+ populated = true;
+ create_refer_sub = on;
+}
+
+void t_hdr_refer_sub::add_extension(const t_parameter &p) {
+ populated = true;
+ extensions.push_back(p);
+}
+
+void t_hdr_refer_sub::set_extensions(const list<t_parameter> &l) {
+ populated = true;
+ extensions = l;
+}
+
+string t_hdr_refer_sub::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s = (create_refer_sub ? "true" : "false");
+ s += param_list2str(extensions);
+
+ return s;
+}
diff --git a/src/parser/hdr_refer_sub.h b/src/parser/hdr_refer_sub.h
new file mode 100644
index 0000000..ba7fd5f
--- /dev/null
+++ b/src/parser/hdr_refer_sub.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Refer-Sub header
+// RFC 4488
+
+#ifndef _H_HDR_REFER_SUB
+#define _H_HDR_REFER_SUB
+
+#include <list>
+#include <string>
+
+#include "header.h"
+#include "parameter.h"
+
+using namespace std;
+
+class t_hdr_refer_sub : public t_header {
+public:
+ bool create_refer_sub;
+ list<t_parameter> extensions;
+
+ t_hdr_refer_sub();
+ void set_create_refer_sub(bool on);
+ void add_extension(const t_parameter &p);
+ void set_extensions(const list<t_parameter> &l);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_refer_to.cpp b/src/parser/hdr_refer_to.cpp
new file mode 100644
index 0000000..ef9dc9a
--- /dev/null
+++ b/src/parser/hdr_refer_to.cpp
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_refer_to.h"
+#include "definitions.h"
+#include "parse_ctrl.h"
+#include "util.h"
+
+t_hdr_refer_to::t_hdr_refer_to() : t_header("Refer-To", "r") {}
+
+void t_hdr_refer_to::set_display(const string &d) {
+ populated = true;
+ display = d;
+}
+
+void t_hdr_refer_to::set_uri(const string &u) {
+ populated = true;
+ uri.set_url(u);
+}
+
+void t_hdr_refer_to::set_uri(const t_url &u) {
+ populated = true;
+ uri = u;
+}
+
+void t_hdr_refer_to::set_params(const list<t_parameter> &l) {
+ populated = true;
+ params = l;
+}
+
+void t_hdr_refer_to::add_param(const t_parameter &p) {
+ populated = true;
+ params.push_back(p);
+}
+
+string t_hdr_refer_to::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ if (display.size() > 0) {
+ s += '"';
+ s += escape(display, '"');
+ s += '"';
+ s += ' ';
+ }
+
+ s += '<';
+ s += uri.encode();
+ s += '>';
+
+ s += param_list2str(params);
+
+ return s;
+}
diff --git a/src/parser/hdr_refer_to.h b/src/parser/hdr_refer_to.h
new file mode 100644
index 0000000..41f1746
--- /dev/null
+++ b/src/parser/hdr_refer_to.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// RFC 3515
+// Refer-To header
+
+#ifndef _H_HDR_REFER_TO
+#define _H_HDR_REFER_TO
+
+#include <string>
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_hdr_refer_to : public t_header {
+public:
+ string display; // display name
+ t_url uri;
+ list<t_parameter> params;
+
+ t_hdr_refer_to();
+ void set_display(const string &d);
+ void set_uri(const string &u);
+ void set_uri(const t_url &u);
+ void set_params(const list<t_parameter> &l);
+ void add_param(const t_parameter &p);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_referred_by.cpp b/src/parser/hdr_referred_by.cpp
new file mode 100644
index 0000000..aa4acf9
--- /dev/null
+++ b/src/parser/hdr_referred_by.cpp
@@ -0,0 +1,80 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_referred_by.h"
+#include "definitions.h"
+#include "parse_ctrl.h"
+#include "util.h"
+
+t_hdr_referred_by::t_hdr_referred_by() : t_header("Referred-By", "b") {}
+
+void t_hdr_referred_by::set_display(const string &d) {
+ populated = true;
+ display = d;
+}
+
+void t_hdr_referred_by::set_uri(const string &u) {
+ populated = true;
+ uri.set_url(u);
+}
+
+void t_hdr_referred_by::set_uri(const t_url &u) {
+ populated = true;
+ uri = u;
+}
+
+void t_hdr_referred_by::set_cid(const string &c) {
+ populated = true;
+ cid = c;
+}
+
+void t_hdr_referred_by::set_params(const list<t_parameter> &l) {
+ populated = true;
+ params = l;
+}
+
+void t_hdr_referred_by::add_param(const t_parameter &p) {
+ populated = true;
+ params.push_back(p);
+}
+
+string t_hdr_referred_by::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ if (display.size() > 0) {
+ s += '"';
+ s += escape(display, '"');
+ s += '"';
+ s += ' ';
+ }
+
+ s += '<';
+ s += uri.encode();
+ s += '>';
+
+ if (cid.size() > 0) {
+ s += ";cid=";
+ s += cid;
+ }
+
+ s += param_list2str(params);
+
+ return s;
+}
diff --git a/src/parser/hdr_referred_by.h b/src/parser/hdr_referred_by.h
new file mode 100644
index 0000000..c1133b8
--- /dev/null
+++ b/src/parser/hdr_referred_by.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// RFC 3892
+// Referred-By header
+
+#ifndef _H_HDR_REFERRED_BY
+#define _H_HDR_REFERRED_BY
+
+#include <string>
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_hdr_referred_by : public t_header {
+public:
+ string display; // display name
+ t_url uri;
+ string cid;
+ list<t_parameter> params;
+
+ t_hdr_referred_by();
+ void set_display(const string &d);
+ void set_uri(const string &u);
+ void set_uri(const t_url &u);
+ void set_cid(const string &c);
+ void set_params(const list<t_parameter> &l);
+ void add_param(const t_parameter &p);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_replaces.cpp b/src/parser/hdr_replaces.cpp
new file mode 100644
index 0000000..a7d7e1b
--- /dev/null
+++ b/src/parser/hdr_replaces.cpp
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_replaces.h"
+
+t_hdr_replaces::t_hdr_replaces() : t_header("Replaces"),
+ early_only(false)
+{}
+
+void t_hdr_replaces::set_call_id(const string &id) {
+ populated = true;
+ call_id = id;
+}
+
+void t_hdr_replaces::set_to_tag(const string &tag) {
+ populated = true;
+ to_tag = tag;
+}
+
+void t_hdr_replaces::set_from_tag(const string &tag) {
+ populated = true;
+ from_tag = tag;
+}
+
+void t_hdr_replaces::set_early_only(const bool on) {
+ populated = true;
+ early_only = on;
+}
+
+void t_hdr_replaces::set_params(const list<t_parameter> &l) {
+ populated = true;
+ params = l;
+}
+
+void t_hdr_replaces::add_param(const t_parameter &p) {
+ populated = true;
+ params.push_back(p);
+}
+
+string t_hdr_replaces::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s += call_id;
+ s += ";to-tag=";
+ s += to_tag;
+ s += ";from-tag=";
+ s += from_tag;
+
+ if (early_only) {
+ s += ";early-only";
+ }
+
+ s += param_list2str(params);
+
+ return s;
+}
+
+bool t_hdr_replaces::is_valid(void) const {
+ return !(call_id.empty() || to_tag.empty() || from_tag.empty());
+}
diff --git a/src/parser/hdr_replaces.h b/src/parser/hdr_replaces.h
new file mode 100644
index 0000000..82acb47
--- /dev/null
+++ b/src/parser/hdr_replaces.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Replaces header
+// RFC 3891
+
+#ifndef _H_HDR_REPLACES
+#define _H_HDR_REPLACES
+
+#include <string>
+#include <list>
+#include "header.h"
+#include "parameter.h"
+
+using namespace std;
+
+class t_hdr_replaces : public t_header {
+public:
+ string call_id;
+ string to_tag;
+ string from_tag;
+ bool early_only;
+ list<t_parameter> params;
+
+ t_hdr_replaces();
+ void set_call_id(const string &id);
+ void set_to_tag(const string &tag);
+ void set_from_tag(const string &tag);
+ void set_early_only(const bool on);
+ void set_params(const list<t_parameter> &l);
+ void add_param(const t_parameter &p);
+ string encode_value(void) const;
+ bool is_valid(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_reply_to.cpp b/src/parser/hdr_reply_to.cpp
new file mode 100644
index 0000000..4609f5e
--- /dev/null
+++ b/src/parser/hdr_reply_to.cpp
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_reply_to.h"
+#include "definitions.h"
+
+t_hdr_reply_to::t_hdr_reply_to() : t_header("Reply-To") {}
+
+void t_hdr_reply_to::set_display(const string &d) {
+ populated = true;
+ display = d;
+}
+
+void t_hdr_reply_to::set_uri(const string &u) {
+ populated = true;
+ uri.set_url(u);
+}
+
+void t_hdr_reply_to::set_uri(const t_url &u) {
+ populated = true;
+ uri = u;
+}
+
+void t_hdr_reply_to::set_params(const list<t_parameter> &l) {
+ populated = true;
+ params = l;
+}
+
+void t_hdr_reply_to::add_param(const t_parameter &p) {
+ populated = true;
+ params.push_back(p);
+}
+
+string t_hdr_reply_to::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ if (display.size() > 0) {
+ s += '"';
+ s += display;
+ s += '"';
+ s += ' ';
+ }
+
+ s += '<';
+ s += uri.encode();
+ s += '>';
+
+ s += param_list2str(params);
+
+ return s;
+}
diff --git a/src/parser/hdr_reply_to.h b/src/parser/hdr_reply_to.h
new file mode 100644
index 0000000..bdf22f5
--- /dev/null
+++ b/src/parser/hdr_reply_to.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Reply-To header
+
+#ifndef _H_HDR_REPLY_TO
+#define _H_HDR_REPLY_TO
+
+#include <string>
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_hdr_reply_to : public t_header {
+public:
+ string display; // display name
+ t_url uri;
+ list<t_parameter> params;
+
+ t_hdr_reply_to();
+ void set_display(const string &d);
+ void set_uri(const string &u);
+ void set_uri(const t_url &u);
+ void set_params(const list<t_parameter> &l);
+ void add_param(const t_parameter &p);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_request_disposition.cpp b/src/parser/hdr_request_disposition.cpp
new file mode 100644
index 0000000..0e4bec0
--- /dev/null
+++ b/src/parser/hdr_request_disposition.cpp
@@ -0,0 +1,213 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_request_disposition.h"
+
+#include <vector>
+#include "util.h"
+
+t_hdr_request_disposition::t_hdr_request_disposition() :
+ t_header("Request-Disposition", "d"),
+ proxy_directive(PROXY_NULL),
+ cancel_directive(CANCEL_NULL),
+ fork_directive(FORK_NULL),
+ recurse_directive(RECURSE_NULL),
+ parallel_directive(PARALLEL_NULL),
+ queue_directive(QUEUE_NULL)
+{}
+
+void t_hdr_request_disposition::set_proxy_directive(t_proxy_directive directive) {
+ populated = true;
+ proxy_directive = directive;
+}
+
+void t_hdr_request_disposition::set_cancel_directive(t_cancel_directive directive) {
+ populated = true;
+ cancel_directive = directive;
+}
+
+void t_hdr_request_disposition::set_fork_directive(t_fork_directive directive) {
+ populated = true;
+ fork_directive = directive;
+}
+
+void t_hdr_request_disposition::set_recurse_directive(t_recurse_directive directive) {
+ populated = true;
+ recurse_directive = directive;
+}
+
+void t_hdr_request_disposition::set_parallel_directive(t_parallel_directive directive) {
+ populated = true;
+ parallel_directive = directive;
+}
+
+void t_hdr_request_disposition::set_queue_directive(t_queue_directive directive) {
+ populated = true;
+ queue_directive = directive;
+}
+
+bool t_hdr_request_disposition::set_directive(const string &s) {
+ if (s == REQDIS_PROXY) {
+ if (proxy_directive == REDIRECT) return false;
+ set_proxy_directive(PROXY);
+ return true;
+ }
+
+ if (s == REQDIS_REDIRECT) {
+ if (proxy_directive == PROXY) return false;
+ set_proxy_directive(REDIRECT);
+ return true;
+ }
+
+ if (s == REQDIS_CANCEL) {
+ if (cancel_directive == NO_CANCEL) return false;
+ set_cancel_directive(CANCEL);
+ return true;
+ }
+
+ if (s == REQDIS_NO_CANCEL) {
+ if (cancel_directive == CANCEL) return false;
+ set_cancel_directive(NO_CANCEL);
+ return true;
+ }
+
+ if (s == REQDIS_FORK) {
+ if (fork_directive == NO_FORK) return false;
+ set_fork_directive(FORK);
+ return true;
+ }
+
+ if (s == REQDIS_NO_FORK) {
+ if (fork_directive == FORK) return false;
+ set_fork_directive(NO_FORK);
+ return true;
+ }
+
+ if (s == REQDIS_RECURSE) {
+ if (recurse_directive == NO_RECURSE) return false;
+ set_recurse_directive(RECURSE);
+ return true;
+ }
+
+ if (s == REQDIS_NO_RECURSE) {
+ if (recurse_directive == RECURSE) return false;
+ set_recurse_directive(NO_RECURSE);
+ return true;
+ }
+
+ if (s == REQDIS_PARALLEL) {
+ if (parallel_directive == SEQUENTIAL) return false;
+ set_parallel_directive(PARALLEL);
+ return true;
+ }
+
+ if (s == REQDIS_SEQUENTIAL) {
+ if (parallel_directive == PARALLEL) return false;
+ set_parallel_directive(SEQUENTIAL);
+ return true;
+ }
+
+ if (s == REQDIS_QUEUE) {
+ if (queue_directive == NO_QUEUE) return false;
+ set_queue_directive(QUEUE);
+ return true;
+ }
+
+ if (s == REQDIS_NO_QUEUE) {
+ if (queue_directive == QUEUE) return false;
+ set_queue_directive(NO_QUEUE);
+ return true;
+ }
+
+ return false;
+}
+
+string t_hdr_request_disposition::encode_value(void) const {
+ if (!populated) return "";
+
+ vector<string> v;
+
+ switch (proxy_directive) {
+ case PROXY:
+ v.push_back(REQDIS_PROXY);
+ break;
+ case REDIRECT:
+ v.push_back(REQDIS_REDIRECT);
+ break;
+ default:
+ break;
+ }
+
+ switch (cancel_directive) {
+ case CANCEL:
+ v.push_back(REQDIS_CANCEL);
+ break;
+ case NO_CANCEL:
+ v.push_back(REQDIS_NO_CANCEL);
+ break;
+ default:
+ break;
+ }
+
+ switch (fork_directive) {
+ case FORK:
+ v.push_back(REQDIS_FORK);
+ break;
+ case NO_FORK:
+ v.push_back(REQDIS_NO_FORK);
+ break;
+ default:
+ break;
+ }
+
+ switch (recurse_directive) {
+ case RECURSE:
+ v.push_back(REQDIS_RECURSE);
+ break;
+ case NO_RECURSE:
+ v.push_back(REQDIS_NO_RECURSE);
+ break;
+ default:
+ break;
+ }
+
+ switch (parallel_directive) {
+ case PARALLEL:
+ v.push_back(REQDIS_PARALLEL);
+ break;
+ case SEQUENTIAL:
+ v.push_back(REQDIS_SEQUENTIAL);
+ break;
+ default:
+ break;
+ }
+
+ switch (queue_directive) {
+ case QUEUE:
+ v.push_back(REQDIS_QUEUE);
+ break;
+ case NO_QUEUE:
+ v.push_back(REQDIS_NO_QUEUE);
+ break;
+ default:
+ break;
+ }
+
+ string s = join_strings(v, ",");
+ return s;
+}
diff --git a/src/parser/hdr_request_disposition.h b/src/parser/hdr_request_disposition.h
new file mode 100644
index 0000000..9ae0988
--- /dev/null
+++ b/src/parser/hdr_request_disposition.h
@@ -0,0 +1,111 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+/**
+ * @file
+ * Request-Disposition header (RFC 3841)
+ */
+
+#ifndef _H_HDR_REQUEST_DISPOSITION
+#define _H_HDR_REQUEST_DISPOSITION
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+#define REQDIS_PROXY "proxy"
+#define REQDIS_REDIRECT "redirect"
+#define REQDIS_CANCEL "cancel"
+#define REQDIS_NO_CANCEL "no-cancel"
+#define REQDIS_FORK "fork"
+#define REQDIS_NO_FORK "no-fork"
+#define REQDIS_RECURSE "recurse"
+#define REQDIS_NO_RECURSE "no-recurse"
+#define REQDIS_PARALLEL "parallel"
+#define REQDIS_SEQUENTIAL "sequential"
+#define REQDIS_QUEUE "queue"
+#define REQDIS_NO_QUEUE "no-queue"
+
+/** Request-Disposition header (RFC 3841) */
+class t_hdr_request_disposition : public t_header {
+public:
+ enum t_proxy_directive {
+ PROXY_NULL,
+ PROXY,
+ REDIRECT
+ };
+
+ enum t_cancel_directive {
+ CANCEL_NULL,
+ CANCEL,
+ NO_CANCEL
+ };
+
+ enum t_fork_directive {
+ FORK_NULL,
+ FORK,
+ NO_FORK
+ };
+
+ enum t_recurse_directive {
+ RECURSE_NULL,
+ RECURSE,
+ NO_RECURSE
+ };
+
+ enum t_parallel_directive {
+ PARALLEL_NULL,
+ PARALLEL,
+ SEQUENTIAL
+ };
+
+ enum t_queue_directive {
+ QUEUE_NULL,
+ QUEUE,
+ NO_QUEUE
+ };
+
+ t_proxy_directive proxy_directive;
+ t_cancel_directive cancel_directive;
+ t_fork_directive fork_directive;
+ t_recurse_directive recurse_directive;
+ t_parallel_directive parallel_directive;
+ t_queue_directive queue_directive;
+
+ t_hdr_request_disposition();
+
+ void set_proxy_directive(t_proxy_directive directive);
+ void set_cancel_directive(t_cancel_directive directive);
+ void set_fork_directive(t_fork_directive directive);
+ void set_recurse_directive(t_recurse_directive directive);
+ void set_parallel_directive(t_parallel_directive directive);
+ void set_queue_directive(t_queue_directive directive);
+
+ /**
+ * Set a directive using one of the tokens define in RFC 3841
+ * @param s [in] Directive token.
+ * @return True if directive set. False if directive is invalid or
+ * conflicts with exisiting directives.
+ */
+ bool set_directive(const string &s);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_require.cpp b/src/parser/hdr_require.cpp
new file mode 100644
index 0000000..adaf38c
--- /dev/null
+++ b/src/parser/hdr_require.cpp
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_require.h"
+
+t_hdr_require::t_hdr_require() : t_header("Require") {};
+
+void t_hdr_require::add_feature(const string &f) {
+ populated = true;
+ if (!contains(f)) {
+ features.push_back(f);
+ }
+}
+
+void t_hdr_require::add_features(const list<string> &l) {
+ if (l.empty()) return;
+
+ for (list<string>::const_iterator i = l.begin(); i != l.end(); i++)
+ {
+ add_feature(*i);
+ }
+ populated = true;
+}
+
+void t_hdr_require::del_feature(const string &f) {
+ features.remove(f);
+}
+
+bool t_hdr_require::contains(const string &f) const {
+ if (!populated) return false;
+
+ for (list<string>::const_iterator i = features.begin();
+ i != features.end(); i++)
+ {
+ if (*i == f) return true;
+ }
+
+ return false;
+}
+
+string t_hdr_require::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<string>::const_iterator i = features.begin();
+ i != features.end(); i++)
+ {
+ if (i != features.begin()) s += ", ";
+ s += *i;
+ }
+
+ return s;
+}
+
+void t_hdr_require::unpopulate(void) {
+ populated = false;
+ features.clear();
+}
diff --git a/src/parser/hdr_require.h b/src/parser/hdr_require.h
new file mode 100644
index 0000000..463e8f3
--- /dev/null
+++ b/src/parser/hdr_require.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Require header
+
+#ifndef _H_HDR_REQUIRE
+#define _H_HDR_REQUIRE
+
+#include <list>
+#include <string>
+#include "header.h"
+
+class t_hdr_require : public t_header {
+public:
+ list<string> features;
+
+ t_hdr_require();
+ void add_feature(const string &f);
+ void add_features(const list<string> &l);
+ void del_feature(const string &f);
+ bool contains(const string &f) const;
+ string encode_value(void) const;
+ void unpopulate(void);
+};
+
+#endif
diff --git a/src/parser/hdr_retry_after.cpp b/src/parser/hdr_retry_after.cpp
new file mode 100644
index 0000000..ee54ea3
--- /dev/null
+++ b/src/parser/hdr_retry_after.cpp
@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_retry_after.h"
+#include "util.h"
+
+t_hdr_retry_after::t_hdr_retry_after() : t_header("Retry-After") {
+ time = 0;
+ duration = 0;
+}
+
+void t_hdr_retry_after::set_time(unsigned long t) {
+ populated = true;
+ time = t;
+}
+
+void t_hdr_retry_after::set_comment(const string &c) {
+ populated = true;
+ comment = c;
+}
+
+void t_hdr_retry_after::set_duration(unsigned long d) {
+ populated = true;
+ duration = d;
+}
+
+void t_hdr_retry_after::add_param(const t_parameter &p) {
+ populated = true;
+ params.push_back(p);
+}
+
+string t_hdr_retry_after::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s = ulong2str(time);
+
+ if (comment.size() > 0) {
+ s += " (";
+ s += comment;
+ s += ')';
+ }
+
+ if (duration > 0) {
+ s += ";duration=";
+ s += ulong2str(duration);
+ }
+
+ s += param_list2str(params);
+
+ return s;
+}
diff --git a/src/parser/hdr_retry_after.h b/src/parser/hdr_retry_after.h
new file mode 100644
index 0000000..759a513
--- /dev/null
+++ b/src/parser/hdr_retry_after.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Retry-After header
+
+#ifndef _H_HDR_RETRY_AFTER
+#define _H_HDR_RETRY_AFTER
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "parameter.h"
+
+using namespace std;
+
+class t_hdr_retry_after : public t_header {
+public:
+ unsigned long time; // in seconds
+ string comment;
+ unsigned long duration; // in seconds
+ list<t_parameter> params;
+
+ t_hdr_retry_after();
+ void set_time(unsigned long t);
+ void set_comment(const string &c);
+ void set_duration(unsigned long d);
+ void add_param(const t_parameter &p);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_route.cpp b/src/parser/hdr_route.cpp
new file mode 100644
index 0000000..8984574
--- /dev/null
+++ b/src/parser/hdr_route.cpp
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_route.h"
+#include "parse_ctrl.h"
+
+t_hdr_route::t_hdr_route() : t_header("Route") {
+ route_to_first_route = false;
+}
+
+void t_hdr_route::add_route(const t_route &r) {
+ populated = true;
+ route_list.push_back(r);
+}
+
+string t_hdr_route::encode(void) const {
+ return (t_parser::multi_values_as_list ?
+ t_header::encode() : encode_multi_header());
+}
+
+string t_hdr_route::encode_multi_header(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_route>::const_iterator i = route_list.begin();
+ i != route_list.end(); i++)
+ {
+ s += header_name;
+ s += ": ";
+ s += i->encode();
+ s += CRLF;
+ }
+
+ return s;
+}
+
+string t_hdr_route::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_route>::const_iterator i = route_list.begin();
+ i != route_list.end(); i++)
+ {
+ if (i != route_list.begin()) s += ",";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_route.h b/src/parser/hdr_route.h
new file mode 100644
index 0000000..a631403
--- /dev/null
+++ b/src/parser/hdr_route.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Route header
+
+#ifndef _H_HDR_ROUTE
+#define _H_HDR_ROUTE
+
+#include <list>
+#include <string>
+#include "route.h"
+#include "header.h"
+#include "parameter.h"
+
+using namespace std;
+
+class t_hdr_route : public t_header {
+public:
+ list<t_route> route_list;
+
+ // If route_to_first_route == true, then the request must be routed
+ // to the first route in the list. Otherwise to the request URI.
+ bool route_to_first_route;
+
+ t_hdr_route();
+ void add_route(const t_route &r);
+ string encode(void) const;
+ string encode_multi_header(void) const;
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_rseq.cpp b/src/parser/hdr_rseq.cpp
new file mode 100644
index 0000000..78fcf98
--- /dev/null
+++ b/src/parser/hdr_rseq.cpp
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_rseq.h"
+#include "util.h"
+
+t_hdr_rseq::t_hdr_rseq() : t_header("RSeq") {
+ resp_nr = 0;
+}
+
+void t_hdr_rseq::set_resp_nr(unsigned long l) {
+ populated = true;
+ resp_nr = l;
+}
+
+string t_hdr_rseq::encode_value(void) const {
+ if (!populated) return "";
+
+ return ulong2str(resp_nr);
+}
+
+bool t_hdr_rseq::operator==(const t_hdr_rseq &h) const {
+ return (resp_nr == h.resp_nr);
+}
diff --git a/src/parser/hdr_rseq.h b/src/parser/hdr_rseq.h
new file mode 100644
index 0000000..601a605
--- /dev/null
+++ b/src/parser/hdr_rseq.h
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// RSeq header
+// RFC 3262
+
+#ifndef _HDR_RSEQ
+#define _HDR_RSEQ
+
+#include <string>
+#include "header.h"
+#include "definitions.h"
+
+using namespace std;
+
+class t_hdr_rseq : public t_header {
+public:
+ unsigned long resp_nr;
+
+ t_hdr_rseq();
+ void set_resp_nr(unsigned long l);
+
+ string encode_value(void) const;
+
+ bool operator==(const t_hdr_rseq &h) const;
+};
+
+#endif
diff --git a/src/parser/hdr_server.cpp b/src/parser/hdr_server.cpp
new file mode 100644
index 0000000..6f59e01
--- /dev/null
+++ b/src/parser/hdr_server.cpp
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_server.h"
+#include "util.h"
+
+t_server::t_server() {}
+
+t_server::t_server(const string &_product, const string &_version,
+ const string &_comment)
+{
+ product = _product;
+ version = _version;
+ comment = _comment;
+}
+
+string t_server::encode(void) const {
+ string s;
+
+ s = product;
+
+ if (version.size() > 0) {
+ s += '/';
+ s += version;
+ }
+
+ if (comment.size() > 0) {
+ if (s.size() > 0) s += ' ';
+ s += "(";
+ s += comment;
+ s += ')';
+ }
+
+ return s;
+}
+
+t_hdr_server::t_hdr_server() : t_header("Server") {};
+
+void t_hdr_server::add_server(const t_server &s) {
+ populated = true;
+ server_info.push_back(s);
+}
+
+string t_hdr_server::get_server_info(void) const {
+ string s;
+
+ for (list<t_server>::const_iterator i = server_info.begin();
+ i != server_info.end(); i++ )
+ {
+ if (i != server_info.begin()) s += ' ';
+ s += i->encode();
+ }
+
+ return s;
+}
+
+string t_hdr_server::encode_value(void) const {
+ if (!populated) return "";
+
+ return get_server_info();
+}
diff --git a/src/parser/hdr_server.h b/src/parser/hdr_server.h
new file mode 100644
index 0000000..cfe9a8f
--- /dev/null
+++ b/src/parser/hdr_server.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Server header
+
+#ifndef _H_HDR_SERVER
+#define _H_HDR_SERVER
+
+#include <list>
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_server {
+public:
+ string product;
+ string version;
+ string comment;
+
+ t_server();
+ t_server(const string &_product, const string &_version,
+ const string &_comment = "");
+ string encode(void) const;
+};
+
+class t_hdr_server : public t_header {
+public:
+ list<t_server> server_info;
+
+ t_hdr_server();
+ void add_server(const t_server &s);
+
+ // Get a string representation of server_info
+ string get_server_info(void) const;
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_service_route.cpp b/src/parser/hdr_service_route.cpp
new file mode 100644
index 0000000..6b0c42c
--- /dev/null
+++ b/src/parser/hdr_service_route.cpp
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_service_route.h"
+#include "parse_ctrl.h"
+#include "util.h"
+
+t_hdr_service_route::t_hdr_service_route() : t_header("Service-Route") {}
+
+void t_hdr_service_route::add_route(const t_route &r) {
+ populated = true;
+ route_list.push_back(r);
+}
+
+string t_hdr_service_route::encode(void) const {
+ return (t_parser::multi_values_as_list ?
+ t_header::encode() : encode_multi_header());
+}
+
+string t_hdr_service_route::encode_multi_header(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_route>::const_iterator i = route_list.begin();
+ i != route_list.end(); i++)
+ {
+ s += header_name;
+ s += ": ";
+ s += i->encode();
+ s += CRLF;
+ }
+
+ return s;
+}
+
+string t_hdr_service_route::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_route>::const_iterator i = route_list.begin();
+ i != route_list.end(); i++)
+ {
+ if (i != route_list.begin()) s += ",";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_service_route.h b/src/parser/hdr_service_route.h
new file mode 100644
index 0000000..0c5a016
--- /dev/null
+++ b/src/parser/hdr_service_route.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Service-Route header
+
+#ifndef _H_HDR_SERVICE_ROUTE
+#define _H_HDR_SERVICE_ROUTE
+
+#include <list>
+#include <string>
+#include "route.h"
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_hdr_service_route : public t_header {
+public:
+ list<t_route> route_list;
+
+ t_hdr_service_route();
+ void add_route(const t_route &r);
+ string encode(void) const;
+ string encode_multi_header(void) const;
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_sip_etag.cpp b/src/parser/hdr_sip_etag.cpp
new file mode 100644
index 0000000..17ac857
--- /dev/null
+++ b/src/parser/hdr_sip_etag.cpp
@@ -0,0 +1,31 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_sip_etag.h"
+
+t_hdr_sip_etag::t_hdr_sip_etag() : t_header("SIP-ETag") {};
+
+void t_hdr_sip_etag::set_etag(const string &_etag) {
+ populated = true;
+ etag = _etag;
+}
+
+string t_hdr_sip_etag::encode_value(void) const {
+ if (!populated) return "";
+ return etag;
+}
diff --git a/src/parser/hdr_sip_etag.h b/src/parser/hdr_sip_etag.h
new file mode 100644
index 0000000..de352e9
--- /dev/null
+++ b/src/parser/hdr_sip_etag.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+/**
+ * @file
+ * SIP-ETag header (RFC 3903)
+ */
+
+#ifndef _HDR_SIP_ETAG_H
+#define _HDR_SIP_ETAG_H
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+/** SIP-ETag header (RFC 3903) */
+class t_hdr_sip_etag : public t_header {
+public:
+ string etag; /**< Entity tag. */
+
+ /** Constructor. */
+ t_hdr_sip_etag();
+
+ /**
+ * Set entity tag.
+ * @param _etag [in] Entity tag to set.
+ */
+ void set_etag(const string &_etag);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_sip_if_match.cpp b/src/parser/hdr_sip_if_match.cpp
new file mode 100644
index 0000000..aef4241
--- /dev/null
+++ b/src/parser/hdr_sip_if_match.cpp
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_sip_if_match.h"
+
+t_hdr_sip_if_match::t_hdr_sip_if_match() : t_header("SIP-If-Match") {};
+
+void t_hdr_sip_if_match::set_etag(const string &_etag) {
+ populated = true;
+ etag = _etag;
+}
+
+string t_hdr_sip_if_match::encode_value(void) const {
+ if (!populated) return "";
+ return etag;
+}
+
+void t_hdr_sip_if_match::clear(void) {
+ etag.clear();
+ populated = false;
+}
diff --git a/src/parser/hdr_sip_if_match.h b/src/parser/hdr_sip_if_match.h
new file mode 100644
index 0000000..67e98f4
--- /dev/null
+++ b/src/parser/hdr_sip_if_match.h
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+/**
+ * @file
+ * SIP-If-Match header (RFC 3903)
+ */
+
+#ifndef _HDR_SIP_IF_MATCH_H
+#define _HDR_SIP_IF_MATCH_H
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+/** SIP-If-Match header (RFC 3903) */
+class t_hdr_sip_if_match : public t_header {
+public:
+ string etag; /**< Entity tag. */
+
+ /** Constructor. */
+ t_hdr_sip_if_match();
+
+ /**
+ * Set entity tag.
+ * @param _etag [in] Entity tag to set.
+ */
+ void set_etag(const string &_etag);
+
+ /** Clear the header. */
+ void clear(void);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_subject.cpp b/src/parser/hdr_subject.cpp
new file mode 100644
index 0000000..3a2094d
--- /dev/null
+++ b/src/parser/hdr_subject.cpp
@@ -0,0 +1,34 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_subject.h"
+#include "parse_ctrl.h"
+
+t_hdr_subject::t_hdr_subject() : t_header("Subject", "s") {};
+
+void t_hdr_subject::set_subject(const string &s) {
+ populated = true;
+ subject = s;
+}
+
+string t_hdr_subject::encode_value(void) const {
+ if (!populated) return "";
+
+ return subject;
+}
diff --git a/src/parser/hdr_subject.h b/src/parser/hdr_subject.h
new file mode 100644
index 0000000..130614a
--- /dev/null
+++ b/src/parser/hdr_subject.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Subject header
+#ifndef _H_HDR_SUBJECT
+#define _H_HDR_SUBJECT
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_subject : public t_header {
+public:
+ string subject;
+
+ t_hdr_subject();
+ void set_subject(const string &s);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_subscription_state.cpp b/src/parser/hdr_subscription_state.cpp
new file mode 100644
index 0000000..2fb4354
--- /dev/null
+++ b/src/parser/hdr_subscription_state.cpp
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_subscription_state.h"
+#include "util.h"
+
+t_hdr_subscription_state::t_hdr_subscription_state() : t_header("Subscription-State") {
+ expires = 0;
+ retry_after = 0;
+}
+
+void t_hdr_subscription_state::set_substate(const string &s) {
+ populated = true;
+ substate = s;
+}
+
+void t_hdr_subscription_state::set_reason(const string &s) {
+ populated = true;
+ reason = s;
+}
+
+void t_hdr_subscription_state::set_expires(unsigned long e) {
+ populated = true;
+ expires = e;
+}
+
+void t_hdr_subscription_state::set_retry_after(unsigned long r) {
+ populated = true;
+ retry_after = r;
+}
+
+void t_hdr_subscription_state::add_extension(const t_parameter &p) {
+ populated = true;
+ extensions.push_back(p);
+}
+
+string t_hdr_subscription_state::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s = substate;
+
+ if (reason.size() > 0) {
+ s += ";reason=";
+ s += reason;
+ }
+
+ if (expires > 0) {
+ s += ";expires=";
+ s += ulong2str(expires);
+ }
+
+ if (retry_after > 0) {
+ s += ";retry-after=";
+ s += ulong2str(retry_after);
+ }
+
+ s += param_list2str(extensions);
+
+ return s;
+}
diff --git a/src/parser/hdr_subscription_state.h b/src/parser/hdr_subscription_state.h
new file mode 100644
index 0000000..b0837d4
--- /dev/null
+++ b/src/parser/hdr_subscription_state.h
@@ -0,0 +1,63 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Subscription-State header
+// RFC 3265
+
+#ifndef _HDR_SUBSCRIPTION_STATE
+#define _HDR_SUBSCRIPTION_STATE
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "parameter.h"
+
+// Subscription states
+#define SUBSTATE_ACTIVE "active"
+#define SUBSTATE_PENDING "pending"
+#define SUBSTATE_TERMINATED "terminated"
+
+// Event reasons
+#define EV_REASON_DEACTIVATED "deactivated"
+#define EV_REASON_PROBATION "probation"
+#define EV_REASON_REJECTED "rejected"
+#define EV_REASON_TIMEOUT "timeout"
+#define EV_REASON_GIVEUP "giveup"
+#define EV_REASON_NORESOURCE "noresource"
+
+using namespace std;
+
+class t_hdr_subscription_state : public t_header {
+public:
+ string substate;
+ string reason;
+ unsigned long expires;
+ unsigned long retry_after;
+ list<t_parameter> extensions;
+
+ t_hdr_subscription_state();
+ void set_substate(const string &s);
+ void set_reason(const string &s);
+ void set_expires(unsigned long e);
+ void set_retry_after(unsigned long r);
+ void add_extension(const t_parameter &p);
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_supported.cpp b/src/parser/hdr_supported.cpp
new file mode 100644
index 0000000..96b6a42
--- /dev/null
+++ b/src/parser/hdr_supported.cpp
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_supported.h"
+#include "parse_ctrl.h"
+
+t_hdr_supported::t_hdr_supported() : t_header("Supported", "k") {};
+
+void t_hdr_supported::add_feature(const string &f) {
+ populated = true;
+ if (!contains(f)) {
+ features.push_back(f);
+ }
+}
+
+void t_hdr_supported::add_features(const list<string> &l) {
+ if (l.empty()) return;
+
+ for (list<string>::const_iterator i = l.begin(); i != l.end(); i++)
+ {
+ add_feature(*i);
+ }
+ populated = true;
+}
+
+void t_hdr_supported::set_empty(void) {
+ populated = true;
+ features.clear();
+}
+
+bool t_hdr_supported::contains(const string &f) const {
+ if (!populated) return false;
+
+ for (list<string>::const_iterator i = features.begin();
+ i != features.end(); i++)
+ {
+ if (*i == f) return true;
+ }
+
+ return false;
+}
+
+string t_hdr_supported::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<string>::const_iterator i = features.begin();
+ i != features.end(); i++)
+ {
+ if (i != features.begin()) s += ",";
+ s += *i;
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_supported.h b/src/parser/hdr_supported.h
new file mode 100644
index 0000000..aa012f1
--- /dev/null
+++ b/src/parser/hdr_supported.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Supported header
+
+#ifndef _H_HDR_SUPPORTED
+#define _H_HDR_SUPPORTED
+
+#include <list>
+#include <string>
+#include "header.h"
+
+#define EXT_100REL "100rel" // RFC 3262
+#define EXT_REPLACES "replaces" // RFC 3891
+#define EXT_NOREFERSUB "norefersub" // RFC 4488
+
+class t_hdr_supported : public t_header {
+public:
+ list<string> features;
+
+ t_hdr_supported();
+ void add_feature(const string &f);
+ void add_features(const list<string> &l);
+
+ // Clear the list of features, but make the header 'populated'.
+ // An empty header will be in the message.
+ void set_empty(void);
+
+ bool contains(const string &f) const;
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_timestamp.cpp b/src/parser/hdr_timestamp.cpp
new file mode 100644
index 0000000..7e1f769
--- /dev/null
+++ b/src/parser/hdr_timestamp.cpp
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_timestamp.h"
+#include "util.h"
+
+t_hdr_timestamp::t_hdr_timestamp() : t_header("Timestamp") {
+ timestamp = 0;
+ delay = 0;
+}
+
+void t_hdr_timestamp::set_timestamp(float t) {
+ populated = true;
+ timestamp = t;
+}
+
+void t_hdr_timestamp::set_delay(float d) {
+ populated = true;
+ delay = d;
+}
+
+string t_hdr_timestamp::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s += float2str(timestamp, 3);
+
+ if (delay != 0) {
+ s += " ";
+ s += float2str(delay, 3);
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_timestamp.h b/src/parser/hdr_timestamp.h
new file mode 100644
index 0000000..9a1780a
--- /dev/null
+++ b/src/parser/hdr_timestamp.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Timestamp header
+
+#ifndef _H_HDR_TIMESTAMP
+#define _H_HDR_TIMESTAMP
+
+#include <string>
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_timestamp : public t_header {
+public:
+ float timestamp;
+ float delay;
+
+ t_hdr_timestamp();
+ void set_timestamp(float t);
+ void set_delay(float d);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_to.cpp b/src/parser/hdr_to.cpp
new file mode 100644
index 0000000..06ee170
--- /dev/null
+++ b/src/parser/hdr_to.cpp
@@ -0,0 +1,80 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_to.h"
+#include "definitions.h"
+#include "parse_ctrl.h"
+#include "util.h"
+
+t_hdr_to::t_hdr_to() : t_header("To", "t") {}
+
+void t_hdr_to::set_display(const string &d) {
+ populated = true;
+ display = d;
+}
+
+void t_hdr_to::set_uri(const string &u) {
+ populated = true;
+ uri.set_url(u);
+}
+
+void t_hdr_to::set_uri(const t_url &u) {
+ populated = true;
+ uri = u;
+}
+
+void t_hdr_to::set_tag(const string &t) {
+ populated = true;
+ tag = t;
+}
+
+void t_hdr_to::set_params(const list<t_parameter> &l) {
+ populated = true;
+ params = l;
+}
+
+void t_hdr_to::add_param(const t_parameter &p) {
+ populated = true;
+ params.push_back(p);
+}
+
+string t_hdr_to::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ if (display.size() > 0) {
+ s += '"';
+ s += escape(display, '"');
+ s += '"';
+ s += ' ';
+ }
+
+ s += '<';
+ s += uri.encode();
+ s += '>';
+
+ if (tag != "") {
+ s += ";tag=";
+ s += tag;
+ }
+
+ s += param_list2str(params);
+
+ return s;
+}
diff --git a/src/parser/hdr_to.h b/src/parser/hdr_to.h
new file mode 100644
index 0000000..3a308ba
--- /dev/null
+++ b/src/parser/hdr_to.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// To header
+
+#ifndef _H_HDR_TO
+#define _H_HDR_TO
+
+#include <string>
+#include "header.h"
+#include "parameter.h"
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_hdr_to : public t_header {
+public:
+ string display; // display name
+ t_url uri;
+ string tag;
+ list<t_parameter> params;
+
+ t_hdr_to();
+ void set_display(const string &d);
+ void set_uri(const string &u);
+ void set_uri(const t_url &u);
+ void set_tag(const string &t);
+ void set_params(const list<t_parameter> &l);
+ void add_param(const t_parameter &p);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_unsupported.cpp b/src/parser/hdr_unsupported.cpp
new file mode 100644
index 0000000..2107fbc
--- /dev/null
+++ b/src/parser/hdr_unsupported.cpp
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_unsupported.h"
+
+t_hdr_unsupported::t_hdr_unsupported() : t_header("Unsupported") {};
+
+void t_hdr_unsupported::add_feature(const string &f) {
+ populated = true;
+ features.push_back(f);
+}
+
+void t_hdr_unsupported::set_features(const list<string> &_features) {
+ populated = true;
+ features = _features;
+}
+
+bool t_hdr_unsupported::contains(const string &f) const {
+ if (!populated) return false;
+
+ for (list<string>::const_iterator i = features.begin();
+ i != features.end(); i++)
+ {
+ if (*i == f) return true;
+ }
+
+ return false;
+}
+
+string t_hdr_unsupported::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<string>::const_iterator i = features.begin();
+ i != features.end(); i++)
+ {
+ if (i != features.begin()) s += ",";
+ s += *i;
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_unsupported.h b/src/parser/hdr_unsupported.h
new file mode 100644
index 0000000..956d2b4
--- /dev/null
+++ b/src/parser/hdr_unsupported.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Unsupported header
+
+#ifndef _H_HDR_UNSUPPORTED
+#define _H_HDR_UNSUPPORTED
+
+#include <list>
+#include <string>
+#include "header.h"
+
+class t_hdr_unsupported : public t_header {
+public:
+ list<string> features;
+
+ t_hdr_unsupported();
+ void add_feature(const string &f);
+ void set_features(const list<string> &_features);
+ bool contains(const string &f) const;
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_user_agent.cpp b/src/parser/hdr_user_agent.cpp
new file mode 100644
index 0000000..0c36f7f
--- /dev/null
+++ b/src/parser/hdr_user_agent.cpp
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_user_agent.h"
+#include "util.h"
+
+t_hdr_user_agent::t_hdr_user_agent() : t_header("User-Agent") {};
+
+void t_hdr_user_agent::add_server(const t_server &s) {
+ populated = true;
+ ua_info.push_back(s);
+}
+
+string t_hdr_user_agent::get_ua_info(void) const {
+ string s;
+
+ for (list<t_server>::const_iterator i = ua_info.begin();
+ i != ua_info.end(); i++ )
+ {
+ if (i != ua_info.begin()) s += ' ';
+ s += i->encode();
+ }
+
+ return s;
+}
+
+string t_hdr_user_agent::encode_value(void) const {
+ if (!populated) return "";
+
+ return get_ua_info();
+}
diff --git a/src/parser/hdr_user_agent.h b/src/parser/hdr_user_agent.h
new file mode 100644
index 0000000..b67a20e
--- /dev/null
+++ b/src/parser/hdr_user_agent.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// User-Agent header
+
+#ifndef _H_HDR_USER_AGENT
+#define _H_HDR_USER_AGENT
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "hdr_server.h"
+
+using namespace std;
+
+class t_hdr_user_agent : public t_header {
+public:
+ list<t_server> ua_info;
+
+ t_hdr_user_agent();
+ void add_server(const t_server &s);
+
+ // Get string representation of ua_info;
+ string get_ua_info(void) const;
+
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_via.cpp b/src/parser/hdr_via.cpp
new file mode 100644
index 0000000..d076bfe
--- /dev/null
+++ b/src/parser/hdr_via.cpp
@@ -0,0 +1,211 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <iostream>
+#include "definitions.h"
+#include "hdr_via.h"
+#include "util.h"
+#include "parse_ctrl.h"
+#include "protocol.h"
+#include "sockets/url.h"
+
+t_via::t_via() {
+ port = 0;
+ ttl = 0;
+ rport_present = false;
+ rport = 0;
+}
+
+t_via::t_via(const string &_host, const int _port, bool add_rport) {
+ protocol_name = "SIP";
+ protocol_version = SIP_VERSION;
+ transport = "UDP";
+ host = _host;
+ branch = RFC3261_COOKIE + random_token(8);
+
+ if (_port != get_default_port("sip")) {
+ port = _port;
+ } else {
+ port = 0;
+ }
+
+ ttl = 0;
+ rport_present = add_rport;
+ rport = 0;
+}
+
+void t_via::add_extension(const t_parameter &p) {
+ extensions.push_back(p);
+}
+
+string t_via::encode(void) const {
+ string s;
+
+ s = protocol_name + '/' + protocol_version + '/' + transport;
+ s += ' ';
+ s += host;
+
+ if (port > 0) {
+ s += ':';
+ s += int2str(port);
+ }
+
+ if (ttl > 0) s += int2str(ttl, ";ttl=%d");
+
+ if (maddr.size() > 0) {
+ s += ";maddr=";
+ s += maddr;
+ }
+
+ if (received.size() > 0) {
+ s += ";received=";
+ s += received;
+ }
+
+ if (rport_present) {
+ s += ";rport";
+ if (rport > 0) {
+ s += "=";
+ s += int2str(rport);
+ }
+ }
+
+ if (branch.size() > 0) {
+ s += ";branch=";
+ s += branch;
+ }
+
+ s += param_list2str(extensions);
+ return s;
+}
+
+void t_via::get_response_dst(t_ip_port &ip_port) const {
+ string url_str("sip:");
+
+ // RFC 3261 18.2.2
+ // Determine the address to send a repsonse to
+ // NOTE: the received-parameter will be added by the listener if needed.
+
+ if (tolower(transport) == "tcp") {
+ // NOTE: The response must be sent over the connection on which
+ // the request was received. The address returned here is an
+ // alternative if that connection is closed already.
+ if (received.size() > 0) {
+ url_str += received;
+ } else {
+ url_str += host;
+ }
+
+ url_str += ":";
+
+ // NOTE: The rport parameter is not processed here as it only
+ // applies to unreliable transports (RFC 3581 4)
+ url_str += int2str(port);
+
+ t_url u(url_str);
+ list<t_ip_port> ip_list = u.get_h_ip_srv("tcp");
+ ip_port = ip_list.front();
+ } else {
+ if (maddr.size() > 0) {
+ url_str += maddr;
+ } else if (received.size() > 0) {
+ url_str += received;
+ } else {
+ url_str += host;
+ }
+
+ // RFC 3581 4
+ if (rport_present && rport > 0) {
+ // NOTE: the rport value will be added by the UDP listener
+ // if the rport parameter without value was present.
+ url_str += ':';
+ url_str += int2str(rport);
+ } else if (port != 0) {
+ url_str += ':';
+ url_str += int2str(port);
+ }
+
+ // If there was no maddr parameter, then the URL will always point to
+ // an IP address; either the host was an IP address or a received parameter
+ // containing an IP address was added (see RFC 3261 18.2.1)
+ // If there was an maddr, then the URL can be a domain that could have
+ // multiple SRV records. RFC 3263 section 5 does not specify what to do in
+ // this case. So just send the response to the first destination.
+ t_url u(url_str);
+ list<t_ip_port> ip_list = u.get_h_ip_srv("udp");
+ ip_port = ip_list.front();
+ }
+}
+
+bool t_via::rfc3261_compliant(void) const {
+ return (branch.find(RFC3261_COOKIE) == 0);
+}
+
+
+t_hdr_via::t_hdr_via() : t_header("Via", "v") {}
+
+void t_hdr_via::add_via(const t_via &v) {
+ populated = true;
+ via_list.push_back(v);
+}
+
+string t_hdr_via::encode(void) const {
+ return (t_parser::multi_values_as_list ?
+ t_header::encode() : encode_multi_header());
+}
+
+string t_hdr_via::encode_multi_header(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_via>::const_iterator i = via_list.begin();
+ i != via_list.end(); i++)
+ {
+ s += (t_parser::compact_headers ? compact_name : header_name);
+ s += ": ";
+ s += i->encode();
+ s += CRLF;
+ }
+
+ return s;
+}
+
+string t_hdr_via::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_via>::const_iterator i = via_list.begin();
+ i != via_list.end(); i++)
+ {
+ if (i != via_list.begin()) s += ",";
+ s += i->encode();
+ }
+
+ return s;
+}
+
+void t_hdr_via::get_response_dst(t_ip_port &ip_port) const {
+ if (!populated) {
+ ip_port.clear();
+ return;
+ }
+
+ via_list.front().get_response_dst(ip_port);
+}
diff --git a/src/parser/hdr_via.h b/src/parser/hdr_via.h
new file mode 100644
index 0000000..e7e6260
--- /dev/null
+++ b/src/parser/hdr_via.h
@@ -0,0 +1,73 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Via header
+
+#ifndef _H_HDR_VIA
+#define _H_HDR_VIA
+
+#include <list>
+#include <string>
+#include "header.h"
+#include "parameter.h"
+
+class t_via {
+public:
+ string protocol_name;
+ string protocol_version;
+ string transport;
+ string host;
+ int port;
+ int ttl;
+ string maddr;
+ string received;
+ string branch;
+
+ // RFC 3581: symetric response routing
+ bool rport_present;
+ int rport;
+
+ list <t_parameter> extensions;
+
+ t_via();
+ t_via(const string &_host, const int _port, bool add_rport = true);
+ void add_extension(const t_parameter &p);
+ string encode(void) const;
+
+ // Get the response destination
+ void get_response_dst(t_ip_port &ip_port) const;
+
+ // Returns true if branch starts with RFC 3261 magic cookie
+ bool rfc3261_compliant(void) const;
+};
+
+class t_hdr_via : public t_header {
+public:
+ list<t_via> via_list;
+
+ t_hdr_via();
+ void add_via(const t_via &v);
+ string encode(void) const;
+ string encode_multi_header(void) const;
+ string encode_value(void) const;
+
+ // Get the response destination
+ void get_response_dst(t_ip_port &ip_port) const;
+};
+
+#endif
diff --git a/src/parser/hdr_warning.cpp b/src/parser/hdr_warning.cpp
new file mode 100644
index 0000000..e77ef35
--- /dev/null
+++ b/src/parser/hdr_warning.cpp
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "hdr_warning.h"
+#include "util.h"
+
+t_warning::t_warning() {
+ code = 0;
+ port = 0;
+}
+
+t_warning::t_warning(const string &_host, int _port, int _code, string _text) {
+ host = _host;
+ port = _port;
+ code = _code;
+
+ switch(code) {
+ case 300: text = WARNING_300; break;
+ case 301: text = WARNING_301; break;
+ case 302: text = WARNING_302; break;
+ case 303: text = WARNING_303; break;
+ case 304: text = WARNING_304; break;
+ case 305: text = WARNING_305; break;
+ case 306: text = WARNING_306; break;
+ case 307: text = WARNING_307; break;
+ case 330: text = WARNING_330; break;
+ case 331: text = WARNING_331; break;
+ case 370: text = WARNING_370; break;
+ case 399: text = WARNING_399; break;
+ default: text = "Warning";
+ }
+
+ if (_text != "") {
+ text += ": ";
+ text += _text;
+ }
+}
+
+string t_warning::encode(void) const {
+ string s;
+
+ s = int2str(code, "%3d");
+ s += ' ';
+ s += host;
+ if (port > 0) s += int2str(port, ":%d");
+ s += ' ';
+ s += '"';
+ s += text;
+ s += '"';
+ return s;
+}
+
+t_hdr_warning::t_hdr_warning() : t_header("Warning") {}
+
+void t_hdr_warning::add_warning(const t_warning &w) {
+ populated = true;
+ warnings.push_back(w);
+}
+
+string t_hdr_warning::encode_value(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ for (list<t_warning>::const_iterator i = warnings.begin();
+ i != warnings.end(); i++)
+ {
+ if (i != warnings.begin()) s += ", ";
+ s += i->encode();
+ }
+
+ return s;
+}
diff --git a/src/parser/hdr_warning.h b/src/parser/hdr_warning.h
new file mode 100644
index 0000000..1bfa200
--- /dev/null
+++ b/src/parser/hdr_warning.h
@@ -0,0 +1,83 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Warning header
+
+#ifndef _H_HDR_WARNING
+#define _H_HDR_WARNING
+
+#include <list>
+#include <string>
+#include "header.h"
+
+// Warning codes
+#define W_300_INCOMPATIBLE_NWK_PROT 300
+#define W_301_INCOMPATIBLE_ADDR_FORMAT 301
+#define W_302_INCOMPATIBLE_TRANS_PROT 302
+#define W_303_INCOMPATIBLE_BW_UNITS 303
+#define W_304_MEDIA_TYPE_NOT_AVAILABLE 304
+#define W_305_INCOMPATIBLE_MEDIA_FORMAT 305
+#define W_306_ATTRIBUTE_NOT_UNDERSTOOD 306
+#define W_307_PARAMETER_NOT_UNDERSTOOD 307
+#define W_330_MULTICAST_NOT_AVAILABLE 330
+#define W_331_UNICAST_NOT_AVAILABLE 331
+#define W_370_INSUFFICIENT_BANDWITH 370
+#define W_399_MISCELLANEOUS 399
+
+// Warning texts
+#define WARNING_300 "Incompatible network protocol"
+#define WARNING_301 "Incompatible network address formats"
+#define WARNING_302 "Incompatible transport protocol"
+#define WARNING_303 "Incompatible bandwith units"
+#define WARNING_304 "Media type not available"
+#define WARNING_305 "Incompatible media format"
+#define WARNING_306 "Attribute not understood"
+#define WARNING_307 "Session description parameter not understood"
+#define WARNING_330 "Multicast not available"
+#define WARNING_331 "Unicast not available"
+#define WARNING_370 "Insufficient bandwith"
+#define WARNING_399 "Miscellanous warning"
+
+using namespace std;
+
+class t_warning {
+public:
+ int code;
+ string host;
+ int port;
+ string text;
+
+ t_warning();
+
+ // The default text will be used as warning appended with passed
+ // text if present
+ t_warning(const string &_host, int _port, int _code, string _text);
+
+ string encode(void) const;
+};
+
+class t_hdr_warning : public t_header {
+public:
+ list<t_warning> warnings;
+
+ t_hdr_warning();
+ void add_warning(const t_warning &w);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/hdr_www_authenticate.cpp b/src/parser/hdr_www_authenticate.cpp
new file mode 100644
index 0000000..c5d3286
--- /dev/null
+++ b/src/parser/hdr_www_authenticate.cpp
@@ -0,0 +1,33 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "hdr_www_authenticate.h"
+#include "definitions.h"
+
+t_hdr_www_authenticate::t_hdr_www_authenticate() : t_header("WWW-Authenticate") {}
+
+void t_hdr_www_authenticate::set_challenge(const t_challenge &c) {
+ populated = true;
+ challenge = c;
+}
+
+string t_hdr_www_authenticate::encode_value(void) const {
+ if (!populated) return "";
+
+ return challenge.encode();
+}
diff --git a/src/parser/hdr_www_authenticate.h b/src/parser/hdr_www_authenticate.h
new file mode 100644
index 0000000..e0d4dd2
--- /dev/null
+++ b/src/parser/hdr_www_authenticate.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// WWW-Authenticate header
+
+#ifndef _HDR_WWW_AUTHENTICATE_H
+#define _HDR_WWW_AUTHENTICATE_H
+
+#include <list>
+#include <string>
+#include "challenge.h"
+#include "header.h"
+
+using namespace std;
+
+class t_hdr_www_authenticate : public t_header {
+public:
+ t_challenge challenge;
+
+ t_hdr_www_authenticate();
+
+ void set_challenge(const t_challenge &c);
+ string encode_value(void) const;
+};
+
+#endif
diff --git a/src/parser/header.cpp b/src/parser/header.cpp
new file mode 100644
index 0000000..622e9a2
--- /dev/null
+++ b/src/parser/header.cpp
@@ -0,0 +1,82 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "header.h"
+#include "parse_ctrl.h"
+#include "protocol.h"
+#include "util.h"
+
+t_header::t_header() :
+ populated(false)
+{}
+
+t_header::t_header(const string &_header_name, const string &_compact_name) :
+ populated(false),
+ header_name(_header_name),
+ compact_name(_compact_name)
+{}
+
+string t_header::encode(void) const {
+ string s;
+
+ if (!populated) return s;
+
+ s = (t_parser::compact_headers && !compact_name.empty() ?
+ compact_name : header_name);
+ s += ": ";
+ s += encode_value();
+ s += CRLF;
+
+ return s;
+}
+
+string t_header::encode_env(void) const {
+ string s("SIP_");
+ s += toupper(replace_char(header_name, '-', '_'));
+ s += '=';
+ s += encode_value();
+
+ return s;
+}
+
+bool t_header::is_populated() const {
+ return populated;
+}
+
+string t_header::get_name(void) const {
+ return header_name;
+}
+
+string t_header::get_value(void) const {
+ string s;
+ string::size_type i;
+
+ if (!populated) return s;
+
+ s = encode();
+ i = s.find(':');
+
+ // The colon cannot be the first or last character
+ if (i == string::npos || i == s.size()-1) return "";
+
+ s = s.substr(i+1);
+ i = s.find(CRLF);
+ s = s.substr(0, i);
+
+ return (trim(s));
+}
diff --git a/src/parser/header.h b/src/parser/header.h
new file mode 100644
index 0000000..5d6f572
--- /dev/null
+++ b/src/parser/header.h
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Base class for message and response headers
+
+#ifndef _HEADER_H
+#define _HEADER_H
+
+#include <string>
+
+using namespace std;
+
+class t_header {
+private:
+ t_header();
+
+protected:
+ bool populated; // true = header is populated
+ string header_name; // Full name of header in SIP messages
+ string compact_name; // Compact name of header in SIP messages
+
+public:
+ virtual ~t_header() {}
+ t_header(const string &_header_name, const string &_compact_name = "");
+
+ // Return the text encoded header (CRLF at end of string)
+ virtual string encode(void) const;
+
+ // Return the text encoded value part (no CRLF at end of string)
+ virtual string encode_value(void) const = 0;
+
+ // Return a environemnt variable setting
+ // The format of the setting is:
+ //
+ // SIP_<header name>=<value>
+ //
+ // The header name is in capitals. Dashes are replaced by underscores.
+ virtual string encode_env(void) const;
+
+ // Get the header name
+ string get_name(void) const;
+
+ // Get text encoding of the header value only.
+ // I.e. without header name and no trailing CRLF
+ string get_value(void) const;
+
+ // Return true if the header is populated
+ bool is_populated(void) const;
+};
+
+#endif
diff --git a/src/parser/identity.cpp b/src/parser/identity.cpp
new file mode 100644
index 0000000..161a44a
--- /dev/null
+++ b/src/parser/identity.cpp
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "identity.h"
+#include "util.h"
+
+t_identity::t_identity() : display(), uri() {}
+
+void t_identity::set_display(const string &d) {
+ display = d;
+}
+
+void t_identity::set_uri(const string &u) {
+ uri.set_url(u);
+}
+
+void t_identity::set_uri(const t_url &u) {
+ uri = u;
+}
+
+string t_identity::encode(void) const {
+ string s;
+
+ if (display.size() > 0) {
+ s += '"';
+ s += escape(display, '"');
+ s += '"';
+ s += ' ';
+ }
+
+ s += '<';
+ s += uri.encode();
+ s += '>';
+
+ return s;
+}
diff --git a/src/parser/identity.h b/src/parser/identity.h
new file mode 100644
index 0000000..6da7d72
--- /dev/null
+++ b/src/parser/identity.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 _IDENTITY_H
+#define _IDENTITY_H
+
+#include <string>
+#include "sockets/url.h"
+
+using namespace std;
+
+class t_identity {
+public:
+ string display; // display name
+ t_url uri;
+
+ t_identity();
+ void set_display(const string &d);
+ void set_uri(const string &u);
+ void set_uri(const t_url &u);
+
+ string encode(void) const;
+};
+
+#endif
diff --git a/src/parser/media_type.cpp b/src/parser/media_type.cpp
new file mode 100644
index 0000000..c9112df
--- /dev/null
+++ b/src/parser/media_type.cpp
@@ -0,0 +1,100 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <cassert>
+#include <cstdlib>
+
+#include "media_type.h"
+#include "util.h"
+#include "utils/mime_database.h"
+
+using namespace std;
+using namespace utils;
+
+t_media::t_media() : q(1.0) {}
+
+t_media::t_media(const string &t, const string &s) :
+ type(t),
+ subtype(s),
+ q(1.0)
+{}
+
+t_media::t_media(const string &mime_type) : q(1.0)
+{
+ vector<string> v = split(mime_type, '/');
+
+ if (v.size() == 2) {
+ type = v[0];
+ subtype = v[1];
+ }
+}
+
+void t_media::add_params(const list<t_parameter> &l) {
+ list<t_parameter>::const_iterator i = l.begin();
+
+ media_param_list.clear();
+ accept_extension_list.clear();
+
+ // Add media parameters
+ while (i != l.end() && i->name != "q") {
+ if (i->name == "charset") {
+ charset = i->value;
+ } else {
+ media_param_list.push_back(*i);
+ }
+ ++i;
+ }
+
+ // Set the quality factor
+ if (i != l.end()) {
+ q = atof(i->value.c_str());
+ i++;
+ }
+
+ // Add accept extension parameters
+ while (i != l.end()) {
+ accept_extension_list.push_back(*i);
+ i++;
+ }
+}
+
+
+string t_media::encode(void) const {
+ string s;
+
+ s = type + '/' + subtype;
+ if (!charset.empty()) {
+ s += ";charset=";
+ s += charset;
+ }
+ s += param_list2str(media_param_list);
+
+ if (q != 1) {
+ s += ";q=";
+ s += float2str(q, 1);
+ }
+
+ s += param_list2str(accept_extension_list);
+
+ return s;
+}
+
+string t_media::get_file_glob(void) const {
+ string file_glob = mime_database->get_glob(type + '/' + subtype);
+ return file_glob;
+}
diff --git a/src/parser/media_type.h b/src/parser/media_type.h
new file mode 100644
index 0000000..5c04c5e
--- /dev/null
+++ b/src/parser/media_type.h
@@ -0,0 +1,84 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+/**
+ * @file
+ * Media MIME type definition.
+ */
+
+#ifndef _MEDIA_TYPE_H
+#define _MEDIA_TYPE_H
+
+#include <list>
+#include <string>
+#include "parameter.h"
+
+using namespace std;
+
+/** Media MIME type definition. */
+class t_media {
+public:
+ string type; /**< main type */
+ string subtype; /**< subtype */
+ string charset; /**< Character set */
+ float q; /**< quality factor */
+ list<t_parameter> media_param_list; /**< media paramters */
+ list<t_parameter> accept_extension_list; /**< accept parameters */
+
+ /** Constructor */
+ t_media();
+
+ /**
+ * Constructor.
+ * Construct object with a specic type and subtype.
+ * @param t [in] type
+ * @param s [in] subtype
+ */
+ t_media(const string &t, const string &s);
+
+ /**
+ * Constructor.
+ * Construct a media object from a mime type name
+ * @param mime_type [in] The mime type name, e.g. "text/plain"
+ */
+ t_media(const string &mime_type);
+
+ /**
+ * Add a parameter list.
+ * Method for parser to add the parsed parameter list l.
+ * l should start with optional media parameters followed
+ * by the q-paramter followed by accept parameters.
+ * @param l [in] The parameter list.
+ */
+ void add_params(const list<t_parameter> &l);
+
+ /**
+ * Encode as string.
+ * @return The encoded media type.
+ */
+ string encode(void) const;
+
+ /**
+ * Get the glob for a file name containing this MIME type.
+ * E.g. <wildcard>.txt for text/plain
+ * @return The file name extension.
+ */
+ string get_file_glob(void) const;
+};
+
+#endif
diff --git a/src/parser/milenage.cpp b/src/parser/milenage.cpp
new file mode 100644
index 0000000..66dae9b
--- /dev/null
+++ b/src/parser/milenage.cpp
@@ -0,0 +1,284 @@
+/*-------------------------------------------------------------------
+ * Example algorithms f1, f1*, f2, f3, f4, f5, f5*
+ *-------------------------------------------------------------------
+ *
+ * A sample implementation of the example 3GPP authentication and
+ * key agreement functions f1, f1*, f2, f3, f4, f5 and f5*. This is
+ * a byte-oriented implementation of the functions, and of the block
+ * cipher kernel function Rijndael.
+ *
+ * This has been coded for clarity, not necessarily for efficiency.
+ *
+ * The functions f2, f3, f4 and f5 share the same inputs and have
+ * been coded together as a single function. f1, f1* and f5* are
+ * all coded separately.
+ *
+ *-----------------------------------------------------------------*/
+
+#include "milenage.h"
+#include "rijndael.h"
+
+/*--------------------------- prototypes --------------------------*/
+
+
+
+/*-------------------------------------------------------------------
+ * Algorithm f1
+ *-------------------------------------------------------------------
+ *
+ * Computes network authentication code MAC-A from key K, random
+ * challenge RAND, sequence number SQN and authentication management
+ * field AMF.
+ *
+ *-----------------------------------------------------------------*/
+
+void f1 ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
+ u8 mac_a[8], u8 op[16] )
+{
+ u8 op_c[16];
+ u8 temp[16];
+ u8 in1[16];
+ u8 out1[16];
+ u8 rijndaelInput[16];
+ u8 i;
+
+ RijndaelKeySchedule( k );
+
+ ComputeOPc( op_c, op );
+
+ for (i=0; i<16; i++)
+ rijndaelInput[i] = rand[i] ^ op_c[i];
+ RijndaelEncrypt( rijndaelInput, temp );
+
+ for (i=0; i<6; i++)
+ {
+ in1[i] = sqn[i];
+ in1[i+8] = sqn[i];
+ }
+ for (i=0; i<2; i++)
+ {
+ in1[i+6] = amf[i];
+ in1[i+14] = amf[i];
+ }
+
+ /* XOR op_c and in1, rotate by r1=64, and XOR *
+ * on the constant c1 (which is all zeroes) */
+
+ for (i=0; i<16; i++)
+ rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
+
+ /* XOR on the value temp computed before */
+
+ for (i=0; i<16; i++)
+ rijndaelInput[i] ^= temp[i];
+
+ RijndaelEncrypt( rijndaelInput, out1 );
+ for (i=0; i<16; i++)
+ out1[i] ^= op_c[i];
+
+ for (i=0; i<8; i++)
+ mac_a[i] = out1[i];
+
+ return;
+} /* end of function f1 */
+
+
+
+/*-------------------------------------------------------------------
+ * Algorithms f2-f5
+ *-------------------------------------------------------------------
+ *
+ * Takes key K and random challenge RAND, and returns response RES,
+ * confidentiality key CK, integrity key IK and anonymity key AK.
+ *
+ *-----------------------------------------------------------------*/
+
+void f2345 ( u8 k[16], u8 rand[16],
+ u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6], u8 op[16] )
+{
+ u8 op_c[16];
+ u8 temp[16];
+ u8 out[16];
+ u8 rijndaelInput[16];
+ u8 i;
+
+ RijndaelKeySchedule( k );
+
+ ComputeOPc( op_c, op );
+
+ for (i=0; i<16; i++)
+ rijndaelInput[i] = rand[i] ^ op_c[i];
+ RijndaelEncrypt( rijndaelInput, temp );
+
+ /* To obtain output block OUT2: XOR OPc and TEMP, *
+ * rotate by r2=0, and XOR on the constant c2 (which *
+ * is all zeroes except that the last bit is 1). */
+
+ for (i=0; i<16; i++)
+ rijndaelInput[i] = temp[i] ^ op_c[i];
+ rijndaelInput[15] ^= 1;
+
+ RijndaelEncrypt( rijndaelInput, out );
+ for (i=0; i<16; i++)
+ out[i] ^= op_c[i];
+
+ for (i=0; i<8; i++)
+ res[i] = out[i+8];
+ for (i=0; i<6; i++)
+ ak[i] = out[i];
+
+ /* To obtain output block OUT3: XOR OPc and TEMP, *
+ * rotate by r3=32, and XOR on the constant c3 (which *
+ * is all zeroes except that the next to last bit is 1). */
+
+ for (i=0; i<16; i++)
+ rijndaelInput[(i+12) % 16] = temp[i] ^ op_c[i];
+ rijndaelInput[15] ^= 2;
+
+ RijndaelEncrypt( rijndaelInput, out );
+ for (i=0; i<16; i++)
+ out[i] ^= op_c[i];
+
+ for (i=0; i<16; i++)
+ ck[i] = out[i];
+
+ /* To obtain output block OUT4: XOR OPc and TEMP, *
+ * rotate by r4=64, and XOR on the constant c4 (which *
+ * is all zeroes except that the 2nd from last bit is 1). */
+
+ for (i=0; i<16; i++)
+ rijndaelInput[(i+8) % 16] = temp[i] ^ op_c[i];
+ rijndaelInput[15] ^= 4;
+
+ RijndaelEncrypt( rijndaelInput, out );
+ for (i=0; i<16; i++)
+ out[i] ^= op_c[i];
+
+ for (i=0; i<16; i++)
+ ik[i] = out[i];
+
+ return;
+} /* end of function f2345 */
+
+
+/*-------------------------------------------------------------------
+ * Algorithm f1*
+ *-------------------------------------------------------------------
+ *
+ * Computes resynch authentication code MAC-S from key K, random
+ * challenge RAND, sequence number SQN and authentication management
+ * field AMF.
+ *
+ *-----------------------------------------------------------------*/
+
+void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
+ u8 mac_s[8], u8 op[16] )
+{
+ u8 op_c[16];
+ u8 temp[16];
+ u8 in1[16];
+ u8 out1[16];
+ u8 rijndaelInput[16];
+ u8 i;
+
+ RijndaelKeySchedule( k );
+
+ ComputeOPc( op_c, op );
+
+ for (i=0; i<16; i++)
+ rijndaelInput[i] = rand[i] ^ op_c[i];
+ RijndaelEncrypt( rijndaelInput, temp );
+
+ for (i=0; i<6; i++)
+ {
+ in1[i] = sqn[i];
+ in1[i+8] = sqn[i];
+ }
+ for (i=0; i<2; i++)
+ {
+ in1[i+6] = amf[i];
+ in1[i+14] = amf[i];
+ }
+
+ /* XOR op_c and in1, rotate by r1=64, and XOR *
+ * on the constant c1 (which is all zeroes) */
+
+ for (i=0; i<16; i++)
+ rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
+
+ /* XOR on the value temp computed before */
+
+ for (i=0; i<16; i++)
+ rijndaelInput[i] ^= temp[i];
+
+ RijndaelEncrypt( rijndaelInput, out1 );
+ for (i=0; i<16; i++)
+ out1[i] ^= op_c[i];
+
+ for (i=0; i<8; i++)
+ mac_s[i] = out1[i+8];
+
+ return;
+} /* end of function f1star */
+
+
+/*-------------------------------------------------------------------
+ * Algorithm f5*
+ *-------------------------------------------------------------------
+ *
+ * Takes key K and random challenge RAND, and returns resynch
+ * anonymity key AK.
+ *
+ *-----------------------------------------------------------------*/
+
+void f5star( u8 k[16], u8 rand[16],
+ u8 ak[6], u8 op[16] )
+{
+ u8 op_c[16];
+ u8 temp[16];
+ u8 out[16];
+ u8 rijndaelInput[16];
+ u8 i;
+
+ RijndaelKeySchedule( k );
+
+ ComputeOPc( op_c, op );
+
+ for (i=0; i<16; i++)
+ rijndaelInput[i] = rand[i] ^ op_c[i];
+ RijndaelEncrypt( rijndaelInput, temp );
+
+ /* To obtain output block OUT5: XOR OPc and TEMP, *
+ * rotate by r5=96, and XOR on the constant c5 (which *
+ * is all zeroes except that the 3rd from last bit is 1). */
+
+ for (i=0; i<16; i++)
+ rijndaelInput[(i+4) % 16] = temp[i] ^ op_c[i];
+ rijndaelInput[15] ^= 8;
+
+ RijndaelEncrypt( rijndaelInput, out );
+ for (i=0; i<16; i++)
+ out[i] ^= op_c[i];
+
+ for (i=0; i<6; i++)
+ ak[i] = out[i];
+
+ return;
+} /* end of function f5star */
+
+
+/*-------------------------------------------------------------------
+ * Function to compute OPc from OP and K. Assumes key schedule has
+ already been performed.
+ *-----------------------------------------------------------------*/
+
+void ComputeOPc( u8 op_c[16], u8 op[16] )
+{
+ u8 i;
+
+ RijndaelEncrypt( op, op_c );
+ for (i=0; i<16; i++)
+ op_c[i] ^= op[i];
+
+ return;
+} /* end of function ComputeOPc */
diff --git a/src/parser/milenage.h b/src/parser/milenage.h
new file mode 100644
index 0000000..a5f407f
--- /dev/null
+++ b/src/parser/milenage.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------
+ * Example algorithms f1, f1*, f2, f3, f4, f5, f5*
+ *-------------------------------------------------------------------
+ *
+ * A sample implementation of the example 3GPP authentication and
+ * key agreement functions f1, f1*, f2, f3, f4, f5 and f5*. This is
+ * a byte-oriented implementation of the functions, and of the block
+ * cipher kernel function Rijndael.
+ *
+ * This has been coded for clarity, not necessarily for efficiency.
+ *
+ * The functions f2, f3, f4 and f5 share the same inputs and have
+ * been coded together as a single function. f1, f1* and f5* are
+ * all coded separately.
+ *
+ *-----------------------------------------------------------------*/
+
+#ifndef MILENAGE_H
+#define MILENAGE_H
+
+typedef unsigned char u8;
+
+
+void f1 ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
+ u8 mac_a[8], u8 op[16] );
+void f2345 ( u8 k[16], u8 rand[16],
+ u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6], u8 op[16] );
+void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
+ u8 mac_s[8], u8 op[16] );
+void f5star( u8 k[16], u8 rand[16],
+ u8 ak[6], u8 op[16] );
+void ComputeOPc( u8 op_c[16], u8 op[16] );
+
+
+#endif
diff --git a/src/parser/parameter.cpp b/src/parser/parameter.cpp
new file mode 100644
index 0000000..ef5e9de
--- /dev/null
+++ b/src/parser/parameter.cpp
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "parameter.h"
+#include "util.h"
+
+t_parameter::t_parameter() {
+ type = VALUE;
+}
+
+t_parameter::t_parameter(const string &n) {
+ type = NOVALUE;
+ name = n;
+}
+
+t_parameter::t_parameter(const string &n, const string &v) {
+ type = VALUE;
+ name = n;
+ value = v;
+}
+
+string t_parameter::encode(void) const {
+ string s;
+
+ s += name;
+
+ if (type == VALUE) {
+ s += '=';
+ if (must_quote(value)) {
+ s += '\"' + value + '\"';
+ } else {
+ s += value;
+ }
+ }
+
+ return s;
+}
+
+bool t_parameter::operator==(const t_parameter &rhs) {
+ return (type == rhs.type && name == rhs.name);
+}
+
+t_parameter str2param(const string &s) {
+ vector<string> l = split_on_first(s, '=');
+ if (l.size() == 1) {
+ return t_parameter(s);
+ } else {
+ return t_parameter(trim(l[0]), trim(l[1]));
+ }
+}
+
+string param_list2str(const list<t_parameter> &l) {
+ string s;
+
+ for (list<t_parameter>::const_iterator i = l.begin();
+ i != l.end(); i++)
+ {
+ s += ';';
+ s += i->encode();
+ }
+
+ return s;
+}
+
+list<t_parameter> str2param_list(const string &s) {
+ list<t_parameter> result;
+
+ vector<string> l = split(s, ';');
+ for (vector<string>::const_iterator i = l.begin(); i != l.end(); i++) {
+ t_parameter p = str2param(trim(*i));
+ result.push_back(p);
+ }
+
+ return result;
+}
diff --git a/src/parser/parameter.h b/src/parser/parameter.h
new file mode 100644
index 0000000..6ef903f
--- /dev/null
+++ b/src/parser/parameter.h
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 _PARAMETER_H
+#define _PARAMETER_H
+
+#include <string>
+#include <list>
+
+using namespace std;
+
+class t_parameter {
+public:
+enum t_param_type{
+ NOVALUE, // a parameter without a value
+ VALUE // parameter having a value (default)
+};
+
+ t_param_type type; // type of parameter
+ string name; // name of parameter
+ string value; // value of parameter if type is VALUE
+
+ t_parameter();
+
+ // Construct a NOVALUE parameter with name = n
+ t_parameter(const string &n);
+
+ // Construct a VALUE parameter with name = n, value = v
+ t_parameter(const string &n, const string &v);
+
+ string encode(void) const;
+
+ bool operator==(const t_parameter &rhs);
+};
+
+// Decode a parameter
+t_parameter str2param(const string &s);
+
+// Encode a parameter list
+string param_list2str(const list<t_parameter> &l);
+
+// Decode a parameter list
+list<t_parameter> str2param_list(const string &s);
+
+#endif
diff --git a/src/parser/parse_ctrl.cpp b/src/parser/parse_ctrl.cpp
new file mode 100644
index 0000000..cfaad81
--- /dev/null
+++ b/src/parser/parse_ctrl.cpp
@@ -0,0 +1,136 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "parse_ctrl.h"
+#include "protocol.h"
+#include "util.h"
+#include "audits/memman.h"
+
+// Interface to Bison
+extern int yyparse(void);
+
+// Interface to Flex
+struct yy_buffer_state;
+extern struct yy_buffer_state *yy_scan_string(const char *);
+extern void yy_delete_buffer(struct yy_buffer_state *);
+
+t_mutex t_parser::mtx_parser;
+bool t_parser::check_max_forwards = true;
+bool t_parser::compact_headers = false;
+bool t_parser::multi_values_as_list = true;
+int t_parser::comment_level = 0;
+list<string> t_parser::parse_errors;
+
+string t_parser::unfold(const string &h) {
+ string::size_type i;
+ string s = h;
+
+ while ((i = s.find("\r\n ")) != string::npos) {
+ s.replace(i, 3, " ");
+ }
+
+ while ((i = s.find("\r\n\t")) != string::npos) {
+ s.replace(i, 3, " ");
+ }
+
+ // This is only for easy testing of hand edited messages
+ // in Linux where the end of line character is \n only.
+ while ((i = s.find("\n ")) != string::npos) {
+ s.replace(i, 2, " ");
+ }
+
+ while ((i = s.find("\n\t")) != string::npos) {
+ s.replace(i, 2, " ");
+ }
+
+ return s;
+}
+
+t_parser::t_context t_parser::context = t_parser::X_INITIAL;
+t_sip_message *t_parser::msg = NULL;
+
+t_sip_message *t_parser::parse(const string &s, list<string> &parse_errors_) {
+ t_mutex_guard guard(mtx_parser);
+
+ int ret;
+ struct yy_buffer_state *b;
+ msg = NULL;
+
+ parse_errors.clear();
+
+ string x = unfold(s);
+
+ b = yy_scan_string(x.c_str());
+ ret = yyparse();
+ yy_delete_buffer(b);
+
+ if (ret != 0) {
+ if (msg) {
+ MEMMAN_DELETE(msg);
+ delete msg;
+ msg = NULL;
+ }
+ throw ret;
+ }
+
+ parse_errors_ = parse_errors;
+ return msg;
+}
+
+t_sip_message *t_parser::parse_headers(const string &s, list<string> &parse_errors_) {
+ string msg("INVITE sip:fake@fake.invalid SIP/2.0");
+ msg += CRLF;
+
+ list<t_parameter> hdr_list = str2param_list(s);
+ for (list<t_parameter>::iterator i = hdr_list.begin();
+ i != hdr_list.end(); i++)
+ {
+ msg += unescape_hex(i->name);
+ msg += ": ";
+ msg += unescape_hex(i->value);
+ msg += CRLF;
+ }
+
+ msg += CRLF;
+
+ return parse(msg, parse_errors_);
+}
+
+void t_parser::enter_ctx_comment(void) {
+ comment_level = 0;
+ context = t_parser::X_COMMENT;
+}
+
+void t_parser::inc_comment_level(void) {
+ comment_level++;
+}
+
+bool t_parser::dec_comment_level(void) {
+ if (comment_level == 0) return false;
+ comment_level--;
+ return true;
+}
+
+void t_parser::add_header_error(const string &header_name) {
+ string s = "Parse error in header: " + header_name;
+ parse_errors.push_back(s);
+}
+
+t_syntax_error::t_syntax_error(const string &e) {
+ error = e;
+}
diff --git a/src/parser/parse_ctrl.h b/src/parser/parse_ctrl.h
new file mode 100644
index 0000000..5270edb
--- /dev/null
+++ b/src/parser/parse_ctrl.h
@@ -0,0 +1,131 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Parser control
+
+#ifndef _PARSE_CTRL_H
+#define _PARSE_CTRL_H
+
+#include "sip_message.h"
+#include "threads/mutex.h"
+
+#define MSG t_parser::msg
+
+#define CTXT_INITIAL (t_parser::context = t_parser::X_INITIAL)
+#define CTXT_URI (t_parser::context = t_parser::X_URI)
+#define CTXT_URI_SPECIAL (t_parser::context = t_parser::X_URI_SPECIAL)
+#define CTXT_LANG (t_parser::context = t_parser::X_LANG)
+#define CTXT_WORD (t_parser::context = t_parser::X_WORD)
+#define CTXT_NUM (t_parser::context = t_parser::X_NUM)
+#define CTXT_DATE (t_parser::context = t_parser::X_DATE)
+#define CTXT_LINE (t_parser::context = t_parser::X_LINE)
+#define CTXT_COMMENT (t_parser::enter_ctx_comment())
+#define CTXT_NEW (t_parser::context = t_parser::X_NEW)
+#define CTXT_AUTH_SCHEME (t_parser::context = t_parser::X_AUTH_SCHEME)
+#define CTXT_IPV6ADDR (t_parser::context = t_parser::X_IPV6ADDR)
+#define CTXT_PARAMVAL (t_parser::context = t_parser::X_PARAMVAL)
+
+#define PARSE_ERROR(h) { t_parser::add_header_error(h); CTXT_INITIAL; }
+
+// The t_parser controls the direction of the scanner/parser
+// process and it stores the results from the parser.
+class t_parser {
+private:
+ /** Mutex to synchronize parse operations */
+ static t_mutex mtx_parser;
+
+ // Level for nested comments
+ static int comment_level;
+
+ // Non-fatal parse errors generated during parsing.
+ static list<string> parse_errors;
+
+ // Unfold SIP headers
+ static string unfold(const string &h);
+
+public:
+enum t_context {
+ X_INITIAL, // Initial context
+ X_URI, // URI context where parameters belong to URI
+ X_URI_SPECIAL, // URI context where parameters belong to SIP header
+ // if URI is not enclosed by < and >
+ X_LANG, // Language tag context
+ X_WORD, // Word context
+ X_NUM, // Number context
+ X_DATE, // Date context
+ X_LINE, // Whole line context
+ X_COMMENT, // Comment context
+ X_NEW, // Start of a new SIP message to distinguish
+ // request from responses
+ X_AUTH_SCHEME, // Authorization scheme context
+ X_IPV6ADDR, // IPv6 address context
+ X_PARAMVAL, // Generic parameter value context
+};
+
+ // Parser options
+ // According to RFC3261 the Max-Forwards header is mandatory, but
+ // many implementations do not send this header.
+ static bool check_max_forwards;
+
+ // Encode headers in compact forom
+ static bool compact_headers;
+
+ // Encode multiple values as comma separated list or multiple headers
+ static bool multi_values_as_list;
+
+ static t_context context; // Scan context
+ static t_sip_message *msg; // Message that has been parsed
+
+ /**
+ * Parse a string representing a SIP message.
+ * @param s [in] String to parse.
+ * @param parse_errors_ [out] List of non-fatal parse errors.
+ * @return The parsed SIP message.
+ * @throw int exception when parsing fails.
+ */
+ static t_sip_message *parse(const string &s, list<string> &parse_errors_);
+
+ /**
+ * Parse a string of headers (hdr1=val1;hdr=val2;...)
+ * The resulting SIP message is a SIP request with a fake request line.
+ * @param s [in] String to parse.
+ * @param parse_errors_ [out] List of non-fatal parse errors.
+ * @return The parsed SIP message.
+ * @throw int exception when parsing fails.
+ */
+ static t_sip_message *parse_headers(const string &s, list<string> &parse_errors_);
+
+ static void enter_ctx_comment(void);
+
+ // Increment and decrement levels for nested comments
+ // dec_comment_level returns false if the level cannot be decremented.
+ static void inc_comment_level(void);
+ static bool dec_comment_level(void);
+
+ // Add parsing error for a header to the list of parse errors
+ static void add_header_error(const string &header_name);
+};
+
+// Error that can be thrown as exception
+class t_syntax_error {
+public:
+ string error;
+ t_syntax_error(const string &e);
+};
+
+#endif
diff --git a/src/parser/parser.cxx b/src/parser/parser.cxx
new file mode 100644
index 0000000..f2aae95
--- /dev/null
+++ b/src/parser/parser.cxx
@@ -0,0 +1,5106 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ T_NUM = 258,
+ T_TOKEN = 259,
+ T_QSTRING = 260,
+ T_COMMENT = 261,
+ T_LINE = 262,
+ T_URI = 263,
+ T_URI_WILDCARD = 264,
+ T_DISPLAY = 265,
+ T_LANG = 266,
+ T_WORD = 267,
+ T_WKDAY = 268,
+ T_MONTH = 269,
+ T_GMT = 270,
+ T_SIP = 271,
+ T_METHOD = 272,
+ T_AUTH_DIGEST = 273,
+ T_AUTH_OTHER = 274,
+ T_IPV6ADDR = 275,
+ T_PARAMVAL = 276,
+ T_HDR_ACCEPT = 277,
+ T_HDR_ACCEPT_ENCODING = 278,
+ T_HDR_ACCEPT_LANGUAGE = 279,
+ T_HDR_ALERT_INFO = 280,
+ T_HDR_ALLOW = 281,
+ T_HDR_ALLOW_EVENTS = 282,
+ T_HDR_AUTHENTICATION_INFO = 283,
+ T_HDR_AUTHORIZATION = 284,
+ T_HDR_CALL_ID = 285,
+ T_HDR_CALL_INFO = 286,
+ T_HDR_CONTACT = 287,
+ T_HDR_CONTENT_DISP = 288,
+ T_HDR_CONTENT_ENCODING = 289,
+ T_HDR_CONTENT_LANGUAGE = 290,
+ T_HDR_CONTENT_LENGTH = 291,
+ T_HDR_CONTENT_TYPE = 292,
+ T_HDR_CSEQ = 293,
+ T_HDR_DATE = 294,
+ T_HDR_ERROR_INFO = 295,
+ T_HDR_EVENT = 296,
+ T_HDR_EXPIRES = 297,
+ T_HDR_FROM = 298,
+ T_HDR_IN_REPLY_TO = 299,
+ T_HDR_MAX_FORWARDS = 300,
+ T_HDR_MIN_EXPIRES = 301,
+ T_HDR_MIME_VERSION = 302,
+ T_HDR_ORGANIZATION = 303,
+ T_HDR_P_ASSERTED_IDENTITY = 304,
+ T_HDR_P_PREFERRED_IDENTITY = 305,
+ T_HDR_PRIORITY = 306,
+ T_HDR_PRIVACY = 307,
+ T_HDR_PROXY_AUTHENTICATE = 308,
+ T_HDR_PROXY_AUTHORIZATION = 309,
+ T_HDR_PROXY_REQUIRE = 310,
+ T_HDR_RACK = 311,
+ T_HDR_RECORD_ROUTE = 312,
+ T_HDR_SERVICE_ROUTE = 313,
+ T_HDR_REFER_SUB = 314,
+ T_HDR_REFER_TO = 315,
+ T_HDR_REFERRED_BY = 316,
+ T_HDR_REPLACES = 317,
+ T_HDR_REPLY_TO = 318,
+ T_HDR_REQUIRE = 319,
+ T_HDR_REQUEST_DISPOSITION = 320,
+ T_HDR_RETRY_AFTER = 321,
+ T_HDR_ROUTE = 322,
+ T_HDR_RSEQ = 323,
+ T_HDR_SERVER = 324,
+ T_HDR_SIP_ETAG = 325,
+ T_HDR_SIP_IF_MATCH = 326,
+ T_HDR_SUBJECT = 327,
+ T_HDR_SUBSCRIPTION_STATE = 328,
+ T_HDR_SUPPORTED = 329,
+ T_HDR_TIMESTAMP = 330,
+ T_HDR_TO = 331,
+ T_HDR_UNSUPPORTED = 332,
+ T_HDR_USER_AGENT = 333,
+ T_HDR_VIA = 334,
+ T_HDR_WARNING = 335,
+ T_HDR_WWW_AUTHENTICATE = 336,
+ T_HDR_UNKNOWN = 337,
+ T_CRLF = 338,
+ T_ERROR = 339,
+ T_NULL = 340
+ };
+#endif
+/* Tokens. */
+#define T_NUM 258
+#define T_TOKEN 259
+#define T_QSTRING 260
+#define T_COMMENT 261
+#define T_LINE 262
+#define T_URI 263
+#define T_URI_WILDCARD 264
+#define T_DISPLAY 265
+#define T_LANG 266
+#define T_WORD 267
+#define T_WKDAY 268
+#define T_MONTH 269
+#define T_GMT 270
+#define T_SIP 271
+#define T_METHOD 272
+#define T_AUTH_DIGEST 273
+#define T_AUTH_OTHER 274
+#define T_IPV6ADDR 275
+#define T_PARAMVAL 276
+#define T_HDR_ACCEPT 277
+#define T_HDR_ACCEPT_ENCODING 278
+#define T_HDR_ACCEPT_LANGUAGE 279
+#define T_HDR_ALERT_INFO 280
+#define T_HDR_ALLOW 281
+#define T_HDR_ALLOW_EVENTS 282
+#define T_HDR_AUTHENTICATION_INFO 283
+#define T_HDR_AUTHORIZATION 284
+#define T_HDR_CALL_ID 285
+#define T_HDR_CALL_INFO 286
+#define T_HDR_CONTACT 287
+#define T_HDR_CONTENT_DISP 288
+#define T_HDR_CONTENT_ENCODING 289
+#define T_HDR_CONTENT_LANGUAGE 290
+#define T_HDR_CONTENT_LENGTH 291
+#define T_HDR_CONTENT_TYPE 292
+#define T_HDR_CSEQ 293
+#define T_HDR_DATE 294
+#define T_HDR_ERROR_INFO 295
+#define T_HDR_EVENT 296
+#define T_HDR_EXPIRES 297
+#define T_HDR_FROM 298
+#define T_HDR_IN_REPLY_TO 299
+#define T_HDR_MAX_FORWARDS 300
+#define T_HDR_MIN_EXPIRES 301
+#define T_HDR_MIME_VERSION 302
+#define T_HDR_ORGANIZATION 303
+#define T_HDR_P_ASSERTED_IDENTITY 304
+#define T_HDR_P_PREFERRED_IDENTITY 305
+#define T_HDR_PRIORITY 306
+#define T_HDR_PRIVACY 307
+#define T_HDR_PROXY_AUTHENTICATE 308
+#define T_HDR_PROXY_AUTHORIZATION 309
+#define T_HDR_PROXY_REQUIRE 310
+#define T_HDR_RACK 311
+#define T_HDR_RECORD_ROUTE 312
+#define T_HDR_SERVICE_ROUTE 313
+#define T_HDR_REFER_SUB 314
+#define T_HDR_REFER_TO 315
+#define T_HDR_REFERRED_BY 316
+#define T_HDR_REPLACES 317
+#define T_HDR_REPLY_TO 318
+#define T_HDR_REQUIRE 319
+#define T_HDR_REQUEST_DISPOSITION 320
+#define T_HDR_RETRY_AFTER 321
+#define T_HDR_ROUTE 322
+#define T_HDR_RSEQ 323
+#define T_HDR_SERVER 324
+#define T_HDR_SIP_ETAG 325
+#define T_HDR_SIP_IF_MATCH 326
+#define T_HDR_SUBJECT 327
+#define T_HDR_SUBSCRIPTION_STATE 328
+#define T_HDR_SUPPORTED 329
+#define T_HDR_TIMESTAMP 330
+#define T_HDR_TO 331
+#define T_HDR_UNSUPPORTED 332
+#define T_HDR_USER_AGENT 333
+#define T_HDR_VIA 334
+#define T_HDR_WARNING 335
+#define T_HDR_WWW_AUTHENTICATE 336
+#define T_HDR_UNKNOWN 337
+#define T_CRLF 338
+#define T_ERROR 339
+#define T_NULL 340
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 19 "parser.yxx"
+
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+#include "media_type.h"
+#include "parameter.h"
+#include "parse_ctrl.h"
+#include "request.h"
+#include "response.h"
+#include "util.h"
+#include "audits/memman.h"
+
+using namespace std;
+
+extern int yylex(void);
+void yyerror(const char *s);
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 49 "parser.yxx"
+{
+ int yyt_int;
+ ulong yyt_ulong;
+ float yyt_float;
+ string *yyt_str;
+ t_parameter *yyt_param;
+ list<t_parameter> *yyt_params;
+ t_media *yyt_media;
+ t_coding *yyt_coding;
+ t_language *yyt_language;
+ t_alert_param *yyt_alert_param;
+ t_info_param *yyt_info_param;
+ list<t_contact_param> *yyt_contacts;
+ t_contact_param *yyt_contact;
+ t_error_param *yyt_error_param;
+ t_identity *yyt_from_addr;
+ t_route *yyt_route;
+ t_server *yyt_server;
+ t_via *yyt_via;
+ t_warning *yyt_warning;
+ t_digest_response *yyt_dig_resp;
+ t_credentials *yyt_credentials;
+ t_digest_challenge *yyt_dig_chlg;
+ t_challenge *yyt_challenge;
+}
+/* Line 193 of yacc.c. */
+#line 310 "parser.cxx"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 216 of yacc.c. */
+#line 323 "parser.cxx"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
+#endif
+{
+ return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 3
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 734
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 99
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 254
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 432
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 791
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 340
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 94, 95, 2, 2, 88, 2, 96, 86, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 87, 89,
+ 91, 90, 92, 2, 93, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 97, 2, 98, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 4, 7, 9, 11, 14, 18, 19,
+ 20, 27, 28, 33, 37, 38, 39, 40, 48, 49,
+ 52, 56, 60, 64, 68, 72, 76, 80, 84, 88,
+ 92, 96, 100, 104, 108, 112, 116, 120, 124, 128,
+ 132, 136, 140, 144, 148, 152, 156, 160, 164, 168,
+ 172, 176, 180, 184, 188, 192, 196, 200, 204, 208,
+ 212, 216, 220, 224, 228, 232, 236, 240, 244, 248,
+ 252, 256, 260, 264, 268, 272, 276, 280, 284, 288,
+ 292, 297, 301, 305, 309, 313, 317, 321, 325, 329,
+ 333, 337, 341, 345, 349, 353, 357, 361, 365, 369,
+ 373, 377, 381, 385, 389, 393, 397, 401, 405, 409,
+ 413, 417, 421, 425, 429, 433, 437, 441, 445, 449,
+ 453, 457, 461, 465, 469, 473, 477, 481, 485, 489,
+ 493, 497, 501, 505, 509, 513, 517, 521, 525, 529,
+ 533, 537, 540, 543, 546, 549, 552, 555, 558, 561,
+ 564, 567, 570, 573, 576, 579, 582, 585, 588, 591,
+ 594, 597, 600, 603, 606, 609, 612, 615, 618, 621,
+ 624, 627, 630, 633, 636, 639, 642, 645, 648, 651,
+ 654, 657, 660, 663, 666, 669, 672, 675, 678, 681,
+ 684, 687, 690, 693, 696, 699, 702, 705, 708, 711,
+ 714, 717, 718, 721, 726, 730, 731, 735, 737, 738,
+ 739, 745, 747, 749, 751, 755, 757, 760, 763, 764,
+ 767, 768, 773, 775, 776, 780, 782, 786, 787, 788,
+ 795, 797, 801, 802, 803, 807, 809, 813, 815, 819,
+ 820, 821, 828, 829, 830, 834, 836, 838, 842, 845,
+ 846, 847, 851, 852, 853, 854, 862, 863, 865, 867,
+ 870, 872, 876, 877, 880, 881, 886, 887, 888, 892,
+ 895, 896, 897, 902, 903, 904, 918, 920, 924, 925,
+ 926, 933, 934, 935, 939, 940, 944, 945, 948, 949,
+ 950, 957, 958, 959, 963, 964, 965, 971, 972, 973,
+ 977, 978, 979, 983, 985, 986, 987, 991, 992, 995,
+ 999, 1000, 1003, 1007, 1009, 1011, 1015, 1017, 1021, 1023,
+ 1027, 1028, 1029, 1037, 1039, 1043, 1044, 1045, 1050, 1051,
+ 1055, 1057, 1061, 1062, 1063, 1069, 1070, 1071, 1072, 1078,
+ 1080, 1084, 1086, 1089, 1091, 1094, 1099, 1100, 1101, 1105,
+ 1106, 1108, 1112, 1113, 1116, 1118, 1121, 1123, 1127, 1129,
+ 1133, 1134, 1138, 1140, 1144, 1146, 1149, 1151, 1155, 1159,
+ 1165, 1167, 1168, 1169, 1175, 1177, 1178, 1179, 1185, 1186,
+ 1187, 1193, 1195, 1199, 1200, 1201, 1207, 1208, 1209, 1213,
+ 1215, 1217, 1221, 1223, 1227, 1229, 1233, 1234, 1238, 1239,
+ 1243, 1244, 1247, 1249, 1253, 1254, 1258, 1259, 1263, 1264,
+ 1267, 1268, 1271, 1272, 1275, 1276, 1277, 1281, 1282, 1283,
+ 1289, 1292, 1294, 1298, 1301, 1302, 1306, 1307, 1311, 1314,
+ 1316, 1318, 1320
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int16 yyrhs[] =
+{
+ 100, 0, -1, -1, 101, 102, -1, 103, -1, 109,
+ -1, 1, 85, -1, 104, 114, 83, -1, -1, -1,
+ 17, 105, 8, 106, 107, 83, -1, -1, 16, 108,
+ 86, 4, -1, 110, 114, 83, -1, -1, -1, -1,
+ 107, 111, 3, 112, 7, 113, 83, -1, -1, 114,
+ 115, -1, 116, 176, 83, -1, 117, 183, 83, -1,
+ 118, 186, 83, -1, 119, 191, 83, -1, 120, 195,
+ 83, -1, 121, 343, 83, -1, 122, 318, 83, -1,
+ 123, 324, 83, -1, 124, 196, 83, -1, 125, 200,
+ 83, -1, 126, 204, 83, -1, 127, 216, 83, -1,
+ 128, 217, 83, -1, 129, 218, 83, -1, 130, 221,
+ 83, -1, 131, 224, 83, -1, 132, 225, 83, -1,
+ 133, 228, 83, -1, 135, 342, 83, -1, 134, 231,
+ 83, -1, 136, 235, 83, -1, 137, 238, 83, -1,
+ 138, 244, 83, -1, 139, 249, 83, -1, 140, 252,
+ 83, -1, 141, 255, 83, -1, 142, 256, 83, -1,
+ 143, 259, 83, -1, 144, 261, 83, -1, 145, 263,
+ 83, -1, 146, 264, 83, -1, 147, 330, 83, -1,
+ 148, 332, 83, -1, 149, 265, 83, -1, 150, 339,
+ 83, -1, 151, 266, 83, -1, 152, 349, 83, -1,
+ 153, 345, 83, -1, 154, 347, 83, -1, 155, 271,
+ 83, -1, 156, 274, 83, -1, 157, 276, 83, -1,
+ 158, 352, 83, -1, 159, 277, 83, -1, 160, 283,
+ 83, -1, 161, 336, 83, -1, 162, 284, 83, -1,
+ 163, 270, 83, -1, 164, 350, 83, -1, 165, 351,
+ 83, -1, 166, 286, 83, -1, 167, 344, 83, -1,
+ 168, 289, 83, -1, 169, 290, 83, -1, 170, 295,
+ 83, -1, 171, 297, 83, -1, 172, 298, 83, -1,
+ 173, 299, 83, -1, 174, 310, 83, -1, 175, 334,
+ 83, -1, 82, 87, 314, 83, -1, 116, 1, 83,
+ -1, 117, 1, 83, -1, 118, 1, 83, -1, 119,
+ 1, 83, -1, 120, 1, 83, -1, 121, 1, 83,
+ -1, 122, 1, 83, -1, 123, 1, 83, -1, 124,
+ 1, 83, -1, 125, 1, 83, -1, 126, 1, 83,
+ -1, 127, 1, 83, -1, 128, 1, 83, -1, 129,
+ 1, 83, -1, 130, 1, 83, -1, 131, 1, 83,
+ -1, 132, 1, 83, -1, 133, 1, 83, -1, 134,
+ 1, 83, -1, 135, 1, 83, -1, 136, 1, 83,
+ -1, 137, 1, 83, -1, 138, 1, 83, -1, 139,
+ 1, 83, -1, 140, 1, 83, -1, 141, 1, 83,
+ -1, 142, 1, 83, -1, 143, 1, 83, -1, 144,
+ 1, 83, -1, 145, 1, 83, -1, 146, 1, 83,
+ -1, 147, 1, 83, -1, 148, 1, 83, -1, 149,
+ 1, 83, -1, 150, 1, 83, -1, 151, 1, 83,
+ -1, 152, 1, 83, -1, 153, 1, 83, -1, 154,
+ 1, 83, -1, 155, 1, 83, -1, 156, 1, 83,
+ -1, 157, 1, 83, -1, 158, 1, 83, -1, 159,
+ 1, 83, -1, 160, 1, 83, -1, 161, 1, 83,
+ -1, 162, 1, 83, -1, 163, 1, 83, -1, 164,
+ 1, 83, -1, 165, 1, 83, -1, 166, 1, 83,
+ -1, 167, 1, 83, -1, 168, 1, 83, -1, 169,
+ 1, 83, -1, 170, 1, 83, -1, 171, 1, 83,
+ -1, 172, 1, 83, -1, 173, 1, 83, -1, 174,
+ 1, 83, -1, 175, 1, 83, -1, 22, 87, -1,
+ 23, 87, -1, 24, 87, -1, 25, 87, -1, 26,
+ 87, -1, 27, 87, -1, 28, 87, -1, 29, 87,
+ -1, 30, 87, -1, 31, 87, -1, 32, 87, -1,
+ 33, 87, -1, 34, 87, -1, 35, 87, -1, 36,
+ 87, -1, 37, 87, -1, 38, 87, -1, 39, 87,
+ -1, 40, 87, -1, 41, 87, -1, 42, 87, -1,
+ 43, 87, -1, 44, 87, -1, 45, 87, -1, 46,
+ 87, -1, 47, 87, -1, 48, 87, -1, 49, 87,
+ -1, 50, 87, -1, 51, 87, -1, 52, 87, -1,
+ 53, 87, -1, 54, 87, -1, 55, 87, -1, 56,
+ 87, -1, 57, 87, -1, 59, 87, -1, 60, 87,
+ -1, 61, 87, -1, 62, 87, -1, 63, 87, -1,
+ 64, 87, -1, 65, 87, -1, 66, 87, -1, 67,
+ 87, -1, 68, 87, -1, 69, 87, -1, 58, 87,
+ -1, 70, 87, -1, 71, 87, -1, 72, 87, -1,
+ 73, 87, -1, 74, 87, -1, 75, 87, -1, 76,
+ 87, -1, 77, 87, -1, 78, 87, -1, 79, 87,
+ -1, 80, 87, -1, 81, 87, -1, -1, 177, 178,
+ -1, 176, 88, 177, 178, -1, 4, 86, 4, -1,
+ -1, 178, 89, 179, -1, 4, -1, -1, -1, 4,
+ 90, 180, 182, 181, -1, 21, -1, 5, -1, 184,
+ -1, 183, 88, 184, -1, 4, -1, 4, 185, -1,
+ 89, 179, -1, -1, 187, 189, -1, -1, 186, 88,
+ 188, 189, -1, 11, -1, -1, 11, 190, 185, -1,
+ 192, -1, 191, 88, 192, -1, -1, -1, 91, 193,
+ 8, 194, 92, 178, -1, 4, -1, 195, 88, 4,
+ -1, -1, -1, 197, 199, 198, -1, 12, -1, 12,
+ 93, 12, -1, 201, -1, 200, 88, 201, -1, -1,
+ -1, 91, 202, 8, 203, 92, 178, -1, -1, -1,
+ 205, 9, 206, -1, 207, -1, 208, -1, 207, 88,
+ 208, -1, 209, 178, -1, -1, -1, 210, 8, 211,
+ -1, -1, -1, -1, 212, 215, 91, 213, 8, 214,
+ 92, -1, -1, 10, -1, 5, -1, 4, 178, -1,
+ 184, -1, 217, 88, 184, -1, -1, 219, 189, -1,
+ -1, 218, 88, 220, 189, -1, -1, -1, 222, 3,
+ 223, -1, 177, 178, -1, -1, -1, 226, 3, 227,
+ 4, -1, -1, -1, 229, 13, 88, 3, 14, 3,
+ 3, 87, 3, 87, 3, 15, 230, -1, 232, -1,
+ 231, 88, 232, -1, -1, -1, 91, 233, 8, 234,
+ 92, 178, -1, -1, -1, 236, 3, 237, -1, -1,
+ 239, 240, 178, -1, -1, 8, 241, -1, -1, -1,
+ 215, 91, 242, 8, 243, 92, -1, -1, -1, 245,
+ 199, 246, -1, -1, -1, 244, 88, 247, 199, 248,
+ -1, -1, -1, 250, 3, 251, -1, -1, -1, 253,
+ 3, 254, -1, 4, -1, -1, -1, 257, 7, 258,
+ -1, -1, 260, 240, -1, 259, 88, 240, -1, -1,
+ 262, 240, -1, 261, 88, 240, -1, 4, -1, 4,
+ -1, 264, 89, 4, -1, 4, -1, 265, 88, 4,
+ -1, 267, -1, 266, 88, 267, -1, -1, -1, 268,
+ 215, 91, 8, 269, 92, 178, -1, 267, -1, 270,
+ 88, 267, -1, -1, -1, 272, 199, 273, 178, -1,
+ -1, 275, 240, 178, -1, 4, -1, 265, 88, 4,
+ -1, -1, -1, 278, 3, 279, 280, 178, -1, -1,
+ -1, -1, 94, 281, 6, 282, 95, -1, 267, -1,
+ 283, 88, 267, -1, 285, -1, 284, 285, -1, 280,
+ -1, 4, 280, -1, 4, 86, 4, 280, -1, -1,
+ -1, 287, 7, 288, -1, -1, 4, -1, 289, 88,
+ 4, -1, -1, 291, 292, -1, 293, -1, 293, 294,
+ -1, 3, -1, 3, 96, 3, -1, 3, -1, 3,
+ 96, 3, -1, -1, 296, 240, 178, -1, 4, -1,
+ 297, 88, 4, -1, 285, -1, 298, 285, -1, 300,
+ -1, 299, 88, 300, -1, 301, 302, 178, -1, 4,
+ 86, 4, 86, 4, -1, 4, -1, -1, -1, 4,
+ 87, 303, 3, 304, -1, 307, -1, -1, -1, 307,
+ 87, 305, 3, 306, -1, -1, -1, 97, 308, 20,
+ 309, 98, -1, 311, -1, 310, 88, 311, -1, -1,
+ -1, 312, 3, 313, 302, 5, -1, -1, -1, 315,
+ 7, 316, -1, 179, -1, 317, -1, 318, 88, 317,
+ -1, 179, -1, 319, 88, 179, -1, 179, -1, 320,
+ 88, 179, -1, -1, 18, 322, 319, -1, -1, 19,
+ 323, 320, -1, -1, 325, 321, -1, 179, -1, 326,
+ 88, 179, -1, -1, 18, 328, 326, -1, -1, 19,
+ 329, 320, -1, -1, 331, 327, -1, -1, 333, 321,
+ -1, -1, 335, 327, -1, -1, -1, 337, 3, 338,
+ -1, -1, -1, 340, 3, 3, 341, 4, -1, 4,
+ 178, -1, 4, -1, 343, 88, 4, -1, 4, 178,
+ -1, -1, 346, 240, 178, -1, -1, 348, 240, 178,
+ -1, 4, 178, -1, 4, -1, 4, -1, 4, -1,
+ 352, 88, 4, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 244, 244, 244, 247, 248, 249, 269, 278, 278,
+ 278, 296, 296, 300, 307, 307, 308, 307, 318, 319,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 333, 334, 335, 336, 337, 338, 339, 340, 341,
+ 342, 343, 344, 345, 346, 347, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, 358, 359, 360, 361,
+ 362, 363, 364, 365, 366, 367, 368, 369, 370, 371,
+ 372, 373, 374, 375, 376, 377, 378, 379, 380, 381,
+ 382, 386, 388, 390, 392, 394, 396, 398, 400, 402,
+ 404, 406, 408, 410, 412, 414, 416, 418, 420, 422,
+ 424, 426, 428, 430, 432, 434, 436, 438, 440, 442,
+ 444, 446, 448, 450, 452, 454, 456, 458, 460, 462,
+ 464, 466, 468, 470, 472, 474, 476, 478, 480, 482,
+ 484, 486, 488, 490, 492, 494, 496, 498, 500, 502,
+ 504, 517, 519, 521, 523, 525, 527, 529, 531, 533,
+ 535, 537, 539, 541, 543, 545, 547, 549, 551, 553,
+ 555, 557, 559, 561, 563, 565, 567, 569, 571, 573,
+ 575, 577, 579, 581, 583, 585, 587, 589, 591, 593,
+ 595, 597, 599, 601, 603, 605, 607, 609, 611, 613,
+ 615, 617, 619, 621, 623, 625, 627, 629, 631, 633,
+ 635, 638, 639, 644, 651, 657, 658, 664, 668, 668,
+ 668, 675, 677, 681, 684, 689, 693, 700, 707, 707,
+ 710, 710, 715, 720, 720, 727, 730, 735, 735, 735,
+ 750, 753, 758, 758, 758, 763, 764, 771, 774, 779,
+ 779, 779, 794, 794, 794, 796, 801, 806, 812, 828,
+ 828, 828, 839, 839, 839, 839, 854, 855, 859, 862,
+ 878, 881, 886, 886, 889, 889, 894, 894, 894, 898,
+ 905, 905, 905, 911, 914, 911, 925, 928, 933, 933,
+ 933, 948, 948, 948, 952, 952, 967, 967, 978, 978,
+ 978, 993, 993, 993, 996, 996, 996, 1001, 1001, 1001,
+ 1005, 1005, 1005, 1009, 1014, 1014, 1014, 1019, 1019, 1022,
+ 1027, 1027, 1030, 1035, 1040, 1043, 1048, 1051, 1056, 1059,
+ 1064, 1064, 1064, 1082, 1085, 1090, 1090, 1090, 1112, 1112,
+ 1120, 1123, 1128, 1128, 1128, 1144, 1145, 1145, 1145, 1149,
+ 1152, 1157, 1160, 1165, 1170, 1177, 1188, 1188, 1188, 1193,
+ 1195, 1198, 1203, 1203, 1206, 1208, 1213, 1214, 1219, 1220,
+ 1225, 1225, 1240, 1243, 1248, 1251, 1256, 1259, 1264, 1292,
+ 1303, 1308, 1308, 1308, 1316, 1321, 1321, 1321, 1329, 1329,
+ 1329, 1336, 1339, 1344, 1344, 1344, 1355, 1355, 1355, 1358,
+ 1378, 1379, 1382, 1390, 1398, 1403, 1409, 1409, 1415, 1415,
+ 1424, 1424, 1429, 1437, 1445, 1445, 1451, 1451, 1460, 1460,
+ 1465, 1465, 1471, 1471, 1476, 1476, 1476, 1480, 1480, 1480,
+ 1487, 1501, 1504, 1509, 1535, 1535, 1543, 1543, 1558, 1569,
+ 1574, 1579, 1583
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "T_NUM", "T_TOKEN", "T_QSTRING",
+ "T_COMMENT", "T_LINE", "T_URI", "T_URI_WILDCARD", "T_DISPLAY", "T_LANG",
+ "T_WORD", "T_WKDAY", "T_MONTH", "T_GMT", "T_SIP", "T_METHOD",
+ "T_AUTH_DIGEST", "T_AUTH_OTHER", "T_IPV6ADDR", "T_PARAMVAL",
+ "T_HDR_ACCEPT", "T_HDR_ACCEPT_ENCODING", "T_HDR_ACCEPT_LANGUAGE",
+ "T_HDR_ALERT_INFO", "T_HDR_ALLOW", "T_HDR_ALLOW_EVENTS",
+ "T_HDR_AUTHENTICATION_INFO", "T_HDR_AUTHORIZATION", "T_HDR_CALL_ID",
+ "T_HDR_CALL_INFO", "T_HDR_CONTACT", "T_HDR_CONTENT_DISP",
+ "T_HDR_CONTENT_ENCODING", "T_HDR_CONTENT_LANGUAGE",
+ "T_HDR_CONTENT_LENGTH", "T_HDR_CONTENT_TYPE", "T_HDR_CSEQ", "T_HDR_DATE",
+ "T_HDR_ERROR_INFO", "T_HDR_EVENT", "T_HDR_EXPIRES", "T_HDR_FROM",
+ "T_HDR_IN_REPLY_TO", "T_HDR_MAX_FORWARDS", "T_HDR_MIN_EXPIRES",
+ "T_HDR_MIME_VERSION", "T_HDR_ORGANIZATION", "T_HDR_P_ASSERTED_IDENTITY",
+ "T_HDR_P_PREFERRED_IDENTITY", "T_HDR_PRIORITY", "T_HDR_PRIVACY",
+ "T_HDR_PROXY_AUTHENTICATE", "T_HDR_PROXY_AUTHORIZATION",
+ "T_HDR_PROXY_REQUIRE", "T_HDR_RACK", "T_HDR_RECORD_ROUTE",
+ "T_HDR_SERVICE_ROUTE", "T_HDR_REFER_SUB", "T_HDR_REFER_TO",
+ "T_HDR_REFERRED_BY", "T_HDR_REPLACES", "T_HDR_REPLY_TO", "T_HDR_REQUIRE",
+ "T_HDR_REQUEST_DISPOSITION", "T_HDR_RETRY_AFTER", "T_HDR_ROUTE",
+ "T_HDR_RSEQ", "T_HDR_SERVER", "T_HDR_SIP_ETAG", "T_HDR_SIP_IF_MATCH",
+ "T_HDR_SUBJECT", "T_HDR_SUBSCRIPTION_STATE", "T_HDR_SUPPORTED",
+ "T_HDR_TIMESTAMP", "T_HDR_TO", "T_HDR_UNSUPPORTED", "T_HDR_USER_AGENT",
+ "T_HDR_VIA", "T_HDR_WARNING", "T_HDR_WWW_AUTHENTICATE", "T_HDR_UNKNOWN",
+ "T_CRLF", "T_ERROR", "T_NULL", "'/'", "':'", "','", "';'", "'='", "'<'",
+ "'>'", "'@'", "'('", "')'", "'.'", "'['", "']'", "$accept",
+ "sip_message", "@1", "sip_message2", "request", "request_line", "@2",
+ "@3", "sip_version", "@4", "response", "status_line", "@5", "@6", "@7",
+ "headers", "header", "hd_accept", "hd_accept_encoding",
+ "hd_accept_language", "hd_alert_info", "hd_allow", "hd_allow_events",
+ "hd_authentication_info", "hd_authorization", "hd_call_id",
+ "hd_call_info", "hd_contact", "hd_content_disp", "hd_content_encoding",
+ "hd_content_language", "hd_content_length", "hd_content_type", "hd_cseq",
+ "hd_date", "hd_error_info", "hd_event", "hd_expires", "hd_from",
+ "hd_in_reply_to", "hd_max_forwards", "hd_min_expires", "hd_mime_version",
+ "hd_organization", "hd_p_asserted_identity", "hd_p_preferred_identity",
+ "hd_priority", "hd_privacy", "hd_proxy_authenticate",
+ "hd_proxy_authorization", "hd_proxy_require", "hd_rack",
+ "hd_record_route", "hd_refer_sub", "hd_refer_to", "hd_referred_by",
+ "hd_replaces", "hd_reply_to", "hd_require", "hd_request_disposition",
+ "hd_retry_after", "hd_route", "hd_rseq", "hd_server", "hd_service_route",
+ "hd_sip_etag", "hd_sip_if_match", "hd_subject", "hd_subscription_state",
+ "hd_supported", "hd_timestamp", "hd_to", "hd_unsupported",
+ "hd_user_agent", "hd_via", "hd_warning", "hd_www_authenticate",
+ "hdr_accept", "media_range", "parameters", "parameter", "@8", "@9",
+ "parameter_val", "hdr_accept_encoding", "content_coding", "q_factor",
+ "hdr_accept_language", "@10", "@11", "language", "@12", "hdr_alert_info",
+ "alert_param", "@13", "@14", "hdr_allow", "hdr_call_id", "@15", "@16",
+ "call_id", "hdr_call_info", "info_param", "@17", "@18", "hdr_contact",
+ "@19", "@20", "contacts", "contact_param", "contact_addr", "@21", "@22",
+ "@23", "@24", "@25", "display_name", "hdr_content_disp",
+ "hdr_content_encoding", "hdr_content_language", "@26", "@27",
+ "hdr_content_length", "@28", "@29", "hdr_content_type", "hdr_cseq",
+ "@30", "@31", "hdr_date", "@32", "@33", "hdr_error_info", "error_param",
+ "@34", "@35", "hdr_expires", "@36", "@37", "hdr_from", "@38",
+ "from_addr", "@39", "@40", "@41", "hdr_in_reply_to", "@42", "@43", "@44",
+ "@45", "hdr_max_forwards", "@46", "@47", "hdr_min_expires", "@48", "@49",
+ "hdr_mime_version", "hdr_organization", "@50", "@51",
+ "hdr_p_asserted_identity", "@52", "hdr_p_preferred_identity", "@53",
+ "hdr_priority", "hdr_privacy", "hdr_proxy_require", "hdr_record_route",
+ "rec_route", "@54", "@55", "hdr_service_route", "hdr_replaces", "@56",
+ "@57", "hdr_reply_to", "@58", "hdr_require", "hdr_retry_after", "@59",
+ "@60", "comment", "@61", "@62", "hdr_route", "hdr_server", "server",
+ "hdr_subject", "@63", "@64", "hdr_supported", "hdr_timestamp", "@65",
+ "hdr_timestamp1", "timestamp", "delay", "hdr_to", "@66",
+ "hdr_unsupported", "hdr_user_agent", "hdr_via", "via_parm",
+ "sent_protocol", "host", "@67", "@68", "@69", "@70", "ipv6reference",
+ "@71", "@72", "hdr_warning", "warning", "@73", "@74", "hdr_unknown",
+ "@75", "@76", "ainfo", "hdr_authentication_info", "digest_response",
+ "auth_params", "credentials", "@77", "@78", "hdr_authorization", "@79",
+ "digest_challenge", "challenge", "@80", "@81", "hdr_proxy_authenticate",
+ "@82", "hdr_proxy_authorization", "@83", "hdr_www_authenticate", "@84",
+ "hdr_rseq", "@85", "@86", "hdr_rack", "@87", "@88", "hdr_event",
+ "hdr_allow_events", "hdr_subscription_state", "hdr_refer_to", "@89",
+ "hdr_referred_by", "@90", "hdr_refer_sub", "hdr_sip_etag",
+ "hdr_sip_if_match", "hdr_request_disposition", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 47, 58, 44, 59,
+ 61, 60, 62, 64, 40, 41, 46, 91, 93
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint16 yyr1[] =
+{
+ 0, 99, 101, 100, 102, 102, 102, 103, 105, 106,
+ 104, 108, 107, 109, 111, 112, 113, 110, 114, 114,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 176, 176, 177, 178, 178, 179, 180, 181,
+ 179, 182, 182, 183, 183, 184, 184, 185, 187, 186,
+ 188, 186, 189, 190, 189, 191, 191, 193, 194, 192,
+ 195, 195, 197, 198, 196, 199, 199, 200, 200, 202,
+ 203, 201, 205, 206, 204, 204, 207, 207, 208, 210,
+ 211, 209, 212, 213, 214, 209, 215, 215, 215, 216,
+ 217, 217, 219, 218, 220, 218, 222, 223, 221, 224,
+ 226, 227, 225, 229, 230, 228, 231, 231, 233, 234,
+ 232, 236, 237, 235, 239, 238, 241, 240, 242, 243,
+ 240, 245, 246, 244, 247, 248, 244, 250, 251, 249,
+ 253, 254, 252, 255, 257, 258, 256, 260, 259, 259,
+ 262, 261, 261, 263, 264, 264, 265, 265, 266, 266,
+ 268, 269, 267, 270, 270, 272, 273, 271, 275, 274,
+ 276, 276, 278, 279, 277, 280, 281, 282, 280, 283,
+ 283, 284, 284, 285, 285, 285, 287, 288, 286, 289,
+ 289, 289, 291, 290, 292, 292, 293, 293, 294, 294,
+ 296, 295, 297, 297, 298, 298, 299, 299, 300, 301,
+ 302, 303, 304, 302, 302, 305, 306, 302, 308, 309,
+ 307, 310, 310, 312, 313, 311, 315, 316, 314, 317,
+ 318, 318, 319, 319, 320, 320, 322, 321, 323, 321,
+ 325, 324, 326, 326, 328, 327, 329, 327, 331, 330,
+ 333, 332, 335, 334, 337, 338, 336, 340, 341, 339,
+ 342, 343, 343, 344, 346, 345, 348, 347, 349, 350,
+ 351, 352, 352
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 0, 2, 1, 1, 2, 3, 0, 0,
+ 6, 0, 4, 3, 0, 0, 0, 7, 0, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 0, 2, 4, 3, 0, 3, 1, 0, 0,
+ 5, 1, 1, 1, 3, 1, 2, 2, 0, 2,
+ 0, 4, 1, 0, 3, 1, 3, 0, 0, 6,
+ 1, 3, 0, 0, 3, 1, 3, 1, 3, 0,
+ 0, 6, 0, 0, 3, 1, 1, 3, 2, 0,
+ 0, 3, 0, 0, 0, 7, 0, 1, 1, 2,
+ 1, 3, 0, 2, 0, 4, 0, 0, 3, 2,
+ 0, 0, 4, 0, 0, 13, 1, 3, 0, 0,
+ 6, 0, 0, 3, 0, 3, 0, 2, 0, 0,
+ 6, 0, 0, 3, 0, 0, 5, 0, 0, 3,
+ 0, 0, 3, 1, 0, 0, 3, 0, 2, 3,
+ 0, 2, 3, 1, 1, 3, 1, 3, 1, 3,
+ 0, 0, 7, 1, 3, 0, 0, 4, 0, 3,
+ 1, 3, 0, 0, 5, 0, 0, 0, 5, 1,
+ 3, 1, 2, 1, 2, 4, 0, 0, 3, 0,
+ 1, 3, 0, 2, 1, 2, 1, 3, 1, 3,
+ 0, 3, 1, 3, 1, 2, 1, 3, 3, 5,
+ 1, 0, 0, 5, 1, 0, 0, 5, 0, 0,
+ 5, 1, 3, 0, 0, 5, 0, 0, 3, 1,
+ 1, 3, 1, 3, 1, 3, 0, 3, 0, 3,
+ 0, 2, 1, 3, 0, 3, 0, 3, 0, 2,
+ 0, 2, 0, 2, 0, 0, 3, 0, 0, 5,
+ 2, 1, 3, 2, 0, 3, 0, 3, 2, 1,
+ 1, 1, 3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint16 yydefact[] =
+{
+ 2, 0, 0, 1, 0, 11, 8, 3, 4, 18,
+ 14, 5, 18, 6, 0, 0, 0, 0, 0, 0,
+ 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 7, 19, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 15, 13, 12, 0, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+ 173, 174, 175, 176, 188, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 198, 199, 200, 386, 0,
+ 0, 0, 205, 0, 215, 0, 213, 0, 0, 0,
+ 0, 227, 0, 225, 0, 230, 0, 0, 421, 0,
+ 0, 207, 389, 390, 0, 0, 0, 0, 0, 0,
+ 0, 0, 239, 0, 237, 0, 0, 0, 245, 246,
+ 205, 0, 256, 0, 205, 0, 0, 260, 0, 0,
+ 0, 0, 0, 0, 0, 0, 205, 0, 0, 0,
+ 0, 0, 0, 0, 0, 278, 0, 276, 0, 205,
+ 0, 0, 0, 0, 0, 0, 256, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 303, 0, 0,
+ 0, 0, 0, 0, 256, 0, 0, 256, 0, 313,
+ 0, 0, 314, 0, 0, 0, 0, 0, 0, 0,
+ 0, 316, 0, 0, 0, 0, 0, 0, 318, 256,
+ 0, 205, 0, 0, 0, 256, 0, 0, 256, 0,
+ 0, 0, 0, 0, 256, 0, 316, 0, 0, 0,
+ 431, 0, 0, 0, 0, 0, 339, 0, 0, 0,
+ 0, 0, 335, 336, 343, 0, 341, 0, 323, 0,
+ 0, 429, 0, 0, 430, 0, 0, 0, 0, 0,
+ 205, 0, 0, 350, 0, 0, 0, 0, 0, 0,
+ 256, 0, 362, 0, 0, 364, 0, 0, 0, 0,
+ 366, 0, 0, 0, 381, 0, 0, 0, 0, 0,
+ 0, 0, 0, 81, 0, 20, 0, 202, 82, 0,
+ 216, 21, 0, 83, 22, 220, 222, 219, 84, 0,
+ 23, 0, 85, 24, 0, 86, 25, 0, 87, 208,
+ 26, 0, 88, 27, 396, 398, 401, 89, 28, 235,
+ 233, 90, 0, 29, 0, 91, 30, 243, 252, 248,
+ 250, 258, 257, 0, 92, 259, 31, 93, 32, 0,
+ 94, 33, 264, 263, 95, 34, 267, 96, 269, 35,
+ 97, 36, 271, 98, 37, 0, 99, 0, 39, 0,
+ 100, 420, 38, 101, 40, 282, 102, 41, 286, 0,
+ 205, 103, 42, 294, 292, 104, 43, 298, 105, 44,
+ 301, 106, 45, 107, 46, 305, 108, 47, 256, 308,
+ 109, 48, 256, 311, 110, 49, 111, 50, 0, 112,
+ 51, 404, 406, 409, 113, 52, 411, 114, 53, 0,
+ 115, 54, 0, 116, 55, 320, 0, 117, 428, 56,
+ 118, 57, 205, 119, 58, 205, 120, 59, 326, 121,
+ 60, 205, 122, 0, 61, 123, 62, 0, 124, 63,
+ 333, 125, 64, 320, 126, 65, 415, 127, 0, 344,
+ 0, 66, 342, 128, 67, 320, 129, 68, 130, 69,
+ 131, 70, 347, 132, 423, 71, 133, 72, 0, 134,
+ 73, 356, 353, 354, 135, 74, 205, 136, 75, 0,
+ 137, 76, 365, 138, 0, 77, 0, 370, 378, 205,
+ 374, 139, 78, 383, 384, 140, 79, 413, 16, 10,
+ 80, 387, 204, 205, 0, 217, 214, 0, 0, 228,
+ 226, 231, 422, 0, 391, 0, 0, 0, 234, 240,
+ 238, 244, 247, 251, 253, 261, 0, 268, 0, 0,
+ 279, 277, 283, 287, 288, 285, 0, 293, 299, 302,
+ 306, 309, 312, 315, 0, 0, 317, 418, 319, 0,
+ 425, 427, 205, 329, 317, 432, 335, 340, 416, 335,
+ 337, 324, 348, 351, 0, 358, 355, 361, 363, 0,
+ 367, 371, 0, 368, 375, 382, 0, 0, 388, 203,
+ 206, 221, 224, 0, 212, 211, 209, 392, 397, 394,
+ 399, 236, 0, 0, 265, 272, 0, 0, 0, 295,
+ 402, 405, 407, 0, 321, 327, 205, 345, 0, 357,
+ 0, 0, 0, 379, 0, 0, 17, 205, 210, 0,
+ 0, 205, 254, 0, 205, 289, 296, 0, 419, 0,
+ 334, 338, 359, 369, 372, 0, 376, 385, 229, 393,
+ 395, 241, 0, 0, 280, 0, 403, 205, 373, 380,
+ 377, 255, 0, 290, 322, 0, 0, 0, 0, 274,
+ 275
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 1, 2, 7, 8, 9, 15, 147, 10, 14,
+ 11, 12, 17, 409, 707, 16, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 211, 212, 417,
+ 232, 643, 748, 716, 215, 216, 420, 218, 219, 637,
+ 427, 638, 222, 223, 429, 713, 226, 239, 240, 648,
+ 450, 243, 244, 452, 722, 246, 247, 651, 248, 249,
+ 250, 251, 653, 252, 723, 772, 499, 255, 258, 260,
+ 261, 656, 263, 264, 657, 267, 269, 270, 658, 272,
+ 273, 790, 276, 277, 487, 727, 282, 283, 662, 285,
+ 286, 500, 663, 728, 775, 288, 289, 667, 666, 756,
+ 291, 292, 668, 294, 295, 669, 298, 300, 301, 670,
+ 303, 304, 306, 307, 310, 313, 322, 327, 328, 329,
+ 759, 369, 340, 341, 682, 343, 344, 348, 353, 354,
+ 686, 364, 580, 738, 357, 365, 366, 377, 378, 692,
+ 384, 386, 387, 602, 603, 696, 389, 390, 393, 396,
+ 399, 400, 401, 619, 742, 778, 744, 780, 620, 702,
+ 765, 403, 404, 405, 706, 411, 412, 708, 233, 234,
+ 718, 720, 446, 645, 646, 236, 237, 731, 533, 674,
+ 675, 315, 316, 318, 319, 407, 408, 359, 360, 688,
+ 324, 325, 733, 280, 229, 381, 334, 335, 337, 338,
+ 332, 372, 375, 351
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -413
+static const yytype_int16 yypact[] =
+{
+ -413, 90, 99, -413, -37, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, 18, 119, 506, 133, 568, 152,
+ -413, 77, 107, 139, 145, 168, 177, 194, 198, 199,
+ 200, 201, 202, 203, 204, 206, 208, 209, 210, 211,
+ 216, 217, 221, 222, 223, 225, 228, 229, 230, 231,
+ 232, 233, 234, 239, 240, 244, 254, 255, 256, 259,
+ 260, 261, 262, 263, 266, 270, 273, 274, 277, 278,
+ 280, 281, 283, 284, 285, 286, 287, 288, 289, 291,
+ 294, 295, -413, -413, 58, 147, 120, 20, 205, 207,
+ 212, 67, 81, 34, 17, 213, 214, 123, 257, 219,
+ 258, 64, 37, 220, 264, 23, 95, 267, 268, 226,
+ 88, 29, 42, 227, 235, 73, 100, 236, 271, 31,
+ 237, 48, 56, 111, 62, 241, 242, 272, 70, 275,
+ 11, 78, 243, 247, 128, 248, 83, 276, 68, 252,
+ 16, 253, 279, 125, -413, -413, -413, 87, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, 136,
+ 215, 66, -413, 224, 245, 69, -413, 246, 72, 167,
+ 269, -413, 75, -413, 301, -413, 79, 302, -413, 82,
+ 303, 238, -413, -413, 85, 304, 305, 164, 306, 307,
+ 282, 308, -413, 89, -413, 309, 310, 290, 218, -413,
+ -413, 292, 140, 311, -413, 312, 314, -413, 91, 315,
+ 92, 167, 316, 317, 319, 318, -413, 320, 321, 322,
+ 327, 323, 324, 300, 325, -413, 93, -413, 326, -413,
+ 328, 329, 330, 332, 331, 333, 132, 334, 101, 282,
+ 335, 337, 336, 338, 339, 341, 340, -413, 342, 343,
+ 344, 347, 345, 102, 132, 346, 103, 132, 348, -413,
+ 350, 351, -413, 49, 352, 353, 265, 354, 355, 164,
+ 356, -413, 104, 357, 358, 359, 360, 105, -413, 140,
+ 361, -413, 362, 363, 365, 132, 366, 367, 132, 368,
+ 369, 282, 370, 371, 132, 372, 373, 374, 375, 377,
+ -413, 112, 378, 380, 399, 381, -413, 113, 382, 383,
+ 407, 384, -40, -413, -413, 15, -413, 385, -413, 114,
+ 386, -413, 387, 388, -413, 389, 390, 391, 408, 392,
+ -413, 393, 394, -413, 115, 395, 396, 421, 397, 398,
+ 132, 400, -413, 116, 401, -413, 19, 402, 403, 122,
+ -413, 9, 404, 124, -413, 427, 405, 409, 265, 435,
+ 410, 411, 450, -413, 478, -413, 486, 251, -413, 487,
+ -413, -413, 491, -413, -413, -413, 413, -413, -413, 488,
+ -413, 412, -413, -413, 494, -413, -413, 495, -413, -413,
+ -413, 487, -413, -413, -413, -413, -413, -413, -413, 414,
+ -413, -413, 492, -413, 415, -413, -413, -413, 497, 251,
+ -413, -413, -413, 417, -413, 251, -413, -413, -413, 491,
+ -413, -413, -413, -413, -413, -413, -413, -413, 251, -413,
+ -413, -413, -413, -413, -413, 422, -413, 501, -413, 420,
+ -413, 251, -413, -413, -413, -413, -413, -413, -413, 423,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, 132, -413,
+ -413, -413, 132, -413, -413, -413, -413, -413, 508, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, 509,
+ -413, -413, 512, -413, -413, -413, 425, -413, 251, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, 513, -413, -413, -413, 514, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, 515, -413,
+ 349, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, 251, -413, -413, -413, 516, -413,
+ -413, 196, -413, 518, -413, -413, -413, -413, -413, 519,
+ -413, -413, -413, -413, 520, -413, 521, 439, -413, -413,
+ 565, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, 487, -413, -413, 167, 245, -413,
+ -413, -413, -413, 39, -413, 487, 487, 510, -413, -413,
+ -413, -413, -413, -413, -413, -413, 167, -413, 649, 651,
+ -413, -413, -413, -413, -413, 251, 282, -413, -413, -413,
+ -413, -413, -413, -413, 487, 487, -413, -413, -413, 647,
+ 251, 251, -413, 251, 573, -413, 563, -413, -413, 563,
+ -413, -413, -413, -413, 655, 564, -413, 251, -413, 575,
+ -413, -413, 639, 251, -413, -413, 9, 579, -413, 251,
+ -413, -413, -413, 571, -413, -413, -413, -413, 576, -413,
+ 577, -413, 574, 659, -413, -413, 654, 578, 661, -413,
+ -413, 583, 577, 668, -413, 251, -413, -413, 580, -413,
+ 670, 672, 671, -413, 674, 673, -413, -413, -413, 487,
+ 487, -413, -413, 676, -413, -413, -413, 487, -413, 588,
+ 251, -413, -413, -413, -413, 584, -413, -413, 251, -413,
+ -413, 251, 589, 680, 251, 592, -413, -413, -413, -413,
+ -413, -413, 598, -413, 251, 683, 600, 685, 299, -413,
+ -413
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -413, -413, -413, -413, -413, -413, -413, -413, 176, -413,
+ -413, -413, -413, -413, -413, 677, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -91, -250,
+ -412, -413, -413, -413, -413, -90, -314, -413, -413, -413,
+ -260, -413, -413, -80, -413, -413, -413, -413, -413, -413,
+ -286, -413, -96, -413, -413, -413, -413, -413, -413, -99,
+ -413, -413, -413, -413, -413, -413, -212, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -123, -413, -413, -413, -413, -413, -413,
+ -413, -293, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, 566, -413, -126, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -353, -413, -413, -413, -413, -130, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -253, -413, -16, -413, -413, -413, -413, -413, -413,
+ -413, -413, 71, -413, -413, -413, -413, -413, 293, -413,
+ -413, 21, 376, -413, -413, -413, -413, -413, 296, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+ -413, -413, -413, -413
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -427
+static const yytype_int16 yytable[] =
+{
+ 459, 473, 356, 504, 465, 368, 257, 635, 266, 579,
+ 395, 519, 361, 617, 523, 362, 478, 394, 245, 362,
+ 362, 220, -252, 362, 284, -249, -242, -252, -284, 491,
+ 302, -284, 326, -284, -307, 241, -320, -307, 274, -307,
+ 463, -320, 552, 305, 714, 555, 578, -310, 13, 333,
+ -310, 561, -310, -424, 363, 558, -424, 336, -424, 209,
+ 715, -426, 210, 342, -426, 271, -426, -328, 235, 388,
+ -328, 355, -328, -360, 314, -320, -360, -273, -360, 367,
+ -320, 548, 238, -320, 382, -400, -400, 383, -320, 299,
+ 3, -408, -408, -232, -335, -304, 287, 606, 581, -335,
+ 4, 317, 611, 5, 19, 363, 618, -291, -252, 363,
+ 363, 221, 339, 363, -284, 5, 6, 546, -410, -410,
+ -307, 217, -320, -325, 259, 242, 406, 20, 275, 376,
+ 594, -218, 527, -310, -262, -346, 144, 461, 528, -424,
+ 498, -201, 462, -412, -412, 461, -201, -426, 213, 415,
+ 462, 214, 421, -328, 416, 424, 146, 422, 430, -360,
+ 425, -320, 433, 431, 148, 436, -349, 434, 440, -320,
+ 437, -349, 453, 441, 468, 471, 488, 454, 426, 469,
+ 472, 489, 444, 445, 502, 517, 521, 538, 544, 503,
+ 518, 522, 539, 545, 149, 566, 572, 584, 597, 608,
+ 567, 573, 585, 598, 609, 615, 224, 622, 227, 225,
+ 616, 228, 623, 230, 253, 256, 231, 254, 214, 413,
+ 265, 278, 710, 210, 279, 671, 150, 296, 308, 672,
+ 297, 309, 151, 717, 719, 582, 311, 320, 330, 312,
+ 321, 331, 345, 349, 370, 346, 350, 371, 373, 379,
+ 665, 374, 380, 391, 397, 152, 392, 398, 262, 268,
+ -266, -270, 730, 719, 153, 281, 612, -281, 290, 293,
+ -297, -300, 323, 352, -417, -332, 358, 385, -414, -352,
+ 402, 154, -383, 531, 532, 155, 156, 157, 158, 159,
+ 160, 161, 694, 162, 449, 163, 164, 165, 166, 457,
+ 460, 414, 680, 167, 168, 681, 458, 418, 169, 170,
+ 171, 683, 172, 485, 789, 173, 174, 175, 176, 177,
+ 178, 179, 476, 410, 712, 633, 180, 181, 439, 423,
+ 482, 182, 636, 736, 419, 495, 737, 769, 770, 507,
+ 634, 183, 184, 185, 510, 776, 186, 187, 188, 189,
+ 190, 640, 428, 191, 515, 690, 697, 192, 650, 652,
+ 193, 194, 542, 700, 195, 196, 661, 197, 198, 703,
+ 199, 200, 201, 202, 203, 204, 205, 711, 206, 655,
+ 729, 207, 208, 709, 432, 435, 438, 442, 443, 447,
+ 448, 451, 455, 456, 464, 466, 724, 467, 470, 474,
+ 475, 477, 570, 479, 480, 481, 483, 484, 486, 490,
+ 576, 492, 493, 494, 496, 592, 497, 501, 505, 678,
+ 506, 508, 509, 511, 601, 512, 513, 514, 516, 520,
+ 624, 524, 735, 525, 526, 529, 530, 534, 535, 537,
+ 540, 541, 628, 543, 547, 549, 550, 687, 551, 553,
+ 554, 556, 557, 559, 560, 562, -330, 631, 564, 691,
+ 565, 568, 563, 569, 571, 574, 575, 577, 583, 586,
+ 587, 588, 589, 590, 591, 593, 595, 596, 599, 600,
+ 604, 605, 632, 607, 610, 613, 760, 621, 625, 614,
+ 210, 231, 626, 629, 630, 214, 639, 768, 641, 642,
+ 649, 771, -223, 221, 774, -249, 242, 647, 654, 660,
+ 659, 275, 673, 676, 664, 677, 679, 684, 685, 689,
+ 693, 695, 721, 698, 699, 398, 701, 784, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 145, 704, 725, 726, 734, -331, 363, 739, 743,
+ 740, 741, 746, 747, 749, 750, 751, 752, 753, 755,
+ 754, 757, 758, 762, 764, 761, 763, 766, 767, 773,
+ 777, 781, 779, 782, 783, 785, 786, 787, 788, 18,
+ 745, 347, 0, 0, 705, 536, 732, 0, 0, 0,
+ 0, 0, 0, 0, 627, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 644
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 250, 261, 128, 289, 254, 131, 96, 419, 99, 362,
+ 140, 304, 1, 4, 307, 4, 266, 1, 1, 4,
+ 4, 1, 5, 4, 1, 8, 9, 10, 5, 279,
+ 1, 8, 1, 10, 5, 1, 5, 8, 1, 10,
+ 252, 10, 335, 1, 5, 338, 86, 5, 85, 1,
+ 8, 344, 10, 5, 94, 341, 8, 1, 10, 1,
+ 21, 5, 4, 1, 8, 1, 10, 5, 1, 1,
+ 8, 1, 10, 5, 1, 5, 8, 13, 10, 1,
+ 10, 331, 1, 5, 1, 18, 19, 4, 10, 1,
+ 0, 18, 19, 12, 83, 7, 1, 390, 83, 83,
+ 1, 1, 83, 16, 86, 94, 97, 12, 91, 94,
+ 94, 91, 1, 94, 91, 16, 17, 329, 18, 19,
+ 91, 1, 91, 12, 1, 91, 1, 8, 91, 1,
+ 380, 11, 83, 91, 11, 7, 3, 5, 89, 91,
+ 8, 83, 10, 18, 19, 5, 88, 91, 1, 83,
+ 10, 4, 83, 91, 88, 83, 4, 88, 83, 91,
+ 88, 91, 83, 88, 87, 83, 83, 88, 83, 91,
+ 88, 88, 83, 88, 83, 83, 83, 88, 11, 88,
+ 88, 88, 18, 19, 83, 83, 83, 83, 83, 88,
+ 88, 88, 88, 88, 87, 83, 83, 83, 83, 83,
+ 88, 88, 88, 88, 88, 83, 1, 83, 1, 4,
+ 88, 4, 88, 1, 1, 1, 4, 4, 4, 83,
+ 1, 1, 634, 4, 4, 518, 87, 1, 1, 522,
+ 4, 4, 87, 645, 646, 365, 1, 1, 1, 4,
+ 4, 4, 1, 1, 1, 4, 4, 4, 1, 1,
+ 500, 4, 4, 1, 1, 87, 4, 4, 1, 1,
+ 3, 3, 674, 675, 87, 1, 396, 3, 1, 1,
+ 3, 3, 1, 1, 3, 3, 1, 1, 3, 3,
+ 1, 87, 3, 18, 19, 87, 87, 87, 87, 87,
+ 87, 87, 96, 87, 12, 87, 87, 87, 87, 9,
+ 8, 86, 552, 87, 87, 555, 88, 83, 87, 87,
+ 87, 561, 87, 13, 15, 87, 87, 87, 87, 87,
+ 87, 87, 3, 147, 638, 416, 87, 87, 90, 83,
+ 3, 87, 422, 686, 89, 3, 689, 749, 750, 3,
+ 89, 87, 87, 87, 3, 757, 87, 87, 87, 87,
+ 87, 431, 83, 87, 7, 6, 606, 87, 454, 458,
+ 87, 87, 3, 616, 87, 87, 489, 87, 87, 619,
+ 87, 87, 87, 87, 87, 87, 87, 637, 87, 469,
+ 666, 87, 87, 633, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 656, 83, 83, 83,
+ 83, 83, 3, 83, 83, 83, 83, 83, 83, 83,
+ 3, 83, 83, 83, 83, 7, 83, 83, 83, 545,
+ 83, 83, 83, 83, 3, 83, 83, 83, 83, 83,
+ 3, 83, 682, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 7, 83, 83, 83, 83, 573, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 7, 83, 585,
+ 83, 83, 88, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 4, 83, 83, 83, 736, 83, 83, 86,
+ 4, 4, 83, 83, 83, 4, 8, 747, 4, 4,
+ 8, 751, 89, 91, 754, 8, 91, 93, 91, 8,
+ 88, 91, 4, 4, 91, 3, 91, 4, 4, 4,
+ 4, 3, 12, 4, 4, 4, 87, 777, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 87, 4, 3, 8, 83, 94, 3, 20,
+ 96, 86, 83, 92, 88, 88, 92, 8, 14, 8,
+ 92, 88, 4, 3, 3, 95, 4, 3, 5, 3,
+ 92, 92, 98, 3, 92, 87, 3, 87, 3, 12,
+ 706, 125, -1, -1, 623, 319, 675, -1, -1, -1,
+ -1, -1, -1, -1, 408, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 441
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint16 yystos[] =
+{
+ 0, 100, 101, 0, 1, 16, 17, 102, 103, 104,
+ 107, 109, 110, 85, 108, 105, 114, 111, 114, 86,
+ 8, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 3, 83, 4, 106, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 1,
+ 4, 176, 177, 1, 4, 183, 184, 1, 186, 187,
+ 1, 91, 191, 192, 1, 4, 195, 1, 4, 343,
+ 1, 4, 179, 317, 318, 1, 324, 325, 1, 196,
+ 197, 1, 91, 200, 201, 1, 204, 205, 207, 208,
+ 209, 210, 212, 1, 4, 216, 1, 184, 217, 1,
+ 218, 219, 1, 221, 222, 1, 177, 224, 1, 225,
+ 226, 1, 228, 229, 1, 91, 231, 232, 1, 4,
+ 342, 1, 235, 236, 1, 238, 239, 1, 244, 245,
+ 1, 249, 250, 1, 252, 253, 1, 4, 255, 1,
+ 256, 257, 1, 259, 260, 1, 261, 262, 1, 4,
+ 263, 1, 4, 264, 1, 330, 331, 1, 332, 333,
+ 1, 4, 265, 1, 339, 340, 1, 266, 267, 268,
+ 1, 4, 349, 1, 345, 346, 1, 347, 348, 1,
+ 271, 272, 1, 274, 275, 1, 4, 265, 276, 1,
+ 4, 352, 1, 277, 278, 1, 267, 283, 1, 336,
+ 337, 1, 4, 94, 280, 284, 285, 1, 267, 270,
+ 1, 4, 350, 1, 4, 351, 1, 286, 287, 1,
+ 4, 344, 1, 4, 289, 1, 290, 291, 1, 295,
+ 296, 1, 4, 297, 1, 285, 298, 1, 4, 299,
+ 300, 301, 1, 310, 311, 312, 1, 334, 335, 112,
+ 107, 314, 315, 83, 86, 83, 88, 178, 83, 89,
+ 185, 83, 88, 83, 83, 88, 11, 189, 83, 193,
+ 83, 88, 83, 83, 88, 83, 83, 88, 83, 90,
+ 83, 88, 83, 83, 18, 19, 321, 83, 83, 12,
+ 199, 83, 202, 83, 88, 83, 83, 9, 88, 178,
+ 8, 5, 10, 215, 83, 178, 83, 83, 83, 88,
+ 83, 83, 88, 189, 83, 83, 3, 83, 178, 83,
+ 83, 83, 3, 83, 83, 13, 83, 233, 83, 88,
+ 83, 178, 83, 83, 83, 3, 83, 83, 8, 215,
+ 240, 83, 83, 88, 199, 83, 83, 3, 83, 83,
+ 3, 83, 83, 83, 83, 7, 83, 83, 88, 240,
+ 83, 83, 88, 240, 83, 83, 83, 83, 89, 83,
+ 83, 18, 19, 327, 83, 83, 321, 83, 83, 88,
+ 83, 83, 3, 83, 83, 88, 215, 83, 178, 83,
+ 83, 83, 240, 83, 83, 240, 83, 83, 199, 83,
+ 83, 240, 83, 88, 83, 83, 83, 88, 83, 83,
+ 3, 83, 83, 88, 83, 83, 3, 83, 86, 280,
+ 281, 83, 285, 83, 83, 88, 83, 83, 83, 83,
+ 83, 83, 7, 83, 178, 83, 83, 83, 88, 83,
+ 83, 3, 292, 293, 83, 83, 240, 83, 83, 88,
+ 83, 83, 285, 83, 86, 83, 88, 4, 97, 302,
+ 307, 83, 83, 88, 3, 83, 83, 327, 7, 83,
+ 83, 7, 4, 177, 89, 179, 184, 188, 190, 8,
+ 192, 4, 4, 180, 317, 322, 323, 93, 198, 8,
+ 201, 206, 208, 211, 91, 184, 220, 223, 227, 88,
+ 8, 232, 237, 241, 91, 178, 247, 246, 251, 254,
+ 258, 240, 240, 4, 328, 329, 4, 3, 267, 91,
+ 178, 178, 273, 178, 4, 4, 279, 267, 338, 4,
+ 6, 267, 288, 4, 96, 3, 294, 178, 4, 4,
+ 300, 87, 308, 178, 87, 311, 313, 113, 316, 178,
+ 179, 189, 185, 194, 5, 21, 182, 179, 319, 179,
+ 320, 12, 203, 213, 189, 4, 3, 234, 242, 199,
+ 179, 326, 320, 341, 8, 178, 280, 280, 282, 3,
+ 96, 86, 303, 20, 305, 302, 83, 92, 181, 88,
+ 88, 92, 8, 14, 92, 8, 248, 88, 4, 269,
+ 178, 95, 3, 4, 3, 309, 3, 5, 178, 179,
+ 179, 178, 214, 3, 178, 243, 179, 92, 304, 98,
+ 306, 92, 3, 92, 178, 87, 3, 87, 3, 15,
+ 230
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ yytype_int16 *bottom;
+ yytype_int16 *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ fprintf (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+ case 4: /* "T_TOKEN" */
+#line 164 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2025 "parser.cxx"
+ break;
+ case 5: /* "T_QSTRING" */
+#line 165 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2030 "parser.cxx"
+ break;
+ case 6: /* "T_COMMENT" */
+#line 166 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2035 "parser.cxx"
+ break;
+ case 7: /* "T_LINE" */
+#line 167 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2040 "parser.cxx"
+ break;
+ case 8: /* "T_URI" */
+#line 168 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2045 "parser.cxx"
+ break;
+ case 10: /* "T_DISPLAY" */
+#line 169 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2050 "parser.cxx"
+ break;
+ case 11: /* "T_LANG" */
+#line 170 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2055 "parser.cxx"
+ break;
+ case 12: /* "T_WORD" */
+#line 171 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2060 "parser.cxx"
+ break;
+ case 17: /* "T_METHOD" */
+#line 172 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2065 "parser.cxx"
+ break;
+ case 19: /* "T_AUTH_OTHER" */
+#line 173 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2070 "parser.cxx"
+ break;
+ case 20: /* "T_IPV6ADDR" */
+#line 174 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2075 "parser.cxx"
+ break;
+ case 21: /* "T_PARAMVAL" */
+#line 175 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2080 "parser.cxx"
+ break;
+ case 82: /* "T_HDR_UNKNOWN" */
+#line 176 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2085 "parser.cxx"
+ break;
+ case 107: /* "sip_version" */
+#line 239 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2090 "parser.cxx"
+ break;
+ case 177: /* "media_range" */
+#line 232 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_media)); delete (yyvaluep->yyt_media); };
+#line 2095 "parser.cxx"
+ break;
+ case 178: /* "parameters" */
+#line 235 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_params)); delete (yyvaluep->yyt_params); };
+#line 2100 "parser.cxx"
+ break;
+ case 179: /* "parameter" */
+#line 233 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_param)); delete (yyvaluep->yyt_param); };
+#line 2105 "parser.cxx"
+ break;
+ case 182: /* "parameter_val" */
+#line 234 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2110 "parser.cxx"
+ break;
+ case 184: /* "content_coding" */
+#line 220 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_coding)); delete (yyvaluep->yyt_coding); };
+#line 2115 "parser.cxx"
+ break;
+ case 189: /* "language" */
+#line 231 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_language)); delete (yyvaluep->yyt_language); };
+#line 2120 "parser.cxx"
+ break;
+ case 192: /* "alert_param" */
+#line 212 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_alert_param)); delete (yyvaluep->yyt_alert_param); };
+#line 2125 "parser.cxx"
+ break;
+ case 199: /* "call_id" */
+#line 214 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2130 "parser.cxx"
+ break;
+ case 201: /* "info_param" */
+#line 230 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_info_param)); delete (yyvaluep->yyt_info_param); };
+#line 2135 "parser.cxx"
+ break;
+ case 207: /* "contacts" */
+#line 219 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_contacts)); delete (yyvaluep->yyt_contacts); };
+#line 2140 "parser.cxx"
+ break;
+ case 208: /* "contact_param" */
+#line 218 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_contact)); delete (yyvaluep->yyt_contact); };
+#line 2145 "parser.cxx"
+ break;
+ case 209: /* "contact_addr" */
+#line 217 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_contact)); delete (yyvaluep->yyt_contact); };
+#line 2150 "parser.cxx"
+ break;
+ case 215: /* "display_name" */
+#line 224 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2155 "parser.cxx"
+ break;
+ case 232: /* "error_param" */
+#line 225 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_error_param)); delete (yyvaluep->yyt_error_param); };
+#line 2160 "parser.cxx"
+ break;
+ case 240: /* "from_addr" */
+#line 226 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_from_addr)); delete (yyvaluep->yyt_from_addr); };
+#line 2165 "parser.cxx"
+ break;
+ case 267: /* "rec_route" */
+#line 236 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_route)); delete (yyvaluep->yyt_route); };
+#line 2170 "parser.cxx"
+ break;
+ case 280: /* "comment" */
+#line 216 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2175 "parser.cxx"
+ break;
+ case 285: /* "server" */
+#line 238 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_server)); delete (yyvaluep->yyt_server); };
+#line 2180 "parser.cxx"
+ break;
+ case 300: /* "via_parm" */
+#line 240 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_via)); delete (yyvaluep->yyt_via); };
+#line 2185 "parser.cxx"
+ break;
+ case 301: /* "sent_protocol" */
+#line 237 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_via)); delete (yyvaluep->yyt_via); };
+#line 2190 "parser.cxx"
+ break;
+ case 302: /* "host" */
+#line 228 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_via)); delete (yyvaluep->yyt_via); };
+#line 2195 "parser.cxx"
+ break;
+ case 307: /* "ipv6reference" */
+#line 229 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2200 "parser.cxx"
+ break;
+ case 311: /* "warning" */
+#line 241 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_warning)); delete (yyvaluep->yyt_warning); };
+#line 2205 "parser.cxx"
+ break;
+ case 314: /* "hdr_unknown" */
+#line 227 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_str)); delete (yyvaluep->yyt_str); };
+#line 2210 "parser.cxx"
+ break;
+ case 319: /* "digest_response" */
+#line 223 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_dig_resp)); delete (yyvaluep->yyt_dig_resp); };
+#line 2215 "parser.cxx"
+ break;
+ case 320: /* "auth_params" */
+#line 213 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_params)); delete (yyvaluep->yyt_params); };
+#line 2220 "parser.cxx"
+ break;
+ case 321: /* "credentials" */
+#line 221 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_credentials)); delete (yyvaluep->yyt_credentials); };
+#line 2225 "parser.cxx"
+ break;
+ case 326: /* "digest_challenge" */
+#line 222 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_dig_chlg)); delete (yyvaluep->yyt_dig_chlg); };
+#line 2230 "parser.cxx"
+ break;
+ case 327: /* "challenge" */
+#line 215 "parser.yxx"
+ { MEMMAN_DELETE((yyvaluep->yyt_challenge)); delete (yyvaluep->yyt_challenge); };
+#line 2235 "parser.cxx"
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol. */
+int yychar;
+
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+ int yystate;
+ int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 244 "parser.yxx"
+ { CTXT_NEW; }
+ break;
+
+ case 6:
+#line 249 "parser.yxx"
+ {
+ /* KLUDGE to work around a memory leak in bison.
+ * T_NULL does never match, so the parser never
+ * gets here. The error keyword causes bison
+ * to eat all input and destroy all tokens returned
+ * by the parser.
+ * Without this workaround the following input causes
+ * the parser to leak:
+ *
+ * INVITE INVITE ....
+ *
+ * In request_line a T_METHOD is returned as look ahead
+ * token when bison tries to match sip_version.
+ * This does not match, but the look ahead token is
+ * never destructed by Bison.
+ */
+ YYABORT;
+ }
+ break;
+
+ case 7:
+#line 269 "parser.yxx"
+ {
+ /* Parsing stops here. Remaining text is
+ * not parsed.
+ */
+ YYACCEPT; }
+ break;
+
+ case 8:
+#line 278 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 9:
+#line 278 "parser.yxx"
+ { CTXT_NEW; }
+ break;
+
+ case 10:
+#line 279 "parser.yxx"
+ {
+ MSG = new t_request();
+ MEMMAN_NEW(MSG);
+ ((t_request *)MSG)->set_method(*(yyvsp[(1) - (6)].yyt_str));
+ ((t_request *)MSG)->uri.set_url(*(yyvsp[(3) - (6)].yyt_str));
+ MSG->version = *(yyvsp[(5) - (6)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(1) - (6)].yyt_str)); delete (yyvsp[(1) - (6)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(3) - (6)].yyt_str)); delete (yyvsp[(3) - (6)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(5) - (6)].yyt_str)); delete (yyvsp[(5) - (6)].yyt_str);
+
+ if (!((t_request *)MSG)->uri.is_valid()) {
+ MEMMAN_DELETE(MSG); delete MSG;
+ MSG = NULL;
+ YYABORT;
+ } }
+ break;
+
+ case 11:
+#line 296 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 12:
+#line 296 "parser.yxx"
+ {
+ (yyval.yyt_str) = (yyvsp[(4) - (4)].yyt_str); }
+ break;
+
+ case 13:
+#line 300 "parser.yxx"
+ {
+ /* Parsing stops here. Remaining text is
+ * not parsed.
+ */
+ YYACCEPT; }
+ break;
+
+ case 14:
+#line 307 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 15:
+#line 307 "parser.yxx"
+ { CTXT_LINE; }
+ break;
+
+ case 16:
+#line 308 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 17:
+#line 308 "parser.yxx"
+ {
+ MSG = new t_response();
+ MEMMAN_NEW(MSG);
+ MSG->version = *(yyvsp[(1) - (7)].yyt_str);
+ ((t_response *)MSG)->code = (yyvsp[(3) - (7)].yyt_ulong);
+ ((t_response *)MSG)->reason = trim(*(yyvsp[(5) - (7)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(1) - (7)].yyt_str)); delete (yyvsp[(1) - (7)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(5) - (7)].yyt_str)); delete (yyvsp[(5) - (7)].yyt_str); }
+ break;
+
+ case 80:
+#line 382 "parser.yxx"
+ {
+ MSG->add_unknown_header(*(yyvsp[(1) - (4)].yyt_str), trim(*(yyvsp[(3) - (4)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(1) - (4)].yyt_str)); delete (yyvsp[(1) - (4)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(3) - (4)].yyt_str)); delete (yyvsp[(3) - (4)].yyt_str); }
+ break;
+
+ case 81:
+#line 387 "parser.yxx"
+ { PARSE_ERROR("Accept"); }
+ break;
+
+ case 82:
+#line 389 "parser.yxx"
+ { PARSE_ERROR("Accept-Encoding"); }
+ break;
+
+ case 83:
+#line 391 "parser.yxx"
+ { PARSE_ERROR("Accept-Language"); }
+ break;
+
+ case 84:
+#line 393 "parser.yxx"
+ { PARSE_ERROR("Alert-Info"); }
+ break;
+
+ case 85:
+#line 395 "parser.yxx"
+ { PARSE_ERROR("Allow"); }
+ break;
+
+ case 86:
+#line 397 "parser.yxx"
+ { PARSE_ERROR("Allow-Events"); }
+ break;
+
+ case 87:
+#line 399 "parser.yxx"
+ { PARSE_ERROR("Authentication-Info"); }
+ break;
+
+ case 88:
+#line 401 "parser.yxx"
+ { PARSE_ERROR("Authorization"); }
+ break;
+
+ case 89:
+#line 403 "parser.yxx"
+ { PARSE_ERROR("Call-ID"); }
+ break;
+
+ case 90:
+#line 405 "parser.yxx"
+ { PARSE_ERROR("Call-Info"); }
+ break;
+
+ case 91:
+#line 407 "parser.yxx"
+ { PARSE_ERROR("Contact"); }
+ break;
+
+ case 92:
+#line 409 "parser.yxx"
+ { PARSE_ERROR("Content-Disposition"); }
+ break;
+
+ case 93:
+#line 411 "parser.yxx"
+ { PARSE_ERROR("Content-Encoding"); }
+ break;
+
+ case 94:
+#line 413 "parser.yxx"
+ { PARSE_ERROR("Content-Language"); }
+ break;
+
+ case 95:
+#line 415 "parser.yxx"
+ { PARSE_ERROR("Content-Length"); }
+ break;
+
+ case 96:
+#line 417 "parser.yxx"
+ { PARSE_ERROR("Content-Type"); }
+ break;
+
+ case 97:
+#line 419 "parser.yxx"
+ { PARSE_ERROR("CSeq"); }
+ break;
+
+ case 98:
+#line 421 "parser.yxx"
+ { PARSE_ERROR("Date"); }
+ break;
+
+ case 99:
+#line 423 "parser.yxx"
+ { PARSE_ERROR("Error-Info"); }
+ break;
+
+ case 100:
+#line 425 "parser.yxx"
+ { PARSE_ERROR("Event"); }
+ break;
+
+ case 101:
+#line 427 "parser.yxx"
+ { PARSE_ERROR("Expires"); }
+ break;
+
+ case 102:
+#line 429 "parser.yxx"
+ { PARSE_ERROR("From"); }
+ break;
+
+ case 103:
+#line 431 "parser.yxx"
+ { PARSE_ERROR("In-Reply-To"); }
+ break;
+
+ case 104:
+#line 433 "parser.yxx"
+ { PARSE_ERROR("Max-Forwards"); }
+ break;
+
+ case 105:
+#line 435 "parser.yxx"
+ { PARSE_ERROR("Min-Expires"); }
+ break;
+
+ case 106:
+#line 437 "parser.yxx"
+ { PARSE_ERROR("MIME-Version"); }
+ break;
+
+ case 107:
+#line 439 "parser.yxx"
+ { PARSE_ERROR("Organization"); }
+ break;
+
+ case 108:
+#line 441 "parser.yxx"
+ { PARSE_ERROR("P-Asserted-Identity"); }
+ break;
+
+ case 109:
+#line 443 "parser.yxx"
+ { PARSE_ERROR("P-Preferred-Identity"); }
+ break;
+
+ case 110:
+#line 445 "parser.yxx"
+ { PARSE_ERROR("Priority"); }
+ break;
+
+ case 111:
+#line 447 "parser.yxx"
+ { PARSE_ERROR("Privacy"); }
+ break;
+
+ case 112:
+#line 449 "parser.yxx"
+ { PARSE_ERROR("Proxy-Authenticate"); }
+ break;
+
+ case 113:
+#line 451 "parser.yxx"
+ { PARSE_ERROR("Proxy-Authorization"); }
+ break;
+
+ case 114:
+#line 453 "parser.yxx"
+ { PARSE_ERROR("Proxy-Require"); }
+ break;
+
+ case 115:
+#line 455 "parser.yxx"
+ { PARSE_ERROR("RAck"); }
+ break;
+
+ case 116:
+#line 457 "parser.yxx"
+ { PARSE_ERROR("Record-Route"); }
+ break;
+
+ case 117:
+#line 459 "parser.yxx"
+ { PARSE_ERROR("Refer-Sub"); }
+ break;
+
+ case 118:
+#line 461 "parser.yxx"
+ { PARSE_ERROR("Refer-To"); }
+ break;
+
+ case 119:
+#line 463 "parser.yxx"
+ { PARSE_ERROR("Referred-By"); }
+ break;
+
+ case 120:
+#line 465 "parser.yxx"
+ { PARSE_ERROR("Replaces"); }
+ break;
+
+ case 121:
+#line 467 "parser.yxx"
+ { PARSE_ERROR("Reply-To"); }
+ break;
+
+ case 122:
+#line 469 "parser.yxx"
+ { PARSE_ERROR("Require"); }
+ break;
+
+ case 123:
+#line 471 "parser.yxx"
+ { PARSE_ERROR("Request-Disposition"); }
+ break;
+
+ case 124:
+#line 473 "parser.yxx"
+ { PARSE_ERROR("Retry-After"); }
+ break;
+
+ case 125:
+#line 475 "parser.yxx"
+ { PARSE_ERROR("Route"); }
+ break;
+
+ case 126:
+#line 477 "parser.yxx"
+ { PARSE_ERROR("RSeq"); }
+ break;
+
+ case 127:
+#line 479 "parser.yxx"
+ { PARSE_ERROR("Server"); }
+ break;
+
+ case 128:
+#line 481 "parser.yxx"
+ { PARSE_ERROR("Service-Route"); }
+ break;
+
+ case 129:
+#line 483 "parser.yxx"
+ { PARSE_ERROR("SIP-ETag"); }
+ break;
+
+ case 130:
+#line 485 "parser.yxx"
+ { PARSE_ERROR("SIP-If-Match"); }
+ break;
+
+ case 131:
+#line 487 "parser.yxx"
+ { PARSE_ERROR("Subject"); }
+ break;
+
+ case 132:
+#line 489 "parser.yxx"
+ { PARSE_ERROR("Subscription-State"); }
+ break;
+
+ case 133:
+#line 491 "parser.yxx"
+ { PARSE_ERROR("Supported"); }
+ break;
+
+ case 134:
+#line 493 "parser.yxx"
+ { PARSE_ERROR("Timestamp"); }
+ break;
+
+ case 135:
+#line 495 "parser.yxx"
+ { PARSE_ERROR("To"); }
+ break;
+
+ case 136:
+#line 497 "parser.yxx"
+ { PARSE_ERROR("Unsupported"); }
+ break;
+
+ case 137:
+#line 499 "parser.yxx"
+ { PARSE_ERROR("User-Agent"); }
+ break;
+
+ case 138:
+#line 501 "parser.yxx"
+ { PARSE_ERROR("Via"); }
+ break;
+
+ case 139:
+#line 503 "parser.yxx"
+ { PARSE_ERROR("Warning"); }
+ break;
+
+ case 140:
+#line 505 "parser.yxx"
+ { PARSE_ERROR("WWW-Authenticate"); }
+ break;
+
+ case 143:
+#line 521 "parser.yxx"
+ { CTXT_LANG; }
+ break;
+
+ case 148:
+#line 531 "parser.yxx"
+ { CTXT_AUTH_SCHEME; }
+ break;
+
+ case 149:
+#line 533 "parser.yxx"
+ { CTXT_WORD; }
+ break;
+
+ case 151:
+#line 537 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 154:
+#line 543 "parser.yxx"
+ { CTXT_LANG; }
+ break;
+
+ case 155:
+#line 545 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 157:
+#line 549 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 158:
+#line 551 "parser.yxx"
+ { CTXT_DATE;}
+ break;
+
+ case 161:
+#line 557 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 162:
+#line 559 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 163:
+#line 561 "parser.yxx"
+ { CTXT_WORD; }
+ break;
+
+ case 164:
+#line 563 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 165:
+#line 565 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 167:
+#line 569 "parser.yxx"
+ { CTXT_LINE; }
+ break;
+
+ case 168:
+#line 571 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 169:
+#line 573 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 172:
+#line 579 "parser.yxx"
+ { CTXT_AUTH_SCHEME; }
+ break;
+
+ case 173:
+#line 581 "parser.yxx"
+ { CTXT_AUTH_SCHEME; }
+ break;
+
+ case 175:
+#line 585 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 176:
+#line 587 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 178:
+#line 591 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 179:
+#line 593 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 180:
+#line 595 "parser.yxx"
+ { CTXT_WORD; }
+ break;
+
+ case 181:
+#line 597 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 184:
+#line 603 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 185:
+#line 605 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 186:
+#line 607 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 188:
+#line 611 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 191:
+#line 617 "parser.yxx"
+ { CTXT_LINE; }
+ break;
+
+ case 194:
+#line 623 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 195:
+#line 625 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 199:
+#line 633 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 200:
+#line 635 "parser.yxx"
+ { CTXT_AUTH_SCHEME; }
+ break;
+
+ case 202:
+#line 639 "parser.yxx"
+ {
+ (yyvsp[(1) - (2)].yyt_media)->add_params(*(yyvsp[(2) - (2)].yyt_params));
+ MSG->hdr_accept.add_media(*(yyvsp[(1) - (2)].yyt_media));
+ MEMMAN_DELETE((yyvsp[(1) - (2)].yyt_media)); delete (yyvsp[(1) - (2)].yyt_media);
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_params)); delete (yyvsp[(2) - (2)].yyt_params); }
+ break;
+
+ case 203:
+#line 644 "parser.yxx"
+ {
+ (yyvsp[(3) - (4)].yyt_media)->add_params(*(yyvsp[(4) - (4)].yyt_params));
+ MSG->hdr_accept.add_media(*(yyvsp[(3) - (4)].yyt_media));
+ MEMMAN_DELETE((yyvsp[(3) - (4)].yyt_media)); delete (yyvsp[(3) - (4)].yyt_media);
+ MEMMAN_DELETE((yyvsp[(4) - (4)].yyt_params)); delete (yyvsp[(4) - (4)].yyt_params); }
+ break;
+
+ case 204:
+#line 651 "parser.yxx"
+ { (yyval.yyt_media) = new t_media(tolower(*(yyvsp[(1) - (3)].yyt_str)), tolower(*(yyvsp[(3) - (3)].yyt_str)));
+ MEMMAN_NEW((yyval.yyt_media));
+ MEMMAN_DELETE((yyvsp[(1) - (3)].yyt_str)); delete (yyvsp[(1) - (3)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+ case 205:
+#line 657 "parser.yxx"
+ { (yyval.yyt_params) = new list<t_parameter>; MEMMAN_NEW((yyval.yyt_params)); }
+ break;
+
+ case 206:
+#line 658 "parser.yxx"
+ {
+ (yyvsp[(1) - (3)].yyt_params)->push_back(*(yyvsp[(3) - (3)].yyt_param));
+ (yyval.yyt_params) = (yyvsp[(1) - (3)].yyt_params);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_param)); delete (yyvsp[(3) - (3)].yyt_param); }
+ break;
+
+ case 207:
+#line 664 "parser.yxx"
+ {
+ (yyval.yyt_param) = new t_parameter(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_NEW((yyval.yyt_param));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 208:
+#line 668 "parser.yxx"
+ { CTXT_PARAMVAL; }
+ break;
+
+ case 209:
+#line 668 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 210:
+#line 668 "parser.yxx"
+ {
+ (yyval.yyt_param) = new t_parameter(tolower(*(yyvsp[(1) - (5)].yyt_str)), *(yyvsp[(4) - (5)].yyt_str));
+ MEMMAN_NEW((yyval.yyt_param));
+ MEMMAN_DELETE((yyvsp[(1) - (5)].yyt_str)); delete (yyvsp[(1) - (5)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(4) - (5)].yyt_str)); delete (yyvsp[(4) - (5)].yyt_str); }
+ break;
+
+ case 211:
+#line 675 "parser.yxx"
+ {
+ (yyval.yyt_str) = (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 212:
+#line 677 "parser.yxx"
+ {
+ (yyval.yyt_str) = (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 213:
+#line 681 "parser.yxx"
+ {
+ MSG->hdr_accept_encoding.add_coding(*(yyvsp[(1) - (1)].yyt_coding));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_coding)); delete (yyvsp[(1) - (1)].yyt_coding); }
+ break;
+
+ case 214:
+#line 684 "parser.yxx"
+ {
+ MSG->hdr_accept_encoding.add_coding(*(yyvsp[(3) - (3)].yyt_coding));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_coding)); delete (yyvsp[(3) - (3)].yyt_coding); }
+ break;
+
+ case 215:
+#line 689 "parser.yxx"
+ {
+ (yyval.yyt_coding) = new t_coding(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_NEW((yyval.yyt_coding));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 216:
+#line 693 "parser.yxx"
+ {
+ (yyval.yyt_coding) = new t_coding(tolower(*(yyvsp[(1) - (2)].yyt_str)));
+ MEMMAN_NEW((yyval.yyt_coding));
+ (yyval.yyt_coding)->q = (yyvsp[(2) - (2)].yyt_float);
+ MEMMAN_DELETE((yyvsp[(1) - (2)].yyt_str)); delete (yyvsp[(1) - (2)].yyt_str); }
+ break;
+
+ case 217:
+#line 700 "parser.yxx"
+ {
+ if ((yyvsp[(2) - (2)].yyt_param)->name != "q") YYERROR;
+ (yyval.yyt_float) = atof((yyvsp[(2) - (2)].yyt_param)->value.c_str());
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_param)); delete (yyvsp[(2) - (2)].yyt_param);
+ }
+ break;
+
+ case 218:
+#line 707 "parser.yxx"
+ { CTXT_LANG; }
+ break;
+
+ case 219:
+#line 707 "parser.yxx"
+ {
+ MSG->hdr_accept_language.add_language(*(yyvsp[(2) - (2)].yyt_language));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_language)); delete (yyvsp[(2) - (2)].yyt_language); }
+ break;
+
+ case 220:
+#line 710 "parser.yxx"
+ { CTXT_LANG; }
+ break;
+
+ case 221:
+#line 710 "parser.yxx"
+ {
+ MSG->hdr_accept_language.add_language(*(yyvsp[(4) - (4)].yyt_language));
+ MEMMAN_DELETE((yyvsp[(4) - (4)].yyt_language)); delete (yyvsp[(4) - (4)].yyt_language); }
+ break;
+
+ case 222:
+#line 715 "parser.yxx"
+ {
+ CTXT_INITIAL;
+ (yyval.yyt_language) = new t_language(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_NEW((yyval.yyt_language));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 223:
+#line 720 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 224:
+#line 720 "parser.yxx"
+ {
+ (yyval.yyt_language) = new t_language(tolower(*(yyvsp[(1) - (3)].yyt_str)));
+ MEMMAN_NEW((yyval.yyt_language));
+ (yyval.yyt_language)->q = (yyvsp[(3) - (3)].yyt_float);
+ MEMMAN_DELETE((yyvsp[(1) - (3)].yyt_str)); delete (yyvsp[(1) - (3)].yyt_str); }
+ break;
+
+ case 225:
+#line 727 "parser.yxx"
+ {
+ MSG->hdr_alert_info.add_param(*(yyvsp[(1) - (1)].yyt_alert_param));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_alert_param)); delete (yyvsp[(1) - (1)].yyt_alert_param); }
+ break;
+
+ case 226:
+#line 730 "parser.yxx"
+ {
+ MSG->hdr_alert_info.add_param(*(yyvsp[(3) - (3)].yyt_alert_param));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_alert_param)); delete (yyvsp[(3) - (3)].yyt_alert_param); }
+ break;
+
+ case 227:
+#line 735 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 228:
+#line 735 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 229:
+#line 735 "parser.yxx"
+ {
+ (yyval.yyt_alert_param) = new t_alert_param();
+ MEMMAN_NEW((yyval.yyt_alert_param));
+ (yyval.yyt_alert_param)->uri.set_url(*(yyvsp[(3) - (6)].yyt_str));
+ (yyval.yyt_alert_param)->parameter_list = *(yyvsp[(6) - (6)].yyt_params);
+
+ if (!(yyval.yyt_alert_param)->uri.is_valid()) {
+ MEMMAN_DELETE((yyval.yyt_alert_param)); delete (yyval.yyt_alert_param);
+ YYERROR;
+ }
+
+ MEMMAN_DELETE((yyvsp[(3) - (6)].yyt_str)); delete (yyvsp[(3) - (6)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(6) - (6)].yyt_params)); delete (yyvsp[(6) - (6)].yyt_params); }
+ break;
+
+ case 230:
+#line 750 "parser.yxx"
+ {
+ MSG->hdr_allow.add_method(*(yyvsp[(1) - (1)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 231:
+#line 753 "parser.yxx"
+ {
+ MSG->hdr_allow.add_method(*(yyvsp[(3) - (3)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+ case 232:
+#line 758 "parser.yxx"
+ { CTXT_WORD; }
+ break;
+
+ case 233:
+#line 758 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 234:
+#line 758 "parser.yxx"
+ {
+ MSG->hdr_call_id.set_call_id(*(yyvsp[(2) - (3)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_str)); delete (yyvsp[(2) - (3)].yyt_str); }
+ break;
+
+ case 235:
+#line 763 "parser.yxx"
+ { (yyval.yyt_str) = (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 236:
+#line 764 "parser.yxx"
+ {
+ (yyval.yyt_str) = new string(*(yyvsp[(1) - (3)].yyt_str) + '@' + *(yyvsp[(3) - (3)].yyt_str));
+ MEMMAN_NEW((yyval.yyt_str));
+ MEMMAN_DELETE((yyvsp[(1) - (3)].yyt_str)); delete (yyvsp[(1) - (3)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+ case 237:
+#line 771 "parser.yxx"
+ {
+ MSG->hdr_call_info.add_param(*(yyvsp[(1) - (1)].yyt_info_param));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_info_param)); delete (yyvsp[(1) - (1)].yyt_info_param); }
+ break;
+
+ case 238:
+#line 774 "parser.yxx"
+ {
+ MSG->hdr_call_info.add_param(*(yyvsp[(3) - (3)].yyt_info_param));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_info_param)); delete (yyvsp[(3) - (3)].yyt_info_param); }
+ break;
+
+ case 239:
+#line 779 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 240:
+#line 779 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 241:
+#line 779 "parser.yxx"
+ {
+ (yyval.yyt_info_param) = new t_info_param();
+ MEMMAN_NEW((yyval.yyt_info_param));
+ (yyval.yyt_info_param)->uri.set_url(*(yyvsp[(3) - (6)].yyt_str));
+ (yyval.yyt_info_param)->parameter_list = *(yyvsp[(6) - (6)].yyt_params);
+
+ if (!(yyval.yyt_info_param)->uri.is_valid()) {
+ MEMMAN_DELETE((yyval.yyt_info_param)); delete (yyval.yyt_info_param);
+ YYERROR;
+ }
+
+ MEMMAN_DELETE((yyvsp[(3) - (6)].yyt_str)); delete (yyvsp[(3) - (6)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(6) - (6)].yyt_params)); delete (yyvsp[(6) - (6)].yyt_params); }
+ break;
+
+ case 242:
+#line 794 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 243:
+#line 794 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 244:
+#line 794 "parser.yxx"
+ {
+ MSG->hdr_contact.set_any(); }
+ break;
+
+ case 245:
+#line 796 "parser.yxx"
+ {
+ MSG->hdr_contact.add_contacts(*(yyvsp[(1) - (1)].yyt_contacts));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_contacts)); delete (yyvsp[(1) - (1)].yyt_contacts); }
+ break;
+
+ case 246:
+#line 801 "parser.yxx"
+ {
+ (yyval.yyt_contacts) = new list<t_contact_param>;
+ MEMMAN_NEW((yyval.yyt_contacts));
+ (yyval.yyt_contacts)->push_back(*(yyvsp[(1) - (1)].yyt_contact));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_contact)); delete (yyvsp[(1) - (1)].yyt_contact); }
+ break;
+
+ case 247:
+#line 806 "parser.yxx"
+ {
+ (yyvsp[(1) - (3)].yyt_contacts)->push_back(*(yyvsp[(3) - (3)].yyt_contact));
+ (yyval.yyt_contacts) = (yyvsp[(1) - (3)].yyt_contacts);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_contact)); delete (yyvsp[(3) - (3)].yyt_contact); }
+ break;
+
+ case 248:
+#line 812 "parser.yxx"
+ {
+ (yyval.yyt_contact) = (yyvsp[(1) - (2)].yyt_contact);
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(2) - (2)].yyt_params)->begin(); i != (yyvsp[(2) - (2)].yyt_params)->end(); i++) {
+ if (i->name == "q") {
+ (yyval.yyt_contact)->set_qvalue(atof(i->value.c_str()));
+ } else if (i->name == "expires") {
+ (yyval.yyt_contact)->set_expires(strtoul(
+ i->value.c_str(), NULL, 10));
+ } else {
+ (yyval.yyt_contact)->add_extension(*i);
+ }
+ }
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_params)); delete (yyvsp[(2) - (2)].yyt_params); }
+ break;
+
+ case 249:
+#line 828 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 250:
+#line 828 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 251:
+#line 828 "parser.yxx"
+ {
+ (yyval.yyt_contact) = new t_contact_param();
+ MEMMAN_NEW((yyval.yyt_contact));
+ (yyval.yyt_contact)->uri.set_url(*(yyvsp[(2) - (3)].yyt_str));
+
+ if (!(yyval.yyt_contact)->uri.is_valid()) {
+ MEMMAN_DELETE((yyval.yyt_contact)); delete (yyval.yyt_contact);
+ YYERROR;
+ }
+
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_str)); delete (yyvsp[(2) - (3)].yyt_str); }
+ break;
+
+ case 252:
+#line 839 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 253:
+#line 839 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 254:
+#line 839 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 255:
+#line 839 "parser.yxx"
+ {
+ (yyval.yyt_contact) = new t_contact_param();
+ MEMMAN_NEW((yyval.yyt_contact));
+ (yyval.yyt_contact)->display = *(yyvsp[(2) - (7)].yyt_str);
+ (yyval.yyt_contact)->uri.set_url(*(yyvsp[(5) - (7)].yyt_str));
+
+ if (!(yyval.yyt_contact)->uri.is_valid()) {
+ MEMMAN_DELETE((yyval.yyt_contact)); delete (yyval.yyt_contact);
+ YYERROR;
+ }
+
+ MEMMAN_DELETE((yyvsp[(2) - (7)].yyt_str)); delete (yyvsp[(2) - (7)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(5) - (7)].yyt_str)); delete (yyvsp[(5) - (7)].yyt_str); }
+ break;
+
+ case 256:
+#line 854 "parser.yxx"
+ { (yyval.yyt_str) = new string(); MEMMAN_NEW((yyval.yyt_str)); }
+ break;
+
+ case 257:
+#line 855 "parser.yxx"
+ {
+ (yyval.yyt_str) = new string(rtrim(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_NEW((yyval.yyt_str));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 258:
+#line 859 "parser.yxx"
+ { (yyval.yyt_str) = (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 259:
+#line 862 "parser.yxx"
+ {
+ MSG->hdr_content_disp.set_type(tolower(*(yyvsp[(1) - (2)].yyt_str)));
+
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(2) - (2)].yyt_params)->begin(); i != (yyvsp[(2) - (2)].yyt_params)->end(); i++) {
+ if (i->name == "filename") {
+ MSG->hdr_content_disp.set_filename(i->value);
+ } else {
+ MSG->hdr_content_disp.add_param(*i);
+ }
+ }
+
+ MEMMAN_DELETE((yyvsp[(1) - (2)].yyt_str)); delete (yyvsp[(1) - (2)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_params)); delete (yyvsp[(2) - (2)].yyt_params); }
+ break;
+
+ case 260:
+#line 878 "parser.yxx"
+ {
+ MSG->hdr_content_encoding.add_coding(*(yyvsp[(1) - (1)].yyt_coding));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_coding)); delete (yyvsp[(1) - (1)].yyt_coding); }
+ break;
+
+ case 261:
+#line 881 "parser.yxx"
+ {
+ MSG->hdr_content_encoding.add_coding(*(yyvsp[(3) - (3)].yyt_coding));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_coding)); delete (yyvsp[(3) - (3)].yyt_coding); }
+ break;
+
+ case 262:
+#line 886 "parser.yxx"
+ { CTXT_LANG; }
+ break;
+
+ case 263:
+#line 886 "parser.yxx"
+ {
+ MSG->hdr_content_language.add_language(*(yyvsp[(2) - (2)].yyt_language));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_language)); delete (yyvsp[(2) - (2)].yyt_language); }
+ break;
+
+ case 264:
+#line 889 "parser.yxx"
+ { CTXT_LANG; }
+ break;
+
+ case 265:
+#line 889 "parser.yxx"
+ {
+ MSG->hdr_content_language.add_language(*(yyvsp[(4) - (4)].yyt_language));
+ MEMMAN_DELETE((yyvsp[(4) - (4)].yyt_language)); delete (yyvsp[(4) - (4)].yyt_language); }
+ break;
+
+ case 266:
+#line 894 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 267:
+#line 894 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 268:
+#line 894 "parser.yxx"
+ {
+ MSG->hdr_content_length.set_length((yyvsp[(2) - (3)].yyt_ulong)); }
+ break;
+
+ case 269:
+#line 898 "parser.yxx"
+ {
+ (yyvsp[(1) - (2)].yyt_media)->add_params(*(yyvsp[(2) - (2)].yyt_params));
+ MSG->hdr_content_type.set_media(*(yyvsp[(1) - (2)].yyt_media));
+ MEMMAN_DELETE((yyvsp[(1) - (2)].yyt_media)); delete (yyvsp[(1) - (2)].yyt_media);
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_params)); delete (yyvsp[(2) - (2)].yyt_params); }
+ break;
+
+ case 270:
+#line 905 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 271:
+#line 905 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 272:
+#line 905 "parser.yxx"
+ {
+ MSG->hdr_cseq.set_seqnr((yyvsp[(2) - (4)].yyt_ulong));
+ MSG->hdr_cseq.set_method(*(yyvsp[(4) - (4)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(4) - (4)].yyt_str)); delete (yyvsp[(4) - (4)].yyt_str); }
+ break;
+
+ case 273:
+#line 911 "parser.yxx"
+ { CTXT_DATE;}
+ break;
+
+ case 274:
+#line 914 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 275:
+#line 914 "parser.yxx"
+ {
+ struct tm t;
+ t.tm_mday = (yyvsp[(4) - (13)].yyt_ulong);
+ t.tm_mon = (yyvsp[(5) - (13)].yyt_int);
+ t.tm_year = (yyvsp[(6) - (13)].yyt_ulong) - 1900;
+ t.tm_hour = (yyvsp[(7) - (13)].yyt_ulong);
+ t.tm_min = (yyvsp[(9) - (13)].yyt_ulong);
+ t.tm_sec = (yyvsp[(11) - (13)].yyt_ulong);
+ MSG->hdr_date.set_date_gm(&t); }
+ break;
+
+ case 276:
+#line 925 "parser.yxx"
+ {
+ MSG->hdr_error_info.add_param(*(yyvsp[(1) - (1)].yyt_error_param));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_error_param)); delete (yyvsp[(1) - (1)].yyt_error_param); }
+ break;
+
+ case 277:
+#line 928 "parser.yxx"
+ {
+ MSG->hdr_error_info.add_param(*(yyvsp[(3) - (3)].yyt_error_param));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_error_param)); delete (yyvsp[(3) - (3)].yyt_error_param); }
+ break;
+
+ case 278:
+#line 933 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 279:
+#line 933 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 280:
+#line 933 "parser.yxx"
+ {
+ (yyval.yyt_error_param) = new t_error_param();
+ MEMMAN_NEW((yyval.yyt_error_param));
+ (yyval.yyt_error_param)->uri.set_url(*(yyvsp[(3) - (6)].yyt_str));
+ (yyval.yyt_error_param)->parameter_list = *(yyvsp[(6) - (6)].yyt_params);
+
+ if (!(yyval.yyt_error_param)->uri.is_valid()) {
+ MEMMAN_DELETE((yyval.yyt_error_param)); delete (yyval.yyt_error_param);
+ YYERROR;
+ }
+
+ MEMMAN_DELETE((yyvsp[(3) - (6)].yyt_str)); delete (yyvsp[(3) - (6)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(6) - (6)].yyt_params)); delete (yyvsp[(6) - (6)].yyt_params); }
+ break;
+
+ case 281:
+#line 948 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 282:
+#line 948 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 283:
+#line 948 "parser.yxx"
+ {
+ MSG->hdr_expires.set_time((yyvsp[(2) - (3)].yyt_ulong)); }
+ break;
+
+ case 284:
+#line 952 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 285:
+#line 952 "parser.yxx"
+ {
+ MSG->hdr_from.set_display((yyvsp[(2) - (3)].yyt_from_addr)->display);
+ MSG->hdr_from.set_uri((yyvsp[(2) - (3)].yyt_from_addr)->uri);
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(3) - (3)].yyt_params)->begin(); i != (yyvsp[(3) - (3)].yyt_params)->end(); i++) {
+ if (i->name == "tag") {
+ MSG->hdr_from.set_tag(i->value);
+ } else {
+ MSG->hdr_from.add_param(*i);
+ }
+ }
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_from_addr)); delete (yyvsp[(2) - (3)].yyt_from_addr);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_params)); delete (yyvsp[(3) - (3)].yyt_params); }
+ break;
+
+ case 286:
+#line 967 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 287:
+#line 967 "parser.yxx"
+ {
+ (yyval.yyt_from_addr) = new t_identity();
+ MEMMAN_NEW((yyval.yyt_from_addr));
+ (yyval.yyt_from_addr)->set_uri(*(yyvsp[(1) - (2)].yyt_str));
+
+ if (!(yyval.yyt_from_addr)->uri.is_valid()) {
+ MEMMAN_DELETE((yyval.yyt_from_addr)); delete (yyval.yyt_from_addr);
+ YYERROR;
+ }
+
+ MEMMAN_DELETE((yyvsp[(1) - (2)].yyt_str)); delete (yyvsp[(1) - (2)].yyt_str); }
+ break;
+
+ case 288:
+#line 978 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 289:
+#line 978 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 290:
+#line 978 "parser.yxx"
+ {
+ (yyval.yyt_from_addr) = new t_identity();
+ MEMMAN_NEW((yyval.yyt_from_addr));
+ (yyval.yyt_from_addr)->set_display(*(yyvsp[(1) - (6)].yyt_str));
+ (yyval.yyt_from_addr)->set_uri(*(yyvsp[(4) - (6)].yyt_str));
+
+ if (!(yyval.yyt_from_addr)->uri.is_valid()) {
+ MEMMAN_DELETE((yyval.yyt_from_addr)); delete (yyval.yyt_from_addr);
+ YYERROR;
+ }
+
+ MEMMAN_DELETE((yyvsp[(1) - (6)].yyt_str)); delete (yyvsp[(1) - (6)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(4) - (6)].yyt_str)); delete (yyvsp[(4) - (6)].yyt_str); }
+ break;
+
+ case 291:
+#line 993 "parser.yxx"
+ { CTXT_WORD; }
+ break;
+
+ case 292:
+#line 993 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 293:
+#line 993 "parser.yxx"
+ {
+ MSG->hdr_in_reply_to.add_call_id(*(yyvsp[(2) - (3)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_str)); delete (yyvsp[(2) - (3)].yyt_str); }
+ break;
+
+ case 294:
+#line 996 "parser.yxx"
+ { CTXT_WORD; }
+ break;
+
+ case 295:
+#line 996 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 296:
+#line 996 "parser.yxx"
+ {
+ MSG->hdr_in_reply_to.add_call_id(*(yyvsp[(4) - (5)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(4) - (5)].yyt_str)); delete (yyvsp[(4) - (5)].yyt_str); }
+ break;
+
+ case 297:
+#line 1001 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 298:
+#line 1001 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 299:
+#line 1001 "parser.yxx"
+ {
+ MSG->hdr_max_forwards.set_max_forwards((yyvsp[(2) - (3)].yyt_ulong)); }
+ break;
+
+ case 300:
+#line 1005 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 301:
+#line 1005 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 302:
+#line 1005 "parser.yxx"
+ {
+ MSG->hdr_min_expires.set_time((yyvsp[(2) - (3)].yyt_ulong)); }
+ break;
+
+ case 303:
+#line 1009 "parser.yxx"
+ {
+ MSG->hdr_mime_version.set_version(*(yyvsp[(1) - (1)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 304:
+#line 1014 "parser.yxx"
+ { CTXT_LINE; }
+ break;
+
+ case 305:
+#line 1014 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 306:
+#line 1014 "parser.yxx"
+ {
+ MSG->hdr_organization.set_name(trim(*(yyvsp[(2) - (3)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_str)); delete (yyvsp[(2) - (3)].yyt_str); }
+ break;
+
+ case 307:
+#line 1019 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 308:
+#line 1019 "parser.yxx"
+ {
+ MSG->hdr_p_asserted_identity.add_identity(*(yyvsp[(2) - (2)].yyt_from_addr));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_from_addr)); delete (yyvsp[(2) - (2)].yyt_from_addr); }
+ break;
+
+ case 309:
+#line 1022 "parser.yxx"
+ {
+ MSG->hdr_p_asserted_identity.add_identity(*(yyvsp[(3) - (3)].yyt_from_addr));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_from_addr)); delete (yyvsp[(3) - (3)].yyt_from_addr); }
+ break;
+
+ case 310:
+#line 1027 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 311:
+#line 1027 "parser.yxx"
+ {
+ MSG->hdr_p_preferred_identity.add_identity(*(yyvsp[(2) - (2)].yyt_from_addr));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_from_addr)); delete (yyvsp[(2) - (2)].yyt_from_addr); }
+ break;
+
+ case 312:
+#line 1030 "parser.yxx"
+ {
+ MSG->hdr_p_preferred_identity.add_identity(*(yyvsp[(3) - (3)].yyt_from_addr));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_from_addr)); delete (yyvsp[(3) - (3)].yyt_from_addr); }
+ break;
+
+ case 313:
+#line 1035 "parser.yxx"
+ {
+ MSG->hdr_priority.set_priority(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 314:
+#line 1040 "parser.yxx"
+ {
+ MSG->hdr_privacy.add_privacy(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 315:
+#line 1043 "parser.yxx"
+ {
+ MSG->hdr_privacy.add_privacy(tolower(*(yyvsp[(3) - (3)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+ case 316:
+#line 1048 "parser.yxx"
+ {
+ MSG->hdr_proxy_require.add_feature(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 317:
+#line 1051 "parser.yxx"
+ {
+ MSG->hdr_proxy_require.add_feature(tolower(*(yyvsp[(3) - (3)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+ case 318:
+#line 1056 "parser.yxx"
+ {
+ MSG->hdr_record_route.add_route(*(yyvsp[(1) - (1)].yyt_route));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_route)); delete (yyvsp[(1) - (1)].yyt_route); }
+ break;
+
+ case 319:
+#line 1059 "parser.yxx"
+ {
+ MSG->hdr_record_route.add_route(*(yyvsp[(3) - (3)].yyt_route));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_route)); delete (yyvsp[(3) - (3)].yyt_route); }
+ break;
+
+ case 320:
+#line 1064 "parser.yxx"
+ { CTXT_URI; }
+ break;
+
+ case 321:
+#line 1064 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 322:
+#line 1065 "parser.yxx"
+ {
+ (yyval.yyt_route) = new t_route;
+ MEMMAN_NEW((yyval.yyt_route));
+ (yyval.yyt_route)->display = *(yyvsp[(2) - (7)].yyt_str);
+ (yyval.yyt_route)->uri.set_url(*(yyvsp[(4) - (7)].yyt_str));
+ (yyval.yyt_route)->set_params(*(yyvsp[(7) - (7)].yyt_params));
+
+ if (!(yyval.yyt_route)->uri.is_valid()) {
+ MEMMAN_DELETE((yyval.yyt_route)); delete (yyval.yyt_route);
+ YYERROR;
+ }
+
+ MEMMAN_DELETE((yyvsp[(2) - (7)].yyt_str)); delete (yyvsp[(2) - (7)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(4) - (7)].yyt_str)); delete (yyvsp[(4) - (7)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(7) - (7)].yyt_params)); delete (yyvsp[(7) - (7)].yyt_params); }
+ break;
+
+ case 323:
+#line 1082 "parser.yxx"
+ {
+ MSG->hdr_service_route.add_route(*(yyvsp[(1) - (1)].yyt_route));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_route)); delete (yyvsp[(1) - (1)].yyt_route); }
+ break;
+
+ case 324:
+#line 1085 "parser.yxx"
+ {
+ MSG->hdr_service_route.add_route(*(yyvsp[(3) - (3)].yyt_route));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_route)); delete (yyvsp[(3) - (3)].yyt_route); }
+ break;
+
+ case 325:
+#line 1090 "parser.yxx"
+ { CTXT_WORD; }
+ break;
+
+ case 326:
+#line 1090 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 327:
+#line 1090 "parser.yxx"
+ {
+ MSG->hdr_replaces.set_call_id(*(yyvsp[(2) - (4)].yyt_str));
+
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(4) - (4)].yyt_params)->begin(); i != (yyvsp[(4) - (4)].yyt_params)->end(); i++) {
+ if (i->name == "to-tag") {
+ MSG->hdr_replaces.set_to_tag(i->value);
+ } else if (i->name == "from-tag") {
+ MSG->hdr_replaces.set_from_tag(i->value);
+ } else if (i->name == "early-only") {
+ MSG->hdr_replaces.set_early_only(true);
+ } else {
+ MSG->hdr_replaces.add_param(*i);
+ }
+ }
+
+ if (!MSG->hdr_replaces.is_valid()) YYERROR;
+
+ MEMMAN_DELETE((yyvsp[(2) - (4)].yyt_str)); delete (yyvsp[(2) - (4)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(4) - (4)].yyt_params)); delete (yyvsp[(4) - (4)].yyt_params); }
+ break;
+
+ case 328:
+#line 1112 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 329:
+#line 1112 "parser.yxx"
+ {
+ MSG->hdr_reply_to.set_display((yyvsp[(2) - (3)].yyt_from_addr)->display);
+ MSG->hdr_reply_to.set_uri((yyvsp[(2) - (3)].yyt_from_addr)->uri);
+ MSG->hdr_reply_to.set_params(*(yyvsp[(3) - (3)].yyt_params));
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_from_addr)); delete (yyvsp[(2) - (3)].yyt_from_addr);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_params)); delete (yyvsp[(3) - (3)].yyt_params); }
+ break;
+
+ case 330:
+#line 1120 "parser.yxx"
+ {
+ MSG->hdr_require.add_feature(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 331:
+#line 1123 "parser.yxx"
+ {
+ MSG->hdr_require.add_feature(tolower(*(yyvsp[(3) - (3)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+ case 332:
+#line 1128 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 333:
+#line 1128 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 334:
+#line 1128 "parser.yxx"
+ {
+ MSG->hdr_retry_after.set_time((yyvsp[(2) - (5)].yyt_ulong));
+ MSG->hdr_retry_after.set_comment(*(yyvsp[(4) - (5)].yyt_str));
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(5) - (5)].yyt_params)->begin(); i != (yyvsp[(5) - (5)].yyt_params)->end(); i++) {
+ if (i->name == "duration") {
+ int d = strtoul(i->value.c_str(), NULL, 10);
+ MSG->hdr_retry_after.set_duration(d);
+ } else {
+ MSG->hdr_retry_after.add_param(*i);
+ }
+ }
+ MEMMAN_DELETE((yyvsp[(4) - (5)].yyt_str)); delete (yyvsp[(4) - (5)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(5) - (5)].yyt_params)); delete (yyvsp[(5) - (5)].yyt_params); }
+ break;
+
+ case 335:
+#line 1144 "parser.yxx"
+ { (yyval.yyt_str) = new string(); MEMMAN_NEW((yyval.yyt_str)); }
+ break;
+
+ case 336:
+#line 1145 "parser.yxx"
+ { CTXT_COMMENT; }
+ break;
+
+ case 337:
+#line 1145 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 338:
+#line 1145 "parser.yxx"
+ {
+ (yyval.yyt_str) = (yyvsp[(3) - (5)].yyt_str); }
+ break;
+
+ case 339:
+#line 1149 "parser.yxx"
+ {
+ MSG->hdr_route.add_route(*(yyvsp[(1) - (1)].yyt_route));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_route)); delete (yyvsp[(1) - (1)].yyt_route); }
+ break;
+
+ case 340:
+#line 1152 "parser.yxx"
+ {
+ MSG->hdr_route.add_route(*(yyvsp[(3) - (3)].yyt_route));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_route)); delete (yyvsp[(3) - (3)].yyt_route); }
+ break;
+
+ case 341:
+#line 1157 "parser.yxx"
+ {
+ MSG->hdr_server.add_server(*(yyvsp[(1) - (1)].yyt_server));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_server)); delete (yyvsp[(1) - (1)].yyt_server); }
+ break;
+
+ case 342:
+#line 1160 "parser.yxx"
+ {
+ MSG->hdr_server.add_server(*(yyvsp[(2) - (2)].yyt_server));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_server)); delete (yyvsp[(2) - (2)].yyt_server); }
+ break;
+
+ case 343:
+#line 1165 "parser.yxx"
+ {
+ (yyval.yyt_server) = new t_server();
+ MEMMAN_NEW((yyval.yyt_server));
+ (yyval.yyt_server)->comment = *(yyvsp[(1) - (1)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 344:
+#line 1170 "parser.yxx"
+ {
+ (yyval.yyt_server) = new t_server();
+ MEMMAN_NEW((yyval.yyt_server));
+ (yyval.yyt_server)->product = *(yyvsp[(1) - (2)].yyt_str);
+ (yyval.yyt_server)->comment = *(yyvsp[(2) - (2)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(1) - (2)].yyt_str)); delete (yyvsp[(1) - (2)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_str)); delete (yyvsp[(2) - (2)].yyt_str); }
+ break;
+
+ case 345:
+#line 1177 "parser.yxx"
+ {
+ (yyval.yyt_server) = new t_server();
+ MEMMAN_NEW((yyval.yyt_server));
+ (yyval.yyt_server)->product = *(yyvsp[(1) - (4)].yyt_str);
+ (yyval.yyt_server)->version = *(yyvsp[(3) - (4)].yyt_str);
+ (yyval.yyt_server)->comment = *(yyvsp[(4) - (4)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(1) - (4)].yyt_str)); delete (yyvsp[(1) - (4)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(3) - (4)].yyt_str)); delete (yyvsp[(3) - (4)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(4) - (4)].yyt_str)); delete (yyvsp[(4) - (4)].yyt_str); }
+ break;
+
+ case 346:
+#line 1188 "parser.yxx"
+ { CTXT_LINE; }
+ break;
+
+ case 347:
+#line 1188 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 348:
+#line 1188 "parser.yxx"
+ {
+ MSG->hdr_subject.set_subject(trim(*(yyvsp[(2) - (3)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_str)); delete (yyvsp[(2) - (3)].yyt_str); }
+ break;
+
+ case 349:
+#line 1193 "parser.yxx"
+ {
+ MSG->hdr_supported.set_empty(); }
+ break;
+
+ case 350:
+#line 1195 "parser.yxx"
+ {
+ MSG->hdr_supported.add_feature(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 351:
+#line 1198 "parser.yxx"
+ {
+ MSG->hdr_supported.add_feature(tolower(*(yyvsp[(3) - (3)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+ case 352:
+#line 1203 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 353:
+#line 1203 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 354:
+#line 1206 "parser.yxx"
+ {
+ MSG->hdr_timestamp.set_timestamp((yyvsp[(1) - (1)].yyt_float)); }
+ break;
+
+ case 355:
+#line 1208 "parser.yxx"
+ {
+ MSG->hdr_timestamp.set_timestamp((yyvsp[(1) - (2)].yyt_float));
+ MSG->hdr_timestamp.set_delay((yyvsp[(2) - (2)].yyt_float)); }
+ break;
+
+ case 356:
+#line 1213 "parser.yxx"
+ { (yyval.yyt_float) = (yyvsp[(1) - (1)].yyt_ulong); }
+ break;
+
+ case 357:
+#line 1214 "parser.yxx"
+ {
+ string s = int2str((yyvsp[(1) - (3)].yyt_ulong)) + '.' + int2str((yyvsp[(3) - (3)].yyt_ulong));
+ (yyval.yyt_float) = atof(s.c_str()); }
+ break;
+
+ case 358:
+#line 1219 "parser.yxx"
+ { (yyval.yyt_float) = (yyvsp[(1) - (1)].yyt_ulong); }
+ break;
+
+ case 359:
+#line 1220 "parser.yxx"
+ {
+ string s = int2str((yyvsp[(1) - (3)].yyt_ulong)) + '.' + int2str((yyvsp[(3) - (3)].yyt_ulong));
+ (yyval.yyt_float) = atof(s.c_str()); }
+ break;
+
+ case 360:
+#line 1225 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 361:
+#line 1225 "parser.yxx"
+ {
+ MSG->hdr_to.set_display((yyvsp[(2) - (3)].yyt_from_addr)->display);
+ MSG->hdr_to.set_uri((yyvsp[(2) - (3)].yyt_from_addr)->uri);
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(3) - (3)].yyt_params)->begin(); i != (yyvsp[(3) - (3)].yyt_params)->end(); i++) {
+ if (i->name == "tag") {
+ MSG->hdr_to.set_tag(i->value);
+ } else {
+ MSG->hdr_to.add_param(*i);
+ }
+ }
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_from_addr)); delete (yyvsp[(2) - (3)].yyt_from_addr);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_params)); delete (yyvsp[(3) - (3)].yyt_params); }
+ break;
+
+ case 362:
+#line 1240 "parser.yxx"
+ {
+ MSG->hdr_unsupported.add_feature(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 363:
+#line 1243 "parser.yxx"
+ {
+ MSG->hdr_unsupported.add_feature(tolower(*(yyvsp[(3) - (3)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+ case 364:
+#line 1248 "parser.yxx"
+ {
+ MSG->hdr_user_agent.add_server(*(yyvsp[(1) - (1)].yyt_server));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_server)); delete (yyvsp[(1) - (1)].yyt_server); }
+ break;
+
+ case 365:
+#line 1251 "parser.yxx"
+ {
+ MSG->hdr_user_agent.add_server(*(yyvsp[(2) - (2)].yyt_server));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_server)); delete (yyvsp[(2) - (2)].yyt_server); }
+ break;
+
+ case 366:
+#line 1256 "parser.yxx"
+ {
+ MSG->hdr_via.add_via(*(yyvsp[(1) - (1)].yyt_via));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_via)); delete (yyvsp[(1) - (1)].yyt_via); }
+ break;
+
+ case 367:
+#line 1259 "parser.yxx"
+ {
+ MSG->hdr_via.add_via(*(yyvsp[(3) - (3)].yyt_via));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_via)); delete (yyvsp[(3) - (3)].yyt_via); }
+ break;
+
+ case 368:
+#line 1264 "parser.yxx"
+ {
+ (yyval.yyt_via) = (yyvsp[(1) - (3)].yyt_via);
+ (yyval.yyt_via)->host = (yyvsp[(2) - (3)].yyt_via)->host;
+ (yyval.yyt_via)->port = (yyvsp[(2) - (3)].yyt_via)->port;
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(3) - (3)].yyt_params)->begin(); i != (yyvsp[(3) - (3)].yyt_params)->end(); i++) {
+ if (i->name == "ttl") {
+ (yyval.yyt_via)->ttl = atoi(i->value.c_str());
+ } else if (i->name == "maddr") {
+ (yyval.yyt_via)->maddr = i->value;
+ } else if (i->name == "received") {
+ (yyval.yyt_via)->received = i->value;
+ } else if (i->name == "branch") {
+ (yyval.yyt_via)->branch = i->value;
+ } else if (i->name == "rport") {
+ (yyval.yyt_via)->rport_present = true;
+ if (i->type == t_parameter::VALUE) {
+ (yyval.yyt_via)->rport =
+ atoi(i->value.c_str());
+ }
+ } else {
+ (yyval.yyt_via)->add_extension(*i);
+ }
+ }
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_via)); delete (yyvsp[(2) - (3)].yyt_via);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_params)); delete (yyvsp[(3) - (3)].yyt_params); }
+ break;
+
+ case 369:
+#line 1292 "parser.yxx"
+ {
+ (yyval.yyt_via) = new t_via();
+ MEMMAN_NEW((yyval.yyt_via));
+ (yyval.yyt_via)->protocol_name = toupper(*(yyvsp[(1) - (5)].yyt_str));
+ (yyval.yyt_via)->protocol_version = *(yyvsp[(3) - (5)].yyt_str);
+ (yyval.yyt_via)->transport = toupper(*(yyvsp[(5) - (5)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(1) - (5)].yyt_str)); delete (yyvsp[(1) - (5)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(3) - (5)].yyt_str)); delete (yyvsp[(3) - (5)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(5) - (5)].yyt_str)); delete (yyvsp[(5) - (5)].yyt_str); }
+ break;
+
+ case 370:
+#line 1303 "parser.yxx"
+ {
+ (yyval.yyt_via) = new t_via();
+ MEMMAN_NEW((yyval.yyt_via));
+ (yyval.yyt_via)->host = *(yyvsp[(1) - (1)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 371:
+#line 1308 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 372:
+#line 1308 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 373:
+#line 1308 "parser.yxx"
+ {
+ if ((yyvsp[(4) - (5)].yyt_ulong) > 65535) YYERROR;
+
+ (yyval.yyt_via) = new t_via();
+ MEMMAN_NEW((yyval.yyt_via));
+ (yyval.yyt_via)->host = *(yyvsp[(1) - (5)].yyt_str);
+ (yyval.yyt_via)->port = (yyvsp[(4) - (5)].yyt_ulong);
+ MEMMAN_DELETE((yyvsp[(1) - (5)].yyt_str)); delete (yyvsp[(1) - (5)].yyt_str); }
+ break;
+
+ case 374:
+#line 1316 "parser.yxx"
+ {
+ (yyval.yyt_via) = new t_via();
+ MEMMAN_NEW((yyval.yyt_via));
+ (yyval.yyt_via)->host = *(yyvsp[(1) - (1)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 375:
+#line 1321 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 376:
+#line 1321 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 377:
+#line 1321 "parser.yxx"
+ {
+ (yyval.yyt_via) = new t_via();
+ MEMMAN_NEW((yyval.yyt_via));
+ (yyval.yyt_via)->host = *(yyvsp[(1) - (5)].yyt_str);
+ (yyval.yyt_via)->port = (yyvsp[(4) - (5)].yyt_ulong);
+ MEMMAN_DELETE((yyvsp[(1) - (5)].yyt_str)); delete (yyvsp[(1) - (5)].yyt_str); }
+ break;
+
+ case 378:
+#line 1329 "parser.yxx"
+ { CTXT_IPV6ADDR; }
+ break;
+
+ case 379:
+#line 1329 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 380:
+#line 1329 "parser.yxx"
+ {
+ // TODO: check correct format of IPv6 address
+ (yyval.yyt_str) = new string('[' + *(yyvsp[(3) - (5)].yyt_str) + ']');
+ MEMMAN_NEW((yyval.yyt_str));
+ MEMMAN_DELETE((yyvsp[(3) - (5)].yyt_str)); }
+ break;
+
+ case 381:
+#line 1336 "parser.yxx"
+ {
+ MSG->hdr_warning.add_warning(*(yyvsp[(1) - (1)].yyt_warning));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_warning)); delete (yyvsp[(1) - (1)].yyt_warning); }
+ break;
+
+ case 382:
+#line 1339 "parser.yxx"
+ {
+ MSG->hdr_warning.add_warning(*(yyvsp[(3) - (3)].yyt_warning));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_warning)); delete (yyvsp[(3) - (3)].yyt_warning); }
+ break;
+
+ case 383:
+#line 1344 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 384:
+#line 1344 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 385:
+#line 1344 "parser.yxx"
+ {
+ (yyval.yyt_warning) = new t_warning();
+ MEMMAN_NEW((yyval.yyt_warning));
+ (yyval.yyt_warning)->code = (yyvsp[(2) - (5)].yyt_ulong);
+ (yyval.yyt_warning)->host = (yyvsp[(4) - (5)].yyt_via)->host;
+ (yyval.yyt_warning)->port = (yyvsp[(4) - (5)].yyt_via)->port;
+ (yyval.yyt_warning)->text = *(yyvsp[(5) - (5)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(4) - (5)].yyt_via)); delete (yyvsp[(4) - (5)].yyt_via);
+ MEMMAN_DELETE((yyvsp[(5) - (5)].yyt_str)); delete (yyvsp[(5) - (5)].yyt_str); }
+ break;
+
+ case 386:
+#line 1355 "parser.yxx"
+ { CTXT_LINE; }
+ break;
+
+ case 387:
+#line 1355 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 388:
+#line 1355 "parser.yxx"
+ { (yyval.yyt_str) = (yyvsp[(2) - (3)].yyt_str); }
+ break;
+
+ case 389:
+#line 1358 "parser.yxx"
+ {
+ if ((yyvsp[(1) - (1)].yyt_param)->name == "nextnonce")
+ MSG->hdr_auth_info.set_next_nonce((yyvsp[(1) - (1)].yyt_param)->value);
+ else if ((yyvsp[(1) - (1)].yyt_param)->name == "qop")
+ MSG->hdr_auth_info.set_message_qop((yyvsp[(1) - (1)].yyt_param)->value);
+ else if ((yyvsp[(1) - (1)].yyt_param)->name == "rspauth")
+ MSG->hdr_auth_info.set_response_auth((yyvsp[(1) - (1)].yyt_param)->value);
+ else if ((yyvsp[(1) - (1)].yyt_param)->name == "cnonce")
+ MSG->hdr_auth_info.set_cnonce((yyvsp[(1) - (1)].yyt_param)->value);
+ else if ((yyvsp[(1) - (1)].yyt_param)->name == "nc") {
+ MSG->hdr_auth_info.set_nonce_count(
+ hex2int((yyvsp[(1) - (1)].yyt_param)->value));
+ }
+ else {
+ YYERROR;
+ }
+
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_param)); delete (yyvsp[(1) - (1)].yyt_param); }
+ break;
+
+ case 392:
+#line 1382 "parser.yxx"
+ {
+ (yyval.yyt_dig_resp) = new t_digest_response();
+ MEMMAN_NEW((yyval.yyt_dig_resp));
+ if (!(yyval.yyt_dig_resp)->set_attr(*(yyvsp[(1) - (1)].yyt_param))) {
+ MEMMAN_DELETE((yyval.yyt_dig_resp)); delete (yyval.yyt_dig_resp);
+ YYERROR;
+ }
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_param)); delete (yyvsp[(1) - (1)].yyt_param); }
+ break;
+
+ case 393:
+#line 1390 "parser.yxx"
+ {
+ (yyval.yyt_dig_resp) = (yyvsp[(1) - (3)].yyt_dig_resp);
+ if (!(yyval.yyt_dig_resp)->set_attr(*(yyvsp[(3) - (3)].yyt_param))) {
+ YYERROR;
+ }
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_param)); delete (yyvsp[(3) - (3)].yyt_param); }
+ break;
+
+ case 394:
+#line 1398 "parser.yxx"
+ {
+ (yyval.yyt_params) = new list<t_parameter>;
+ MEMMAN_NEW((yyval.yyt_params));
+ (yyval.yyt_params)->push_back(*(yyvsp[(1) - (1)].yyt_param));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_param)); delete (yyvsp[(1) - (1)].yyt_param); }
+ break;
+
+ case 395:
+#line 1403 "parser.yxx"
+ {
+ (yyval.yyt_params) = (yyvsp[(1) - (3)].yyt_params);
+ (yyval.yyt_params)->push_back(*(yyvsp[(3) - (3)].yyt_param));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_param)); delete (yyvsp[(3) - (3)].yyt_param); }
+ break;
+
+ case 396:
+#line 1409 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 397:
+#line 1409 "parser.yxx"
+ {
+ (yyval.yyt_credentials) = new t_credentials;
+ MEMMAN_NEW((yyval.yyt_credentials));
+ (yyval.yyt_credentials)->auth_scheme = AUTH_DIGEST;
+ (yyval.yyt_credentials)->digest_response = *(yyvsp[(3) - (3)].yyt_dig_resp);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_dig_resp)); delete (yyvsp[(3) - (3)].yyt_dig_resp); }
+ break;
+
+ case 398:
+#line 1415 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 399:
+#line 1415 "parser.yxx"
+ {
+ (yyval.yyt_credentials) = new t_credentials;
+ MEMMAN_NEW((yyval.yyt_credentials));
+ (yyval.yyt_credentials)->auth_scheme = *(yyvsp[(1) - (3)].yyt_str);
+ (yyval.yyt_credentials)->auth_params = *(yyvsp[(3) - (3)].yyt_params);
+ MEMMAN_DELETE((yyvsp[(1) - (3)].yyt_str)); delete (yyvsp[(1) - (3)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_params)); delete (yyvsp[(3) - (3)].yyt_params); }
+ break;
+
+ case 400:
+#line 1424 "parser.yxx"
+ { CTXT_AUTH_SCHEME; }
+ break;
+
+ case 401:
+#line 1424 "parser.yxx"
+ {
+ MSG->hdr_authorization.add_credentials(*(yyvsp[(2) - (2)].yyt_credentials));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_credentials)); delete (yyvsp[(2) - (2)].yyt_credentials); }
+ break;
+
+ case 402:
+#line 1429 "parser.yxx"
+ {
+ (yyval.yyt_dig_chlg) = new t_digest_challenge();
+ MEMMAN_NEW((yyval.yyt_dig_chlg));
+ if (!(yyval.yyt_dig_chlg)->set_attr(*(yyvsp[(1) - (1)].yyt_param))) {
+ MEMMAN_DELETE((yyval.yyt_dig_chlg)); delete (yyval.yyt_dig_chlg);
+ YYERROR;
+ }
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_param)); delete (yyvsp[(1) - (1)].yyt_param); }
+ break;
+
+ case 403:
+#line 1437 "parser.yxx"
+ {
+ (yyval.yyt_dig_chlg) = (yyvsp[(1) - (3)].yyt_dig_chlg);
+ if (!(yyval.yyt_dig_chlg)->set_attr(*(yyvsp[(3) - (3)].yyt_param))) {
+ YYERROR;
+ }
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_param)); delete (yyvsp[(3) - (3)].yyt_param); }
+ break;
+
+ case 404:
+#line 1445 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 405:
+#line 1445 "parser.yxx"
+ {
+ (yyval.yyt_challenge) = new t_challenge;
+ MEMMAN_NEW((yyval.yyt_challenge));
+ (yyval.yyt_challenge)->auth_scheme = AUTH_DIGEST;
+ (yyval.yyt_challenge)->digest_challenge = *(yyvsp[(3) - (3)].yyt_dig_chlg);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_dig_chlg)); delete (yyvsp[(3) - (3)].yyt_dig_chlg); }
+ break;
+
+ case 406:
+#line 1451 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 407:
+#line 1451 "parser.yxx"
+ {
+ (yyval.yyt_challenge) = new t_challenge;
+ MEMMAN_NEW((yyval.yyt_challenge));
+ (yyval.yyt_challenge)->auth_scheme = *(yyvsp[(1) - (3)].yyt_str);
+ (yyval.yyt_challenge)->auth_params = *(yyvsp[(3) - (3)].yyt_params);
+ MEMMAN_DELETE((yyvsp[(1) - (3)].yyt_str)); delete (yyvsp[(1) - (3)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_params)); delete (yyvsp[(3) - (3)].yyt_params); }
+ break;
+
+ case 408:
+#line 1460 "parser.yxx"
+ { CTXT_AUTH_SCHEME; }
+ break;
+
+ case 409:
+#line 1460 "parser.yxx"
+ {
+ MSG->hdr_proxy_authenticate.set_challenge(*(yyvsp[(2) - (2)].yyt_challenge));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_challenge)); delete (yyvsp[(2) - (2)].yyt_challenge); }
+ break;
+
+ case 410:
+#line 1465 "parser.yxx"
+ { CTXT_AUTH_SCHEME; }
+ break;
+
+ case 411:
+#line 1465 "parser.yxx"
+ {
+ MSG->hdr_proxy_authorization.
+ add_credentials(*(yyvsp[(2) - (2)].yyt_credentials));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_credentials)); delete (yyvsp[(2) - (2)].yyt_credentials); }
+ break;
+
+ case 412:
+#line 1471 "parser.yxx"
+ { CTXT_AUTH_SCHEME; }
+ break;
+
+ case 413:
+#line 1471 "parser.yxx"
+ {
+ MSG->hdr_www_authenticate.set_challenge(*(yyvsp[(2) - (2)].yyt_challenge));
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_challenge)); delete (yyvsp[(2) - (2)].yyt_challenge); }
+ break;
+
+ case 414:
+#line 1476 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 415:
+#line 1476 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 416:
+#line 1476 "parser.yxx"
+ {
+ MSG->hdr_rseq.set_resp_nr((yyvsp[(2) - (3)].yyt_ulong)); }
+ break;
+
+ case 417:
+#line 1480 "parser.yxx"
+ { CTXT_NUM; }
+ break;
+
+ case 418:
+#line 1480 "parser.yxx"
+ { CTXT_INITIAL; }
+ break;
+
+ case 419:
+#line 1480 "parser.yxx"
+ {
+ MSG->hdr_rack.set_resp_nr((yyvsp[(2) - (5)].yyt_ulong));
+ MSG->hdr_rack.set_cseq_nr((yyvsp[(3) - (5)].yyt_ulong));
+ MSG->hdr_rack.set_method(*(yyvsp[(5) - (5)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(5) - (5)].yyt_str)); delete (yyvsp[(5) - (5)].yyt_str); }
+ break;
+
+ case 420:
+#line 1487 "parser.yxx"
+ {
+ MSG->hdr_event.set_event_type(tolower(*(yyvsp[(1) - (2)].yyt_str)));
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(2) - (2)].yyt_params)->begin(); i != (yyvsp[(2) - (2)].yyt_params)->end(); i++) {
+ if (i->name == "id") {
+ MSG->hdr_event.set_id(i->value);
+ } else {
+ MSG->hdr_event.add_event_param(*i);
+ }
+ }
+ MEMMAN_DELETE((yyvsp[(1) - (2)].yyt_str)); delete (yyvsp[(1) - (2)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_params)); delete (yyvsp[(2) - (2)].yyt_params); }
+ break;
+
+ case 421:
+#line 1501 "parser.yxx"
+ {
+ MSG->hdr_allow_events.add_event_type(tolower(*(yyvsp[(1) - (1)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 422:
+#line 1504 "parser.yxx"
+ {
+ MSG->hdr_allow_events.add_event_type(tolower(*(yyvsp[(3) - (3)].yyt_str)));
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+ case 423:
+#line 1509 "parser.yxx"
+ {
+ MSG->hdr_subscription_state.set_substate(tolower(*(yyvsp[(1) - (2)].yyt_str)));
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(2) - (2)].yyt_params)->begin(); i != (yyvsp[(2) - (2)].yyt_params)->end(); i++) {
+ if (i->name == "reason") {
+ MSG->hdr_subscription_state.
+ set_reason(tolower(i->value));
+ } else if (i->name == "expires") {
+ MSG->hdr_subscription_state.
+ set_expires(strtoul(
+ i->value.c_str(),
+ NULL, 10));
+ } else if (i->name == "retry-after") {
+ MSG->hdr_subscription_state.
+ set_retry_after(strtoul(
+ i->value.c_str(),
+ NULL, 10));
+ } else {
+ MSG->hdr_subscription_state.
+ add_extension(*i);
+ }
+ }
+ MEMMAN_DELETE((yyvsp[(1) - (2)].yyt_str)); delete (yyvsp[(1) - (2)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_params)); delete (yyvsp[(2) - (2)].yyt_params); }
+ break;
+
+ case 424:
+#line 1535 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 425:
+#line 1535 "parser.yxx"
+ {
+ MSG->hdr_refer_to.set_display((yyvsp[(2) - (3)].yyt_from_addr)->display);
+ MSG->hdr_refer_to.set_uri((yyvsp[(2) - (3)].yyt_from_addr)->uri);
+ MSG->hdr_refer_to.set_params(*(yyvsp[(3) - (3)].yyt_params));
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_from_addr)); delete (yyvsp[(2) - (3)].yyt_from_addr);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_params)); delete (yyvsp[(3) - (3)].yyt_params); }
+ break;
+
+ case 426:
+#line 1543 "parser.yxx"
+ { CTXT_URI_SPECIAL; }
+ break;
+
+ case 427:
+#line 1543 "parser.yxx"
+ {
+ MSG->hdr_referred_by.set_display((yyvsp[(2) - (3)].yyt_from_addr)->display);
+ MSG->hdr_referred_by.set_uri((yyvsp[(2) - (3)].yyt_from_addr)->uri);
+ list<t_parameter>::const_iterator i;
+ for (i = (yyvsp[(3) - (3)].yyt_params)->begin(); i != (yyvsp[(3) - (3)].yyt_params)->end(); i++) {
+ if (i->name == "cid") {
+ MSG->hdr_referred_by.set_cid(i->value);
+ } else {
+ MSG->hdr_referred_by.add_param(*i);
+ }
+ }
+ MEMMAN_DELETE((yyvsp[(2) - (3)].yyt_from_addr)); delete (yyvsp[(2) - (3)].yyt_from_addr);
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_params)); delete (yyvsp[(3) - (3)].yyt_params); }
+ break;
+
+ case 428:
+#line 1558 "parser.yxx"
+ {
+ string value(tolower(*(yyvsp[(1) - (2)].yyt_str)));
+ if (value != "true" && value != "false") {
+ YYERROR;
+ }
+ MSG->hdr_refer_sub.set_create_refer_sub(value == "true");
+ MSG->hdr_refer_sub.set_extensions(*(yyvsp[(2) - (2)].yyt_params));
+ MEMMAN_DELETE((yyvsp[(1) - (2)].yyt_str)); delete (yyvsp[(1) - (2)].yyt_str);
+ MEMMAN_DELETE((yyvsp[(2) - (2)].yyt_params)); delete (yyvsp[(2) - (2)].yyt_params); }
+ break;
+
+ case 429:
+#line 1569 "parser.yxx"
+ {
+ MSG->hdr_sip_etag.set_etag(*(yyvsp[(1) - (1)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 430:
+#line 1574 "parser.yxx"
+ {
+ MSG->hdr_sip_if_match.set_etag(*(yyvsp[(1) - (1)].yyt_str));
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 431:
+#line 1579 "parser.yxx"
+ {
+ bool ret = MSG->hdr_request_disposition.set_directive(*(yyvsp[(1) - (1)].yyt_str));
+ if (!ret) YYERROR;
+ MEMMAN_DELETE((yyvsp[(1) - (1)].yyt_str)); delete (yyvsp[(1) - (1)].yyt_str); }
+ break;
+
+ case 432:
+#line 1583 "parser.yxx"
+ {
+ bool ret = MSG->hdr_request_disposition.set_directive(*(yyvsp[(3) - (3)].yyt_str));
+ if (!ret) YYERROR;
+ MEMMAN_DELETE((yyvsp[(3) - (3)].yyt_str)); delete (yyvsp[(3) - (3)].yyt_str); }
+ break;
+
+
+/* Line 1267 of yacc.c. */
+#line 4885 "parser.cxx"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+#line 1588 "parser.yxx"
+
+
+void
+yyerror (const char *s) /* Called by yyparse on error */
+{
+ // printf ("%s\n", s);
+}
+
diff --git a/src/parser/parser.h b/src/parser/parser.h
new file mode 100644
index 0000000..fb4ff54
--- /dev/null
+++ b/src/parser/parser.h
@@ -0,0 +1,252 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ T_NUM = 258,
+ T_TOKEN = 259,
+ T_QSTRING = 260,
+ T_COMMENT = 261,
+ T_LINE = 262,
+ T_URI = 263,
+ T_URI_WILDCARD = 264,
+ T_DISPLAY = 265,
+ T_LANG = 266,
+ T_WORD = 267,
+ T_WKDAY = 268,
+ T_MONTH = 269,
+ T_GMT = 270,
+ T_SIP = 271,
+ T_METHOD = 272,
+ T_AUTH_DIGEST = 273,
+ T_AUTH_OTHER = 274,
+ T_IPV6ADDR = 275,
+ T_PARAMVAL = 276,
+ T_HDR_ACCEPT = 277,
+ T_HDR_ACCEPT_ENCODING = 278,
+ T_HDR_ACCEPT_LANGUAGE = 279,
+ T_HDR_ALERT_INFO = 280,
+ T_HDR_ALLOW = 281,
+ T_HDR_ALLOW_EVENTS = 282,
+ T_HDR_AUTHENTICATION_INFO = 283,
+ T_HDR_AUTHORIZATION = 284,
+ T_HDR_CALL_ID = 285,
+ T_HDR_CALL_INFO = 286,
+ T_HDR_CONTACT = 287,
+ T_HDR_CONTENT_DISP = 288,
+ T_HDR_CONTENT_ENCODING = 289,
+ T_HDR_CONTENT_LANGUAGE = 290,
+ T_HDR_CONTENT_LENGTH = 291,
+ T_HDR_CONTENT_TYPE = 292,
+ T_HDR_CSEQ = 293,
+ T_HDR_DATE = 294,
+ T_HDR_ERROR_INFO = 295,
+ T_HDR_EVENT = 296,
+ T_HDR_EXPIRES = 297,
+ T_HDR_FROM = 298,
+ T_HDR_IN_REPLY_TO = 299,
+ T_HDR_MAX_FORWARDS = 300,
+ T_HDR_MIN_EXPIRES = 301,
+ T_HDR_MIME_VERSION = 302,
+ T_HDR_ORGANIZATION = 303,
+ T_HDR_P_ASSERTED_IDENTITY = 304,
+ T_HDR_P_PREFERRED_IDENTITY = 305,
+ T_HDR_PRIORITY = 306,
+ T_HDR_PRIVACY = 307,
+ T_HDR_PROXY_AUTHENTICATE = 308,
+ T_HDR_PROXY_AUTHORIZATION = 309,
+ T_HDR_PROXY_REQUIRE = 310,
+ T_HDR_RACK = 311,
+ T_HDR_RECORD_ROUTE = 312,
+ T_HDR_SERVICE_ROUTE = 313,
+ T_HDR_REFER_SUB = 314,
+ T_HDR_REFER_TO = 315,
+ T_HDR_REFERRED_BY = 316,
+ T_HDR_REPLACES = 317,
+ T_HDR_REPLY_TO = 318,
+ T_HDR_REQUIRE = 319,
+ T_HDR_REQUEST_DISPOSITION = 320,
+ T_HDR_RETRY_AFTER = 321,
+ T_HDR_ROUTE = 322,
+ T_HDR_RSEQ = 323,
+ T_HDR_SERVER = 324,
+ T_HDR_SIP_ETAG = 325,
+ T_HDR_SIP_IF_MATCH = 326,
+ T_HDR_SUBJECT = 327,
+ T_HDR_SUBSCRIPTION_STATE = 328,
+ T_HDR_SUPPORTED = 329,
+ T_HDR_TIMESTAMP = 330,
+ T_HDR_TO = 331,
+ T_HDR_UNSUPPORTED = 332,
+ T_HDR_USER_AGENT = 333,
+ T_HDR_VIA = 334,
+ T_HDR_WARNING = 335,
+ T_HDR_WWW_AUTHENTICATE = 336,
+ T_HDR_UNKNOWN = 337,
+ T_CRLF = 338,
+ T_ERROR = 339,
+ T_NULL = 340
+ };
+#endif
+/* Tokens. */
+#define T_NUM 258
+#define T_TOKEN 259
+#define T_QSTRING 260
+#define T_COMMENT 261
+#define T_LINE 262
+#define T_URI 263
+#define T_URI_WILDCARD 264
+#define T_DISPLAY 265
+#define T_LANG 266
+#define T_WORD 267
+#define T_WKDAY 268
+#define T_MONTH 269
+#define T_GMT 270
+#define T_SIP 271
+#define T_METHOD 272
+#define T_AUTH_DIGEST 273
+#define T_AUTH_OTHER 274
+#define T_IPV6ADDR 275
+#define T_PARAMVAL 276
+#define T_HDR_ACCEPT 277
+#define T_HDR_ACCEPT_ENCODING 278
+#define T_HDR_ACCEPT_LANGUAGE 279
+#define T_HDR_ALERT_INFO 280
+#define T_HDR_ALLOW 281
+#define T_HDR_ALLOW_EVENTS 282
+#define T_HDR_AUTHENTICATION_INFO 283
+#define T_HDR_AUTHORIZATION 284
+#define T_HDR_CALL_ID 285
+#define T_HDR_CALL_INFO 286
+#define T_HDR_CONTACT 287
+#define T_HDR_CONTENT_DISP 288
+#define T_HDR_CONTENT_ENCODING 289
+#define T_HDR_CONTENT_LANGUAGE 290
+#define T_HDR_CONTENT_LENGTH 291
+#define T_HDR_CONTENT_TYPE 292
+#define T_HDR_CSEQ 293
+#define T_HDR_DATE 294
+#define T_HDR_ERROR_INFO 295
+#define T_HDR_EVENT 296
+#define T_HDR_EXPIRES 297
+#define T_HDR_FROM 298
+#define T_HDR_IN_REPLY_TO 299
+#define T_HDR_MAX_FORWARDS 300
+#define T_HDR_MIN_EXPIRES 301
+#define T_HDR_MIME_VERSION 302
+#define T_HDR_ORGANIZATION 303
+#define T_HDR_P_ASSERTED_IDENTITY 304
+#define T_HDR_P_PREFERRED_IDENTITY 305
+#define T_HDR_PRIORITY 306
+#define T_HDR_PRIVACY 307
+#define T_HDR_PROXY_AUTHENTICATE 308
+#define T_HDR_PROXY_AUTHORIZATION 309
+#define T_HDR_PROXY_REQUIRE 310
+#define T_HDR_RACK 311
+#define T_HDR_RECORD_ROUTE 312
+#define T_HDR_SERVICE_ROUTE 313
+#define T_HDR_REFER_SUB 314
+#define T_HDR_REFER_TO 315
+#define T_HDR_REFERRED_BY 316
+#define T_HDR_REPLACES 317
+#define T_HDR_REPLY_TO 318
+#define T_HDR_REQUIRE 319
+#define T_HDR_REQUEST_DISPOSITION 320
+#define T_HDR_RETRY_AFTER 321
+#define T_HDR_ROUTE 322
+#define T_HDR_RSEQ 323
+#define T_HDR_SERVER 324
+#define T_HDR_SIP_ETAG 325
+#define T_HDR_SIP_IF_MATCH 326
+#define T_HDR_SUBJECT 327
+#define T_HDR_SUBSCRIPTION_STATE 328
+#define T_HDR_SUPPORTED 329
+#define T_HDR_TIMESTAMP 330
+#define T_HDR_TO 331
+#define T_HDR_UNSUPPORTED 332
+#define T_HDR_USER_AGENT 333
+#define T_HDR_VIA 334
+#define T_HDR_WARNING 335
+#define T_HDR_WWW_AUTHENTICATE 336
+#define T_HDR_UNKNOWN 337
+#define T_CRLF 338
+#define T_ERROR 339
+#define T_NULL 340
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 49 "parser.yxx"
+{
+ int yyt_int;
+ ulong yyt_ulong;
+ float yyt_float;
+ string *yyt_str;
+ t_parameter *yyt_param;
+ list<t_parameter> *yyt_params;
+ t_media *yyt_media;
+ t_coding *yyt_coding;
+ t_language *yyt_language;
+ t_alert_param *yyt_alert_param;
+ t_info_param *yyt_info_param;
+ list<t_contact_param> *yyt_contacts;
+ t_contact_param *yyt_contact;
+ t_error_param *yyt_error_param;
+ t_identity *yyt_from_addr;
+ t_route *yyt_route;
+ t_server *yyt_server;
+ t_via *yyt_via;
+ t_warning *yyt_warning;
+ t_digest_response *yyt_dig_resp;
+ t_credentials *yyt_credentials;
+ t_digest_challenge *yyt_dig_chlg;
+ t_challenge *yyt_challenge;
+}
+/* Line 1529 of yacc.c. */
+#line 245 "parser.h"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
diff --git a/src/parser/parser.yxx b/src/parser/parser.yxx
new file mode 100644
index 0000000..6f53e3c
--- /dev/null
+++ b/src/parser/parser.yxx
@@ -0,0 +1,1594 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <cstdio>
+#include <cstdlib>
+#include <string>
+#include "media_type.h"
+#include "parameter.h"
+#include "parse_ctrl.h"
+#include "request.h"
+#include "response.h"
+#include "util.h"
+#include "audits/memman.h"
+
+using namespace std;
+
+extern int yylex(void);
+void yyerror(const char *s);
+%}
+
+// The %debug option causes a problem with the %destructor options later on.
+// The bison compilor generates undefined symbols:
+//
+// parser.y: In function `void yysymprint(FILE*, int, yystype)':
+// parser.y:0: error: `null' undeclared (first use this function)
+//
+// So if you need to debug, then outcomment the %destructor first. This will
+// do no harm to your debugging, it only will cause memory leaks during
+// error handling.
+//
+// %debug
+
+%union {
+ int yyt_int;
+ ulong yyt_ulong;
+ float yyt_float;
+ string *yyt_str;
+ t_parameter *yyt_param;
+ list<t_parameter> *yyt_params;
+ t_media *yyt_media;
+ t_coding *yyt_coding;
+ t_language *yyt_language;
+ t_alert_param *yyt_alert_param;
+ t_info_param *yyt_info_param;
+ list<t_contact_param> *yyt_contacts;
+ t_contact_param *yyt_contact;
+ t_error_param *yyt_error_param;
+ t_identity *yyt_from_addr;
+ t_route *yyt_route;
+ t_server *yyt_server;
+ t_via *yyt_via;
+ t_warning *yyt_warning;
+ t_digest_response *yyt_dig_resp;
+ t_credentials *yyt_credentials;
+ t_digest_challenge *yyt_dig_chlg;
+ t_challenge *yyt_challenge;
+}
+
+%token <yyt_ulong> T_NUM
+%token <yyt_str> T_TOKEN
+%token <yyt_str> T_QSTRING
+%token <yyt_str> T_COMMENT
+%token <yyt_str> T_LINE
+%token <yyt_str> T_URI
+%token T_URI_WILDCARD
+%token <yyt_str> T_DISPLAY
+%token <yyt_str> T_LANG
+%token <yyt_str> T_WORD
+%token <yyt_int> T_WKDAY
+%token <yyt_int> T_MONTH
+%token T_GMT
+%token T_SIP
+%token <yyt_str> T_METHOD
+%token T_AUTH_DIGEST
+%token <yyt_str> T_AUTH_OTHER
+%token <yyt_str> T_IPV6ADDR
+%token <yyt_str> T_PARAMVAL
+
+%token T_HDR_ACCEPT
+%token T_HDR_ACCEPT_ENCODING
+%token T_HDR_ACCEPT_LANGUAGE
+%token T_HDR_ALERT_INFO
+%token T_HDR_ALLOW
+%token T_HDR_ALLOW_EVENTS
+%token T_HDR_AUTHENTICATION_INFO
+%token T_HDR_AUTHORIZATION
+%token T_HDR_CALL_ID
+%token T_HDR_CALL_INFO
+%token T_HDR_CONTACT
+%token T_HDR_CONTENT_DISP
+%token T_HDR_CONTENT_ENCODING
+%token T_HDR_CONTENT_LANGUAGE
+%token T_HDR_CONTENT_LENGTH
+%token T_HDR_CONTENT_TYPE
+%token T_HDR_CSEQ
+%token T_HDR_DATE
+%token T_HDR_ERROR_INFO
+%token T_HDR_EVENT
+%token T_HDR_EXPIRES
+%token T_HDR_FROM
+%token T_HDR_IN_REPLY_TO
+%token T_HDR_MAX_FORWARDS
+%token T_HDR_MIN_EXPIRES
+%token T_HDR_MIME_VERSION
+%token T_HDR_ORGANIZATION
+%token T_HDR_P_ASSERTED_IDENTITY
+%token T_HDR_P_PREFERRED_IDENTITY
+%token T_HDR_PRIORITY
+%token T_HDR_PRIVACY
+%token T_HDR_PROXY_AUTHENTICATE
+%token T_HDR_PROXY_AUTHORIZATION
+%token T_HDR_PROXY_REQUIRE
+%token T_HDR_RACK
+%token T_HDR_RECORD_ROUTE
+%token T_HDR_SERVICE_ROUTE
+%token T_HDR_REFER_SUB
+%token T_HDR_REFER_TO
+%token T_HDR_REFERRED_BY
+%token T_HDR_REPLACES
+%token T_HDR_REPLY_TO
+%token T_HDR_REQUIRE
+%token T_HDR_REQUEST_DISPOSITION
+%token T_HDR_RETRY_AFTER
+%token T_HDR_ROUTE
+%token T_HDR_RSEQ
+%token T_HDR_SERVER
+%token T_HDR_SIP_ETAG
+%token T_HDR_SIP_IF_MATCH
+%token T_HDR_SUBJECT
+%token T_HDR_SUBSCRIPTION_STATE
+%token T_HDR_SUPPORTED
+%token T_HDR_TIMESTAMP
+%token T_HDR_TO
+%token T_HDR_UNSUPPORTED
+%token T_HDR_USER_AGENT
+%token T_HDR_VIA
+%token T_HDR_WARNING
+%token T_HDR_WWW_AUTHENTICATE
+%token <yyt_str> T_HDR_UNKNOWN
+
+%token T_CRLF
+
+%token T_ERROR
+
+// The token T_NULL is never returned by the scanner.
+%token T_NULL
+
+%destructor { MEMMAN_DELETE($$); delete $$; } T_TOKEN;
+%destructor { MEMMAN_DELETE($$); delete $$; } T_QSTRING
+%destructor { MEMMAN_DELETE($$); delete $$; } T_COMMENT
+%destructor { MEMMAN_DELETE($$); delete $$; } T_LINE
+%destructor { MEMMAN_DELETE($$); delete $$; } T_URI
+%destructor { MEMMAN_DELETE($$); delete $$; } T_DISPLAY
+%destructor { MEMMAN_DELETE($$); delete $$; } T_LANG
+%destructor { MEMMAN_DELETE($$); delete $$; } T_WORD
+%destructor { MEMMAN_DELETE($$); delete $$; } T_METHOD
+%destructor { MEMMAN_DELETE($$); delete $$; } T_AUTH_OTHER
+%destructor { MEMMAN_DELETE($$); delete $$; } T_IPV6ADDR
+%destructor { MEMMAN_DELETE($$); delete $$; } T_PARAMVAL
+%destructor { MEMMAN_DELETE($$); delete $$; } T_HDR_UNKNOWN
+
+%type <yyt_alert_param> alert_param
+%type <yyt_params> auth_params
+%type <yyt_str> call_id
+%type <yyt_challenge> challenge
+%type <yyt_str> comment
+%type <yyt_contact> contact_addr
+%type <yyt_contact> contact_param
+%type <yyt_contacts> contacts
+%type <yyt_coding> content_coding
+%type <yyt_credentials> credentials
+%type <yyt_float> delay
+%type <yyt_dig_chlg> digest_challenge
+%type <yyt_dig_resp> digest_response
+%type <yyt_str> display_name
+%type <yyt_error_param> error_param
+%type <yyt_from_addr> from_addr
+%type <yyt_str> hdr_unknown
+%type <yyt_via> host
+%type <yyt_str> ipv6reference
+%type <yyt_info_param> info_param
+%type <yyt_language> language
+%type <yyt_media> media_range
+%type <yyt_param> parameter
+%type <yyt_str> parameter_val
+%type <yyt_params> parameters
+%type <yyt_float> q_factor
+%type <yyt_route> rec_route
+%type <yyt_via> sent_protocol
+%type <yyt_server> server
+%type <yyt_str> sip_version
+%type <yyt_float> timestamp
+%type <yyt_via> via_parm
+%type <yyt_warning> warning
+
+%destructor { MEMMAN_DELETE($$); delete $$; } alert_param
+%destructor { MEMMAN_DELETE($$); delete $$; } auth_params
+%destructor { MEMMAN_DELETE($$); delete $$; } call_id
+%destructor { MEMMAN_DELETE($$); delete $$; } challenge
+%destructor { MEMMAN_DELETE($$); delete $$; } comment
+%destructor { MEMMAN_DELETE($$); delete $$; } contact_addr
+%destructor { MEMMAN_DELETE($$); delete $$; } contact_param
+%destructor { MEMMAN_DELETE($$); delete $$; } contacts
+%destructor { MEMMAN_DELETE($$); delete $$; } content_coding
+%destructor { MEMMAN_DELETE($$); delete $$; } credentials
+%destructor { MEMMAN_DELETE($$); delete $$; } digest_challenge
+%destructor { MEMMAN_DELETE($$); delete $$; } digest_response
+%destructor { MEMMAN_DELETE($$); delete $$; } display_name
+%destructor { MEMMAN_DELETE($$); delete $$; } error_param
+%destructor { MEMMAN_DELETE($$); delete $$; } from_addr
+%destructor { MEMMAN_DELETE($$); delete $$; } hdr_unknown
+%destructor { MEMMAN_DELETE($$); delete $$; } host
+%destructor { MEMMAN_DELETE($$); delete $$; } ipv6reference
+%destructor { MEMMAN_DELETE($$); delete $$; } info_param
+%destructor { MEMMAN_DELETE($$); delete $$; } language
+%destructor { MEMMAN_DELETE($$); delete $$; } media_range
+%destructor { MEMMAN_DELETE($$); delete $$; } parameter
+%destructor { MEMMAN_DELETE($$); delete $$; } parameter_val
+%destructor { MEMMAN_DELETE($$); delete $$; } parameters
+%destructor { MEMMAN_DELETE($$); delete $$; } rec_route
+%destructor { MEMMAN_DELETE($$); delete $$; } sent_protocol
+%destructor { MEMMAN_DELETE($$); delete $$; } server
+%destructor { MEMMAN_DELETE($$); delete $$; } sip_version
+%destructor { MEMMAN_DELETE($$); delete $$; } via_parm
+%destructor { MEMMAN_DELETE($$); delete $$; } warning
+
+%%
+sip_message: { CTXT_NEW; } sip_message2
+;
+
+sip_message2: request
+ | response
+ | error T_NULL {
+ /* KLUDGE to work around a memory leak in bison.
+ * T_NULL does never match, so the parser never
+ * gets here. The error keyword causes bison
+ * to eat all input and destroy all tokens returned
+ * by the parser.
+ * Without this workaround the following input causes
+ * the parser to leak:
+ *
+ * INVITE INVITE ....
+ *
+ * In request_line a T_METHOD is returned as look ahead
+ * token when bison tries to match sip_version.
+ * This does not match, but the look ahead token is
+ * never destructed by Bison.
+ */
+ YYABORT;
+ }
+;
+
+request: request_line headers T_CRLF {
+ /* Parsing stops here. Remaining text is
+ * not parsed.
+ */
+ YYACCEPT; }
+;
+
+// KLUDGE: The use of CTXT_NEW is a kludge, to get the T_SIP symbol
+// for the SIP version
+request_line: T_METHOD { CTXT_URI; } T_URI { CTXT_NEW; }
+ sip_version T_CRLF {
+ MSG = new t_request();
+ MEMMAN_NEW(MSG);
+ ((t_request *)MSG)->set_method(*$1);
+ ((t_request *)MSG)->uri.set_url(*$3);
+ MSG->version = *$5;
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($3); delete $3;
+ MEMMAN_DELETE($5); delete $5;
+
+ if (!((t_request *)MSG)->uri.is_valid()) {
+ MEMMAN_DELETE(MSG); delete MSG;
+ MSG = NULL;
+ YYABORT;
+ } }
+;
+
+sip_version: T_SIP { CTXT_INITIAL; } '/' T_TOKEN {
+ $$ = $4; }
+;
+
+response: status_line headers T_CRLF {
+ /* Parsing stops here. Remaining text is
+ * not parsed.
+ */
+ YYACCEPT; }
+;
+
+status_line: sip_version { CTXT_NUM; } T_NUM { CTXT_LINE; } T_LINE
+ { CTXT_INITIAL; } T_CRLF {
+ MSG = new t_response();
+ MEMMAN_NEW(MSG);
+ MSG->version = *$1;
+ ((t_response *)MSG)->code = $3;
+ ((t_response *)MSG)->reason = trim(*$5);
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($5); delete $5; }
+;
+
+headers: /* empty */
+ | headers header
+;
+
+header: hd_accept hdr_accept T_CRLF
+ | hd_accept_encoding hdr_accept_encoding T_CRLF
+ | hd_accept_language hdr_accept_language T_CRLF
+ | hd_alert_info hdr_alert_info T_CRLF
+ | hd_allow hdr_allow T_CRLF
+ | hd_allow_events hdr_allow_events T_CRLF
+ | hd_authentication_info hdr_authentication_info T_CRLF
+ | hd_authorization hdr_authorization T_CRLF
+ | hd_call_id hdr_call_id T_CRLF
+ | hd_call_info hdr_call_info T_CRLF
+ | hd_contact hdr_contact T_CRLF
+ | hd_content_disp hdr_content_disp T_CRLF
+ | hd_content_encoding hdr_content_encoding T_CRLF
+ | hd_content_language hdr_content_language T_CRLF
+ | hd_content_length hdr_content_length T_CRLF
+ | hd_content_type hdr_content_type T_CRLF
+ | hd_cseq hdr_cseq T_CRLF
+ | hd_date hdr_date T_CRLF
+ | hd_event hdr_event T_CRLF
+ | hd_error_info hdr_error_info T_CRLF
+ | hd_expires hdr_expires T_CRLF
+ | hd_from hdr_from T_CRLF
+ | hd_in_reply_to hdr_in_reply_to T_CRLF
+ | hd_max_forwards hdr_max_forwards T_CRLF
+ | hd_min_expires hdr_min_expires T_CRLF
+ | hd_mime_version hdr_mime_version T_CRLF
+ | hd_organization hdr_organization T_CRLF
+ | hd_p_asserted_identity hdr_p_asserted_identity T_CRLF
+ | hd_p_preferred_identity hdr_p_preferred_identity T_CRLF
+ | hd_priority hdr_priority T_CRLF
+ | hd_privacy hdr_privacy T_CRLF
+ | hd_proxy_authenticate hdr_proxy_authenticate T_CRLF
+ | hd_proxy_authorization hdr_proxy_authorization T_CRLF
+ | hd_proxy_require hdr_proxy_require T_CRLF
+ | hd_rack hdr_rack T_CRLF
+ | hd_record_route hdr_record_route T_CRLF
+ | hd_refer_sub hdr_refer_sub T_CRLF
+ | hd_refer_to hdr_refer_to T_CRLF
+ | hd_referred_by hdr_referred_by T_CRLF
+ | hd_replaces hdr_replaces T_CRLF
+ | hd_reply_to hdr_reply_to T_CRLF
+ | hd_require hdr_require T_CRLF
+ | hd_request_disposition hdr_request_disposition T_CRLF
+ | hd_retry_after hdr_retry_after T_CRLF
+ | hd_route hdr_route T_CRLF
+ | hd_rseq hdr_rseq T_CRLF
+ | hd_server hdr_server T_CRLF
+ | hd_service_route hdr_service_route T_CRLF
+ | hd_sip_etag hdr_sip_etag T_CRLF
+ | hd_sip_if_match hdr_sip_if_match T_CRLF
+ | hd_subject hdr_subject T_CRLF
+ | hd_subscription_state hdr_subscription_state T_CRLF
+ | hd_supported hdr_supported T_CRLF
+ | hd_timestamp hdr_timestamp T_CRLF
+ | hd_to hdr_to T_CRLF
+ | hd_unsupported hdr_unsupported T_CRLF
+ | hd_user_agent hdr_user_agent T_CRLF
+ | hd_via hdr_via T_CRLF
+ | hd_warning hdr_warning T_CRLF
+ | hd_www_authenticate hdr_www_authenticate T_CRLF
+ | T_HDR_UNKNOWN ':' hdr_unknown T_CRLF {
+ MSG->add_unknown_header(*$1, trim(*$3));
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($3); delete $3; }
+ | hd_accept error T_CRLF
+ { PARSE_ERROR("Accept"); }
+ | hd_accept_encoding error T_CRLF
+ { PARSE_ERROR("Accept-Encoding"); }
+ | hd_accept_language error T_CRLF
+ { PARSE_ERROR("Accept-Language"); }
+ | hd_alert_info error T_CRLF
+ { PARSE_ERROR("Alert-Info"); }
+ | hd_allow error T_CRLF
+ { PARSE_ERROR("Allow"); }
+ | hd_allow_events error T_CRLF
+ { PARSE_ERROR("Allow-Events"); }
+ | hd_authentication_info error T_CRLF
+ { PARSE_ERROR("Authentication-Info"); }
+ | hd_authorization error T_CRLF
+ { PARSE_ERROR("Authorization"); }
+ | hd_call_id error T_CRLF
+ { PARSE_ERROR("Call-ID"); }
+ | hd_call_info error T_CRLF
+ { PARSE_ERROR("Call-Info"); }
+ | hd_contact error T_CRLF
+ { PARSE_ERROR("Contact"); }
+ | hd_content_disp error T_CRLF
+ { PARSE_ERROR("Content-Disposition"); }
+ | hd_content_encoding error T_CRLF
+ { PARSE_ERROR("Content-Encoding"); }
+ | hd_content_language error T_CRLF
+ { PARSE_ERROR("Content-Language"); }
+ | hd_content_length error T_CRLF
+ { PARSE_ERROR("Content-Length"); }
+ | hd_content_type error T_CRLF
+ { PARSE_ERROR("Content-Type"); }
+ | hd_cseq error T_CRLF
+ { PARSE_ERROR("CSeq"); }
+ | hd_date error T_CRLF
+ { PARSE_ERROR("Date"); }
+ | hd_error_info error T_CRLF
+ { PARSE_ERROR("Error-Info"); }
+ | hd_event error T_CRLF
+ { PARSE_ERROR("Event"); }
+ | hd_expires error T_CRLF
+ { PARSE_ERROR("Expires"); }
+ | hd_from error T_CRLF
+ { PARSE_ERROR("From"); }
+ | hd_in_reply_to error T_CRLF
+ { PARSE_ERROR("In-Reply-To"); }
+ | hd_max_forwards error T_CRLF
+ { PARSE_ERROR("Max-Forwards"); }
+ | hd_min_expires error T_CRLF
+ { PARSE_ERROR("Min-Expires"); }
+ | hd_mime_version error T_CRLF
+ { PARSE_ERROR("MIME-Version"); }
+ | hd_organization error T_CRLF
+ { PARSE_ERROR("Organization"); }
+ | hd_p_asserted_identity error T_CRLF
+ { PARSE_ERROR("P-Asserted-Identity"); }
+ | hd_p_preferred_identity error T_CRLF
+ { PARSE_ERROR("P-Preferred-Identity"); }
+ | hd_priority error T_CRLF
+ { PARSE_ERROR("Priority"); }
+ | hd_privacy error T_CRLF
+ { PARSE_ERROR("Privacy"); }
+ | hd_proxy_authenticate error T_CRLF
+ { PARSE_ERROR("Proxy-Authenticate"); }
+ | hd_proxy_authorization error T_CRLF
+ { PARSE_ERROR("Proxy-Authorization"); }
+ | hd_proxy_require error T_CRLF
+ { PARSE_ERROR("Proxy-Require"); }
+ | hd_rack error T_CRLF
+ { PARSE_ERROR("RAck"); }
+ | hd_record_route error T_CRLF
+ { PARSE_ERROR("Record-Route"); }
+ | hd_refer_sub error T_CRLF
+ { PARSE_ERROR("Refer-Sub"); }
+ | hd_refer_to error T_CRLF
+ { PARSE_ERROR("Refer-To"); }
+ | hd_referred_by error T_CRLF
+ { PARSE_ERROR("Referred-By"); }
+ | hd_replaces error T_CRLF
+ { PARSE_ERROR("Replaces"); }
+ | hd_reply_to error T_CRLF
+ { PARSE_ERROR("Reply-To"); }
+ | hd_require error T_CRLF
+ { PARSE_ERROR("Require"); }
+ | hd_request_disposition error T_CRLF
+ { PARSE_ERROR("Request-Disposition"); }
+ | hd_retry_after error T_CRLF
+ { PARSE_ERROR("Retry-After"); }
+ | hd_route error T_CRLF
+ { PARSE_ERROR("Route"); }
+ | hd_rseq error T_CRLF
+ { PARSE_ERROR("RSeq"); }
+ | hd_server error T_CRLF
+ { PARSE_ERROR("Server"); }
+ | hd_service_route error T_CRLF
+ { PARSE_ERROR("Service-Route"); }
+ | hd_sip_etag error T_CRLF
+ { PARSE_ERROR("SIP-ETag"); }
+ | hd_sip_if_match error T_CRLF
+ { PARSE_ERROR("SIP-If-Match"); }
+ | hd_subject error T_CRLF
+ { PARSE_ERROR("Subject"); }
+ | hd_subscription_state error T_CRLF
+ { PARSE_ERROR("Subscription-State"); }
+ | hd_supported error T_CRLF
+ { PARSE_ERROR("Supported"); }
+ | hd_timestamp error T_CRLF
+ { PARSE_ERROR("Timestamp"); }
+ | hd_to error T_CRLF
+ { PARSE_ERROR("To"); }
+ | hd_unsupported error T_CRLF
+ { PARSE_ERROR("Unsupported"); }
+ | hd_user_agent error T_CRLF
+ { PARSE_ERROR("User-Agent"); }
+ | hd_via error T_CRLF
+ { PARSE_ERROR("Via"); }
+ | hd_warning error T_CRLF
+ { PARSE_ERROR("Warning"); }
+ | hd_www_authenticate error T_CRLF
+ { PARSE_ERROR("WWW-Authenticate"); }
+;
+
+
+// KLUDGE
+// These rules are needed to get the error recovery working.
+// Many header rules start with a context change. As Bison uses
+// one token look ahead to determine a matching rule, the context
+// change must be done before Bison tries to match the error rule.
+// Changing the context header and once again at the header rule
+// does no harm as the context change operator is idem-potent.
+
+hd_accept: T_HDR_ACCEPT ':'
+;
+hd_accept_encoding: T_HDR_ACCEPT_ENCODING ':'
+;
+hd_accept_language: T_HDR_ACCEPT_LANGUAGE ':' { CTXT_LANG; }
+;
+hd_alert_info: T_HDR_ALERT_INFO ':'
+;
+hd_allow: T_HDR_ALLOW ':'
+;
+hd_allow_events: T_HDR_ALLOW_EVENTS ':'
+;
+hd_authentication_info: T_HDR_AUTHENTICATION_INFO ':'
+;
+hd_authorization: T_HDR_AUTHORIZATION ':' { CTXT_AUTH_SCHEME; }
+;
+hd_call_id: T_HDR_CALL_ID ':' { CTXT_WORD; }
+;
+hd_call_info: T_HDR_CALL_INFO ':'
+;
+hd_contact: T_HDR_CONTACT ':' { CTXT_URI_SPECIAL; }
+;
+hd_content_disp: T_HDR_CONTENT_DISP ':'
+;
+hd_content_encoding: T_HDR_CONTENT_ENCODING ':'
+;
+hd_content_language: T_HDR_CONTENT_LANGUAGE ':' { CTXT_LANG; }
+;
+hd_content_length: T_HDR_CONTENT_LENGTH ':' { CTXT_NUM; }
+;
+hd_content_type: T_HDR_CONTENT_TYPE ':'
+;
+hd_cseq: T_HDR_CSEQ ':' { CTXT_NUM; }
+;
+hd_date: T_HDR_DATE ':' { CTXT_DATE;}
+;
+hd_error_info: T_HDR_ERROR_INFO ':'
+;
+hd_event: T_HDR_EVENT ':'
+;
+hd_expires: T_HDR_EXPIRES ':' { CTXT_NUM; }
+;
+hd_from: T_HDR_FROM ':' { CTXT_URI_SPECIAL; }
+;
+hd_in_reply_to: T_HDR_IN_REPLY_TO ':' { CTXT_WORD; }
+;
+hd_max_forwards: T_HDR_MAX_FORWARDS ':' { CTXT_NUM; }
+;
+hd_min_expires: T_HDR_MIN_EXPIRES ':' { CTXT_NUM; }
+;
+hd_mime_version: T_HDR_MIME_VERSION ':'
+;
+hd_organization: T_HDR_ORGANIZATION ':' { CTXT_LINE; }
+;
+hd_p_asserted_identity: T_HDR_P_ASSERTED_IDENTITY ':' { CTXT_URI_SPECIAL; }
+;
+hd_p_preferred_identity: T_HDR_P_PREFERRED_IDENTITY ':' { CTXT_URI_SPECIAL; }
+;
+hd_priority: T_HDR_PRIORITY ':'
+;
+hd_privacy: T_HDR_PRIVACY ':'
+;
+hd_proxy_authenticate: T_HDR_PROXY_AUTHENTICATE ':' { CTXT_AUTH_SCHEME; }
+;
+hd_proxy_authorization: T_HDR_PROXY_AUTHORIZATION ':' { CTXT_AUTH_SCHEME; }
+;
+hd_proxy_require: T_HDR_PROXY_REQUIRE ':'
+;
+hd_rack: T_HDR_RACK ':' { CTXT_NUM; }
+;
+hd_record_route: T_HDR_RECORD_ROUTE ':' { CTXT_URI; }
+;
+hd_refer_sub: T_HDR_REFER_SUB ':'
+;
+hd_refer_to: T_HDR_REFER_TO ':' { CTXT_URI_SPECIAL; }
+;
+hd_referred_by: T_HDR_REFERRED_BY ':' { CTXT_URI_SPECIAL; }
+;
+hd_replaces: T_HDR_REPLACES ':' { CTXT_WORD; }
+;
+hd_reply_to: T_HDR_REPLY_TO ':' { CTXT_URI_SPECIAL; }
+;
+hd_require: T_HDR_REQUIRE ':'
+;
+hd_request_disposition: T_HDR_REQUEST_DISPOSITION ':'
+;
+hd_retry_after: T_HDR_RETRY_AFTER ':' { CTXT_NUM; }
+;
+hd_route: T_HDR_ROUTE ':' { CTXT_URI; }
+;
+hd_rseq: T_HDR_RSEQ ':' { CTXT_NUM; }
+;
+hd_server: T_HDR_SERVER ':'
+;
+hd_service_route: T_HDR_SERVICE_ROUTE ':' { CTXT_URI; }
+;
+hd_sip_etag: T_HDR_SIP_ETAG ':'
+;
+hd_sip_if_match: T_HDR_SIP_IF_MATCH ':'
+;
+hd_subject: T_HDR_SUBJECT ':' { CTXT_LINE; }
+;
+hd_subscription_state: T_HDR_SUBSCRIPTION_STATE ':'
+;
+hd_supported: T_HDR_SUPPORTED ':'
+;
+hd_timestamp: T_HDR_TIMESTAMP ':' { CTXT_NUM; }
+;
+hd_to: T_HDR_TO ':' { CTXT_URI_SPECIAL; }
+;
+hd_unsupported: T_HDR_UNSUPPORTED ':'
+;
+hd_user_agent: T_HDR_USER_AGENT ':'
+;
+hd_via: T_HDR_VIA ':'
+;
+hd_warning: T_HDR_WARNING ':' { CTXT_NUM; }
+;
+hd_www_authenticate: T_HDR_WWW_AUTHENTICATE ':' { CTXT_AUTH_SCHEME; }
+;
+
+hdr_accept: /* empty */
+ | media_range parameters {
+ $1->add_params(*$2);
+ MSG->hdr_accept.add_media(*$1);
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($2); delete $2; }
+ | hdr_accept ',' media_range parameters {
+ $3->add_params(*$4);
+ MSG->hdr_accept.add_media(*$3);
+ MEMMAN_DELETE($3); delete $3;
+ MEMMAN_DELETE($4); delete $4; }
+;
+
+media_range: T_TOKEN '/' T_TOKEN { $$ = new t_media(tolower(*$1), tolower(*$3));
+ MEMMAN_NEW($$);
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+parameters: /* empty */ { $$ = new list<t_parameter>; MEMMAN_NEW($$); }
+ | parameters ';' parameter {
+ $1->push_back(*$3);
+ $$ = $1;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+parameter: T_TOKEN {
+ $$ = new t_parameter(tolower(*$1));
+ MEMMAN_NEW($$);
+ MEMMAN_DELETE($1); delete $1; }
+ | T_TOKEN '=' { CTXT_PARAMVAL; } parameter_val { CTXT_INITIAL; } {
+ $$ = new t_parameter(tolower(*$1), *$4);
+ MEMMAN_NEW($$);
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($4); delete $4; }
+;
+
+parameter_val: T_PARAMVAL {
+ $$ = $1; }
+ | T_QSTRING {
+ $$ = $1; }
+;
+
+hdr_accept_encoding: content_coding {
+ MSG->hdr_accept_encoding.add_coding(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_accept_encoding ',' content_coding {
+ MSG->hdr_accept_encoding.add_coding(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+content_coding: T_TOKEN {
+ $$ = new t_coding(tolower(*$1));
+ MEMMAN_NEW($$);
+ MEMMAN_DELETE($1); delete $1; }
+ | T_TOKEN q_factor {
+ $$ = new t_coding(tolower(*$1));
+ MEMMAN_NEW($$);
+ $$->q = $2;
+ MEMMAN_DELETE($1); delete $1; }
+;
+
+q_factor: ';' parameter {
+ if ($2->name != "q") YYERROR;
+ $$ = atof($2->value.c_str());
+ MEMMAN_DELETE($2); delete $2;
+ }
+;
+
+hdr_accept_language: { CTXT_LANG; } language {
+ MSG->hdr_accept_language.add_language(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+ | hdr_accept_language ',' { CTXT_LANG; } language {
+ MSG->hdr_accept_language.add_language(*$4);
+ MEMMAN_DELETE($4); delete $4; }
+;
+
+language: T_LANG {
+ CTXT_INITIAL;
+ $$ = new t_language(tolower(*$1));
+ MEMMAN_NEW($$);
+ MEMMAN_DELETE($1); delete $1; }
+ | T_LANG { CTXT_INITIAL; } q_factor {
+ $$ = new t_language(tolower(*$1));
+ MEMMAN_NEW($$);
+ $$->q = $3;
+ MEMMAN_DELETE($1); delete $1; }
+;
+
+hdr_alert_info: alert_param {
+ MSG->hdr_alert_info.add_param(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_alert_info ',' alert_param {
+ MSG->hdr_alert_info.add_param(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+alert_param: '<' { CTXT_URI; } T_URI { CTXT_INITIAL; } '>' parameters {
+ $$ = new t_alert_param();
+ MEMMAN_NEW($$);
+ $$->uri.set_url(*$3);
+ $$->parameter_list = *$6;
+
+ if (!$$->uri.is_valid()) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+
+ MEMMAN_DELETE($3); delete $3;
+ MEMMAN_DELETE($6); delete $6; }
+;
+
+hdr_allow: T_TOKEN {
+ MSG->hdr_allow.add_method(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_allow ',' T_TOKEN {
+ MSG->hdr_allow.add_method(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_call_id: { CTXT_WORD; } call_id { CTXT_INITIAL; } {
+ MSG->hdr_call_id.set_call_id(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+call_id: T_WORD { $$ = $1; }
+ | T_WORD '@' T_WORD {
+ $$ = new string(*$1 + '@' + *$3);
+ MEMMAN_NEW($$);
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_call_info: info_param {
+ MSG->hdr_call_info.add_param(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_call_info ',' info_param {
+ MSG->hdr_call_info.add_param(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+info_param: '<' { CTXT_URI; } T_URI { CTXT_INITIAL; } '>' parameters {
+ $$ = new t_info_param();
+ MEMMAN_NEW($$);
+ $$->uri.set_url(*$3);
+ $$->parameter_list = *$6;
+
+ if (!$$->uri.is_valid()) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+
+ MEMMAN_DELETE($3); delete $3;
+ MEMMAN_DELETE($6); delete $6; }
+;
+
+hdr_contact: { CTXT_URI_SPECIAL; } T_URI_WILDCARD { CTXT_INITIAL; } {
+ MSG->hdr_contact.set_any(); }
+ | contacts {
+ MSG->hdr_contact.add_contacts(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+;
+
+contacts: contact_param {
+ $$ = new list<t_contact_param>;
+ MEMMAN_NEW($$);
+ $$->push_back(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | contacts ',' contact_param {
+ $1->push_back(*$3);
+ $$ = $1;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+contact_param: contact_addr parameters {
+ $$ = $1;
+ list<t_parameter>::const_iterator i;
+ for (i = $2->begin(); i != $2->end(); i++) {
+ if (i->name == "q") {
+ $$->set_qvalue(atof(i->value.c_str()));
+ } else if (i->name == "expires") {
+ $$->set_expires(strtoul(
+ i->value.c_str(), NULL, 10));
+ } else {
+ $$->add_extension(*i);
+ }
+ }
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+contact_addr: { CTXT_URI_SPECIAL; } T_URI { CTXT_INITIAL; } {
+ $$ = new t_contact_param();
+ MEMMAN_NEW($$);
+ $$->uri.set_url(*$2);
+
+ if (!$$->uri.is_valid()) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+
+ MEMMAN_DELETE($2); delete $2; }
+ | { CTXT_URI_SPECIAL; } display_name '<' { CTXT_URI; } T_URI { CTXT_INITIAL; } '>' {
+ $$ = new t_contact_param();
+ MEMMAN_NEW($$);
+ $$->display = *$2;
+ $$->uri.set_url(*$5);
+
+ if (!$$->uri.is_valid()) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+
+ MEMMAN_DELETE($2); delete $2;
+ MEMMAN_DELETE($5); delete $5; }
+;
+
+display_name: /* empty */ { $$ = new string(); MEMMAN_NEW($$); }
+ | T_DISPLAY {
+ $$ = new string(rtrim(*$1));
+ MEMMAN_NEW($$);
+ MEMMAN_DELETE($1); delete $1; }
+ | T_QSTRING { $$ = $1; }
+;
+
+hdr_content_disp: T_TOKEN parameters {
+ MSG->hdr_content_disp.set_type(tolower(*$1));
+
+ list<t_parameter>::const_iterator i;
+ for (i = $2->begin(); i != $2->end(); i++) {
+ if (i->name == "filename") {
+ MSG->hdr_content_disp.set_filename(i->value);
+ } else {
+ MSG->hdr_content_disp.add_param(*i);
+ }
+ }
+
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_content_encoding: content_coding {
+ MSG->hdr_content_encoding.add_coding(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_content_encoding ',' content_coding {
+ MSG->hdr_content_encoding.add_coding(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_content_language: { CTXT_LANG; } language {
+ MSG->hdr_content_language.add_language(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+ | hdr_content_language ',' { CTXT_LANG; } language {
+ MSG->hdr_content_language.add_language(*$4);
+ MEMMAN_DELETE($4); delete $4; }
+;
+
+hdr_content_length: { CTXT_NUM; } T_NUM { CTXT_INITIAL; } {
+ MSG->hdr_content_length.set_length($2); }
+;
+
+hdr_content_type: media_range parameters {
+ $1->add_params(*$2);
+ MSG->hdr_content_type.set_media(*$1);
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_cseq: { CTXT_NUM; } T_NUM { CTXT_INITIAL; } T_TOKEN {
+ MSG->hdr_cseq.set_seqnr($2);
+ MSG->hdr_cseq.set_method(*$4);
+ MEMMAN_DELETE($4); delete $4; }
+;
+
+hdr_date: { CTXT_DATE;}
+ T_WKDAY ',' T_NUM T_MONTH T_NUM
+ T_NUM ':' T_NUM ':' T_NUM T_GMT
+ { CTXT_INITIAL; } {
+ struct tm t;
+ t.tm_mday = $4;
+ t.tm_mon = $5;
+ t.tm_year = $6 - 1900;
+ t.tm_hour = $7;
+ t.tm_min = $9;
+ t.tm_sec = $11;
+ MSG->hdr_date.set_date_gm(&t); }
+;
+
+hdr_error_info: error_param {
+ MSG->hdr_error_info.add_param(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_error_info ',' error_param {
+ MSG->hdr_error_info.add_param(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+error_param: '<' { CTXT_URI; } T_URI { CTXT_INITIAL; } '>' parameters {
+ $$ = new t_error_param();
+ MEMMAN_NEW($$);
+ $$->uri.set_url(*$3);
+ $$->parameter_list = *$6;
+
+ if (!$$->uri.is_valid()) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+
+ MEMMAN_DELETE($3); delete $3;
+ MEMMAN_DELETE($6); delete $6; }
+;
+
+hdr_expires: { CTXT_NUM; } T_NUM { CTXT_INITIAL; } {
+ MSG->hdr_expires.set_time($2); }
+;
+
+hdr_from: { CTXT_URI_SPECIAL; } from_addr parameters {
+ MSG->hdr_from.set_display($2->display);
+ MSG->hdr_from.set_uri($2->uri);
+ list<t_parameter>::const_iterator i;
+ for (i = $3->begin(); i != $3->end(); i++) {
+ if (i->name == "tag") {
+ MSG->hdr_from.set_tag(i->value);
+ } else {
+ MSG->hdr_from.add_param(*i);
+ }
+ }
+ MEMMAN_DELETE($2); delete $2;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+from_addr: T_URI { CTXT_INITIAL; } {
+ $$ = new t_identity();
+ MEMMAN_NEW($$);
+ $$->set_uri(*$1);
+
+ if (!$$->uri.is_valid()) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+
+ MEMMAN_DELETE($1); delete $1; }
+ | display_name '<' { CTXT_URI; } T_URI { CTXT_INITIAL; } '>' {
+ $$ = new t_identity();
+ MEMMAN_NEW($$);
+ $$->set_display(*$1);
+ $$->set_uri(*$4);
+
+ if (!$$->uri.is_valid()) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($4); delete $4; }
+;
+
+hdr_in_reply_to: { CTXT_WORD; } call_id { CTXT_INITIAL; } {
+ MSG->hdr_in_reply_to.add_call_id(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+ | hdr_in_reply_to ',' { CTXT_WORD; } call_id { CTXT_INITIAL; } {
+ MSG->hdr_in_reply_to.add_call_id(*$4);
+ MEMMAN_DELETE($4); delete $4; }
+;
+
+hdr_max_forwards: { CTXT_NUM; } T_NUM { CTXT_INITIAL; } {
+ MSG->hdr_max_forwards.set_max_forwards($2); }
+;
+
+hdr_min_expires: { CTXT_NUM; } T_NUM { CTXT_INITIAL; } {
+ MSG->hdr_min_expires.set_time($2); }
+;
+
+hdr_mime_version: T_TOKEN {
+ MSG->hdr_mime_version.set_version(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+;
+
+hdr_organization: { CTXT_LINE; } T_LINE { CTXT_INITIAL; } {
+ MSG->hdr_organization.set_name(trim(*$2));
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_p_asserted_identity: { CTXT_URI_SPECIAL; } from_addr {
+ MSG->hdr_p_asserted_identity.add_identity(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+ | hdr_p_asserted_identity ',' from_addr {
+ MSG->hdr_p_asserted_identity.add_identity(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_p_preferred_identity: { CTXT_URI_SPECIAL; } from_addr {
+ MSG->hdr_p_preferred_identity.add_identity(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+ | hdr_p_preferred_identity ',' from_addr {
+ MSG->hdr_p_preferred_identity.add_identity(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_priority: T_TOKEN {
+ MSG->hdr_priority.set_priority(tolower(*$1));
+ MEMMAN_DELETE($1); delete $1; }
+;
+
+hdr_privacy: T_TOKEN {
+ MSG->hdr_privacy.add_privacy(tolower(*$1));
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_privacy ';' T_TOKEN {
+ MSG->hdr_privacy.add_privacy(tolower(*$3));
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_proxy_require: T_TOKEN {
+ MSG->hdr_proxy_require.add_feature(tolower(*$1));
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_proxy_require ',' T_TOKEN {
+ MSG->hdr_proxy_require.add_feature(tolower(*$3));
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_record_route: rec_route {
+ MSG->hdr_record_route.add_route(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_record_route ',' rec_route {
+ MSG->hdr_record_route.add_route(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+rec_route: { CTXT_URI; } display_name '<' T_URI { CTXT_INITIAL; } '>'
+ parameters {
+ $$ = new t_route;
+ MEMMAN_NEW($$);
+ $$->display = *$2;
+ $$->uri.set_url(*$4);
+ $$->set_params(*$7);
+
+ if (!$$->uri.is_valid()) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+
+ MEMMAN_DELETE($2); delete $2;
+ MEMMAN_DELETE($4); delete $4;
+ MEMMAN_DELETE($7); delete $7; }
+;
+
+hdr_service_route: rec_route {
+ MSG->hdr_service_route.add_route(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_service_route ',' rec_route {
+ MSG->hdr_service_route.add_route(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_replaces: { CTXT_WORD; } call_id { CTXT_INITIAL; } parameters {
+ MSG->hdr_replaces.set_call_id(*$2);
+
+ list<t_parameter>::const_iterator i;
+ for (i = $4->begin(); i != $4->end(); i++) {
+ if (i->name == "to-tag") {
+ MSG->hdr_replaces.set_to_tag(i->value);
+ } else if (i->name == "from-tag") {
+ MSG->hdr_replaces.set_from_tag(i->value);
+ } else if (i->name == "early-only") {
+ MSG->hdr_replaces.set_early_only(true);
+ } else {
+ MSG->hdr_replaces.add_param(*i);
+ }
+ }
+
+ if (!MSG->hdr_replaces.is_valid()) YYERROR;
+
+ MEMMAN_DELETE($2); delete $2;
+ MEMMAN_DELETE($4); delete $4; }
+;
+
+hdr_reply_to: { CTXT_URI_SPECIAL; } from_addr parameters {
+ MSG->hdr_reply_to.set_display($2->display);
+ MSG->hdr_reply_to.set_uri($2->uri);
+ MSG->hdr_reply_to.set_params(*$3);
+ MEMMAN_DELETE($2); delete $2;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_require: T_TOKEN {
+ MSG->hdr_require.add_feature(tolower(*$1));
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_proxy_require ',' T_TOKEN {
+ MSG->hdr_require.add_feature(tolower(*$3));
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_retry_after: { CTXT_NUM; } T_NUM { CTXT_INITIAL; } comment parameters {
+ MSG->hdr_retry_after.set_time($2);
+ MSG->hdr_retry_after.set_comment(*$4);
+ list<t_parameter>::const_iterator i;
+ for (i = $5->begin(); i != $5->end(); i++) {
+ if (i->name == "duration") {
+ int d = strtoul(i->value.c_str(), NULL, 10);
+ MSG->hdr_retry_after.set_duration(d);
+ } else {
+ MSG->hdr_retry_after.add_param(*i);
+ }
+ }
+ MEMMAN_DELETE($4); delete $4;
+ MEMMAN_DELETE($5); delete $5; }
+;
+
+comment: /* empty */ { $$ = new string(); MEMMAN_NEW($$); }
+ | '(' { CTXT_COMMENT; } T_COMMENT { CTXT_INITIAL; } ')' {
+ $$ = $3; }
+;
+
+hdr_route: rec_route {
+ MSG->hdr_route.add_route(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_route ',' rec_route {
+ MSG->hdr_route.add_route(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_server: server {
+ MSG->hdr_server.add_server(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_server server {
+ MSG->hdr_server.add_server(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+server: comment {
+ $$ = new t_server();
+ MEMMAN_NEW($$);
+ $$->comment = *$1;
+ MEMMAN_DELETE($1); delete $1; }
+ | T_TOKEN comment {
+ $$ = new t_server();
+ MEMMAN_NEW($$);
+ $$->product = *$1;
+ $$->comment = *$2;
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($2); delete $2; }
+ | T_TOKEN '/' T_TOKEN comment {
+ $$ = new t_server();
+ MEMMAN_NEW($$);
+ $$->product = *$1;
+ $$->version = *$3;
+ $$->comment = *$4;
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($3); delete $3;
+ MEMMAN_DELETE($4); delete $4; }
+;
+
+hdr_subject: { CTXT_LINE; } T_LINE { CTXT_INITIAL; } {
+ MSG->hdr_subject.set_subject(trim(*$2));
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_supported: /* empty */ {
+ MSG->hdr_supported.set_empty(); }
+ | T_TOKEN {
+ MSG->hdr_supported.add_feature(tolower(*$1));
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_supported ',' T_TOKEN {
+ MSG->hdr_supported.add_feature(tolower(*$3));
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_timestamp: { CTXT_NUM; } hdr_timestamp1 { CTXT_INITIAL; }
+;
+
+hdr_timestamp1: timestamp {
+ MSG->hdr_timestamp.set_timestamp($1); }
+ | timestamp delay {
+ MSG->hdr_timestamp.set_timestamp($1);
+ MSG->hdr_timestamp.set_delay($2); }
+;
+
+timestamp: T_NUM { $$ = $1; }
+ | T_NUM '.' T_NUM {
+ string s = int2str($1) + '.' + int2str($3);
+ $$ = atof(s.c_str()); }
+;
+
+delay: T_NUM { $$ = $1; }
+ | T_NUM '.' T_NUM {
+ string s = int2str($1) + '.' + int2str($3);
+ $$ = atof(s.c_str()); }
+;
+
+hdr_to: { CTXT_URI_SPECIAL; } from_addr parameters {
+ MSG->hdr_to.set_display($2->display);
+ MSG->hdr_to.set_uri($2->uri);
+ list<t_parameter>::const_iterator i;
+ for (i = $3->begin(); i != $3->end(); i++) {
+ if (i->name == "tag") {
+ MSG->hdr_to.set_tag(i->value);
+ } else {
+ MSG->hdr_to.add_param(*i);
+ }
+ }
+ MEMMAN_DELETE($2); delete $2;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_unsupported: T_TOKEN {
+ MSG->hdr_unsupported.add_feature(tolower(*$1));
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_unsupported ',' T_TOKEN {
+ MSG->hdr_unsupported.add_feature(tolower(*$3));
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_user_agent: server {
+ MSG->hdr_user_agent.add_server(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_user_agent server {
+ MSG->hdr_user_agent.add_server(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_via: via_parm {
+ MSG->hdr_via.add_via(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_via ',' via_parm {
+ MSG->hdr_via.add_via(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+via_parm: sent_protocol host parameters {
+ $$ = $1;
+ $$->host = $2->host;
+ $$->port = $2->port;
+ list<t_parameter>::const_iterator i;
+ for (i = $3->begin(); i != $3->end(); i++) {
+ if (i->name == "ttl") {
+ $$->ttl = atoi(i->value.c_str());
+ } else if (i->name == "maddr") {
+ $$->maddr = i->value;
+ } else if (i->name == "received") {
+ $$->received = i->value;
+ } else if (i->name == "branch") {
+ $$->branch = i->value;
+ } else if (i->name == "rport") {
+ $$->rport_present = true;
+ if (i->type == t_parameter::VALUE) {
+ $$->rport =
+ atoi(i->value.c_str());
+ }
+ } else {
+ $$->add_extension(*i);
+ }
+ }
+ MEMMAN_DELETE($2); delete $2;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+sent_protocol: T_TOKEN '/' T_TOKEN '/' T_TOKEN {
+ $$ = new t_via();
+ MEMMAN_NEW($$);
+ $$->protocol_name = toupper(*$1);
+ $$->protocol_version = *$3;
+ $$->transport = toupper(*$5);
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($3); delete $3;
+ MEMMAN_DELETE($5); delete $5; }
+;
+
+host: T_TOKEN {
+ $$ = new t_via();
+ MEMMAN_NEW($$);
+ $$->host = *$1;
+ MEMMAN_DELETE($1); delete $1; }
+ | T_TOKEN ':' { CTXT_NUM; } T_NUM { CTXT_INITIAL; } {
+ if ($4 > 65535) YYERROR;
+
+ $$ = new t_via();
+ MEMMAN_NEW($$);
+ $$->host = *$1;
+ $$->port = $4;
+ MEMMAN_DELETE($1); delete $1; }
+ | ipv6reference {
+ $$ = new t_via();
+ MEMMAN_NEW($$);
+ $$->host = *$1;
+ MEMMAN_DELETE($1); delete $1; }
+ | ipv6reference ':' { CTXT_NUM; } T_NUM { CTXT_INITIAL; } {
+ $$ = new t_via();
+ MEMMAN_NEW($$);
+ $$->host = *$1;
+ $$->port = $4;
+ MEMMAN_DELETE($1); delete $1; }
+;
+
+ipv6reference: '[' { CTXT_IPV6ADDR; } T_IPV6ADDR { CTXT_INITIAL; } ']' {
+ // TODO: check correct format of IPv6 address
+ $$ = new string('[' + *$3 + ']');
+ MEMMAN_NEW($$);
+ MEMMAN_DELETE($3); }
+;
+
+hdr_warning: warning {
+ MSG->hdr_warning.add_warning(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_warning ',' warning {
+ MSG->hdr_warning.add_warning(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+warning: { CTXT_NUM; } T_NUM { CTXT_INITIAL; } host T_QSTRING {
+ $$ = new t_warning();
+ MEMMAN_NEW($$);
+ $$->code = $2;
+ $$->host = $4->host;
+ $$->port = $4->port;
+ $$->text = *$5;
+ MEMMAN_DELETE($4); delete $4;
+ MEMMAN_DELETE($5); delete $5; }
+;
+
+hdr_unknown: { CTXT_LINE; } T_LINE { CTXT_INITIAL; } { $$ = $2; }
+;
+
+ainfo: parameter {
+ if ($1->name == "nextnonce")
+ MSG->hdr_auth_info.set_next_nonce($1->value);
+ else if ($1->name == "qop")
+ MSG->hdr_auth_info.set_message_qop($1->value);
+ else if ($1->name == "rspauth")
+ MSG->hdr_auth_info.set_response_auth($1->value);
+ else if ($1->name == "cnonce")
+ MSG->hdr_auth_info.set_cnonce($1->value);
+ else if ($1->name == "nc") {
+ MSG->hdr_auth_info.set_nonce_count(
+ hex2int($1->value));
+ }
+ else {
+ YYERROR;
+ }
+
+ MEMMAN_DELETE($1); delete $1; }
+;
+
+hdr_authentication_info: ainfo
+ | hdr_authentication_info ',' ainfo
+;
+
+digest_response: parameter {
+ $$ = new t_digest_response();
+ MEMMAN_NEW($$);
+ if (!$$->set_attr(*$1)) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+ MEMMAN_DELETE($1); delete $1; }
+ | digest_response ',' parameter {
+ $$ = $1;
+ if (!$$->set_attr(*$3)) {
+ YYERROR;
+ }
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+auth_params: parameter {
+ $$ = new list<t_parameter>;
+ MEMMAN_NEW($$);
+ $$->push_back(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+ | auth_params ',' parameter {
+ $$ = $1;
+ $$->push_back(*$3);
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+credentials: T_AUTH_DIGEST { CTXT_INITIAL; } digest_response {
+ $$ = new t_credentials;
+ MEMMAN_NEW($$);
+ $$->auth_scheme = AUTH_DIGEST;
+ $$->digest_response = *$3;
+ MEMMAN_DELETE($3); delete $3; }
+ | T_AUTH_OTHER { CTXT_INITIAL; } auth_params {
+ $$ = new t_credentials;
+ MEMMAN_NEW($$);
+ $$->auth_scheme = *$1;
+ $$->auth_params = *$3;
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_authorization: { CTXT_AUTH_SCHEME; } credentials {
+ MSG->hdr_authorization.add_credentials(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+digest_challenge: parameter {
+ $$ = new t_digest_challenge();
+ MEMMAN_NEW($$);
+ if (!$$->set_attr(*$1)) {
+ MEMMAN_DELETE($$); delete $$;
+ YYERROR;
+ }
+ MEMMAN_DELETE($1); delete $1; }
+ | digest_challenge ',' parameter {
+ $$ = $1;
+ if (!$$->set_attr(*$3)) {
+ YYERROR;
+ }
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+challenge: T_AUTH_DIGEST { CTXT_INITIAL; } digest_challenge {
+ $$ = new t_challenge;
+ MEMMAN_NEW($$);
+ $$->auth_scheme = AUTH_DIGEST;
+ $$->digest_challenge = *$3;
+ MEMMAN_DELETE($3); delete $3; }
+ | T_AUTH_OTHER { CTXT_INITIAL; } auth_params {
+ $$ = new t_challenge;
+ MEMMAN_NEW($$);
+ $$->auth_scheme = *$1;
+ $$->auth_params = *$3;
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_proxy_authenticate: { CTXT_AUTH_SCHEME; } challenge {
+ MSG->hdr_proxy_authenticate.set_challenge(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_proxy_authorization: { CTXT_AUTH_SCHEME; } credentials {
+ MSG->hdr_proxy_authorization.
+ add_credentials(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_www_authenticate: { CTXT_AUTH_SCHEME; } challenge {
+ MSG->hdr_www_authenticate.set_challenge(*$2);
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_rseq: { CTXT_NUM; } T_NUM { CTXT_INITIAL; } {
+ MSG->hdr_rseq.set_resp_nr($2); }
+;
+
+hdr_rack: { CTXT_NUM; } T_NUM T_NUM { CTXT_INITIAL; } T_TOKEN {
+ MSG->hdr_rack.set_resp_nr($2);
+ MSG->hdr_rack.set_cseq_nr($3);
+ MSG->hdr_rack.set_method(*$5);
+ MEMMAN_DELETE($5); delete $5; }
+;
+
+hdr_event: T_TOKEN parameters {
+ MSG->hdr_event.set_event_type(tolower(*$1));
+ list<t_parameter>::const_iterator i;
+ for (i = $2->begin(); i != $2->end(); i++) {
+ if (i->name == "id") {
+ MSG->hdr_event.set_id(i->value);
+ } else {
+ MSG->hdr_event.add_event_param(*i);
+ }
+ }
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_allow_events: T_TOKEN {
+ MSG->hdr_allow_events.add_event_type(tolower(*$1));
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_allow_events ',' T_TOKEN {
+ MSG->hdr_allow_events.add_event_type(tolower(*$3));
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_subscription_state: T_TOKEN parameters {
+ MSG->hdr_subscription_state.set_substate(tolower(*$1));
+ list<t_parameter>::const_iterator i;
+ for (i = $2->begin(); i != $2->end(); i++) {
+ if (i->name == "reason") {
+ MSG->hdr_subscription_state.
+ set_reason(tolower(i->value));
+ } else if (i->name == "expires") {
+ MSG->hdr_subscription_state.
+ set_expires(strtoul(
+ i->value.c_str(),
+ NULL, 10));
+ } else if (i->name == "retry-after") {
+ MSG->hdr_subscription_state.
+ set_retry_after(strtoul(
+ i->value.c_str(),
+ NULL, 10));
+ } else {
+ MSG->hdr_subscription_state.
+ add_extension(*i);
+ }
+ }
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_refer_to: { CTXT_URI_SPECIAL; } from_addr parameters {
+ MSG->hdr_refer_to.set_display($2->display);
+ MSG->hdr_refer_to.set_uri($2->uri);
+ MSG->hdr_refer_to.set_params(*$3);
+ MEMMAN_DELETE($2); delete $2;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_referred_by: { CTXT_URI_SPECIAL; } from_addr parameters {
+ MSG->hdr_referred_by.set_display($2->display);
+ MSG->hdr_referred_by.set_uri($2->uri);
+ list<t_parameter>::const_iterator i;
+ for (i = $3->begin(); i != $3->end(); i++) {
+ if (i->name == "cid") {
+ MSG->hdr_referred_by.set_cid(i->value);
+ } else {
+ MSG->hdr_referred_by.add_param(*i);
+ }
+ }
+ MEMMAN_DELETE($2); delete $2;
+ MEMMAN_DELETE($3); delete $3; }
+;
+
+hdr_refer_sub: T_TOKEN parameters {
+ string value(tolower(*$1));
+ if (value != "true" && value != "false") {
+ YYERROR;
+ }
+ MSG->hdr_refer_sub.set_create_refer_sub(value == "true");
+ MSG->hdr_refer_sub.set_extensions(*$2);
+ MEMMAN_DELETE($1); delete $1;
+ MEMMAN_DELETE($2); delete $2; }
+;
+
+hdr_sip_etag: T_TOKEN {
+ MSG->hdr_sip_etag.set_etag(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+;
+
+hdr_sip_if_match: T_TOKEN {
+ MSG->hdr_sip_if_match.set_etag(*$1);
+ MEMMAN_DELETE($1); delete $1; }
+;
+
+hdr_request_disposition: T_TOKEN {
+ bool ret = MSG->hdr_request_disposition.set_directive(*$1);
+ if (!ret) YYERROR;
+ MEMMAN_DELETE($1); delete $1; }
+ | hdr_request_disposition ',' T_TOKEN {
+ bool ret = MSG->hdr_request_disposition.set_directive(*$3);
+ if (!ret) YYERROR;
+ MEMMAN_DELETE($3); delete $3; }
+
+%%
+
+void
+yyerror (const char *s) /* Called by yyparse on error */
+{
+ // printf ("%s\n", s);
+}
diff --git a/src/parser/request.cpp b/src/parser/request.cpp
new file mode 100644
index 0000000..1e678d4
--- /dev/null
+++ b/src/parser/request.cpp
@@ -0,0 +1,769 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "request.h"
+#include "util.h"
+#include "parse_ctrl.h"
+#include "protocol.h"
+#include "milenage.h"
+#include "audits/memman.h"
+#include <sstream>
+#include <cc++/digest.h>
+
+using namespace ost;
+
+// AKAv1-MD5 algorithm specific helpers
+
+#define B64_ENC_SZ(x) (4 * ((x + 2) / 3))
+#define B64_DEC_SZ(x) (3 * ((x + 3) / 4))
+
+int b64_enc(const u8 * src, u8 * dst, int len)
+{
+ static char tbl[64] = {
+ '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','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','0','1','2','3',
+ '4','5','6','7','8','9','+','/'
+ };
+ u8 * dst0 = dst;
+ int i, v, div = len / 3, mod = len % 3;
+
+ for (i = 0; i < div * 3; i += 3) {
+
+ v = (src[i+0] & 0xfc) >> 2;
+ *(dst++) = tbl[v];
+
+ v = (src[i+0] & 0x03) << 4;
+ v |= (src[i+1] & 0xf0) >> 4;
+ *(dst++) = tbl[v];
+
+ v = (src[i+1] & 0x0f) << 2;
+ v |= (src[i+2] & 0xc0) >> 6;
+ *(dst++) = tbl[v];
+
+ v = src[i+2] & 0x3f;
+ *(dst++) = tbl[v];
+ }
+
+ if (mod == 1) {
+ v = (src[i+0] & 0xfc) >> 2;
+ *(dst++) = tbl[v];
+
+ v = (src[i+0] & 0x03) << 4;
+ *(dst++) = tbl[v];
+
+ *(dst++) = '=';
+ *(dst++) = '=';
+ } else if (mod == 2) {
+ v = (src[i+0] & 0xfc) >> 2;
+ *(dst++) = tbl[v];
+
+ v = (src[i+0] & 0x03) << 4;
+ v |= (src[i+1] & 0xf0) >> 4;
+ *(dst++) = tbl[v];
+
+ v = (src[i+1] & 0x0f) << 2;
+ *(dst++) = tbl[v];
+
+ *(dst++) = '=';
+ }
+
+ return dst - dst0;
+}
+
+static int b64_val(u8 x)
+{
+ if (x >= 'A' && x <= 'Z')
+ return x - 'A';
+ else if (x >= 'a' && x <= 'z')
+ return x - 'a' + 26;
+ else if (x >= '0' && x <= '9')
+ return x - '0' + 52;
+ else if (x == '+')
+ return 62;
+ else if (x == '/')
+ return 63;
+ //else if (x == '=')
+ return -1;
+}
+
+int b64_dec(const u8 * src, u8 * dst, int len)
+{
+ u8 * dst0 = dst;
+ int i, x1, x2, x3, x4;
+
+ if (len % 4)
+ return 0;
+
+ for (i=0; i+4 < len; i += 4) {
+ x1 = b64_val(*(src++));
+ x2 = b64_val(*(src++));
+ x3 = b64_val(*(src++));
+ x4 = b64_val(*(src++));
+
+ *(dst++) = (x1 << 2) | ((x2 & 0x30) >> 4);
+ *(dst++) = ((x2 & 0x0F) << 4) | ((x3 & 0x3C) >> 2);
+ *(dst++) = ((x3 & 0x03) << 6) | (x4 & 0x3F);
+ }
+
+ if (len) {
+ x1 = b64_val(*(src++));
+ x2 = b64_val(*(src++));
+ x3 = b64_val(*(src++));
+ x4 = b64_val(*(src++));
+
+ *(dst++) = (x1 << 2) | ((x2 & 0x30) >> 4);
+ if (x3 != -1) {
+ *(dst++) = ((x2 & 0x0F) << 4) | ((x3 & 0x3C) >> 2);
+ if (x4 != -1)
+ *(dst++) = ((x3 & 0x03) << 6) | (x4 & 0x3F);
+ }
+ }
+
+ return dst - dst0;
+}
+
+#define HASH_HEX_LEN 32
+#define HASH_LEN 16
+
+// authentication with AKAv1-MD5 algorithm (RFC 3310)
+
+bool t_request::authorize_akav1_md5(const t_digest_challenge &dchlg,
+ const string &username, const string &passwd, uint8 *op, uint8 *amf,
+ unsigned long nc,
+ const string &cnonce, const string &qop, string &resp,
+ string &fail_reason) const
+{
+ u8 nonce64[B64_DEC_SZ(dchlg.nonce.size())];
+ int len = b64_dec((const u8 *)dchlg.nonce.c_str(), nonce64, dchlg.nonce.size());
+ u8 rnd[AKA_RANDLEN];
+ u8 sqnxoraka[AKA_SQNLEN];
+ u8 sqn[AKA_SQNLEN];
+ u8 k[AKA_KLEN];
+ u8 res[AKA_RESLEN];
+ u8 ck[AKA_CKLEN];
+ u8 ik[AKA_IKLEN];
+ u8 ak[AKA_AKLEN];
+ int i;
+
+ if (len < AKA_RANDLEN+AKA_AUTNLEN) {
+ fail_reason = "nonce base64 data too short (need 32 bytes)";
+ return false;
+ }
+
+ memset(rnd, 0, AKA_RANDLEN);
+ memset(sqnxoraka, 0, AKA_SQNLEN);
+ memset(k, 0, AKA_KLEN);
+
+ memcpy(rnd, nonce64, AKA_RANDLEN);
+ memcpy(sqnxoraka, nonce64 + AKA_RANDLEN, AKA_SQNLEN);
+ memcpy(k, passwd.c_str(), passwd.size());
+
+ f2345(k, rnd, res, ck, ik, ak, op);
+
+ for (i=0; i < AKA_SQNLEN; i++)
+ sqn[i] = sqnxoraka[i] ^ ak[i];
+
+ string res_str = string((char *)res, AKA_RESLEN);
+
+ return authorize_md5(dchlg, username, res_str, nc, cnonce, qop,
+ resp, fail_reason);
+}
+
+// authentication with MD5 algorithm
+
+bool t_request::authorize_md5(const t_digest_challenge &dchlg,
+ const string &username, const string &passwd, unsigned long nc,
+ const string &cnonce, const string &qop, string &resp,
+ string &fail_reason) const
+{
+ string A1, A2;
+ // RFC 2617 3.2.2.2
+ A1 = username + ":" + dchlg.realm + ":" + passwd;
+
+ // RFC 2617 3.2.2.3
+ if (cmp_nocase(qop, QOP_AUTH) == 0 || qop == "") {
+ A2 = method2str(method, unknown_method) + ":" + uri.encode();
+ } else {
+ A2 = method2str(method, unknown_method) + ":" + uri.encode();
+ A2 += ":";
+ if (body) {
+ MD5Digest MD5body;
+ MD5body << body->encode();
+ ostringstream os;
+ os << MD5body;
+ A2 += os.str();
+ } else {
+ MD5Digest MD5body;
+ MD5body << "";
+ ostringstream os;
+ os << MD5body;
+ A2 += os.str();
+ }
+ }
+
+ // RFC 2716 3.2.2.1
+ // Caculate digest
+ MD5Digest MD5A1;
+ MD5Digest MD5A2;
+ ostringstream HA1;
+ ostringstream HA2;
+
+ MD5A1 << A1;
+ MD5A2 << A2;
+ HA1 << MD5A1;
+ HA2 << MD5A2;
+
+ string x;
+
+ if (cmp_nocase(qop, QOP_AUTH) == 0 || cmp_nocase(qop, QOP_AUTH_INT) == 0) {
+ x = HA1.str() + ":";
+ x += dchlg.nonce + ":";
+ x += int2str(nc, "%08x") + ":";
+ x += cnonce + ":";
+ x += qop + ":";
+ x += HA2.str();
+ } else {
+ x = HA1.str() + ":";
+ x += dchlg.nonce + ":";
+ x += HA2.str();
+ }
+
+ MD5Digest digest;
+ digest << x;
+ ostringstream dresp;
+ dresp << digest;
+
+ resp = dresp.str();
+
+ return true;
+}
+
+bool t_request::authorize(const t_challenge &chlg, t_user *user_config,
+ const string &username, const string &passwd, unsigned long nc,
+ const string &cnonce, t_credentials &cr, string &fail_reason) const
+{
+ // Only Digest authentication is supported
+ if (cmp_nocase(chlg.auth_scheme, AUTH_DIGEST) != 0) {
+ fail_reason = "Authentication scheme " + chlg.auth_scheme;
+ fail_reason += " not supported.";
+ return false;
+ }
+
+ const t_digest_challenge &dchlg = chlg.digest_challenge;
+
+ string qop = "";
+
+ // Determine QOP
+ // If both auth and auth-int are supported by the server, then
+ // choose auth to avoid problems with SIP ALGs. A SIP ALG rewrites
+ // the body of a message, thereby breaking auth-int authentication.
+ if (!dchlg.qop_options.empty()) {
+ const list<string>::const_iterator i = find(
+ dchlg.qop_options.begin(), dchlg.qop_options.end(),
+ QOP_AUTH_INT);
+ const list<string>::const_iterator j = find(
+ dchlg.qop_options.begin(), dchlg.qop_options.end(),
+ QOP_AUTH);
+ if (j != dchlg.qop_options.end())
+ qop = QOP_AUTH;
+ else {
+ if (i != dchlg.qop_options.end())
+ qop = QOP_AUTH_INT;
+ else {
+ fail_reason = "Non of the qop values are supported.";
+ return false;
+ }
+ }
+ }
+
+ bool ret = false;
+ string resp;
+
+ if (cmp_nocase(dchlg.algorithm, ALG_MD5) == 0) {
+ ret = authorize_md5(dchlg, username, passwd, nc, cnonce,
+ qop, resp, fail_reason);
+ } else if (cmp_nocase(dchlg.algorithm, ALG_AKAV1_MD5) == 0) {
+ uint8 aka_op[AKA_OPLEN];
+ uint8 aka_amf[AKA_AMFLEN];
+ user_config->get_auth_aka_op(aka_op);
+ user_config->get_auth_aka_amf(aka_amf);
+
+ ret = authorize_akav1_md5(dchlg, username, passwd, aka_op, aka_amf, nc, cnonce,
+ qop, resp, fail_reason);
+ } else {
+ fail_reason = "Authentication algorithm " + dchlg.algorithm;
+ fail_reason += " not supported.";
+ return false;
+ }
+
+ if (!ret) return false;
+
+ // Create credentials
+ cr.auth_scheme = AUTH_DIGEST;
+ t_digest_response &dr = cr.digest_response;
+
+ dr.dresponse = resp;
+ dr.username = username;
+ dr.realm = dchlg.realm;
+ dr.nonce = dchlg.nonce;
+ dr.digest_uri = uri;
+ dr.algorithm = dchlg.algorithm;
+ dr.opaque = dchlg.opaque;
+
+ // RFC 2617 3.2.2
+ if (qop != "") {
+ dr.message_qop = qop;
+ dr.cnonce = cnonce;
+ dr.nonce_count = nc;
+ }
+
+ return true;
+}
+
+t_request::t_request() : t_sip_message(),
+ transport_specified(false),
+ method(METHOD_UNKNOWN)
+{
+}
+
+t_request::t_request(const t_request &r) : t_sip_message(r),
+ destinations(r.destinations),
+ transport_specified(r.transport_specified),
+ uri(r.uri),
+ method(r.method),
+ unknown_method(r.unknown_method)
+{
+}
+
+t_request::t_request(const t_method m) : t_sip_message() {
+ method = m;
+}
+
+void t_request::set_method(const string &s) {
+ method = str2method(s);
+ if (method == METHOD_UNKNOWN) {
+ unknown_method = s;
+ }
+}
+
+string t_request::encode(bool add_content_length) {
+ string s;
+
+ s = method2str(method, unknown_method) + ' ' + uri.encode();
+ s += " SIP/";
+ s += version;
+ s += CRLF;
+ s += t_sip_message::encode(add_content_length);
+ return s;
+}
+
+list<string> t_request::encode_env(void) {
+ string s;
+ list<string> l = t_sip_message::encode_env();
+
+ s = "SIPREQUEST_METHOD=";
+ s += method2str(method, unknown_method);
+ l.push_back(s);
+
+ s = "SIPREQUEST_URI=";
+ s += uri.encode();
+ l.push_back(s);
+
+ return l;
+}
+
+t_sip_message *t_request::copy(void) const {
+ t_sip_message *m = new t_request(*this);
+ MEMMAN_NEW(m);
+ return m;
+}
+
+void t_request::set_route(const t_url &target_uri, const list<t_route> &route_set) {
+ // RFC 3261 12.2.1.1
+ if (route_set.empty()) {
+ uri = target_uri;
+ } else {
+ if (route_set.front().uri.get_lr()) {
+ // Loose routing
+ uri = target_uri;
+ for (list<t_route>::const_iterator i = route_set.begin();
+ i != route_set.end(); ++i)
+ {
+ hdr_route.add_route(*i);
+ }
+ hdr_route.route_to_first_route = true;
+ } else {
+ // Strict routing
+ uri = route_set.front().uri;
+ for (list<t_route>::const_iterator i = route_set.begin();
+ i != route_set.end(); ++i)
+ {
+ if (i != route_set.begin()) {
+ hdr_route.add_route(*i);
+ }
+ }
+
+ // Add target uri to the route list
+ t_route route;
+ route.uri = target_uri;
+ hdr_route.add_route(route);
+ }
+ }
+}
+
+t_response *t_request::create_response(int code, string reason) const
+{
+ t_response *r;
+
+ r = new t_response(code, reason);
+ MEMMAN_NEW(r);
+
+ r->src_ip_port_request = src_ip_port;
+
+ r->hdr_from = hdr_from;
+ r->hdr_call_id = hdr_call_id;
+ r->hdr_cseq = hdr_cseq;
+ r->hdr_via = hdr_via;
+ r->hdr_to = hdr_to;
+
+ // Create a to-tag if none was present in the request
+ // NOTE: 100 Trying should not get a to-tag
+ if (hdr_to.tag.size() == 0 && code != R_100_TRYING) {
+ r->hdr_to.set_tag(NEW_TAG);
+ }
+
+ // Server
+ SET_HDR_SERVER(r->hdr_server);
+
+ return r;
+}
+
+bool t_request::is_valid(bool &fatal, string &reason) const {
+ if (!t_sip_message::is_valid(fatal, reason)) return false;
+
+ fatal = false;
+
+ if (t_parser::check_max_forwards && !hdr_max_forwards.is_populated()) {
+ reason = "Max-Forwards header missing";
+ return false;
+ }
+
+ // RFC 3261 8.1.1.5
+ // The CSeq method must match the request method.
+ if (hdr_cseq.method != method) {
+ reason = "CSeq method does not match request method";
+ return false;
+ }
+
+ switch(method) {
+ case INVITE:
+ if (!hdr_contact.is_populated()) {
+ reason = "Contact header missing";
+ return false;
+ }
+ break;
+ case PRACK:
+ // RFC 3262 7.1
+ if (!hdr_rack.is_populated()) {
+ reason = "RAck header missing";
+ return false;
+ }
+ break;
+ case SUBSCRIBE:
+ // RFC 3265 7.1, 7.2
+ if (!hdr_contact.is_populated()) {
+ reason = "Contact header missing";
+ return false;
+ }
+
+ if (!hdr_event.is_populated()) {
+ reason = "Event header missing";
+ return false;
+ }
+ break;
+ case NOTIFY:
+ // RFC 3265 7.1, 7.2
+ if (!hdr_contact.is_populated()) {
+ reason = "Contact header missing";
+ return false;
+ }
+
+ if (!hdr_event.is_populated()) {
+ reason = "Event header missing";
+ return false;
+ }
+
+ // RFC 3265 7.2
+ // Subscription-State header is mandatory
+ // As an exception Twinkle allows an unsollicited NOTIFY for MWI
+ // without a Subscription-State header. Asterisk sends
+ // unsollicited NOTIFY requests.
+ if (!hdr_to.tag.empty() ||
+ hdr_event.event_type != SIP_EVENT_MSG_SUMMARY)
+ {
+ if (!hdr_subscription_state.is_populated()) {
+ reason = "Subscription-State header missing";
+ return false;
+ }
+ }
+
+ // The Subscription-State header is mandatory.
+ // However, Asterisk uses an expired draft for sending
+ // unsollicitied NOTIFY messages without a Subscription-State
+ // header. As Asterisk is popular, Twinkle allows this.
+ break;
+ case REFER:
+ // RFC 3515 2.4.1
+ if (!hdr_refer_to.is_populated()) {
+ reason = "Refer-To header missing";
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (hdr_replaces.is_populated()) {
+ // RFC 3891 3
+ if (method != INVITE) {
+ reason = "Replaces header not allowed";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void t_request::add_destinations(const t_user &user_profile, const t_url &dst_uri) {
+ t_url dest;
+ if (dst_uri.get_scheme() == "tel")
+ {
+ // Send a tel-URI to the configure domain for the user.
+ dest = "sip:" + user_profile.get_domain();
+ }
+ else
+ {
+ dest = dst_uri;
+ }
+
+ if ((user_profile.get_sip_transport() == SIP_TRANS_AUTO ||
+ user_profile.get_sip_transport() == SIP_TRANS_TCP)
+ &&
+ (dest.get_transport().empty() ||
+ cmp_nocase(dest.get_transport(), "tcp") == 0))
+ {
+ list<t_ip_port> l = dest.get_h_ip_srv("tcp");
+ destinations.insert(destinations.end(), l.begin(), l.end());
+ }
+
+ // Add UDP destinations after TCP, so UDP will be used as a fallback
+ // for large messages, when TCP fails. If the message is not large,
+ // then the TCP destinations will be removed later.
+ // NOTE: If a message is larger than 64K, it cannot be sent via UDP
+ if ((user_profile.get_sip_transport() == SIP_TRANS_AUTO ||
+ user_profile.get_sip_transport() == SIP_TRANS_UDP)
+ &&
+ (dest.get_transport().empty() ||
+ cmp_nocase(dest.get_transport(), "udp") == 0)
+ &&
+ (get_encoded_size() < 65536))
+ {
+ list<t_ip_port> l = dest.get_h_ip_srv("udp");
+ destinations.insert(destinations.end(), l.begin(), l.end());
+ }
+
+ transport_specified = !dest.get_transport().empty();
+}
+
+void t_request::calc_destinations(const t_user &user_profile) {
+ destinations.clear();
+
+ // Send a REGISTER to the registrar if provisioned.
+ if (method == REGISTER && user_profile.get_use_registrar()) {
+ add_destinations(user_profile, user_profile.get_registrar());
+ return;
+ }
+
+ // Bypass the proxy for an out-of-dialog SUBSCRIBE if provisioned.
+ if (method == SUBSCRIBE && hdr_to.tag.empty()) {
+ if (hdr_event.event_type == SIP_EVENT_MSG_SUMMARY) {
+ if (!user_profile.get_mwi_via_proxy()) {
+ // Take Request-URI
+ add_destinations(user_profile, uri);
+ return;
+ }
+ }
+ }
+
+ if (!user_profile.get_use_outbound_proxy() ||
+ (hdr_to.tag != "" && !user_profile.get_all_requests_to_proxy())) {
+ // A mid dialog request will go to the host in the contact
+ // header (put in the request-URI in this request) or route list
+ // specified in the final response of the invite (the Route-header in
+ // this request).
+ // Note that an ACK for a failed INVITE (3XX-6XX) will be
+ // sent by the transaction layer to the ipaddr/port of the
+ // INVITE.
+ if (hdr_route.is_populated() && hdr_route.route_to_first_route) {
+ // Take URI from first route-header
+ t_url &u = hdr_route.route_list.front().uri;
+ add_destinations(user_profile, u);
+ } else {
+ // Take Request-URI
+ add_destinations(user_profile, uri);
+ }
+ }
+
+ // Send request to outbound proxy if configured
+ if (user_profile.get_use_outbound_proxy()) {
+ if (user_profile.get_non_resolvable_to_proxy() && !destinations.empty())
+ {
+ // The destination has been resolved, so do not
+ // use the outbound proxy in this case.
+ return;
+ }
+
+ if (user_profile.get_all_requests_to_proxy() || hdr_to.tag == "") {
+ // All requests should go to the proxy.
+ // Override destination by the outbound proxy address.
+ destinations.clear();
+ add_destinations(user_profile, user_profile.get_outbound_proxy());
+ }
+ }
+}
+
+void t_request::get_destination(t_ip_port &ip_port, const t_user &user_profile) {
+ if (destinations.empty()) calc_destinations(user_profile);
+
+ // RFC 3261 18.1.1
+ // If the message size is larger than 1300 then the message must be
+ // sent over TCP.
+ // If the destination URI indicated an explicit transport, then the
+ // destination calculation picked the possible destinations already.
+ // The size cannot influence this calculation anymore.
+ if (user_profile.get_sip_transport() == SIP_TRANS_AUTO &&
+ !destinations.empty() &&
+ destinations.front().transport == "tcp" &&
+ get_encoded_size() <= user_profile.get_sip_transport_udp_threshold() &&
+ !transport_specified)
+ {
+ // The message can be sent over UDP. Remove all TCP destinations.
+ while (!destinations.empty() && destinations.front().transport == "tcp") {
+ destinations.pop_front();
+ }
+ }
+
+ get_current_destination(ip_port);
+}
+
+void t_request::get_current_destination(t_ip_port &ip_port) {
+ if (destinations.empty()) {
+ // No destinations could be found.
+ ip_port.transport = "udp";
+ ip_port.ipaddr = 0;
+ ip_port.port = 0;
+ } else {
+ // Return first destination
+ ip_port = destinations.front();
+ }
+}
+
+bool t_request::next_destination(void) {
+ if (destinations.size() <= 1) return false;
+
+ // Remove current destination
+ destinations.pop_front();
+ return true;
+}
+
+void t_request::set_destination(const t_ip_port &ip_port) {
+ destinations.clear();
+ destinations.push_back(ip_port);
+}
+
+bool t_request::www_authorize(const t_challenge &chlg, t_user *user_config,
+ const string &username, const string &passwd, unsigned long nc,
+ const string &cnonce, t_credentials &cr, string &fail_reason)
+{
+ if (!authorize(chlg, user_config, username, passwd, nc, cnonce, cr, fail_reason)) {
+ return false;
+ }
+
+ hdr_authorization.add_credentials(cr);
+
+ return true;
+}
+
+bool t_request::proxy_authorize(const t_challenge &chlg, t_user *user_config,
+ const string &username, const string &passwd, unsigned long nc,
+ const string &cnonce, t_credentials &cr, string &fail_reason)
+{
+ if (!authorize(chlg, user_config, username, passwd, nc, cnonce, cr, fail_reason)) {
+ return false;
+ }
+
+ hdr_proxy_authorization.add_credentials(cr);
+
+ return true;
+}
+
+void t_request::calc_local_ip(void) {
+ t_ip_port dst;
+
+ get_current_destination(dst);
+ if (dst.ipaddr != 0) {
+ local_ip_ = get_src_ip4_address_for_dst(dst.ipaddr);
+ }
+}
+
+bool t_request::is_registration_request(void) const {
+ if (method != REGISTER) return false;
+
+ if (hdr_expires.is_populated() && hdr_expires.time > 0) return true;
+
+ if (hdr_contact.is_populated() &&
+ !hdr_contact.contact_list.empty() &&
+ hdr_contact.contact_list.front().is_expires_present() &&
+ hdr_contact.contact_list.front().get_expires() > 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool t_request::is_de_registration_request(void) const {
+ if (method != REGISTER) return false;
+
+ if (hdr_expires.is_populated() && hdr_expires.time == 0) return true;
+
+ if (hdr_contact.is_populated() &&
+ !hdr_contact.contact_list.empty() &&
+ hdr_contact.contact_list.front().is_expires_present() &&
+ hdr_contact.contact_list.front().get_expires() == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/parser/request.h b/src/parser/request.h
new file mode 100644
index 0000000..a2fe879
--- /dev/null
+++ b/src/parser/request.h
@@ -0,0 +1,218 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Request
+
+#ifndef _REQUEST_H
+#define _REQUEST_H
+
+#include <string>
+#include "response.h"
+#include "sip_message.h"
+#include "sockets/url.h"
+#include "user.h"
+
+// Forward declaration
+class t_user;
+
+using namespace std;
+
+class t_request : public t_sip_message {
+private:
+ /**
+ * A DNS lookup on the request URI (or outbound proxy) might resolve
+ * into multiple destinations. @ref get_destination() will return the first
+ * destination. All destinations are stored here.
+ * @ref next_destination() will remove the first destination of this
+ * list.
+ */
+ list<t_ip_port> destinations;
+
+ /**
+ * Indicates if the destination specified a transport, i.e. via the
+ * transport parameter in a URI.
+ */
+ bool transport_specified;
+
+ /**
+ * Add destinations for a given URI based on transport settings.
+ * @param user_profile [in] User profile
+ * @param dst_uri [in] The URI to resolve.
+ */
+ void add_destinations(const t_user &user_profile, const t_url &dst_uri);
+
+ /**
+ * Calculate credentials based on the challenge.
+ * @param chlg [in] The challenge
+ * @param user_config [in] User configuration for user to be authorized.
+ * @param username [in] User authentication name
+ * @param passwd [in] Authentication password.
+ * @param nc [in] Nonce count
+ * @param cnonce [in] Client nonce
+ * @param cr [out] Credentials on succesful return.
+ * @param fail_reason [out] Failure reason on failure return.
+ * @return false, if authorization fails.
+ * @return true, if authorization succeeded
+ */
+ bool authorize(const t_challenge &chlg, t_user *user_config,
+ const string &username, const string &passwd, unsigned long nc,
+ const string &cnonce, t_credentials &cr,
+ string &fail_reason) const;
+
+ /**
+ * Calculate MD5 response based on the challenge.
+ * @param chlg [in] The challenge
+ * @param username [in] User authentication name
+ * @param passwd [in] Authentication password.
+ * @param nc [in] Nonce count
+ * @param cnonce [in] Client nonce
+ * @param qop [in] Quality of protection
+ * @param resp [out] Response on succesful return.
+ * @param fail_reason [out] Failure reason on failure return.
+ * @return false, if authorization fails.
+ * @return true, if authorization succeeded
+ */
+ bool authorize_md5(const t_digest_challenge &dchlg,
+ const string &username, const string &passwd, unsigned long nc,
+ const string &cnonce, const string &qop, string &resp,
+ string &fail_reason) const;
+
+ /**
+ * Calculate AKAv1-MD5 response based on the challenge.
+ * @param chlg [in] The challenge
+ * @param username [in] User authentication name
+ * @param passwd [in] Authentication password.
+ * @param op [in] Operator variant key
+ * @param amf [in] Authentication method field
+ * @param nc [in] Nonce count
+ * @param cnonce [in] Client nonce
+ * @param qop [in] Quality of protection
+ * @param resp [out] Response on succesful return.
+ * @param fail_reason [out] Failure reason on failure return.
+ * @return false, if authorization fails.
+ * @return true, if authorization succeeded
+ */
+ bool authorize_akav1_md5(const t_digest_challenge &dchlg,
+ const string &username, const string &passwd,
+ uint8 *op, uint8 *amf,
+ unsigned long nc,
+ const string &cnonce, const string &qop, string &resp,
+ string &fail_reason) const;
+
+
+public:
+ t_url uri;
+ t_method method;
+ string unknown_method; // set if method is UNKNOWN
+
+ t_request();
+ t_request(const t_request &r);
+ t_request(const t_method m);
+
+ t_msg_type get_type(void) const { return MSG_REQUEST; }
+ void set_method(const string &s);
+ string encode(bool add_content_length = true);
+ list<string> encode_env(void);
+ t_sip_message *copy(void) const;
+
+ /**
+ * Set the Request-URI and the Route header.
+ * This is done according to the procedures of RFC 3261 12.2.1.1
+ * @param target_uri [in] The URI of the destination for this request.
+ * @param route_set [in] The route set for this request (may be empty).
+ */
+ void set_route(const t_url &target_uri, const list<t_route> &route_set);
+
+ // Create a response with response code based on the
+ // request. The response is created following the general
+ // rules in RFC 3261 8.2.6.2.
+ // The to-hdr is simply copied from the request to the
+ // response.
+ // If the to-tag is missing, then
+ // a to-tag will be generated and added to the to-header
+ // of the response.
+ // A specific reason may be added to the status code.
+ t_response *create_response(int code, string reason = "") const;
+
+ bool is_valid(bool &fatal, string &reason) const;
+
+ // Calculate the set of possible destinations for this request.
+ void calc_destinations(const t_user &user_profile);
+
+ // Get destination to send this request to.
+ void get_destination(t_ip_port &ip_port, const t_user &user_profile);
+ void get_current_destination(t_ip_port &ip_port);
+
+ // Move to next destination. This method should only be called after
+ // calc_destination() was called.
+ // Returns true if there is a next destination, otherwise returns false.
+ bool next_destination(void);
+
+ // Set a single destination to send this request to.
+ void set_destination(const t_ip_port &ip_port);
+
+ /**
+ * Create WWW authorization credentials based on the challenge.
+ * @param chlg [in] The challenge
+ * @param user_config [in] User configuration for user to be authorized.
+ * @param username [in] User authentication name
+ * @param passwd [in] Authentication password.
+ * @param nc [in] Nonce count
+ * @param cnonce [in] Client nonce
+ * @param cr [out] Credentials on succesful return.
+ * @param fail_reason [out] Failure reason on failure return.
+ * @return false, if challenge is not supported.
+ * @return true, if authorization succeeded
+ */
+ bool www_authorize(const t_challenge &chlg, t_user *user_config,
+ const string &username, const string &passwd, unsigned long nc,
+ const string &cnonce, t_credentials &cr, string &fail_reason);
+
+ /**
+ * Create proxy authorization credentials based on the challenge.
+ * @param chlg [in] The challenge
+ * @param user_config [in] User configuration for user to be authorized.
+ * @param username [in] User authentication name
+ * @param passwd [in] Authentication password.
+ * @param nc [in] Nonce count
+ * @param cnonce [in] Client nonce
+ * @param cr [out] Credentials on succesful return.
+ * @param fail_reason [out] Failure reason on failure return.
+ * @return false, if challenge is not supported.
+ * @return true, if authorization succeeded
+ */
+ bool proxy_authorize(const t_challenge &chlg, t_user *user_config,
+ const string &username, const string &passwd, unsigned long nc,
+ const string &cnonce, t_credentials &cr, string &fail_reason);
+
+ virtual void calc_local_ip(void);
+
+ /**
+ * Check if the request is a registration request.
+ * @return True if the request is a registration request, otherwise false.
+ */
+ bool is_registration_request(void) const;
+
+ /**
+ * Check if the request is a de-registration request.
+ * @return True if the request is a de-registration request, otherwise false.
+ */
+ bool is_de_registration_request(void) const;
+};
+
+#endif
diff --git a/src/parser/response.cpp b/src/parser/response.cpp
new file mode 100755
index 0000000..83f47eb
--- /dev/null
+++ b/src/parser/response.cpp
@@ -0,0 +1,237 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <cassert>
+
+#include "response.h"
+#include "util.h"
+#include "parse_ctrl.h"
+#include "audits/memman.h"
+
+t_response::t_response() : t_sip_message() {}
+
+t_response::t_response(const t_response &r) : t_sip_message(r) ,
+ code(r.code),
+ reason(r.reason),
+ src_ip_port_request(r.src_ip_port_request)
+{
+}
+
+t_response::t_response(int _code, string _reason) : t_sip_message() {
+ code = _code;
+
+ if (_reason == "") {
+ switch (code) {
+ case 100: reason = REASON_100; break;
+ case 180: reason = REASON_180; break;
+ case 181: reason = REASON_181; break;
+ case 182: reason = REASON_182; break;
+ case 183: reason = REASON_183; break;
+ case 200: reason = REASON_200; break;
+ case 202: reason = REASON_202; break;
+ case 300: reason = REASON_300; break;
+ case 301: reason = REASON_301; break;
+ case 302: reason = REASON_302; break;
+ case 305: reason = REASON_305; break;
+ case 380: reason = REASON_380; break;
+ case 400: reason = REASON_400; break;
+ case 401: reason = REASON_401; break;
+ case 402: reason = REASON_402; break;
+ case 403: reason = REASON_403; break;
+ case 404: reason = REASON_404; break;
+ case 405: reason = REASON_405; break;
+ case 406: reason = REASON_406; break;
+ case 407: reason = REASON_407; break;
+ case 408: reason = REASON_408; break;
+ case 410: reason = REASON_410; break;
+ case 412: reason = REASON_412; break;
+ case 413: reason = REASON_413; break;
+ case 414: reason = REASON_414; break;
+ case 415: reason = REASON_415; break;
+ case 416: reason = REASON_416; break;
+ case 420: reason = REASON_420; break;
+ case 421: reason = REASON_421; break;
+ case 423: reason = REASON_423; break;
+ case 480: reason = REASON_480; break;
+ case 481: reason = REASON_481; break;
+ case 482: reason = REASON_482; break;
+ case 483: reason = REASON_483; break;
+ case 484: reason = REASON_484; break;
+ case 485: reason = REASON_485; break;
+ case 486: reason = REASON_486; break;
+ case 487: reason = REASON_487; break;
+ case 488: reason = REASON_488; break;
+ case 489: reason = REASON_489; break;
+ case 491: reason = REASON_491; break;
+ case 493: reason = REASON_493; break;
+ case 500: reason = REASON_500; break;
+ case 501: reason = REASON_501; break;
+ case 502: reason = REASON_502; break;
+ case 503: reason = REASON_503; break;
+ case 504: reason = REASON_504; break;
+ case 505: reason = REASON_505; break;
+ case 513: reason = REASON_513; break;
+ case 600: reason = REASON_600; break;
+ case 603: reason = REASON_603; break;
+ case 604: reason = REASON_604; break;
+ case 606: reason = REASON_606; break;
+ default: reason = "Unknown Error";
+ }
+ } else {
+ reason = _reason;
+ }
+}
+
+int t_response::get_class(void) const {
+ return code / 100;
+}
+
+bool t_response::is_provisional(void) const {
+ return (get_class() == R_1XX);
+}
+
+bool t_response::is_final(void) const {
+ return (get_class() != R_1XX);
+}
+
+bool t_response::is_success(void) const {
+ return (get_class() == R_2XX);
+}
+
+string t_response::encode(bool add_content_length) {
+ string s;
+
+ s = "SIP/" + version + ' ' + int2str(code, "%3d") + ' ' + reason;
+ s += CRLF;
+ s += t_sip_message::encode(add_content_length);
+
+ return s;
+}
+
+list<string> t_response::encode_env(void) {
+ string s;
+
+ list<string> l = t_sip_message::encode_env();
+
+ s = "SIPSTATUS_CODE=";
+ s += int2str(code, "%3d");
+ l.push_back(s);
+
+ s = "SIPSTATUS_REASON=";
+ s += reason;
+ l.push_back(s);
+
+ return l;
+}
+
+t_sip_message *t_response::copy(void) const {
+ t_sip_message *m = new t_response(*this);
+ MEMMAN_NEW(m);
+ return m;
+}
+
+bool t_response::is_valid(bool &fatal, string &reason) const {
+ if (!t_sip_message::is_valid(fatal, reason)) return false;
+
+ fatal = false;
+
+ switch(hdr_cseq.method) {
+ case INVITE:
+ if (get_class() == R_2XX && !hdr_contact.is_populated()) {
+ reason = "Contact header missing";
+ return false;
+ }
+ break;
+ case SUBSCRIBE:
+ // RFC 3265 7.1, 7.2
+ /*
+ Some SIP servers do not send the mandatory Expires header.
+ For interoperability this deviation is allowed.
+ if (get_class()== R_2XX && !hdr_expires.is_populated()) {
+ reason = "Expires header missing";
+ return false;
+ }
+ */
+
+ switch (code) {
+ case R_489_BAD_EVENT:
+ if (!hdr_allow_events.is_populated()) {
+ reason = "Allow-Events header missing";
+ return false;
+ }
+ break;
+ }
+
+ break;
+ case NOTIFY:
+ // RFC 3265 7.1, 7.2
+ switch (code) {
+ case R_489_BAD_EVENT:
+ if (!hdr_allow_events.is_populated()) {
+ reason = "Allow-Events header is missing";
+ return false;
+ }
+ break;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ if (hdr_rseq.is_populated()) {
+ // RFC 3262 7.1
+ // The value ranges from 1 to 2**32 - 1
+ if (hdr_rseq.resp_nr == 0) {
+ reason = "RSeq is zero";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool t_response::must_authenticate(void) const {
+ return (code == R_401_UNAUTHORIZED &&
+ hdr_www_authenticate.is_populated() ||
+ code == R_407_PROXY_AUTH_REQUIRED &&
+ hdr_proxy_authenticate.is_populated());
+}
+
+void t_response::get_destination(t_ip_port &ip_port) const {
+ assert(hdr_via.is_populated());
+
+ if (src_ip_port_request.transport == "tcp") {
+ // RFC 3261 18.2.2
+ // For TCP the response should be sent on the connection on which
+ // the request was received. So the address returned here is the
+ // alternative destination when the connection is closed already.
+ ip_port = src_ip_port_request;
+ } else {
+ hdr_via.get_response_dst(ip_port);
+ }
+}
+
+void t_response::calc_local_ip(void) {
+ t_ip_port dst;
+
+ get_destination(dst);
+ if (dst.ipaddr != 0) {
+ local_ip_ = get_src_ip4_address_for_dst(dst.ipaddr);
+ }
+}
diff --git a/src/parser/response.h b/src/parser/response.h
new file mode 100644
index 0000000..a2f87c6
--- /dev/null
+++ b/src/parser/response.h
@@ -0,0 +1,214 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Response
+
+#ifndef _H_RESPONSE
+#define _H_RESPONSE
+
+#include <string>
+#include "sip_message.h"
+
+using namespace std;
+
+// Repsonse codes
+// Informational
+#define R_100_TRYING 100
+#define R_180_RINGING 180
+#define R_181_CALL_IS_BEING_FORWARDED 181
+#define R_182_QUEUED 182
+#define R_183_SESSION_PROGRESS 183
+
+// Success
+#define R_200_OK 200
+#define R_202_ACCEPTED 202
+
+// Redirection
+#define R_300_MULTIPLE_CHOICES 300
+#define R_301_MOVED_PERMANENTLY 301
+#define R_302_MOVED_TEMPORARILY 302
+#define R_305_USE_PROXY 305
+#define R_380_ALTERNATIVE_SERVICE 380
+
+// Client error
+#define R_400_BAD_REQUEST 400
+#define R_401_UNAUTHORIZED 401
+#define R_402_PAYMENT_REQUIRED 402
+#define R_403_FORBIDDEN 403
+#define R_404_NOT_FOUND 404
+#define R_405_METHOD_NOT_ALLOWED 405
+#define R_406_NOT_ACCEPTABLE 406
+#define R_407_PROXY_AUTH_REQUIRED 407
+#define R_408_REQUEST_TIMEOUT 408
+#define R_410_GONE 410
+#define R_412_CONDITIONAL_REQUEST_FAILED 412
+#define R_413_REQ_ENTITY_TOO_LARGE 413
+#define R_414_REQ_URI_TOO_LARGE 414
+#define R_415_UNSUPPORTED_MEDIA_TYPE 415
+#define R_416_UNSUPPORTED_URI_SCHEME 416
+#define R_420_BAD_EXTENSION 420
+#define R_421_EXTENSION_REQUIRED 421
+#define R_423_INTERVAL_TOO_BRIEF 423
+#define R_480_TEMP_NOT_AVAILABLE 480
+#define R_481_TRANSACTION_NOT_EXIST 481
+#define R_482_LOOP_DETECTED 482
+#define R_483_TOO_MANY_HOPS 483
+#define R_484_ADDRESS_INCOMPLETE 484
+#define R_485_AMBIGUOUS 485
+#define R_486_BUSY_HERE 486
+#define R_487_REQUEST_TERMINATED 487
+#define R_488_NOT_ACCEPTABLE_HERE 488
+#define R_489_BAD_EVENT 489
+#define R_491_REQUEST_PENDING 491
+#define R_493_UNDECIPHERABLE 493
+
+// Server error
+#define R_500_INTERNAL_SERVER_ERROR 500
+#define R_501_NOT_IMPLEMENTED 501
+#define R_502_BAD_GATEWAY 502
+#define R_503_SERVICE_UNAVAILABLE 503
+#define R_504_SERVER_TIMEOUT 504
+#define R_505_SIP_VERSION_NOT_SUPPORTED 505
+#define R_513_MESSAGE_TOO_LARGE 513
+
+// Global failure
+#define R_600_BUSY_EVERYWHERE 600
+#define R_603_DECLINE 603
+#define R_604_NOT_EXIST_ANYWHERE 604
+#define R_606_NOT_ACCEPTABLE 606
+
+// Response classes
+#define R_1XX 1 // Informational
+#define R_2XX 2 // Success
+#define R_3XX 3 // Redirection
+#define R_4XX 4 // Client error
+#define R_5XX 5 // Server error
+#define R_6XX 6 // Global failure
+
+// Default reason strings
+#define REASON_100 "Trying"
+#define REASON_180 "Ringing"
+#define REASON_181 "Call Is Being Forwarded"
+#define REASON_182 "Queued"
+#define REASON_183 "Session Progress"
+
+#define REASON_200 "OK"
+#define REASON_202 "Accepted"
+
+#define REASON_300 "Multiple Choices"
+#define REASON_301 "Moved Permanently"
+#define REASON_302 "Moved Temporarily"
+#define REASON_305 "Use Proxy"
+#define REASON_380 "Alternative Service"
+
+#define REASON_400 "Bad Request"
+#define REASON_401 "Unauthorized"
+#define REASON_402 "Payment Required"
+#define REASON_403 "Forbidden"
+#define REASON_404 "Not Found"
+#define REASON_405 "Method Not Allowed"
+#define REASON_406 "Not Acceptable"
+#define REASON_407 "Proxy Authentication Required"
+#define REASON_408 "Request Timeout"
+#define REASON_410 "Gone"
+#define REASON_412 "Conditional Request Failed"
+#define REASON_413 "Request Entity Too Large"
+#define REASON_414 "Request-URI Too Large"
+#define REASON_415 "Unsupported Media Type"
+#define REASON_416 "Unsupported URI Scheme"
+#define REASON_420 "Bad Extension"
+#define REASON_421 "Extension Required"
+#define REASON_423 "Interval Too Brief"
+#define REASON_480 "Temporarily Not Available"
+#define REASON_481 "Call Leg/Transaction Does Not Exist"
+#define REASON_482 "Loop Detected"
+#define REASON_483 "Too Many Hops"
+#define REASON_484 "Address Incomplete"
+#define REASON_485 "Ambiguous"
+#define REASON_486 "Busy Here"
+#define REASON_487 "Request Terminated"
+#define REASON_488 "Not Acceptable Here"
+#define REASON_489 "Bad Event"
+#define REASON_491 "Request Pending"
+#define REASON_493 "Undecipherable"
+
+#define REASON_500 "Internal Server Error"
+#define REASON_501 "Not Implemented"
+#define REASON_502 "Bad Gateway"
+#define REASON_503 "Service Unavailable"
+#define REASON_504 "Server Time-out"
+#define REASON_505 "SIP Version Not Supported"
+#define REASON_513 "Message Too Large"
+
+#define REASON_600 "Busy Everywhere"
+#define REASON_603 "Decline"
+#define REASON_604 "Does Not Exist Anywhere"
+#define REASON_606 "Not Acceptable"
+
+// The protocol allows a SIP response to have a non-default reason
+// phrase that gives a more detailed reason.
+
+// RFC 3261 21.4.18
+// Code 480 should have a specific reason phrase
+#define REASON_480_NO_ANSWER "User not responding"
+
+// RFC 3265 3.2.4
+#define REASON_481_SUBSCRIPTION_NOT_EXIST "Subscription does not exist"
+
+
+class t_response : public t_sip_message {
+public:
+ int code;
+ string reason;
+
+ /** The source address of the request generating this response. */
+ t_ip_port src_ip_port_request;
+
+ t_response();
+ t_response(const t_response &r);
+ t_response(int _code, string _reason = "");
+
+ t_msg_type get_type(void) const { return MSG_RESPONSE; }
+
+ // Return the response class 1,2,3,4,5,6
+ int get_class(void) const;
+
+ bool is_provisional(void) const;
+ bool is_final(void) const;
+ bool is_success(void) const;
+
+ string encode(bool add_content_length = true);
+ list<string> encode_env(void);
+ t_sip_message *copy(void) const;
+
+ bool is_valid(bool &fatal, string &reason) const;
+
+ // Returns true if the response is a 401/407 with
+ // the proper authenticate header.
+ bool must_authenticate(void) const;
+
+ /**
+ * Get the destination address for sending the response.
+ * @param ip_port [out] The destination address.
+ */
+ void get_destination(t_ip_port &ip_port) const;
+
+ virtual void calc_local_ip(void);
+};
+
+#endif
diff --git a/src/parser/rijndael.cpp b/src/parser/rijndael.cpp
new file mode 100644
index 0000000..0ac000b
--- /dev/null
+++ b/src/parser/rijndael.cpp
@@ -0,0 +1,440 @@
+/*-------------------------------------------------------------------
+ * Rijndael Implementation
+ *-------------------------------------------------------------------
+ *
+ * A sample 32-bit orientated implementation of Rijndael, the
+ * suggested kernel for the example 3GPP authentication and key
+ * agreement functions.
+ *
+ * This implementation draws on the description in section 5.2 of
+ * the AES proposal and also on the implementation by
+ * Dr B. R. Gladman <brg@gladman.uk.net> 9th October 2000.
+ * It uses a number of large (4k) lookup tables to implement the
+ * algorithm in an efficient manner.
+ *
+ * Note: in this implementation the State is stored in four 32-bit
+ * words, one per column of the State, with the top byte of the
+ * column being the _least_ significant byte of the word.
+ *
+*-----------------------------------------------------------------*/
+
+#include "twinkle_config.h"
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+
+/* Circular byte rotates of 32 bit values */
+
+#define rot1(x) ((x << 8) | (x >> 24))
+#define rot2(x) ((x << 16) | (x >> 16))
+#define rot3(x) ((x << 24) | (x >> 8))
+
+/* Extract a byte from a 32-bit u32 */
+
+#define byte0(x) ((u8)(x))
+#define byte1(x) ((u8)(x >> 8))
+#define byte2(x) ((u8)(x >> 16))
+#define byte3(x) ((u8)(x >> 24))
+
+
+/* Put or get a 32 bit u32 (v) in machine order from a byte *
+ * address in (x) */
+
+#ifndef WORDS_BIGENDIAN
+
+#define u32_in(x) (*(u32*)(x))
+#define u32_out(x,y) (*(u32*)(x) = y)
+
+#else
+
+/* Invert byte order in a 32 bit variable */
+
+__inline u32 byte_swap(const u32 x)
+{
+ return rot1(x) & 0x00ff00ff | rot3(x) & 0xff00ff00;
+}
+__inline u32 u32_in(const u8 x[])
+{
+ return byte_swap(*(u32*)x);
+};
+__inline void u32_out(u8 x[], const u32 v)
+{
+ *(u32*)x = byte_swap(v);
+};
+
+#endif
+
+/*--------------- The lookup tables ----------------------------*/
+
+static u32 rnd_con[10] =
+{
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+};
+
+static u32 ft_tab[4][256] =
+{
+ {
+ 0xA56363C6,0x847C7CF8,0x997777EE,0x8D7B7BF6,0x0DF2F2FF,0xBD6B6BD6,0xB16F6FDE,0x54C5C591,
+ 0x50303060,0x03010102,0xA96767CE,0x7D2B2B56,0x19FEFEE7,0x62D7D7B5,0xE6ABAB4D,0x9A7676EC,
+ 0x45CACA8F,0x9D82821F,0x40C9C989,0x877D7DFA,0x15FAFAEF,0xEB5959B2,0xC947478E,0x0BF0F0FB,
+ 0xECADAD41,0x67D4D4B3,0xFDA2A25F,0xEAAFAF45,0xBF9C9C23,0xF7A4A453,0x967272E4,0x5BC0C09B,
+ 0xC2B7B775,0x1CFDFDE1,0xAE93933D,0x6A26264C,0x5A36366C,0x413F3F7E,0x02F7F7F5,0x4FCCCC83,
+ 0x5C343468,0xF4A5A551,0x34E5E5D1,0x08F1F1F9,0x937171E2,0x73D8D8AB,0x53313162,0x3F15152A,
+ 0x0C040408,0x52C7C795,0x65232346,0x5EC3C39D,0x28181830,0xA1969637,0x0F05050A,0xB59A9A2F,
+ 0x0907070E,0x36121224,0x9B80801B,0x3DE2E2DF,0x26EBEBCD,0x6927274E,0xCDB2B27F,0x9F7575EA,
+ 0x1B090912,0x9E83831D,0x742C2C58,0x2E1A1A34,0x2D1B1B36,0xB26E6EDC,0xEE5A5AB4,0xFBA0A05B,
+ 0xF65252A4,0x4D3B3B76,0x61D6D6B7,0xCEB3B37D,0x7B292952,0x3EE3E3DD,0x712F2F5E,0x97848413,
+ 0xF55353A6,0x68D1D1B9,0000000000,0x2CEDEDC1,0x60202040,0x1FFCFCE3,0xC8B1B179,0xED5B5BB6,
+ 0xBE6A6AD4,0x46CBCB8D,0xD9BEBE67,0x4B393972,0xDE4A4A94,0xD44C4C98,0xE85858B0,0x4ACFCF85,
+ 0x6BD0D0BB,0x2AEFEFC5,0xE5AAAA4F,0x16FBFBED,0xC5434386,0xD74D4D9A,0x55333366,0x94858511,
+ 0xCF45458A,0x10F9F9E9,0x06020204,0x817F7FFE,0xF05050A0,0x443C3C78,0xBA9F9F25,0xE3A8A84B,
+ 0xF35151A2,0xFEA3A35D,0xC0404080,0x8A8F8F05,0xAD92923F,0xBC9D9D21,0x48383870,0x04F5F5F1,
+ 0xDFBCBC63,0xC1B6B677,0x75DADAAF,0x63212142,0x30101020,0x1AFFFFE5,0x0EF3F3FD,0x6DD2D2BF,
+ 0x4CCDCD81,0x140C0C18,0x35131326,0x2FECECC3,0xE15F5FBE,0xA2979735,0xCC444488,0x3917172E,
+ 0x57C4C493,0xF2A7A755,0x827E7EFC,0x473D3D7A,0xAC6464C8,0xE75D5DBA,0x2B191932,0x957373E6,
+ 0xA06060C0,0x98818119,0xD14F4F9E,0x7FDCDCA3,0x66222244,0x7E2A2A54,0xAB90903B,0x8388880B,
+ 0xCA46468C,0x29EEEEC7,0xD3B8B86B,0x3C141428,0x79DEDEA7,0xE25E5EBC,0x1D0B0B16,0x76DBDBAD,
+ 0x3BE0E0DB,0x56323264,0x4E3A3A74,0x1E0A0A14,0xDB494992,0x0A06060C,0x6C242448,0xE45C5CB8,
+ 0x5DC2C29F,0x6ED3D3BD,0xEFACAC43,0xA66262C4,0xA8919139,0xA4959531,0x37E4E4D3,0x8B7979F2,
+ 0x32E7E7D5,0x43C8C88B,0x5937376E,0xB76D6DDA,0x8C8D8D01,0x64D5D5B1,0xD24E4E9C,0xE0A9A949,
+ 0xB46C6CD8,0xFA5656AC,0x07F4F4F3,0x25EAEACF,0xAF6565CA,0x8E7A7AF4,0xE9AEAE47,0x18080810,
+ 0xD5BABA6F,0x887878F0,0x6F25254A,0x722E2E5C,0x241C1C38,0xF1A6A657,0xC7B4B473,0x51C6C697,
+ 0x23E8E8CB,0x7CDDDDA1,0x9C7474E8,0x211F1F3E,0xDD4B4B96,0xDCBDBD61,0x868B8B0D,0x858A8A0F,
+ 0x907070E0,0x423E3E7C,0xC4B5B571,0xAA6666CC,0xD8484890,0x05030306,0x01F6F6F7,0x120E0E1C,
+ 0xA36161C2,0x5F35356A,0xF95757AE,0xD0B9B969,0x91868617,0x58C1C199,0x271D1D3A,0xB99E9E27,
+ 0x38E1E1D9,0x13F8F8EB,0xB398982B,0x33111122,0xBB6969D2,0x70D9D9A9,0x898E8E07,0xA7949433,
+ 0xB69B9B2D,0x221E1E3C,0x92878715,0x20E9E9C9,0x49CECE87,0xFF5555AA,0x78282850,0x7ADFDFA5,
+ 0x8F8C8C03,0xF8A1A159,0x80898909,0x170D0D1A,0xDABFBF65,0x31E6E6D7,0xC6424284,0xB86868D0,
+ 0xC3414182,0xB0999929,0x772D2D5A,0x110F0F1E,0xCBB0B07B,0xFC5454A8,0xD6BBBB6D,0x3A16162C
+ },
+ {
+ 0x6363C6A5,0x7C7CF884,0x7777EE99,0x7B7BF68D,0xF2F2FF0D,0x6B6BD6BD,0x6F6FDEB1,0xC5C59154,
+ 0x30306050,0x01010203,0x6767CEA9,0x2B2B567D,0xFEFEE719,0xD7D7B562,0xABAB4DE6,0x7676EC9A,
+ 0xCACA8F45,0x82821F9D,0xC9C98940,0x7D7DFA87,0xFAFAEF15,0x5959B2EB,0x47478EC9,0xF0F0FB0B,
+ 0xADAD41EC,0xD4D4B367,0xA2A25FFD,0xAFAF45EA,0x9C9C23BF,0xA4A453F7,0x7272E496,0xC0C09B5B,
+ 0xB7B775C2,0xFDFDE11C,0x93933DAE,0x26264C6A,0x36366C5A,0x3F3F7E41,0xF7F7F502,0xCCCC834F,
+ 0x3434685C,0xA5A551F4,0xE5E5D134,0xF1F1F908,0x7171E293,0xD8D8AB73,0x31316253,0x15152A3F,
+ 0x0404080C,0xC7C79552,0x23234665,0xC3C39D5E,0x18183028,0x969637A1,0x05050A0F,0x9A9A2FB5,
+ 0x07070E09,0x12122436,0x80801B9B,0xE2E2DF3D,0xEBEBCD26,0x27274E69,0xB2B27FCD,0x7575EA9F,
+ 0x0909121B,0x83831D9E,0x2C2C5874,0x1A1A342E,0x1B1B362D,0x6E6EDCB2,0x5A5AB4EE,0xA0A05BFB,
+ 0x5252A4F6,0x3B3B764D,0xD6D6B761,0xB3B37DCE,0x2929527B,0xE3E3DD3E,0x2F2F5E71,0x84841397,
+ 0x5353A6F5,0xD1D1B968,0000000000,0xEDEDC12C,0x20204060,0xFCFCE31F,0xB1B179C8,0x5B5BB6ED,
+ 0x6A6AD4BE,0xCBCB8D46,0xBEBE67D9,0x3939724B,0x4A4A94DE,0x4C4C98D4,0x5858B0E8,0xCFCF854A,
+ 0xD0D0BB6B,0xEFEFC52A,0xAAAA4FE5,0xFBFBED16,0x434386C5,0x4D4D9AD7,0x33336655,0x85851194,
+ 0x45458ACF,0xF9F9E910,0x02020406,0x7F7FFE81,0x5050A0F0,0x3C3C7844,0x9F9F25BA,0xA8A84BE3,
+ 0x5151A2F3,0xA3A35DFE,0x404080C0,0x8F8F058A,0x92923FAD,0x9D9D21BC,0x38387048,0xF5F5F104,
+ 0xBCBC63DF,0xB6B677C1,0xDADAAF75,0x21214263,0x10102030,0xFFFFE51A,0xF3F3FD0E,0xD2D2BF6D,
+ 0xCDCD814C,0x0C0C1814,0x13132635,0xECECC32F,0x5F5FBEE1,0x979735A2,0x444488CC,0x17172E39,
+ 0xC4C49357,0xA7A755F2,0x7E7EFC82,0x3D3D7A47,0x6464C8AC,0x5D5DBAE7,0x1919322B,0x7373E695,
+ 0x6060C0A0,0x81811998,0x4F4F9ED1,0xDCDCA37F,0x22224466,0x2A2A547E,0x90903BAB,0x88880B83,
+ 0x46468CCA,0xEEEEC729,0xB8B86BD3,0x1414283C,0xDEDEA779,0x5E5EBCE2,0x0B0B161D,0xDBDBAD76,
+ 0xE0E0DB3B,0x32326456,0x3A3A744E,0x0A0A141E,0x494992DB,0x06060C0A,0x2424486C,0x5C5CB8E4,
+ 0xC2C29F5D,0xD3D3BD6E,0xACAC43EF,0x6262C4A6,0x919139A8,0x959531A4,0xE4E4D337,0x7979F28B,
+ 0xE7E7D532,0xC8C88B43,0x37376E59,0x6D6DDAB7,0x8D8D018C,0xD5D5B164,0x4E4E9CD2,0xA9A949E0,
+ 0x6C6CD8B4,0x5656ACFA,0xF4F4F307,0xEAEACF25,0x6565CAAF,0x7A7AF48E,0xAEAE47E9,0x08081018,
+ 0xBABA6FD5,0x7878F088,0x25254A6F,0x2E2E5C72,0x1C1C3824,0xA6A657F1,0xB4B473C7,0xC6C69751,
+ 0xE8E8CB23,0xDDDDA17C,0x7474E89C,0x1F1F3E21,0x4B4B96DD,0xBDBD61DC,0x8B8B0D86,0x8A8A0F85,
+ 0x7070E090,0x3E3E7C42,0xB5B571C4,0x6666CCAA,0x484890D8,0x03030605,0xF6F6F701,0x0E0E1C12,
+ 0x6161C2A3,0x35356A5F,0x5757AEF9,0xB9B969D0,0x86861791,0xC1C19958,0x1D1D3A27,0x9E9E27B9,
+ 0xE1E1D938,0xF8F8EB13,0x98982BB3,0x11112233,0x6969D2BB,0xD9D9A970,0x8E8E0789,0x949433A7,
+ 0x9B9B2DB6,0x1E1E3C22,0x87871592,0xE9E9C920,0xCECE8749,0x5555AAFF,0x28285078,0xDFDFA57A,
+ 0x8C8C038F,0xA1A159F8,0x89890980,0x0D0D1A17,0xBFBF65DA,0xE6E6D731,0x424284C6,0x6868D0B8,
+ 0x414182C3,0x999929B0,0x2D2D5A77,0x0F0F1E11,0xB0B07BCB,0x5454A8FC,0xBBBB6DD6,0x16162C3A
+ },
+ {
+ 0x63C6A563,0x7CF8847C,0x77EE9977,0x7BF68D7B,0xF2FF0DF2,0x6BD6BD6B,0x6FDEB16F,0xC59154C5,
+ 0x30605030,0x01020301,0x67CEA967,0x2B567D2B,0xFEE719FE,0xD7B562D7,0xAB4DE6AB,0x76EC9A76,
+ 0xCA8F45CA,0x821F9D82,0xC98940C9,0x7DFA877D,0xFAEF15FA,0x59B2EB59,0x478EC947,0xF0FB0BF0,
+ 0xAD41ECAD,0xD4B367D4,0xA25FFDA2,0xAF45EAAF,0x9C23BF9C,0xA453F7A4,0x72E49672,0xC09B5BC0,
+ 0xB775C2B7,0xFDE11CFD,0x933DAE93,0x264C6A26,0x366C5A36,0x3F7E413F,0xF7F502F7,0xCC834FCC,
+ 0x34685C34,0xA551F4A5,0xE5D134E5,0xF1F908F1,0x71E29371,0xD8AB73D8,0x31625331,0x152A3F15,
+ 0x04080C04,0xC79552C7,0x23466523,0xC39D5EC3,0x18302818,0x9637A196,0x050A0F05,0x9A2FB59A,
+ 0x070E0907,0x12243612,0x801B9B80,0xE2DF3DE2,0xEBCD26EB,0x274E6927,0xB27FCDB2,0x75EA9F75,
+ 0x09121B09,0x831D9E83,0x2C58742C,0x1A342E1A,0x1B362D1B,0x6EDCB26E,0x5AB4EE5A,0xA05BFBA0,
+ 0x52A4F652,0x3B764D3B,0xD6B761D6,0xB37DCEB3,0x29527B29,0xE3DD3EE3,0x2F5E712F,0x84139784,
+ 0x53A6F553,0xD1B968D1,0000000000,0xEDC12CED,0x20406020,0xFCE31FFC,0xB179C8B1,0x5BB6ED5B,
+ 0x6AD4BE6A,0xCB8D46CB,0xBE67D9BE,0x39724B39,0x4A94DE4A,0x4C98D44C,0x58B0E858,0xCF854ACF,
+ 0xD0BB6BD0,0xEFC52AEF,0xAA4FE5AA,0xFBED16FB,0x4386C543,0x4D9AD74D,0x33665533,0x85119485,
+ 0x458ACF45,0xF9E910F9,0x02040602,0x7FFE817F,0x50A0F050,0x3C78443C,0x9F25BA9F,0xA84BE3A8,
+ 0x51A2F351,0xA35DFEA3,0x4080C040,0x8F058A8F,0x923FAD92,0x9D21BC9D,0x38704838,0xF5F104F5,
+ 0xBC63DFBC,0xB677C1B6,0xDAAF75DA,0x21426321,0x10203010,0xFFE51AFF,0xF3FD0EF3,0xD2BF6DD2,
+ 0xCD814CCD,0x0C18140C,0x13263513,0xECC32FEC,0x5FBEE15F,0x9735A297,0x4488CC44,0x172E3917,
+ 0xC49357C4,0xA755F2A7,0x7EFC827E,0x3D7A473D,0x64C8AC64,0x5DBAE75D,0x19322B19,0x73E69573,
+ 0x60C0A060,0x81199881,0x4F9ED14F,0xDCA37FDC,0x22446622,0x2A547E2A,0x903BAB90,0x880B8388,
+ 0x468CCA46,0xEEC729EE,0xB86BD3B8,0x14283C14,0xDEA779DE,0x5EBCE25E,0x0B161D0B,0xDBAD76DB,
+ 0xE0DB3BE0,0x32645632,0x3A744E3A,0x0A141E0A,0x4992DB49,0x060C0A06,0x24486C24,0x5CB8E45C,
+ 0xC29F5DC2,0xD3BD6ED3,0xAC43EFAC,0x62C4A662,0x9139A891,0x9531A495,0xE4D337E4,0x79F28B79,
+ 0xE7D532E7,0xC88B43C8,0x376E5937,0x6DDAB76D,0x8D018C8D,0xD5B164D5,0x4E9CD24E,0xA949E0A9,
+ 0x6CD8B46C,0x56ACFA56,0xF4F307F4,0xEACF25EA,0x65CAAF65,0x7AF48E7A,0xAE47E9AE,0x08101808,
+ 0xBA6FD5BA,0x78F08878,0x254A6F25,0x2E5C722E,0x1C38241C,0xA657F1A6,0xB473C7B4,0xC69751C6,
+ 0xE8CB23E8,0xDDA17CDD,0x74E89C74,0x1F3E211F,0x4B96DD4B,0xBD61DCBD,0x8B0D868B,0x8A0F858A,
+ 0x70E09070,0x3E7C423E,0xB571C4B5,0x66CCAA66,0x4890D848,0x03060503,0xF6F701F6,0x0E1C120E,
+ 0x61C2A361,0x356A5F35,0x57AEF957,0xB969D0B9,0x86179186,0xC19958C1,0x1D3A271D,0x9E27B99E,
+ 0xE1D938E1,0xF8EB13F8,0x982BB398,0x11223311,0x69D2BB69,0xD9A970D9,0x8E07898E,0x9433A794,
+ 0x9B2DB69B,0x1E3C221E,0x87159287,0xE9C920E9,0xCE8749CE,0x55AAFF55,0x28507828,0xDFA57ADF,
+ 0x8C038F8C,0xA159F8A1,0x89098089,0x0D1A170D,0xBF65DABF,0xE6D731E6,0x4284C642,0x68D0B868,
+ 0x4182C341,0x9929B099,0x2D5A772D,0x0F1E110F,0xB07BCBB0,0x54A8FC54,0xBB6DD6BB,0x162C3A16
+ },
+ {
+ 0xC6A56363,0xF8847C7C,0xEE997777,0xF68D7B7B,0xFF0DF2F2,0xD6BD6B6B,0xDEB16F6F,0x9154C5C5,
+ 0x60503030,0x02030101,0xCEA96767,0x567D2B2B,0xE719FEFE,0xB562D7D7,0x4DE6ABAB,0xEC9A7676,
+ 0x8F45CACA,0x1F9D8282,0x8940C9C9,0xFA877D7D,0xEF15FAFA,0xB2EB5959,0x8EC94747,0xFB0BF0F0,
+ 0x41ECADAD,0xB367D4D4,0x5FFDA2A2,0x45EAAFAF,0x23BF9C9C,0x53F7A4A4,0xE4967272,0x9B5BC0C0,
+ 0x75C2B7B7,0xE11CFDFD,0x3DAE9393,0x4C6A2626,0x6C5A3636,0x7E413F3F,0xF502F7F7,0x834FCCCC,
+ 0x685C3434,0x51F4A5A5,0xD134E5E5,0xF908F1F1,0xE2937171,0xAB73D8D8,0x62533131,0x2A3F1515,
+ 0x080C0404,0x9552C7C7,0x46652323,0x9D5EC3C3,0x30281818,0x37A19696,0x0A0F0505,0x2FB59A9A,
+ 0x0E090707,0x24361212,0x1B9B8080,0xDF3DE2E2,0xCD26EBEB,0x4E692727,0x7FCDB2B2,0xEA9F7575,
+ 0x121B0909,0x1D9E8383,0x58742C2C,0x342E1A1A,0x362D1B1B,0xDCB26E6E,0xB4EE5A5A,0x5BFBA0A0,
+ 0xA4F65252,0x764D3B3B,0xB761D6D6,0x7DCEB3B3,0x527B2929,0xDD3EE3E3,0x5E712F2F,0x13978484,
+ 0xA6F55353,0xB968D1D1,0000000000,0xC12CEDED,0x40602020,0xE31FFCFC,0x79C8B1B1,0xB6ED5B5B,
+ 0xD4BE6A6A,0x8D46CBCB,0x67D9BEBE,0x724B3939,0x94DE4A4A,0x98D44C4C,0xB0E85858,0x854ACFCF,
+ 0xBB6BD0D0,0xC52AEFEF,0x4FE5AAAA,0xED16FBFB,0x86C54343,0x9AD74D4D,0x66553333,0x11948585,
+ 0x8ACF4545,0xE910F9F9,0x04060202,0xFE817F7F,0xA0F05050,0x78443C3C,0x25BA9F9F,0x4BE3A8A8,
+ 0xA2F35151,0x5DFEA3A3,0x80C04040,0x058A8F8F,0x3FAD9292,0x21BC9D9D,0x70483838,0xF104F5F5,
+ 0x63DFBCBC,0x77C1B6B6,0xAF75DADA,0x42632121,0x20301010,0xE51AFFFF,0xFD0EF3F3,0xBF6DD2D2,
+ 0x814CCDCD,0x18140C0C,0x26351313,0xC32FECEC,0xBEE15F5F,0x35A29797,0x88CC4444,0x2E391717,
+ 0x9357C4C4,0x55F2A7A7,0xFC827E7E,0x7A473D3D,0xC8AC6464,0xBAE75D5D,0x322B1919,0xE6957373,
+ 0xC0A06060,0x19988181,0x9ED14F4F,0xA37FDCDC,0x44662222,0x547E2A2A,0x3BAB9090,0x0B838888,
+ 0x8CCA4646,0xC729EEEE,0x6BD3B8B8,0x283C1414,0xA779DEDE,0xBCE25E5E,0x161D0B0B,0xAD76DBDB,
+ 0xDB3BE0E0,0x64563232,0x744E3A3A,0x141E0A0A,0x92DB4949,0x0C0A0606,0x486C2424,0xB8E45C5C,
+ 0x9F5DC2C2,0xBD6ED3D3,0x43EFACAC,0xC4A66262,0x39A89191,0x31A49595,0xD337E4E4,0xF28B7979,
+ 0xD532E7E7,0x8B43C8C8,0x6E593737,0xDAB76D6D,0x018C8D8D,0xB164D5D5,0x9CD24E4E,0x49E0A9A9,
+ 0xD8B46C6C,0xACFA5656,0xF307F4F4,0xCF25EAEA,0xCAAF6565,0xF48E7A7A,0x47E9AEAE,0x10180808,
+ 0x6FD5BABA,0xF0887878,0x4A6F2525,0x5C722E2E,0x38241C1C,0x57F1A6A6,0x73C7B4B4,0x9751C6C6,
+ 0xCB23E8E8,0xA17CDDDD,0xE89C7474,0x3E211F1F,0x96DD4B4B,0x61DCBDBD,0x0D868B8B,0x0F858A8A,
+ 0xE0907070,0x7C423E3E,0x71C4B5B5,0xCCAA6666,0x90D84848,0x06050303,0xF701F6F6,0x1C120E0E,
+ 0xC2A36161,0x6A5F3535,0xAEF95757,0x69D0B9B9,0x17918686,0x9958C1C1,0x3A271D1D,0x27B99E9E,
+ 0xD938E1E1,0xEB13F8F8,0x2BB39898,0x22331111,0xD2BB6969,0xA970D9D9,0x07898E8E,0x33A79494,
+ 0x2DB69B9B,0x3C221E1E,0x15928787,0xC920E9E9,0x8749CECE,0xAAFF5555,0x50782828,0xA57ADFDF,
+ 0x038F8C8C,0x59F8A1A1,0x09808989,0x1A170D0D,0x65DABFBF,0xD731E6E6,0x84C64242,0xD0B86868,
+ 0x82C34141,0x29B09999,0x5A772D2D,0x1E110F0F,0x7BCBB0B0,0xA8FC5454,0x6DD6BBBB,0x2C3A1616
+ }
+};
+
+static u32 fl_tab[4][256] =
+{
+ {
+ 0x00000063,0x0000007C,0x00000077,0x0000007B,0x000000F2,0x0000006B,0x0000006F,0x000000C5,
+ 0x00000030,0x00000001,0x00000067,0x0000002B,0x000000FE,0x000000D7,0x000000AB,0x00000076,
+ 0x000000CA,0x00000082,0x000000C9,0x0000007D,0x000000FA,0x00000059,0x00000047,0x000000F0,
+ 0x000000AD,0x000000D4,0x000000A2,0x000000AF,0x0000009C,0x000000A4,0x00000072,0x000000C0,
+ 0x000000B7,0x000000FD,0x00000093,0x00000026,0x00000036,0x0000003F,0x000000F7,0x000000CC,
+ 0x00000034,0x000000A5,0x000000E5,0x000000F1,0x00000071,0x000000D8,0x00000031,0x00000015,
+ 0x00000004,0x000000C7,0x00000023,0x000000C3,0x00000018,0x00000096,0x00000005,0x0000009A,
+ 0x00000007,0x00000012,0x00000080,0x000000E2,0x000000EB,0x00000027,0x000000B2,0x00000075,
+ 0x00000009,0x00000083,0x0000002C,0x0000001A,0x0000001B,0x0000006E,0x0000005A,0x000000A0,
+ 0x00000052,0x0000003B,0x000000D6,0x000000B3,0x00000029,0x000000E3,0x0000002F,0x00000084,
+ 0x00000053,0x000000D1,0x00000000,0x000000ED,0x00000020,0x000000FC,0x000000B1,0x0000005B,
+ 0x0000006A,0x000000CB,0x000000BE,0x00000039,0x0000004A,0x0000004C,0x00000058,0x000000CF,
+ 0x000000D0,0x000000EF,0x000000AA,0x000000FB,0x00000043,0x0000004D,0x00000033,0x00000085,
+ 0x00000045,0x000000F9,0x00000002,0x0000007F,0x00000050,0x0000003C,0x0000009F,0x000000A8,
+ 0x00000051,0x000000A3,0x00000040,0x0000008F,0x00000092,0x0000009D,0x00000038,0x000000F5,
+ 0x000000BC,0x000000B6,0x000000DA,0x00000021,0x00000010,0x000000FF,0x000000F3,0x000000D2,
+ 0x000000CD,0x0000000C,0x00000013,0x000000EC,0x0000005F,0x00000097,0x00000044,0x00000017,
+ 0x000000C4,0x000000A7,0x0000007E,0x0000003D,0x00000064,0x0000005D,0x00000019,0x00000073,
+ 0x00000060,0x00000081,0x0000004F,0x000000DC,0x00000022,0x0000002A,0x00000090,0x00000088,
+ 0x00000046,0x000000EE,0x000000B8,0x00000014,0x000000DE,0x0000005E,0x0000000B,0x000000DB,
+ 0x000000E0,0x00000032,0x0000003A,0x0000000A,0x00000049,0x00000006,0x00000024,0x0000005C,
+ 0x000000C2,0x000000D3,0x000000AC,0x00000062,0x00000091,0x00000095,0x000000E4,0x00000079,
+ 0x000000E7,0x000000C8,0x00000037,0x0000006D,0x0000008D,0x000000D5,0x0000004E,0x000000A9,
+ 0x0000006C,0x00000056,0x000000F4,0x000000EA,0x00000065,0x0000007A,0x000000AE,0x00000008,
+ 0x000000BA,0x00000078,0x00000025,0x0000002E,0x0000001C,0x000000A6,0x000000B4,0x000000C6,
+ 0x000000E8,0x000000DD,0x00000074,0x0000001F,0x0000004B,0x000000BD,0x0000008B,0x0000008A,
+ 0x00000070,0x0000003E,0x000000B5,0x00000066,0x00000048,0x00000003,0x000000F6,0x0000000E,
+ 0x00000061,0x00000035,0x00000057,0x000000B9,0x00000086,0x000000C1,0x0000001D,0x0000009E,
+ 0x000000E1,0x000000F8,0x00000098,0x00000011,0x00000069,0x000000D9,0x0000008E,0x00000094,
+ 0x0000009B,0x0000001E,0x00000087,0x000000E9,0x000000CE,0x00000055,0x00000028,0x000000DF,
+ 0x0000008C,0x000000A1,0x00000089,0x0000000D,0x000000BF,0x000000E6,0x00000042,0x00000068,
+ 0x00000041,0x00000099,0x0000002D,0x0000000F,0x000000B0,0x00000054,0x000000BB,0x00000016
+ },
+ {
+ 0x00006300,0x00007C00,0x00007700,0x00007B00,0x0000F200,0x00006B00,0x00006F00,0x0000C500,
+ 0x00003000,0x00000100,0x00006700,0x00002B00,0x0000FE00,0x0000D700,0x0000AB00,0x00007600,
+ 0x0000CA00,0x00008200,0x0000C900,0x00007D00,0x0000FA00,0x00005900,0x00004700,0x0000F000,
+ 0x0000AD00,0x0000D400,0x0000A200,0x0000AF00,0x00009C00,0x0000A400,0x00007200,0x0000C000,
+ 0x0000B700,0x0000FD00,0x00009300,0x00002600,0x00003600,0x00003F00,0x0000F700,0x0000CC00,
+ 0x00003400,0x0000A500,0x0000E500,0x0000F100,0x00007100,0x0000D800,0x00003100,0x00001500,
+ 0x00000400,0x0000C700,0x00002300,0x0000C300,0x00001800,0x00009600,0x00000500,0x00009A00,
+ 0x00000700,0x00001200,0x00008000,0x0000E200,0x0000EB00,0x00002700,0x0000B200,0x00007500,
+ 0x00000900,0x00008300,0x00002C00,0x00001A00,0x00001B00,0x00006E00,0x00005A00,0x0000A000,
+ 0x00005200,0x00003B00,0x0000D600,0x0000B300,0x00002900,0x0000E300,0x00002F00,0x00008400,
+ 0x00005300,0x0000D100,0000000000,0x0000ED00,0x00002000,0x0000FC00,0x0000B100,0x00005B00,
+ 0x00006A00,0x0000CB00,0x0000BE00,0x00003900,0x00004A00,0x00004C00,0x00005800,0x0000CF00,
+ 0x0000D000,0x0000EF00,0x0000AA00,0x0000FB00,0x00004300,0x00004D00,0x00003300,0x00008500,
+ 0x00004500,0x0000F900,0x00000200,0x00007F00,0x00005000,0x00003C00,0x00009F00,0x0000A800,
+ 0x00005100,0x0000A300,0x00004000,0x00008F00,0x00009200,0x00009D00,0x00003800,0x0000F500,
+ 0x0000BC00,0x0000B600,0x0000DA00,0x00002100,0x00001000,0x0000FF00,0x0000F300,0x0000D200,
+ 0x0000CD00,0x00000C00,0x00001300,0x0000EC00,0x00005F00,0x00009700,0x00004400,0x00001700,
+ 0x0000C400,0x0000A700,0x00007E00,0x00003D00,0x00006400,0x00005D00,0x00001900,0x00007300,
+ 0x00006000,0x00008100,0x00004F00,0x0000DC00,0x00002200,0x00002A00,0x00009000,0x00008800,
+ 0x00004600,0x0000EE00,0x0000B800,0x00001400,0x0000DE00,0x00005E00,0x00000B00,0x0000DB00,
+ 0x0000E000,0x00003200,0x00003A00,0x00000A00,0x00004900,0x00000600,0x00002400,0x00005C00,
+ 0x0000C200,0x0000D300,0x0000AC00,0x00006200,0x00009100,0x00009500,0x0000E400,0x00007900,
+ 0x0000E700,0x0000C800,0x00003700,0x00006D00,0x00008D00,0x0000D500,0x00004E00,0x0000A900,
+ 0x00006C00,0x00005600,0x0000F400,0x0000EA00,0x00006500,0x00007A00,0x0000AE00,0x00000800,
+ 0x0000BA00,0x00007800,0x00002500,0x00002E00,0x00001C00,0x0000A600,0x0000B400,0x0000C600,
+ 0x0000E800,0x0000DD00,0x00007400,0x00001F00,0x00004B00,0x0000BD00,0x00008B00,0x00008A00,
+ 0x00007000,0x00003E00,0x0000B500,0x00006600,0x00004800,0x00000300,0x0000F600,0x00000E00,
+ 0x00006100,0x00003500,0x00005700,0x0000B900,0x00008600,0x0000C100,0x00001D00,0x00009E00,
+ 0x0000E100,0x0000F800,0x00009800,0x00001100,0x00006900,0x0000D900,0x00008E00,0x00009400,
+ 0x00009B00,0x00001E00,0x00008700,0x0000E900,0x0000CE00,0x00005500,0x00002800,0x0000DF00,
+ 0x00008C00,0x0000A100,0x00008900,0x00000D00,0x0000BF00,0x0000E600,0x00004200,0x00006800,
+ 0x00004100,0x00009900,0x00002D00,0x00000F00,0x0000B000,0x00005400,0x0000BB00,0x00001600
+ },
+ {
+ 0x00630000,0x007C0000,0x00770000,0x007B0000,0x00F20000,0x006B0000,0x006F0000,0x00C50000,
+ 0x00300000,0x00010000,0x00670000,0x002B0000,0x00FE0000,0x00D70000,0x00AB0000,0x00760000,
+ 0x00CA0000,0x00820000,0x00C90000,0x007D0000,0x00FA0000,0x00590000,0x00470000,0x00F00000,
+ 0x00AD0000,0x00D40000,0x00A20000,0x00AF0000,0x009C0000,0x00A40000,0x00720000,0x00C00000,
+ 0x00B70000,0x00FD0000,0x00930000,0x00260000,0x00360000,0x003F0000,0x00F70000,0x00CC0000,
+ 0x00340000,0x00A50000,0x00E50000,0x00F10000,0x00710000,0x00D80000,0x00310000,0x00150000,
+ 0x00040000,0x00C70000,0x00230000,0x00C30000,0x00180000,0x00960000,0x00050000,0x009A0000,
+ 0x00070000,0x00120000,0x00800000,0x00E20000,0x00EB0000,0x00270000,0x00B20000,0x00750000,
+ 0x00090000,0x00830000,0x002C0000,0x001A0000,0x001B0000,0x006E0000,0x005A0000,0x00A00000,
+ 0x00520000,0x003B0000,0x00D60000,0x00B30000,0x00290000,0x00E30000,0x002F0000,0x00840000,
+ 0x00530000,0x00D10000,0000000000,0x00ED0000,0x00200000,0x00FC0000,0x00B10000,0x005B0000,
+ 0x006A0000,0x00CB0000,0x00BE0000,0x00390000,0x004A0000,0x004C0000,0x00580000,0x00CF0000,
+ 0x00D00000,0x00EF0000,0x00AA0000,0x00FB0000,0x00430000,0x004D0000,0x00330000,0x00850000,
+ 0x00450000,0x00F90000,0x00020000,0x007F0000,0x00500000,0x003C0000,0x009F0000,0x00A80000,
+ 0x00510000,0x00A30000,0x00400000,0x008F0000,0x00920000,0x009D0000,0x00380000,0x00F50000,
+ 0x00BC0000,0x00B60000,0x00DA0000,0x00210000,0x00100000,0x00FF0000,0x00F30000,0x00D20000,
+ 0x00CD0000,0x000C0000,0x00130000,0x00EC0000,0x005F0000,0x00970000,0x00440000,0x00170000,
+ 0x00C40000,0x00A70000,0x007E0000,0x003D0000,0x00640000,0x005D0000,0x00190000,0x00730000,
+ 0x00600000,0x00810000,0x004F0000,0x00DC0000,0x00220000,0x002A0000,0x00900000,0x00880000,
+ 0x00460000,0x00EE0000,0x00B80000,0x00140000,0x00DE0000,0x005E0000,0x000B0000,0x00DB0000,
+ 0x00E00000,0x00320000,0x003A0000,0x000A0000,0x00490000,0x00060000,0x00240000,0x005C0000,
+ 0x00C20000,0x00D30000,0x00AC0000,0x00620000,0x00910000,0x00950000,0x00E40000,0x00790000,
+ 0x00E70000,0x00C80000,0x00370000,0x006D0000,0x008D0000,0x00D50000,0x004E0000,0x00A90000,
+ 0x006C0000,0x00560000,0x00F40000,0x00EA0000,0x00650000,0x007A0000,0x00AE0000,0x00080000,
+ 0x00BA0000,0x00780000,0x00250000,0x002E0000,0x001C0000,0x00A60000,0x00B40000,0x00C60000,
+ 0x00E80000,0x00DD0000,0x00740000,0x001F0000,0x004B0000,0x00BD0000,0x008B0000,0x008A0000,
+ 0x00700000,0x003E0000,0x00B50000,0x00660000,0x00480000,0x00030000,0x00F60000,0x000E0000,
+ 0x00610000,0x00350000,0x00570000,0x00B90000,0x00860000,0x00C10000,0x001D0000,0x009E0000,
+ 0x00E10000,0x00F80000,0x00980000,0x00110000,0x00690000,0x00D90000,0x008E0000,0x00940000,
+ 0x009B0000,0x001E0000,0x00870000,0x00E90000,0x00CE0000,0x00550000,0x00280000,0x00DF0000,
+ 0x008C0000,0x00A10000,0x00890000,0x000D0000,0x00BF0000,0x00E60000,0x00420000,0x00680000,
+ 0x00410000,0x00990000,0x002D0000,0x000F0000,0x00B00000,0x00540000,0x00BB0000,0x00160000
+ },
+ {
+ 0x63000000,0x7C000000,0x77000000,0x7B000000,0xF2000000,0x6B000000,0x6F000000,0xC5000000,
+ 0x30000000,0x01000000,0x67000000,0x2B000000,0xFE000000,0xD7000000,0xAB000000,0x76000000,
+ 0xCA000000,0x82000000,0xC9000000,0x7D000000,0xFA000000,0x59000000,0x47000000,0xF0000000,
+ 0xAD000000,0xD4000000,0xA2000000,0xAF000000,0x9C000000,0xA4000000,0x72000000,0xC0000000,
+ 0xB7000000,0xFD000000,0x93000000,0x26000000,0x36000000,0x3F000000,0xF7000000,0xCC000000,
+ 0x34000000,0xA5000000,0xE5000000,0xF1000000,0x71000000,0xD8000000,0x31000000,0x15000000,
+ 0x04000000,0xC7000000,0x23000000,0xC3000000,0x18000000,0x96000000,0x05000000,0x9A000000,
+ 0x07000000,0x12000000,0x80000000,0xE2000000,0xEB000000,0x27000000,0xB2000000,0x75000000,
+ 0x09000000,0x83000000,0x2C000000,0x1A000000,0x1B000000,0x6E000000,0x5A000000,0xA0000000,
+ 0x52000000,0x3B000000,0xD6000000,0xB3000000,0x29000000,0xE3000000,0x2F000000,0x84000000,
+ 0x53000000,0xD1000000,0000000000,0xED000000,0x20000000,0xFC000000,0xB1000000,0x5B000000,
+ 0x6A000000,0xCB000000,0xBE000000,0x39000000,0x4A000000,0x4C000000,0x58000000,0xCF000000,
+ 0xD0000000,0xEF000000,0xAA000000,0xFB000000,0x43000000,0x4D000000,0x33000000,0x85000000,
+ 0x45000000,0xF9000000,0x02000000,0x7F000000,0x50000000,0x3C000000,0x9F000000,0xA8000000,
+ 0x51000000,0xA3000000,0x40000000,0x8F000000,0x92000000,0x9D000000,0x38000000,0xF5000000,
+ 0xBC000000,0xB6000000,0xDA000000,0x21000000,0x10000000,0xFF000000,0xF3000000,0xD2000000,
+ 0xCD000000,0x0C000000,0x13000000,0xEC000000,0x5F000000,0x97000000,0x44000000,0x17000000,
+ 0xC4000000,0xA7000000,0x7E000000,0x3D000000,0x64000000,0x5D000000,0x19000000,0x73000000,
+ 0x60000000,0x81000000,0x4F000000,0xDC000000,0x22000000,0x2A000000,0x90000000,0x88000000,
+ 0x46000000,0xEE000000,0xB8000000,0x14000000,0xDE000000,0x5E000000,0x0B000000,0xDB000000,
+ 0xE0000000,0x32000000,0x3A000000,0x0A000000,0x49000000,0x06000000,0x24000000,0x5C000000,
+ 0xC2000000,0xD3000000,0xAC000000,0x62000000,0x91000000,0x95000000,0xE4000000,0x79000000,
+ 0xE7000000,0xC8000000,0x37000000,0x6D000000,0x8D000000,0xD5000000,0x4E000000,0xA9000000,
+ 0x6C000000,0x56000000,0xF4000000,0xEA000000,0x65000000,0x7A000000,0xAE000000,0x08000000,
+ 0xBA000000,0x78000000,0x25000000,0x2E000000,0x1C000000,0xA6000000,0xB4000000,0xC6000000,
+ 0xE8000000,0xDD000000,0x74000000,0x1F000000,0x4B000000,0xBD000000,0x8B000000,0x8A000000,
+ 0x70000000,0x3E000000,0xB5000000,0x66000000,0x48000000,0x03000000,0xF6000000,0x0E000000,
+ 0x61000000,0x35000000,0x57000000,0xB9000000,0x86000000,0xC1000000,0x1D000000,0x9E000000,
+ 0xE1000000,0xF8000000,0x98000000,0x11000000,0x69000000,0xD9000000,0x8E000000,0x94000000,
+ 0x9B000000,0x1E000000,0x87000000,0xE9000000,0xCE000000,0x55000000,0x28000000,0xDF000000,
+ 0x8C000000,0xA1000000,0x89000000,0x0D000000,0xBF000000,0xE6000000,0x42000000,0x68000000,
+ 0x41000000,0x99000000,0x2D000000,0x0F000000,0xB0000000,0x54000000,0xBB000000,0x16000000
+ }
+};
+
+/*----------------- The workspace ------------------------------*/
+
+static u32 Ekey[44]; /* The expanded key */
+
+/*------ The round Function. 4 table lookups and 4 Exors ------*/
+#define f_rnd(x, n) \
+ ( ft_tab[0][byte0(x[n])] \
+ ^ ft_tab[1][byte1(x[(n + 1) & 3])] \
+ ^ ft_tab[2][byte2(x[(n + 2) & 3])] \
+ ^ ft_tab[3][byte3(x[(n + 3) & 3])] )
+
+#define f_round(bo, bi, k) \
+ bo[0] = f_rnd(bi, 0) ^ k[0]; \
+ bo[1] = f_rnd(bi, 1) ^ k[1]; \
+ bo[2] = f_rnd(bi, 2) ^ k[2]; \
+ bo[3] = f_rnd(bi, 3) ^ k[3]; \
+ k += 4
+
+/*--- The S Box lookup used in constructing the Key schedule ---*/
+#define ls_box(x) \
+ ( fl_tab[0][byte0(x)] \
+ ^ fl_tab[1][byte1(x)] \
+ ^ fl_tab[2][byte2(x)] \
+ ^ fl_tab[3][byte3(x)] )
+
+/*------------ The last round function (no MixColumn) ----------*/
+#define lf_rnd(x, n) \
+ ( fl_tab[0][byte0(x[n])] \
+ ^ fl_tab[1][byte1(x[(n + 1) & 3])] \
+ ^ fl_tab[2][byte2(x[(n + 2) & 3])] \
+ ^ fl_tab[3][byte3(x[(n + 3) & 3])] )
+
+
+/*-----------------------------------------------------------
+ * RijndaelKeySchedule
+ * Initialise the key schedule from a supplied key
+ */
+void RijndaelKeySchedule(u8 key[16])
+{
+ u32 t;
+ u32 *ek=Ekey, /* pointer to the expanded key */
+ *rc=rnd_con; /* pointer to the round constant */
+
+ Ekey[0] = u32_in(key );
+ Ekey[1] = u32_in(key + 4);
+ Ekey[2] = u32_in(key + 8);
+ Ekey[3] = u32_in(key + 12);
+
+ while(ek < Ekey + 40)
+ {
+ t = rot3(ek[3]);
+ ek[4] = ek[0] ^ ls_box(t) ^ *rc++;
+ ek[5] = ek[1] ^ ek[4];
+ ek[6] = ek[2] ^ ek[5];
+ ek[7] = ek[3] ^ ek[6];
+ ek += 4;
+ }
+}
+
+/*-----------------------------------------------------------
+ * RijndaelEncrypt
+ * Encrypt an input block
+ */
+void RijndaelEncrypt(u8 in[16], u8 out[16])
+{
+ u32 b0[4], b1[4], *kp = Ekey;
+
+ b0[0] = u32_in(in ) ^ *kp++;
+ b0[1] = u32_in(in + 4) ^ *kp++;
+ b0[2] = u32_in(in + 8) ^ *kp++;
+ b0[3] = u32_in(in + 12) ^ *kp++;
+
+ f_round(b1, b0, kp);
+ f_round(b0, b1, kp);
+ f_round(b1, b0, kp);
+ f_round(b0, b1, kp);
+ f_round(b1, b0, kp);
+ f_round(b0, b1, kp);
+ f_round(b1, b0, kp);
+ f_round(b0, b1, kp);
+ f_round(b1, b0, kp);
+
+ u32_out(out, lf_rnd(b1, 0) ^ kp[0]);
+ u32_out(out + 4, lf_rnd(b1, 1) ^ kp[1]);
+ u32_out(out + 8, lf_rnd(b1, 2) ^ kp[2]);
+ u32_out(out + 12, lf_rnd(b1, 3) ^ kp[3]);
+}
diff --git a/src/parser/rijndael.h b/src/parser/rijndael.h
new file mode 100644
index 0000000..4e728a5
--- /dev/null
+++ b/src/parser/rijndael.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------
+ * Example algorithms f1, f1*, f2, f3, f4, f5, f5*
+ *-------------------------------------------------------------------
+ *
+ * A sample implementation of the example 3GPP authentication and
+ * key agreement functions f1, f1*, f2, f3, f4, f5 and f5*. This is
+ * a byte-oriented implementation of the functions, and of the block
+ * cipher kernel function Rijndael.
+ *
+ * This has been coded for clarity, not necessarily for efficiency.
+ *
+ * The functions f2, f3, f4 and f5 share the same inputs and have
+ * been coded together as a single function. f1, f1* and f5* are
+ * all coded separately.
+ *
+ *-----------------------------------------------------------------*/
+
+#ifndef RIJNDAEL_H
+#define RIJNDAEL_H
+
+
+void RijndaelKeySchedule( u8 key[16] );
+void RijndaelEncrypt( u8 input[16], u8 output[16] );
+
+
+#endif
diff --git a/src/parser/route.cpp b/src/parser/route.cpp
new file mode 100644
index 0000000..cf57098
--- /dev/null
+++ b/src/parser/route.cpp
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "definitions.h"
+#include "route.h"
+#include "parse_ctrl.h"
+#include "util.h"
+
+void t_route::add_param(const t_parameter &p) {
+ params.push_back(p);
+}
+
+void t_route::set_params(const list<t_parameter> &l) {
+ params = l;
+}
+
+string t_route::encode(void) const {
+ string s;
+
+ if (display.size() > 0) {
+ s += '"';
+ s += escape(display, '"');
+ s += '"';
+ s += ' ';
+ }
+
+ s += '<';
+ s += uri.encode();
+ s += '>';
+
+ s += param_list2str(params);
+ return s;
+}
diff --git a/src/parser/route.h b/src/parser/route.h
new file mode 100644
index 0000000..3e07b47
--- /dev/null
+++ b/src/parser/route.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// Route item
+
+#ifndef _H_ROUTE
+#define _H_ROUTE
+
+#include <list>
+#include <string>
+#include "parameter.h"
+
+using namespace std;
+
+class t_route {
+public:
+ string display;
+ t_url uri;
+ list<t_parameter> params;
+
+ void add_param(const t_parameter &p);
+ void set_params(const list<t_parameter> &l);
+ string encode(void) const;
+};
+
+#endif
diff --git a/src/parser/scanner.cxx b/src/parser/scanner.cxx
new file mode 100644
index 0000000..c1c0f23
--- /dev/null
+++ b/src/parser/scanner.cxx
@@ -0,0 +1,3485 @@
+
+#line 3 "scanner.cxx"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
+void yy_delete_buffer (YY_BUFFER_STATE b );
+void yy_flush_buffer (YY_BUFFER_STATE b );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
+
+void *yyalloc (yy_size_t );
+void *yyrealloc (void *,yy_size_t );
+void yyfree (void * );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ (yytext_ptr) -= (yy_more_len); \
+ yyleng = (size_t) (yy_cp - (yytext_ptr)); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 163
+#define YY_END_OF_BUFFER 164
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_acclist[1388] =
+ { 0,
+ 164, 67, 163, 66, 67, 163, 65, 163, 67, 163,
+ 62, 67, 163, 63, 67, 163, 61, 62, 67, 163,
+ 61, 62, 67, 163, 40, 61, 62, 67, 163, 16,
+ 61, 62, 67, 163, 44, 61, 62, 67, 163, 13,
+ 61, 62, 67, 163, 22, 61, 62, 67, 163, 9,
+ 61, 62, 67, 163, 53, 61, 62, 67, 163, 15,
+ 61, 62, 67, 163, 11, 61, 62, 67, 163, 20,
+ 61, 62, 67, 163, 61, 62, 67, 163, 39, 61,
+ 62, 67, 163, 51, 61, 62, 67, 163, 55, 61,
+ 62, 67, 163, 6, 61, 62, 67, 163, 58, 61,
+
+ 62, 67, 163, 61, 62, 67, 163, 72, 74, 163,
+ 16454, 73, 74, 163, 75, 163, 74, 163, 72, 74,
+ 163,16454, 68, 74, 163,16454, 71, 72, 74, 163,
+ 16454, 79, 81, 163, 80, 81, 163, 82, 163, 81,
+ 163, 79, 81, 163, 76, 81, 163, 78, 79, 81,
+ 163, 87, 163, 86, 163, 87, 163, 85, 87, 163,
+ 83, 87, 163, 98, 163, 97, 98, 163, 100, 163,
+ 98, 163, 96, 98, 163, 103, 163, 102, 103, 163,
+ 105, 163, 103, 163, 101, 103, 163, 108, 163, 107,
+ 108, 163, 110, 163, 108, 163, 106, 108, 163, 133,
+
+ 163, 132, 133, 163, 135, 163, 133, 163, 131, 133,
+ 163, 133, 163, 133, 163, 133, 163, 133, 163, 133,
+ 163, 133, 163, 133, 163, 133, 163, 133, 163, 133,
+ 163, 133, 163, 136, 163, 138, 163, 139, 163, 94,
+ 163, 93, 163, 94, 163, 91, 94, 163, 92, 94,
+ 163, 88, 94, 163, 143, 163, 142, 143, 163, 145,
+ 163, 143, 163, 141, 143, 163, 141, 143, 163, 149,
+ 163, 148, 149, 163, 151, 163, 149, 163, 147, 149,
+ 163, 147, 149, 163, 163, 95, 163, 154, 163, 153,
+ 154, 163, 156, 163, 154, 163, 152, 154, 163, 160,
+
+ 163, 159, 160, 163, 162, 163, 160, 163, 157, 160,
+ 163, 158, 160, 163, 64, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 55, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 72,16454,16454, 8262, 72,16454, 69, 79, 79,
+ 77, 86, 85, 84, 99, 96, 104, 101, 109, 106,
+
+ 134, 131, 136, 137, 93, 91, 92, 90, 89, 144,
+ 141, 141, 150, 147, 147, 155, 152, 161, 157, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 58, 61, 62, 61, 62, 61, 62, 96, 96,
+
+ 121, 125, 129, 119, 115, 130, 118, 124, 123, 120,
+ 122, 111, 128, 127, 116, 126, 117, 114, 112, 113,
+ 140, 141, 147, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 17, 61, 62, 18, 61,
+ 62, 61, 62, 61, 62, 61, 62, 22, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 35, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 47, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+
+ 61, 62, 61, 62, 61, 62, 61, 62, 96, 96,
+ 147, 61, 62, 61, 62, 5, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 20, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 46,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 96, 96, 147, 1,
+
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 48, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 96, 96, 146, 147, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 9, 61, 62, 61, 62,
+
+ 11, 61, 62, 61, 62, 61, 62, 21, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 31, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 43, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 51, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 59, 61, 62, 61, 62, 96, 96, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 30, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 39, 61, 62, 61, 62, 41, 61, 62, 42,
+ 61, 62, 61, 62, 61, 62, 61, 62, 49, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 96, 96, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 10,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+
+ 61, 62, 38, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 53, 61, 62,
+ 54, 61, 62, 61, 62, 61, 62, 61, 62, 96,
+ 61, 62, 61, 62, 4, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 19, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 57, 61, 62, 61, 62, 96, 61, 62, 61, 62,
+
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 23, 61, 62, 61,
+ 62, 61, 62, 25, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 40, 61, 62, 61, 62, 45, 61, 62, 61, 62,
+ 61, 62, 61, 62, 56, 61, 62, 61, 62, 61,
+ 62, 61, 62, 6, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 16, 61,
+ 62, 24, 61, 62, 26, 61, 62, 27, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+
+ 36, 61, 62, 61, 62, 61, 62, 50, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 8, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 34,
+ 61, 62, 61, 62, 37, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 15, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 2, 61, 62, 3, 61, 62, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 61, 62, 13, 61, 62, 14, 61, 62, 61, 62,
+ 61, 62, 61, 62, 61, 62, 61, 62, 61, 62,
+ 60, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 61, 62, 61,
+ 62, 61, 62, 61, 62, 61, 62, 32, 61, 62,
+ 61, 62, 61, 62, 52, 61, 62, 7, 61, 62,
+ 12, 61, 62, 28, 61, 62, 61, 62, 33, 61,
+ 62, 44, 61, 62, 29, 61, 62
+ } ;
+
+static yyconst flex_int16_t yy_accept[715] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 4, 7, 9, 11, 14, 17, 21, 25,
+ 30, 35, 40, 45, 50, 55, 60, 65, 70, 75,
+ 79, 84, 89, 94, 99, 104, 108, 112, 115, 117,
+ 119, 123, 127, 132, 135, 138, 140, 142, 145, 148,
+ 152, 154, 156, 158, 161, 164, 166, 169, 171, 173,
+ 176, 178, 181, 183, 185, 188, 190, 193, 195, 197,
+ 200, 202, 205, 207, 209, 212, 214, 216, 218, 220,
+
+ 222, 224, 226, 228, 230, 232, 234, 236, 238, 240,
+ 242, 244, 246, 249, 252, 255, 257, 260, 262, 264,
+ 267, 270, 272, 275, 277, 279, 282, 285, 286, 288,
+ 290, 293, 295, 297, 300, 302, 305, 307, 309, 312,
+ 315, 316, 317, 319, 321, 323, 325, 327, 329, 331,
+ 333, 335, 337, 339, 341, 343, 345, 347, 349, 351,
+ 353, 355, 357, 359, 361, 363, 365, 367, 369, 372,
+ 374, 376, 378, 380, 382, 384, 384, 385, 386, 386,
+ 388, 389, 390, 390, 391, 392, 392, 393, 393, 394,
+ 394, 395, 396, 396, 397, 398, 399, 400, 401, 402,
+
+ 403, 403, 403, 403, 403, 403, 403, 403, 403, 403,
+ 403, 403, 403, 403, 403, 403, 403, 403, 403, 404,
+ 405, 405, 406, 406, 407, 408, 408, 409, 410, 411,
+ 412, 413, 414, 415, 416, 417, 418, 419, 420, 422,
+ 424, 426, 428, 430, 432, 434, 436, 438, 440, 442,
+ 444, 446, 448, 450, 452, 454, 456, 458, 460, 462,
+ 464, 466, 468, 470, 472, 474, 476, 478, 480, 482,
+ 484, 486, 488, 490, 492, 495, 497, 499, 499, 500,
+ 501, 502, 503, 504, 505, 506, 507, 508, 509, 510,
+ 511, 512, 513, 514, 515, 516, 517, 518, 519, 520,
+
+ 521, 523, 524, 526, 528, 530, 532, 534, 536, 539,
+ 542, 544, 546, 548, 551, 553, 555, 557, 559, 561,
+ 563, 565, 567, 569, 571, 574, 576, 578, 580, 582,
+ 584, 586, 589, 591, 593, 595, 597, 599, 601, 603,
+ 605, 607, 609, 610, 611, 612, 614, 616, 619, 621,
+ 623, 625, 627, 629, 631, 634, 636, 638, 640, 642,
+ 644, 646, 648, 650, 652, 654, 656, 658, 660, 662,
+ 664, 666, 668, 670, 673, 675, 677, 679, 681, 683,
+ 685, 687, 689, 691, 693, 695, 697, 698, 699, 700,
+ 703, 705, 707, 709, 711, 713, 715, 717, 719, 721,
+
+ 723, 725, 727, 729, 731, 733, 735, 737, 739, 741,
+ 743, 745, 747, 749, 751, 753, 755, 757, 760, 762,
+ 764, 766, 768, 770, 772, 774, 776, 778, 780, 782,
+ 783, 784, 786, 788, 790, 792, 794, 796, 799, 801,
+ 804, 806, 808, 811, 813, 815, 817, 819, 821, 823,
+ 825, 827, 830, 832, 834, 836, 838, 840, 842, 844,
+ 846, 848, 851, 853, 855, 857, 859, 862, 864, 866,
+ 868, 870, 872, 875, 877, 878, 879, 881, 883, 885,
+ 887, 889, 891, 893, 895, 897, 899, 901, 903, 905,
+ 907, 909, 911, 914, 916, 918, 920, 922, 925, 927,
+
+ 930, 933, 935, 937, 939, 942, 944, 946, 948, 950,
+ 952, 954, 956, 957, 958, 960, 962, 964, 966, 968,
+ 970, 973, 975, 977, 979, 981, 983, 985, 987, 989,
+ 991, 993, 995, 997, 999, 1001, 1003, 1006, 1008, 1010,
+ 1012, 1014, 1016, 1018, 1021, 1024, 1026, 1028, 1030, 1031,
+ 1033, 1035, 1038, 1040, 1042, 1044, 1046, 1048, 1050, 1052,
+ 1054, 1057, 1059, 1061, 1063, 1065, 1067, 1069, 1071, 1073,
+ 1075, 1077, 1079, 1081, 1083, 1085, 1087, 1089, 1091, 1094,
+ 1096, 1097, 1099, 1101, 1103, 1105, 1107, 1109, 1111, 1113,
+ 1115, 1117, 1120, 1122, 1124, 1127, 1129, 1131, 1133, 1135,
+
+ 1137, 1139, 1141, 1144, 1146, 1149, 1151, 1153, 1155, 1158,
+ 1160, 1162, 1164, 1167, 1169, 1171, 1173, 1175, 1177, 1179,
+ 1182, 1185, 1188, 1191, 1193, 1195, 1197, 1199, 1201, 1204,
+ 1206, 1208, 1211, 1213, 1215, 1217, 1219, 1221, 1224, 1226,
+ 1228, 1230, 1232, 1234, 1236, 1238, 1240, 1243, 1245, 1248,
+ 1250, 1252, 1254, 1256, 1258, 1260, 1262, 1264, 1267, 1269,
+ 1271, 1273, 1275, 1277, 1279, 1281, 1284, 1287, 1289, 1291,
+ 1293, 1295, 1297, 1299, 1301, 1303, 1305, 1307, 1309, 1311,
+ 1313, 1316, 1319, 1321, 1323, 1325, 1327, 1329, 1331, 1334,
+ 1336, 1338, 1340, 1342, 1344, 1346, 1348, 1350, 1352, 1354,
+
+ 1356, 1358, 1361, 1363, 1365, 1368, 1371, 1374, 1377, 1379,
+ 1382, 1385, 1388, 1388
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 5, 6, 1, 1, 5, 1, 5, 7,
+ 8, 9, 5, 1, 10, 11, 12, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 14, 15, 16,
+ 1, 17, 12, 1, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 18, 19, 18, 1, 5, 5, 20, 21, 22, 23,
+
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 12, 1, 12, 5, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[46] =
+ { 0,
+ 1, 2, 3, 3, 4, 5, 6, 6, 4, 7,
+ 8, 9, 8, 10, 11, 12, 13, 14, 15, 16,
+ 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17
+ } ;
+
+static yyconst flex_int16_t yy_base[761] =
+ { 0,
+ 0, 19, 64, 83, 102, 121, 128, 138, 157, 0,
+ 202, 206, 209, 212, 224, 265, 6, 71, 216, 226,
+ 307, 0, 352, 375, 1453, 1452, 397, 421, 446, 465,
+ 1459, 1462, 1462, 1462, 1455, 0, 1462, 0, 220, 0,
+ 198, 1437, 108, 1419, 1422, 0, 0, 49, 1417, 78,
+ 241, 215, 79, 110, 1425, 228, 270, 1462, 1462, 1462,
+ 484, 229, 503, 0, 1462, 1462, 1462, 522, 1462, 541,
+ 277, 1462, 1449, 1462, 1445, 1462, 1462, 1462, 1447, 1439,
+ 1462, 1462, 1462, 1445, 0, 1462, 1462, 1462, 1444, 1433,
+ 1462, 1462, 1462, 1442, 1431, 115, 1419, 217, 1410, 106,
+
+ 218, 1407, 1418, 253, 244, 1415, 0, 1462, 1435, 543,
+ 1462, 1434, 1462, 1462, 86, 1462, 1462, 1462, 1433, 0,
+ 1407, 1462, 1462, 1462, 1431, 0, 1405, 1462, 1462, 1462,
+ 1462, 1462, 1429, 0, 1462, 1462, 1462, 1428, 0, 1462,
+ 1462, 0, 0, 1408, 258, 1390, 1397, 1394, 1402, 1386,
+ 1387, 1399, 1387, 1387, 1410, 1376, 120, 1392, 239, 258,
+ 1395, 391, 1376, 1391, 1377, 1378, 351, 1380, 0, 1373,
+ 1386, 1389, 1371, 1365, 378, 371, 395, 1462, 412, 0,
+ 1462, 0, 1390, 0, 1462, 560, 1462, 1402, 1462, 1398,
+ 1462, 1462, 0, 1393, 1462, 0, 1462, 1389, 1462, 1388,
+
+ 1363, 1373, 1376, 1376, 1368, 1356, 1361, 123, 258, 1360,
+ 1351, 1352, 1351, 1354, 1355, 1347, 1362, 1362, 0, 1462,
+ 564, 1462, 1381, 1462, 1462, 293, 1462, 1462, 1462, 0,
+ 1348, 1462, 0, 1356, 1462, 0, 1462, 0, 1357, 1343,
+ 1345, 1351, 1346, 1337, 1339, 1350, 1339, 1339, 1343, 1338,
+ 1332, 1358, 1343, 1356, 1345, 1326, 1326, 362, 1319, 1331,
+ 1326, 1335, 1327, 1317, 1319, 1316, 1318, 1312, 1342, 336,
+ 1316, 1326, 1309, 1311, 0, 1314, 1336, 289, 1335, 1334,
+ 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462,
+ 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462,
+
+ 0, 1319, 1307, 1302, 1298, 381, 1329, 337, 0, 0,
+ 1301, 1298, 1299, 0, 1311, 1309, 1323, 1308, 1298, 1292,
+ 1305, 1291, 1307, 1282, 0, 1288, 1287, 220, 378, 1279,
+ 1298, 0, 409, 412, 1297, 1298, 1285, 1280, 1282, 1306,
+ 1287, 1294, 1303, 1302, 1273, 1271, 1299, 1298, 1274, 1269,
+ 1277, 1282, 1270, 1292, 0, 1277, 1265, 1265, 1257, 1254,
+ 1268, 1271, 1269, 1265, 1270, 1281, 1267, 394, 1267, 1278,
+ 1249, 1249, 1275, 0, 1247, 1261, 1243, 1256, 1258, 1242,
+ 1241, 1238, 1241, 1255, 1241, 1233, 1262, 1261, 1231, 1259,
+ 1240, 1243, 1227, 1237, 437, 1225, 1224, 1234, 1223, 1229,
+
+ 1222, 1234, 1222, 1211, 1218, 1230, 1214, 1208, 418, 1241,
+ 324, 1226, 1225, 1209, 1208, 1222, 1225, 0, 1220, 1223,
+ 1232, 1200, 1210, 1198, 1216, 1201, 1208, 1207, 1193, 1218,
+ 1217, 0, 433, 1193, 1184, 1196, 1178, 0, 1197, 0,
+ 1211, 1184, 0, 1172, 1173, 1177, 1185, 1192, 1172, 1173,
+ 1162, 0, 1165, 1180, 1166, 1162, 1167, 1177, 1161, 1161,
+ 1184, 0, 1168, 1182, 1165, 1158, 0, 1154, 1164, 1152,
+ 1146, 1158, 0, 1154, 1170, 1169, 1145, 1157, 1148, 1148,
+ 1149, 1150, 1135, 546, 1143, 1157, 1146, 1124, 1124, 1121,
+ 1135, 1121, 0, 1118, 1120, 1121, 1130, 0, 1140, 0,
+
+ 0, 1126, 1109, 1110, 0, 1126, 1106, 1121, 1105, 1100,
+ 1105, 1113, 1126, 1125, 1112, 1100, 1095, 1095, 1107, 1087,
+ 0, 1097, 1091, 454, 1079, 1088, 1079, 1080, 1088, 1091,
+ 1086, 1090, 1088, 1084, 1067, 1066, 0, 1084, 1076, 1079,
+ 1068, 1062, 1072, 0, 0, 1072, 1056, 1061, 1082, 1057,
+ 1064, 0, 1048, 1047, 1056, 1042, 1057, 1043, 1042, 1039,
+ 0, 1037, 1047, 1034, 1026, 1028, 1051, 1037, 455, 1030,
+ 1016, 1010, 1013, 1013, 1009, 1026, 1013, 1022, 0, 1002,
+ 1030, 1016, 998, 999, 1008, 1001, 997, 997, 1001, 992,
+ 957, 0, 934, 929, 0, 928, 932, 949, 925, 920,
+
+ 919, 931, 0, 916, 0, 902, 888, 880, 0, 879,
+ 877, 878, 0, 863, 863, 856, 865, 847, 841, 0,
+ 0, 0, 0, 848, 826, 807, 809, 808, 0, 797,
+ 806, 0, 819, 806, 794, 800, 790, 0, 784, 790,
+ 797, 789, 791, 791, 785, 767, 0, 771, 0, 770,
+ 564, 556, 557, 570, 550, 543, 549, 0, 541, 549,
+ 543, 541, 530, 517, 515, 0, 0, 524, 506, 518,
+ 515, 498, 502, 513, 493, 492, 508, 503, 493, 497,
+ 0, 0, 488, 475, 474, 484, 480, 468, 0, 481,
+ 463, 456, 466, 469, 449, 425, 432, 417, 406, 365,
+
+ 368, 0, 352, 79, 0, 0, 0, 0, 52, 0,
+ 0, 0, 1462, 585, 602, 619, 636, 653, 670, 687,
+ 704, 721, 738, 755, 772, 789, 803, 817, 834, 851,
+ 868, 885, 902, 919, 936, 947, 961, 978, 995, 1012,
+ 459, 1026, 1036, 1049, 1065, 1081, 471, 1092, 1103, 1114,
+ 1125, 1136, 1147, 1158, 1169, 1180, 1191, 1202, 1213, 1224
+ } ;
+
+static yyconst flex_int16_t yy_def[761] =
+ { 0,
+ 714, 713, 715, 715, 716, 716, 717, 717, 713, 9,
+ 718, 718, 719, 719, 720, 720, 721, 721, 722, 722,
+ 713, 21, 723, 723, 724, 724, 725, 725, 726, 726,
+ 713, 713, 713, 713, 713, 727, 713, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 729, 713, 713, 713,
+ 730, 731, 730, 732, 713, 713, 713, 733, 713, 733,
+ 734, 713, 735, 713, 713, 713, 713, 713, 713, 736,
+ 713, 713, 713, 713, 737, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+
+ 713, 713, 713, 713, 713, 713, 738, 713, 713, 739,
+ 713, 740, 713, 713, 713, 713, 713, 713, 713, 741,
+ 741, 713, 713, 713, 713, 742, 742, 713, 713, 713,
+ 713, 713, 713, 743, 713, 713, 713, 713, 744, 713,
+ 713, 727, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 729, 713, 731, 713, 745, 63,
+ 713, 732, 746, 70, 713, 734, 713, 735, 713, 713,
+ 713, 713, 747, 748, 713, 737, 713, 713, 713, 713,
+
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 738, 713,
+ 739, 713, 740, 713, 713, 713, 713, 713, 713, 741,
+ 741, 713, 742, 742, 713, 743, 713, 744, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 745, 749, 750,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+
+ 741, 742, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 751, 752, 742, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 753, 754, 742, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 755,
+ 756, 742, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 757, 758, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 759, 713, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 760, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 713, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 0, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713
+ } ;
+
+static yyconst flex_int16_t yy_nxt[1508] =
+ { 0,
+ 32, 33, 34, 35, 713, 37, 32, 32, 108, 109,
+ 713, 32, 713, 32, 32, 32, 32, 32, 32, 32,
+ 33, 34, 35, 38, 37, 32, 32, 38, 38, 38,
+ 32, 38, 32, 32, 32, 32, 32, 32, 39, 40,
+ 41, 42, 43, 44, 38, 38, 45, 38, 46, 47,
+ 48, 38, 49, 50, 38, 51, 52, 53, 54, 55,
+ 56, 38, 38, 38, 57, 58, 59, 60, 156, 62,
+ 57, 57, 63, 108, 109, 57, 157, 57, 57, 60,
+ 60, 57, 57, 57, 58, 59, 60, 159, 62, 57,
+ 57, 63, 227, 228, 57, 712, 57, 57, 60, 60,
+
+ 57, 57, 64, 65, 66, 67, 168, 69, 64, 64,
+ 70, 711, 169, 64, 160, 64, 67, 67, 67, 64,
+ 64, 64, 65, 66, 67, 207, 69, 64, 64, 70,
+ 72, 73, 64, 74, 64, 67, 67, 67, 64, 64,
+ 72, 73, 170, 74, 151, 208, 75, 171, 152, 201,
+ 153, 253, 254, 288, 202, 289, 75, 76, 77, 78,
+ 79, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+
+ 80, 80, 81, 82, 83, 84, 81, 82, 83, 84,
+ 87, 88, 89, 87, 88, 89, 81, 147, 111, 112,
+ 81, 90, 113, 114, 90, 92, 93, 94, 111, 112,
+ 176, 148, 113, 114, 115, 149, 95, 209, 165, 369,
+ 204, 144, 166, 96, 115, 178, 97, 173, 98, 99,
+ 145, 210, 100, 205, 167, 101, 102, 103, 256, 146,
+ 161, 104, 105, 370, 162, 106, 92, 93, 94, 174,
+ 216, 176, 213, 257, 163, 177, 214, 95, 164, 187,
+ 188, 240, 189, 217, 96, 258, 178, 97, 241, 98,
+ 99, 259, 215, 100, 290, 190, 101, 102, 103, 227,
+
+ 228, 291, 104, 105, 181, 713, 106, 116, 117, 118,
+ 119, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 121, 120, 120, 120, 120, 120,
+ 120, 120, 122, 123, 124, 125, 352, 122, 122, 122,
+ 353, 456, 457, 122, 335, 122, 122, 122, 122, 122,
+ 122, 270, 176, 336, 127, 122, 123, 124, 125, 176,
+ 122, 122, 122, 177, 710, 271, 122, 178, 122, 122,
+ 122, 122, 122, 122, 178, 322, 176, 127, 131, 132,
+
+ 133, 371, 323, 411, 349, 372, 709, 134, 708, 134,
+ 134, 178, 261, 179, 350, 262, 134, 134, 134, 134,
+ 134, 134, 131, 132, 133, 263, 264, 181, 178, 265,
+ 412, 134, 375, 134, 134, 377, 376, 453, 707, 378,
+ 134, 134, 134, 134, 134, 134, 135, 136, 137, 138,
+ 706, 140, 135, 135, 454, 705, 477, 135, 704, 438,
+ 135, 135, 135, 478, 135, 135, 136, 137, 138, 439,
+ 140, 135, 135, 558, 230, 230, 135, 559, 599, 135,
+ 135, 135, 703, 135, 175, 179, 279, 279, 600, 177,
+ 175, 175, 702, 701, 700, 175, 699, 175, 175, 181,
+
+ 178, 175, 175, 175, 179, 698, 697, 696, 177, 175,
+ 175, 695, 694, 693, 175, 692, 175, 175, 181, 178,
+ 175, 175, 182, 183, 691, 690, 689, 688, 182, 182,
+ 687, 686, 685, 182, 684, 182, 683, 185, 682, 182,
+ 182, 182, 183, 681, 680, 222, 223, 182, 182, 224,
+ 225, 679, 182, 678, 182, 677, 185, 676, 182, 182,
+ 675, 226, 187, 188, 674, 189, 222, 223, 522, 523,
+ 224, 225, 673, 672, 671, 670, 524, 669, 190, 668,
+ 667, 666, 226, 665, 525, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+
+ 36, 36, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+ 91, 91, 91, 91, 107, 107, 107, 107, 107, 107,
+ 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
+ 107, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 139,
+ 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
+
+ 139, 139, 139, 139, 139, 139, 142, 664, 663, 142,
+ 142, 662, 661, 660, 659, 658, 657, 656, 142, 142,
+ 143, 655, 654, 143, 143, 653, 652, 651, 650, 649,
+ 648, 647, 143, 143, 175, 175, 646, 175, 175, 175,
+ 175, 175, 175, 175, 175, 645, 175, 175, 175, 175,
+ 175, 180, 180, 644, 180, 180, 180, 180, 180, 180,
+ 180, 180, 180, 180, 180, 180, 180, 180, 177, 177,
+ 643, 177, 177, 177, 177, 177, 177, 177, 177, 642,
+ 177, 177, 177, 177, 177, 182, 641, 640, 182, 639,
+ 182, 182, 182, 182, 182, 638, 637, 636, 182, 182,
+
+ 182, 182, 184, 184, 635, 184, 634, 184, 184, 184,
+ 184, 184, 633, 184, 632, 184, 184, 184, 184, 186,
+ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
+ 186, 186, 186, 186, 186, 186, 188, 188, 188, 188,
+ 631, 188, 188, 188, 188, 188, 188, 188, 188, 188,
+ 630, 188, 188, 194, 629, 628, 627, 626, 625, 624,
+ 623, 622, 194, 194, 196, 196, 196, 196, 196, 196,
+ 196, 621, 196, 196, 196, 196, 196, 196, 219, 219,
+ 620, 219, 219, 219, 219, 219, 219, 219, 219, 219,
+ 219, 219, 219, 219, 219, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 223, 223, 223, 223, 223, 619, 223, 223,
+ 223, 223, 223, 223, 223, 223, 618, 223, 223, 233,
+ 617, 616, 233, 233, 615, 614, 613, 612, 611, 193,
+ 610, 233, 233, 236, 609, 236, 608, 607, 606, 605,
+ 604, 236, 238, 603, 602, 238, 238, 601, 238, 598,
+ 597, 596, 238, 595, 238, 238, 278, 594, 278, 593,
+ 592, 278, 278, 591, 590, 589, 278, 278, 588, 587,
+ 278, 278, 183, 586, 183, 585, 584, 183, 183, 583,
+ 582, 193, 183, 580, 579, 578, 183, 183, 280, 577,
+
+ 576, 575, 574, 573, 572, 571, 570, 280, 280, 343,
+ 569, 568, 567, 566, 565, 564, 563, 562, 343, 343,
+ 344, 561, 560, 557, 556, 555, 554, 553, 552, 344,
+ 344, 387, 551, 550, 193, 193, 548, 547, 546, 545,
+ 387, 387, 388, 544, 543, 542, 541, 540, 539, 538,
+ 537, 388, 388, 430, 536, 535, 534, 533, 532, 531,
+ 530, 529, 430, 430, 431, 528, 527, 526, 521, 520,
+ 519, 518, 517, 431, 431, 475, 516, 515, 193, 193,
+ 512, 511, 510, 509, 475, 475, 476, 508, 507, 506,
+ 505, 504, 503, 502, 501, 476, 476, 513, 500, 499,
+
+ 498, 497, 496, 495, 494, 493, 513, 513, 514, 492,
+ 491, 490, 489, 488, 487, 486, 485, 514, 514, 549,
+ 484, 483, 482, 481, 480, 479, 193, 193, 549, 549,
+ 581, 474, 473, 472, 471, 470, 469, 468, 467, 581,
+ 581, 466, 465, 464, 463, 462, 461, 460, 459, 458,
+ 455, 452, 451, 450, 449, 448, 447, 446, 445, 444,
+ 443, 442, 441, 440, 437, 436, 435, 434, 433, 432,
+ 193, 193, 429, 428, 427, 426, 425, 424, 423, 422,
+ 421, 420, 419, 418, 417, 416, 415, 414, 413, 410,
+ 409, 408, 407, 406, 405, 404, 403, 402, 401, 400,
+
+ 399, 398, 397, 396, 395, 394, 393, 392, 391, 390,
+ 389, 193, 193, 386, 385, 384, 383, 382, 381, 380,
+ 379, 374, 373, 368, 367, 366, 365, 364, 363, 362,
+ 361, 360, 359, 358, 357, 356, 355, 354, 351, 348,
+ 347, 346, 345, 193, 193, 342, 341, 340, 339, 338,
+ 337, 334, 333, 332, 331, 330, 329, 328, 327, 326,
+ 325, 324, 321, 320, 319, 318, 317, 316, 315, 314,
+ 313, 312, 311, 310, 309, 308, 307, 306, 305, 304,
+ 303, 302, 301, 222, 300, 299, 298, 297, 296, 295,
+ 294, 293, 292, 287, 286, 285, 284, 283, 282, 281,
+
+ 200, 198, 193, 191, 187, 185, 277, 276, 275, 274,
+ 273, 272, 269, 268, 267, 266, 260, 255, 252, 251,
+ 250, 249, 248, 247, 246, 245, 244, 243, 242, 239,
+ 237, 235, 234, 232, 231, 229, 222, 220, 218, 212,
+ 211, 206, 203, 200, 199, 198, 197, 195, 193, 192,
+ 191, 187, 172, 158, 155, 154, 150, 141, 713, 129,
+ 129, 31, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+
+ 713, 713, 713, 713, 713, 713, 713
+ } ;
+
+static yyconst flex_int16_t yy_chk[1508] =
+ { 0,
+ 1, 1, 1, 1, 0, 1, 1, 1, 17, 17,
+ 0, 1, 0, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 3, 3, 3, 3, 48, 3,
+ 3, 3, 3, 18, 18, 3, 48, 3, 3, 3,
+ 3, 3, 3, 4, 4, 4, 4, 50, 4, 4,
+ 4, 4, 115, 115, 4, 709, 4, 4, 4, 4,
+
+ 4, 4, 5, 5, 5, 5, 53, 5, 5, 5,
+ 5, 704, 53, 5, 50, 5, 5, 5, 5, 5,
+ 5, 6, 6, 6, 6, 100, 6, 6, 6, 6,
+ 7, 7, 6, 7, 6, 6, 6, 6, 6, 6,
+ 8, 8, 54, 8, 43, 100, 7, 54, 43, 96,
+ 43, 157, 157, 208, 96, 208, 8, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+
+ 9, 9, 11, 11, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 14, 14, 14, 11, 41, 19, 19,
+ 12, 13, 19, 19, 14, 15, 15, 15, 20, 20,
+ 62, 41, 20, 20, 19, 41, 15, 101, 52, 328,
+ 98, 39, 52, 15, 20, 62, 15, 56, 15, 15,
+ 39, 101, 15, 98, 52, 15, 15, 15, 159, 39,
+ 51, 15, 15, 328, 51, 15, 16, 16, 16, 56,
+ 105, 57, 104, 159, 51, 57, 104, 16, 51, 71,
+ 71, 145, 71, 105, 16, 160, 57, 16, 145, 16,
+ 16, 160, 104, 16, 209, 71, 16, 16, 16, 226,
+
+ 226, 209, 16, 16, 278, 278, 16, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 23, 23, 23, 23, 308, 23, 23, 23,
+ 308, 411, 411, 23, 270, 23, 23, 23, 23, 23,
+ 23, 167, 176, 270, 23, 24, 24, 24, 24, 175,
+ 24, 24, 24, 175, 703, 167, 24, 176, 24, 24,
+ 24, 24, 24, 24, 175, 258, 177, 24, 27, 27,
+
+ 27, 329, 258, 368, 306, 329, 701, 27, 700, 27,
+ 27, 177, 162, 179, 306, 162, 27, 27, 27, 27,
+ 27, 27, 28, 28, 28, 162, 162, 179, 179, 162,
+ 368, 28, 333, 28, 28, 334, 333, 409, 699, 334,
+ 28, 28, 28, 28, 28, 28, 29, 29, 29, 29,
+ 698, 29, 29, 29, 409, 697, 433, 29, 696, 395,
+ 29, 29, 29, 433, 29, 30, 30, 30, 30, 395,
+ 30, 30, 30, 524, 741, 741, 30, 524, 569, 30,
+ 30, 30, 695, 30, 61, 61, 747, 747, 569, 61,
+ 61, 61, 694, 693, 692, 61, 691, 61, 61, 61,
+
+ 61, 61, 61, 63, 63, 690, 688, 687, 63, 63,
+ 63, 686, 685, 684, 63, 683, 63, 63, 63, 63,
+ 63, 63, 68, 68, 680, 679, 678, 677, 68, 68,
+ 676, 675, 674, 68, 673, 68, 672, 68, 671, 68,
+ 68, 70, 70, 670, 669, 110, 110, 70, 70, 110,
+ 110, 668, 70, 665, 70, 664, 70, 663, 70, 70,
+ 662, 110, 186, 186, 661, 186, 221, 221, 484, 484,
+ 221, 221, 660, 659, 657, 656, 484, 655, 186, 654,
+ 653, 652, 221, 651, 484, 714, 714, 714, 714, 714,
+ 714, 714, 714, 714, 714, 714, 714, 714, 714, 714,
+
+ 714, 714, 715, 715, 715, 715, 715, 715, 715, 715,
+ 715, 715, 715, 715, 715, 715, 715, 715, 715, 716,
+ 716, 716, 716, 716, 716, 716, 716, 716, 716, 716,
+ 716, 716, 716, 716, 716, 716, 717, 717, 717, 717,
+ 717, 717, 717, 717, 717, 717, 717, 717, 717, 717,
+ 717, 717, 717, 718, 718, 718, 718, 718, 718, 718,
+ 718, 718, 718, 718, 718, 718, 718, 718, 718, 718,
+ 719, 719, 719, 719, 719, 719, 719, 719, 719, 719,
+ 719, 719, 719, 719, 719, 719, 719, 720, 720, 720,
+ 720, 720, 720, 720, 720, 720, 720, 720, 720, 720,
+
+ 720, 720, 720, 720, 721, 721, 721, 721, 721, 721,
+ 721, 721, 721, 721, 721, 721, 721, 721, 721, 721,
+ 721, 722, 722, 722, 722, 722, 722, 722, 722, 722,
+ 722, 722, 722, 722, 722, 722, 722, 722, 723, 723,
+ 723, 723, 723, 723, 723, 723, 723, 723, 723, 723,
+ 723, 723, 723, 723, 723, 724, 724, 724, 724, 724,
+ 724, 724, 724, 724, 724, 724, 724, 724, 724, 724,
+ 724, 724, 725, 725, 725, 725, 725, 725, 725, 725,
+ 725, 725, 725, 725, 725, 725, 725, 725, 725, 726,
+ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726,
+
+ 726, 726, 726, 726, 726, 726, 727, 650, 648, 727,
+ 727, 646, 645, 644, 643, 642, 641, 640, 727, 727,
+ 728, 639, 637, 728, 728, 636, 635, 634, 633, 631,
+ 630, 628, 728, 728, 729, 729, 627, 729, 729, 729,
+ 729, 729, 729, 729, 729, 626, 729, 729, 729, 729,
+ 729, 730, 730, 625, 730, 730, 730, 730, 730, 730,
+ 730, 730, 730, 730, 730, 730, 730, 730, 731, 731,
+ 624, 731, 731, 731, 731, 731, 731, 731, 731, 619,
+ 731, 731, 731, 731, 731, 732, 618, 617, 732, 616,
+ 732, 732, 732, 732, 732, 615, 614, 612, 732, 732,
+
+ 732, 732, 733, 733, 611, 733, 610, 733, 733, 733,
+ 733, 733, 608, 733, 607, 733, 733, 733, 733, 734,
+ 734, 734, 734, 734, 734, 734, 734, 734, 734, 734,
+ 734, 734, 734, 734, 734, 734, 735, 735, 735, 735,
+ 606, 735, 735, 735, 735, 735, 735, 735, 735, 735,
+ 604, 735, 735, 736, 602, 601, 600, 599, 598, 597,
+ 596, 594, 736, 736, 737, 737, 737, 737, 737, 737,
+ 737, 593, 737, 737, 737, 737, 737, 737, 738, 738,
+ 591, 738, 738, 738, 738, 738, 738, 738, 738, 738,
+ 738, 738, 738, 738, 738, 739, 739, 739, 739, 739,
+
+ 739, 739, 739, 739, 739, 739, 739, 739, 739, 739,
+ 739, 739, 740, 740, 740, 740, 740, 590, 740, 740,
+ 740, 740, 740, 740, 740, 740, 589, 740, 740, 742,
+ 588, 587, 742, 742, 586, 585, 584, 583, 582, 581,
+ 580, 742, 742, 743, 578, 743, 577, 576, 575, 574,
+ 573, 743, 744, 572, 571, 744, 744, 570, 744, 568,
+ 567, 566, 744, 565, 744, 744, 745, 564, 745, 563,
+ 562, 745, 745, 560, 559, 558, 745, 745, 557, 556,
+ 745, 745, 746, 555, 746, 554, 553, 746, 746, 551,
+ 550, 549, 746, 548, 547, 546, 746, 746, 748, 543,
+
+ 542, 541, 540, 539, 538, 536, 535, 748, 748, 749,
+ 534, 533, 532, 531, 530, 529, 528, 527, 749, 749,
+ 750, 526, 525, 523, 522, 520, 519, 518, 517, 750,
+ 750, 751, 516, 515, 514, 513, 512, 511, 510, 509,
+ 751, 751, 752, 508, 507, 506, 504, 503, 502, 499,
+ 497, 752, 752, 753, 496, 495, 494, 492, 491, 490,
+ 489, 488, 753, 753, 754, 487, 486, 485, 483, 482,
+ 481, 480, 479, 754, 754, 755, 478, 477, 476, 475,
+ 474, 472, 471, 470, 755, 755, 756, 469, 468, 466,
+ 465, 464, 463, 461, 460, 756, 756, 757, 459, 458,
+
+ 457, 456, 455, 454, 453, 451, 757, 757, 758, 450,
+ 449, 448, 447, 446, 445, 444, 442, 758, 758, 759,
+ 441, 439, 437, 436, 435, 434, 431, 430, 759, 759,
+ 760, 429, 428, 427, 426, 425, 424, 423, 422, 760,
+ 760, 421, 420, 419, 417, 416, 415, 414, 413, 412,
+ 410, 408, 407, 406, 405, 404, 403, 402, 401, 400,
+ 399, 398, 397, 396, 394, 393, 392, 391, 390, 389,
+ 388, 387, 386, 385, 384, 383, 382, 381, 380, 379,
+ 378, 377, 376, 375, 373, 372, 371, 370, 369, 367,
+ 366, 365, 364, 363, 362, 361, 360, 359, 358, 357,
+
+ 356, 354, 353, 352, 351, 350, 349, 348, 347, 346,
+ 345, 344, 343, 342, 341, 340, 339, 338, 337, 336,
+ 335, 331, 330, 327, 326, 324, 323, 322, 321, 320,
+ 319, 318, 317, 316, 315, 313, 312, 311, 307, 305,
+ 304, 303, 302, 280, 279, 277, 276, 274, 273, 272,
+ 271, 269, 268, 267, 266, 265, 264, 263, 262, 261,
+ 260, 259, 257, 256, 255, 254, 253, 252, 251, 250,
+ 249, 248, 247, 246, 245, 244, 243, 242, 241, 240,
+ 239, 234, 231, 223, 218, 217, 216, 215, 214, 213,
+ 212, 211, 210, 207, 206, 205, 204, 203, 202, 201,
+
+ 200, 198, 194, 190, 188, 183, 174, 173, 172, 171,
+ 170, 168, 166, 165, 164, 163, 161, 158, 156, 155,
+ 154, 153, 152, 151, 150, 149, 148, 147, 146, 144,
+ 138, 133, 127, 125, 121, 119, 112, 109, 106, 103,
+ 102, 99, 97, 95, 94, 90, 89, 84, 80, 79,
+ 75, 73, 55, 49, 45, 44, 42, 35, 31, 26,
+ 25, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
+
+ 713, 713, 713, 713, 713, 713, 713
+ } ;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
+static char *yy_full_match;
+static int yy_lp;
+static int yy_looking_for_trail_begin = 0;
+static int yy_full_lp;
+static int *yy_full_state;
+#define YY_TRAILING_MASK 0x2000
+#define YY_TRAILING_HEAD_MASK 0x4000
+#define REJECT \
+{ \
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \
+yy_cp = (yy_full_match); /* restore poss. backed-over text */ \
+(yy_lp) = yy_full_lp; /* restore orig. accepting pos. */ \
+(yy_state_ptr) = yy_full_state; /* restore orig. state */ \
+yy_current_state = *(yy_state_ptr); /* restore curr. state */ \
+++(yy_lp); \
+goto find_rule; \
+}
+
+static int yy_more_flag = 0;
+static int yy_more_len = 0;
+#define yymore() ((yy_more_flag) = 1)
+#define YY_MORE_ADJ (yy_more_len)
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "scanner.lxx"
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+#line 20 "scanner.lxx"
+#include <cstdio>
+#include <cstring>
+#include <math.h>
+#include <string>
+#include "parse_ctrl.h"
+#include "parser.h"
+#include "util.h"
+#include "audits/memman.h"
+
+using namespace std;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 1240 "scanner.cxx"
+
+#define INITIAL 0
+#define C_URI 1
+#define C_URI_SPECIAL 2
+#define C_QSTRING 3
+#define C_LANG 4
+#define C_WORD 5
+#define C_NUM 6
+#define C_DATE 7
+#define C_LINE 8
+#define C_COMMENT 9
+#define C_NEW 10
+#define C_AUTH_SCHEME 11
+#define C_RPAREN 12
+#define C_IPV6ADDR 13
+#define C_PARAMVAL 14
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr );
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+ static int yy_start_stack_ptr = 0;
+ static int yy_start_stack_depth = 0;
+ static int *yy_start_stack = NULL;
+
+ static void yy_push_state (int new_state );
+
+ static void yy_pop_state (void );
+
+ static int yy_top_state (void );
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 58 "scanner.lxx"
+
+ switch (t_parser::context) {
+ case t_parser::X_URI: BEGIN(C_URI); break;
+ case t_parser::X_URI_SPECIAL: BEGIN(C_URI_SPECIAL); break;
+ case t_parser::X_LANG: BEGIN(C_LANG); break;
+ case t_parser::X_WORD: BEGIN(C_WORD); break;
+ case t_parser::X_NUM: BEGIN(C_NUM); break;
+ case t_parser::X_DATE: BEGIN(C_DATE); break;
+ case t_parser::X_LINE: BEGIN(C_LINE); break;
+ case t_parser::X_COMMENT: BEGIN(C_COMMENT); break;
+ case t_parser::X_NEW: BEGIN(C_NEW); break;
+ case t_parser::X_AUTH_SCHEME: BEGIN(C_AUTH_SCHEME); break;
+ case t_parser::X_IPV6ADDR: BEGIN(C_IPV6ADDR); break;
+ case t_parser::X_PARAMVAL: BEGIN(C_PARAMVAL); break;
+ default: BEGIN(INITIAL);
+ }
+
+ /* Headers */
+#line 1439 "scanner.cxx"
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ /* Create the reject buffer large enough to save one state per allowed character. */
+ if ( ! (yy_state_buf) )
+ (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE );
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
+
+ yy_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ (yy_more_len) = 0;
+ if ( (yy_more_flag) )
+ {
+ (yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
+ (yy_more_flag) = 0;
+ }
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of yytext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+
+ (yy_state_ptr) = (yy_state_buf);
+ *(yy_state_ptr)++ = yy_current_state;
+
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 714 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *(yy_state_ptr)++ = yy_current_state;
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 1462 );
+
+yy_find_action:
+ yy_current_state = *--(yy_state_ptr);
+ (yy_lp) = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+ for ( ; ; ) /* until we find what rule we matched */
+ {
+ if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] )
+ {
+ yy_act = yy_acclist[(yy_lp)];
+ if ( yy_act & YY_TRAILING_HEAD_MASK ||
+ yy_looking_for_trail_begin )
+ {
+ if ( yy_act == yy_looking_for_trail_begin )
+ {
+ yy_looking_for_trail_begin = 0;
+ yy_act &= ~YY_TRAILING_HEAD_MASK;
+ break;
+ }
+ }
+ else if ( yy_act & YY_TRAILING_MASK )
+ {
+ yy_looking_for_trail_begin = yy_act & ~YY_TRAILING_MASK;
+ yy_looking_for_trail_begin |= YY_TRAILING_HEAD_MASK;
+ }
+ else
+ {
+ (yy_full_match) = yy_cp;
+ yy_full_state = (yy_state_ptr);
+ yy_full_lp = (yy_lp);
+ break;
+ }
+ ++(yy_lp);
+ goto find_rule;
+ }
+ --yy_cp;
+ yy_current_state = *--(yy_state_ptr);
+ (yy_lp) = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 76 "scanner.lxx"
+{ return T_HDR_ACCEPT; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 77 "scanner.lxx"
+{ return T_HDR_ACCEPT_ENCODING; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 78 "scanner.lxx"
+{ return T_HDR_ACCEPT_LANGUAGE; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 79 "scanner.lxx"
+{ return T_HDR_ALERT_INFO; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 80 "scanner.lxx"
+{ return T_HDR_ALLOW; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 81 "scanner.lxx"
+{ return T_HDR_ALLOW_EVENTS; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 82 "scanner.lxx"
+{ return T_HDR_AUTHENTICATION_INFO; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 83 "scanner.lxx"
+{ return T_HDR_AUTHORIZATION; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 84 "scanner.lxx"
+{ return T_HDR_CALL_ID; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 85 "scanner.lxx"
+{ return T_HDR_CALL_INFO; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 86 "scanner.lxx"
+{ return T_HDR_CONTACT; }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 87 "scanner.lxx"
+{ return T_HDR_CONTENT_DISP; }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 88 "scanner.lxx"
+{ return T_HDR_CONTENT_ENCODING; }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 89 "scanner.lxx"
+{ return T_HDR_CONTENT_LANGUAGE; }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 90 "scanner.lxx"
+{ return T_HDR_CONTENT_LENGTH; }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 91 "scanner.lxx"
+{ return T_HDR_CONTENT_TYPE; }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 92 "scanner.lxx"
+{ return T_HDR_CSEQ; }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 93 "scanner.lxx"
+{ return T_HDR_DATE; }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 94 "scanner.lxx"
+{ return T_HDR_ERROR_INFO; }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 95 "scanner.lxx"
+{ return T_HDR_EVENT; }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 96 "scanner.lxx"
+{ return T_HDR_EXPIRES; }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 97 "scanner.lxx"
+{ return T_HDR_FROM; }
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 98 "scanner.lxx"
+{ return T_HDR_IN_REPLY_TO; }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 99 "scanner.lxx"
+{ return T_HDR_MAX_FORWARDS; }
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 100 "scanner.lxx"
+{ return T_HDR_MIN_EXPIRES; }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 101 "scanner.lxx"
+{ return T_HDR_MIME_VERSION; }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 102 "scanner.lxx"
+{ return T_HDR_ORGANIZATION; }
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 103 "scanner.lxx"
+{ return T_HDR_P_ASSERTED_IDENTITY; }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 104 "scanner.lxx"
+{ return T_HDR_P_PREFERRED_IDENTITY; }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 105 "scanner.lxx"
+{ return T_HDR_PRIORITY; }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 106 "scanner.lxx"
+{ return T_HDR_PRIVACY; }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 107 "scanner.lxx"
+{ return T_HDR_PROXY_AUTHENTICATE; }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 108 "scanner.lxx"
+{ return T_HDR_PROXY_AUTHORIZATION; }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 109 "scanner.lxx"
+{ return T_HDR_PROXY_REQUIRE; }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 110 "scanner.lxx"
+{ return T_HDR_RACK; }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 111 "scanner.lxx"
+{ return T_HDR_RECORD_ROUTE; }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 112 "scanner.lxx"
+{ return T_HDR_SERVICE_ROUTE; }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 113 "scanner.lxx"
+{ return T_HDR_REFER_SUB; }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 114 "scanner.lxx"
+{ return T_HDR_REFER_TO; }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 115 "scanner.lxx"
+{ return T_HDR_REFERRED_BY; }
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 116 "scanner.lxx"
+{ return T_HDR_REPLACES; }
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 117 "scanner.lxx"
+{ return T_HDR_REPLY_TO; }
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 118 "scanner.lxx"
+{ return T_HDR_REQUIRE; }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 119 "scanner.lxx"
+{return T_HDR_REQUEST_DISPOSITION; }
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 120 "scanner.lxx"
+{ return T_HDR_RETRY_AFTER; }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 121 "scanner.lxx"
+{ return T_HDR_ROUTE; }
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 122 "scanner.lxx"
+{ return T_HDR_RSEQ; }
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 123 "scanner.lxx"
+{ return T_HDR_SERVER; }
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 124 "scanner.lxx"
+{ return T_HDR_SIP_ETAG; }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 125 "scanner.lxx"
+{ return T_HDR_SIP_IF_MATCH; }
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 126 "scanner.lxx"
+{ return T_HDR_SUBJECT; }
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 127 "scanner.lxx"
+{ return T_HDR_SUBSCRIPTION_STATE; }
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 128 "scanner.lxx"
+{ return T_HDR_SUPPORTED; }
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 129 "scanner.lxx"
+{ return T_HDR_TIMESTAMP; }
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 130 "scanner.lxx"
+{ return T_HDR_TO; }
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 131 "scanner.lxx"
+{ return T_HDR_UNSUPPORTED; }
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 132 "scanner.lxx"
+{ return T_HDR_USER_AGENT; }
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 133 "scanner.lxx"
+{ return T_HDR_VIA; }
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 134 "scanner.lxx"
+{ return T_HDR_WARNING; }
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 135 "scanner.lxx"
+{ return T_HDR_WWW_AUTHENTICATE; }
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 136 "scanner.lxx"
+{ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_HDR_UNKNOWN; }
+ YY_BREAK
+/* Token as define in RFC 3261 */
+case 62:
+YY_RULE_SETUP
+#line 141 "scanner.lxx"
+{ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_TOKEN; }
+ YY_BREAK
+/* Switch to quoted string context */
+case 63:
+YY_RULE_SETUP
+#line 146 "scanner.lxx"
+{ yy_push_state(C_QSTRING); }
+ YY_BREAK
+/* End of line */
+case 64:
+/* rule 64 can match eol */
+YY_RULE_SETUP
+#line 149 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 65:
+/* rule 65 can match eol */
+YY_RULE_SETUP
+#line 150 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 152 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+/* Single character token */
+case 67:
+YY_RULE_SETUP
+#line 155 "scanner.lxx"
+{ return yytext[0]; }
+ YY_BREAK
+/* URI.
+ This context scans a URI including parameters.
+ The syntax of a URI will be checked outside the scanner
+ */
+case 68:
+YY_RULE_SETUP
+#line 161 "scanner.lxx"
+{ yy_push_state(C_QSTRING); }
+ YY_BREAK
+case 69:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 162 "scanner.lxx"
+{
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_DISPLAY; }
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 166 "scanner.lxx"
+{
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_URI; }
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 170 "scanner.lxx"
+{ return T_URI_WILDCARD; }
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 171 "scanner.lxx"
+{
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_URI; }
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 175 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 176 "scanner.lxx"
+{ return yytext[0]; }
+ YY_BREAK
+case 75:
+/* rule 75 can match eol */
+YY_RULE_SETUP
+#line 177 "scanner.lxx"
+{ return T_ERROR; }
+ YY_BREAK
+/* URI special case.
+ In several headers (eg. From, To, Contact, Reply-To) the URI
+ can be enclosed by < and >
+ If it is enclosed then parameters belong to the URI, if it
+ is not enclosed then parameters belong to the header.
+ Parameters are seperated by a semi-colon.
+ For the URI special case, parameters belong to the header.
+ If the parser receives a < from the scanner, then the parser
+ will switch to the normal URI case.
+ The syntax of a URI will be checked outside the scanner
+ */
+case 76:
+YY_RULE_SETUP
+#line 190 "scanner.lxx"
+{ yy_push_state(C_QSTRING); }
+ YY_BREAK
+case 77:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 191 "scanner.lxx"
+{
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_DISPLAY; }
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 195 "scanner.lxx"
+{ return T_URI_WILDCARD; }
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 196 "scanner.lxx"
+{
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_URI; }
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 200 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 201 "scanner.lxx"
+{ return yytext[0]; }
+ YY_BREAK
+case 82:
+/* rule 82 can match eol */
+YY_RULE_SETUP
+#line 202 "scanner.lxx"
+{ return T_ERROR; }
+ YY_BREAK
+/* Quoted string (starting after open quote, closing quote
+ will be consumed but not returned. */
+case 83:
+YY_RULE_SETUP
+#line 206 "scanner.lxx"
+{ yymore(); }
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 207 "scanner.lxx"
+{ yymore(); }
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 208 "scanner.lxx"
+{ yy_pop_state();
+ yytext[strlen(yytext)-1] = '\0';
+ yylval.yyt_str = new string(unescape(string(yytext)));
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_QSTRING; }
+ YY_BREAK
+case 86:
+/* rule 86 can match eol */
+YY_RULE_SETUP
+#line 213 "scanner.lxx"
+{ yy_pop_state(); return T_ERROR; }
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 214 "scanner.lxx"
+{ yy_pop_state(); return T_ERROR; }
+ YY_BREAK
+/* Comment (starting after LPAREN till RPAREN) */
+case 88:
+YY_RULE_SETUP
+#line 217 "scanner.lxx"
+{ yymore(); }
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 218 "scanner.lxx"
+{ yymore(); }
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 219 "scanner.lxx"
+{ yymore(); }
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 220 "scanner.lxx"
+{ t_parser::inc_comment_level(); yymore(); }
+ YY_BREAK
+case 92:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 221 "scanner.lxx"
+{ if (t_parser::dec_comment_level()) {
+ BEGIN(C_RPAREN);
+ yymore();
+ } else {
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_COMMENT;
+ }
+ }
+ YY_BREAK
+case 93:
+/* rule 93 can match eol */
+YY_RULE_SETUP
+#line 230 "scanner.lxx"
+{ return T_ERROR; }
+ YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 231 "scanner.lxx"
+{ return T_ERROR; }
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 232 "scanner.lxx"
+{ BEGIN(C_COMMENT); yymore(); }
+ YY_BREAK
+/* Language tag */
+case 96:
+YY_RULE_SETUP
+#line 235 "scanner.lxx"
+{ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_LANG; }
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 238 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 239 "scanner.lxx"
+{ return yytext[0]; }
+ YY_BREAK
+case 99:
+/* rule 99 can match eol */
+YY_RULE_SETUP
+#line 240 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 100:
+/* rule 100 can match eol */
+YY_RULE_SETUP
+#line 241 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+/* Word */
+case 101:
+YY_RULE_SETUP
+#line 244 "scanner.lxx"
+{ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_WORD; }
+ YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 247 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 248 "scanner.lxx"
+{ return yytext[0]; }
+ YY_BREAK
+case 104:
+/* rule 104 can match eol */
+YY_RULE_SETUP
+#line 249 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 105:
+/* rule 105 can match eol */
+YY_RULE_SETUP
+#line 250 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+/* Number */
+case 106:
+YY_RULE_SETUP
+#line 253 "scanner.lxx"
+{ yylval.yyt_ulong = strtoul(yytext, NULL, 10); return T_NUM; }
+ YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 254 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 255 "scanner.lxx"
+{ return yytext[0]; }
+ YY_BREAK
+case 109:
+/* rule 109 can match eol */
+YY_RULE_SETUP
+#line 256 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 110:
+/* rule 110 can match eol */
+YY_RULE_SETUP
+#line 257 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+/* Date */
+case 111:
+YY_RULE_SETUP
+#line 260 "scanner.lxx"
+{ yylval.yyt_int = 1; return T_WKDAY; }
+ YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 261 "scanner.lxx"
+{ yylval.yyt_int = 2; return T_WKDAY; }
+ YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 262 "scanner.lxx"
+{ yylval.yyt_int = 3; return T_WKDAY; }
+ YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 263 "scanner.lxx"
+{ yylval.yyt_int = 4; return T_WKDAY; }
+ YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 264 "scanner.lxx"
+{ yylval.yyt_int = 5; return T_WKDAY; }
+ YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 265 "scanner.lxx"
+{ yylval.yyt_int = 6; return T_WKDAY; }
+ YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 266 "scanner.lxx"
+{ yylval.yyt_int = 0; return T_WKDAY; }
+ YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 267 "scanner.lxx"
+{ yylval.yyt_int = 0; return T_MONTH; }
+ YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 268 "scanner.lxx"
+{ yylval.yyt_int = 1; return T_MONTH; }
+ YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 269 "scanner.lxx"
+{ yylval.yyt_int = 2; return T_MONTH; }
+ YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 270 "scanner.lxx"
+{ yylval.yyt_int = 3; return T_MONTH; }
+ YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 271 "scanner.lxx"
+{ yylval.yyt_int = 4; return T_MONTH; }
+ YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 272 "scanner.lxx"
+{ yylval.yyt_int = 5; return T_MONTH; }
+ YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 273 "scanner.lxx"
+{ yylval.yyt_int = 6; return T_MONTH; }
+ YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 274 "scanner.lxx"
+{ yylval.yyt_int = 7; return T_MONTH; }
+ YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 275 "scanner.lxx"
+{ yylval.yyt_int = 8; return T_MONTH; }
+ YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 276 "scanner.lxx"
+{ yylval.yyt_int = 9; return T_MONTH; }
+ YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 277 "scanner.lxx"
+{ yylval.yyt_int = 10; return T_MONTH; }
+ YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 278 "scanner.lxx"
+{ yylval.yyt_int = 11; return T_MONTH; }
+ YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 279 "scanner.lxx"
+{ return T_GMT; }
+ YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 280 "scanner.lxx"
+{ yylval.yyt_ulong = strtoul(yytext, NULL, 10); return T_NUM; }
+ YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 281 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 282 "scanner.lxx"
+{ return yytext[0]; }
+ YY_BREAK
+case 134:
+/* rule 134 can match eol */
+YY_RULE_SETUP
+#line 283 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 135:
+/* rule 135 can match eol */
+YY_RULE_SETUP
+#line 284 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+/* Get all text till end of line */
+case 136:
+YY_RULE_SETUP
+#line 287 "scanner.lxx"
+{ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_LINE; }
+ YY_BREAK
+case 137:
+/* rule 137 can match eol */
+YY_RULE_SETUP
+#line 290 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 138:
+/* rule 138 can match eol */
+YY_RULE_SETUP
+#line 291 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 292 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+/* Start of a new message */
+case 140:
+YY_RULE_SETUP
+#line 295 "scanner.lxx"
+{ return T_SIP; }
+ YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 296 "scanner.lxx"
+{ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_METHOD; }
+ YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 299 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 300 "scanner.lxx"
+{ return T_ERROR; }
+ YY_BREAK
+case 144:
+/* rule 144 can match eol */
+YY_RULE_SETUP
+#line 301 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 145:
+/* rule 145 can match eol */
+YY_RULE_SETUP
+#line 302 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+/* Authorization scheme */
+case 146:
+YY_RULE_SETUP
+#line 305 "scanner.lxx"
+{ return T_AUTH_DIGEST; }
+ YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 306 "scanner.lxx"
+{ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_AUTH_OTHER; }
+ YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 309 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 310 "scanner.lxx"
+{ return T_ERROR; }
+ YY_BREAK
+case 150:
+/* rule 150 can match eol */
+YY_RULE_SETUP
+#line 311 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 151:
+/* rule 151 can match eol */
+YY_RULE_SETUP
+#line 312 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+/* IPv6 address
+ * NOTE: the validity of the format is not checked here.
+ */
+case 152:
+YY_RULE_SETUP
+#line 317 "scanner.lxx"
+{ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_IPV6ADDR; }
+ YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 320 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 321 "scanner.lxx"
+{ return T_ERROR; }
+ YY_BREAK
+case 155:
+/* rule 155 can match eol */
+YY_RULE_SETUP
+#line 322 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 156:
+/* rule 156 can match eol */
+YY_RULE_SETUP
+#line 323 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+/* Parameter values may contain an IPv6 address or reference. */
+case 157:
+YY_RULE_SETUP
+#line 326 "scanner.lxx"
+{ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_PARAMVAL; }
+ YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 329 "scanner.lxx"
+{ yy_push_state(C_QSTRING); }
+ YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 330 "scanner.lxx"
+/* Skip white space */
+ YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 331 "scanner.lxx"
+{ return T_ERROR; }
+ YY_BREAK
+case 161:
+/* rule 161 can match eol */
+YY_RULE_SETUP
+#line 332 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 162:
+/* rule 162 can match eol */
+YY_RULE_SETUP
+#line 333 "scanner.lxx"
+{ return T_CRLF; }
+ YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 334 "scanner.lxx"
+ECHO;
+ YY_BREAK
+#line 2482 "scanner.cxx"
+ case YY_STATE_EOF(INITIAL):
+ case YY_STATE_EOF(C_URI):
+ case YY_STATE_EOF(C_URI_SPECIAL):
+ case YY_STATE_EOF(C_QSTRING):
+ case YY_STATE_EOF(C_LANG):
+ case YY_STATE_EOF(C_WORD):
+ case YY_STATE_EOF(C_NUM):
+ case YY_STATE_EOF(C_DATE):
+ case YY_STATE_EOF(C_LINE):
+ case YY_STATE_EOF(C_COMMENT):
+ case YY_STATE_EOF(C_NEW):
+ case YY_STATE_EOF(C_AUTH_SCHEME):
+ case YY_STATE_EOF(C_RPAREN):
+ case YY_STATE_EOF(C_IPV6ADDR):
+ case YY_STATE_EOF(C_PARAMVAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( yywrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+
+ (yy_state_ptr) = (yy_state_buf);
+ *(yy_state_ptr)++ = yy_current_state;
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 714 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *(yy_state_ptr)++ = yy_current_state;
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+
+ register YY_CHAR yy_c = 1;
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 714 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 713);
+ if ( ! yy_is_jam )
+ *(yy_state_ptr)++ = yy_current_state;
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp )
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up yytext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve yytext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
+
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+ yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ *
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree((void *) b->yy_ch_buf );
+
+ yyfree((void *) b );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ yy_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack();
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void yypop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param str a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+ static void yy_push_state (int new_state )
+{
+ if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) )
+ {
+ yy_size_t new_size;
+
+ (yy_start_stack_depth) += YY_START_STACK_INCR;
+ new_size = (yy_start_stack_depth) * sizeof( int );
+
+ if ( ! (yy_start_stack) )
+ (yy_start_stack) = (int *) yyalloc(new_size );
+
+ else
+ (yy_start_stack) = (int *) yyrealloc((void *) (yy_start_stack),new_size );
+
+ if ( ! (yy_start_stack) )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START;
+
+ BEGIN(new_state);
+}
+
+ static void yy_pop_state (void)
+{
+ if ( --(yy_start_stack_ptr) < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN((yy_start_stack)[(yy_start_stack_ptr)]);
+}
+
+ static int yy_top_state (void)
+{
+ return (yy_start_stack)[(yy_start_stack_ptr) - 1];
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = (yy_hold_char); \
+ (yy_c_buf_p) = yytext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the input stream.
+ *
+ */
+FILE *yyget_in (void)
+{
+ return yyin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *yyget_out (void)
+{
+ return yyout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int yyget_leng (void)
+{
+ return yyleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *yyget_text (void)
+{
+ return yytext;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * in_str )
+{
+ yyin = in_str ;
+}
+
+void yyset_out (FILE * out_str )
+{
+ yyout = out_str ;
+}
+
+int yyget_debug (void)
+{
+ return yy_flex_debug;
+}
+
+void yyset_debug (int bdebug )
+{
+ yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+ (yy_start_stack_ptr) = 0;
+ (yy_start_stack_depth) = 0;
+ (yy_start_stack) = NULL;
+
+ (yy_state_buf) = 0;
+ (yy_state_ptr) = 0;
+ (yy_full_match) = 0;
+ (yy_lp) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ yyfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Destroy the start condition stack. */
+ yyfree((yy_start_stack) );
+ (yy_start_stack) = NULL;
+
+ yyfree ( (yy_state_buf) );
+ (yy_state_buf) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *yyrealloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 334 "scanner.lxx"
diff --git a/src/parser/scanner.lxx b/src/parser/scanner.lxx
new file mode 100644
index 0000000..05ffb97
--- /dev/null
+++ b/src/parser/scanner.lxx
@@ -0,0 +1,333 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <cstdio>
+#include <cstring>
+#include <math.h>
+#include <string>
+#include "parse_ctrl.h"
+#include "parser.h"
+#include "util.h"
+#include "audits/memman.h"
+
+using namespace std;
+%}
+
+%option noyywrap
+%option stack
+
+DIGIT [0-9]
+HEXDIG [0-9a-fA-F]
+ALPHA [a-zA-Z]
+CAPITALS [A-Z]
+ALNUM [a-zA-Z0-9]
+TOKEN_SYM [[:alnum:]\-\.!%\*_\+\`\'~]
+WORD_SYM [[:alnum:]\-\.!%\*_\+\`\'~\(\)<>:\\\"\/\[\]\?\{\}]
+
+%x C_URI
+%x C_URI_SPECIAL
+%x C_QSTRING
+%x C_LANG
+%x C_WORD
+%x C_NUM
+%x C_DATE
+%x C_LINE
+%x C_COMMENT
+%x C_NEW
+%x C_AUTH_SCHEME
+%x C_RPAREN
+%x C_IPV6ADDR
+%x C_PARAMVAL
+
+%%
+ switch (t_parser::context) {
+ case t_parser::X_URI: BEGIN(C_URI); break;
+ case t_parser::X_URI_SPECIAL: BEGIN(C_URI_SPECIAL); break;
+ case t_parser::X_LANG: BEGIN(C_LANG); break;
+ case t_parser::X_WORD: BEGIN(C_WORD); break;
+ case t_parser::X_NUM: BEGIN(C_NUM); break;
+ case t_parser::X_DATE: BEGIN(C_DATE); break;
+ case t_parser::X_LINE: BEGIN(C_LINE); break;
+ case t_parser::X_COMMENT: BEGIN(C_COMMENT); break;
+ case t_parser::X_NEW: BEGIN(C_NEW); break;
+ case t_parser::X_AUTH_SCHEME: BEGIN(C_AUTH_SCHEME); break;
+ case t_parser::X_IPV6ADDR: BEGIN(C_IPV6ADDR); break;
+ case t_parser::X_PARAMVAL: BEGIN(C_PARAMVAL); break;
+ default: BEGIN(INITIAL);
+ }
+
+ /* Headers */
+^Accept { return T_HDR_ACCEPT; }
+^Accept-Encoding { return T_HDR_ACCEPT_ENCODING; }
+^Accept-Language { return T_HDR_ACCEPT_LANGUAGE; }
+^Alert-Info { return T_HDR_ALERT_INFO; }
+^Allow { return T_HDR_ALLOW; }
+^(Allow-Events)|u { return T_HDR_ALLOW_EVENTS; }
+^Authentication-Info { return T_HDR_AUTHENTICATION_INFO; }
+^Authorization { return T_HDR_AUTHORIZATION; }
+^(Call-ID)|i { return T_HDR_CALL_ID; }
+^Call-Info { return T_HDR_CALL_INFO; }
+^(Contact)|m { return T_HDR_CONTACT; }
+^Content-Disposition { return T_HDR_CONTENT_DISP; }
+^(Content-Encoding)|e { return T_HDR_CONTENT_ENCODING; }
+^Content-Language { return T_HDR_CONTENT_LANGUAGE; }
+^(Content-Length)|l { return T_HDR_CONTENT_LENGTH; }
+^(Content-Type)|c { return T_HDR_CONTENT_TYPE; }
+^CSeq { return T_HDR_CSEQ; }
+^Date { return T_HDR_DATE; }
+^Error-Info { return T_HDR_ERROR_INFO; }
+^(Event)|o { return T_HDR_EVENT; }
+^Expires { return T_HDR_EXPIRES; }
+^(From|f) { return T_HDR_FROM; }
+^In-Reply-To { return T_HDR_IN_REPLY_TO; }
+^Max-Forwards { return T_HDR_MAX_FORWARDS; }
+^Min-Expires { return T_HDR_MIN_EXPIRES; }
+^MIME-Version { return T_HDR_MIME_VERSION; }
+^Organization { return T_HDR_ORGANIZATION; }
+^P-Asserted-Identity { return T_HDR_P_ASSERTED_IDENTITY; }
+^P-Preferred-Identity { return T_HDR_P_PREFERRED_IDENTITY; }
+^Priority { return T_HDR_PRIORITY; }
+^Privacy { return T_HDR_PRIVACY; }
+^Proxy-Authenticate { return T_HDR_PROXY_AUTHENTICATE; }
+^Proxy-Authorization { return T_HDR_PROXY_AUTHORIZATION; }
+^Proxy-Require { return T_HDR_PROXY_REQUIRE; }
+^RAck { return T_HDR_RACK; }
+^Record-Route { return T_HDR_RECORD_ROUTE; }
+^Service-Route { return T_HDR_SERVICE_ROUTE; }
+^Refer-Sub { return T_HDR_REFER_SUB; }
+^(Refer-To)|r { return T_HDR_REFER_TO; }
+^(Referred-By)|b { return T_HDR_REFERRED_BY; }
+^Replaces { return T_HDR_REPLACES; }
+^Reply-To { return T_HDR_REPLY_TO; }
+^Require { return T_HDR_REQUIRE; }
+^(Request-Disposition)|d {return T_HDR_REQUEST_DISPOSITION; }
+^Retry-After { return T_HDR_RETRY_AFTER; }
+^Route { return T_HDR_ROUTE; }
+^RSeq { return T_HDR_RSEQ; }
+^Server { return T_HDR_SERVER; }
+^SIP-ETag { return T_HDR_SIP_ETAG; }
+^SIP-If-Match { return T_HDR_SIP_IF_MATCH; }
+^(Subject)|s { return T_HDR_SUBJECT; }
+^Subscription-State { return T_HDR_SUBSCRIPTION_STATE; }
+^(Supported)|k { return T_HDR_SUPPORTED; }
+^Timestamp { return T_HDR_TIMESTAMP; }
+^(To)|t { return T_HDR_TO; }
+^unsupported { return T_HDR_UNSUPPORTED; }
+^User-Agent { return T_HDR_USER_AGENT; }
+^(Via)|v { return T_HDR_VIA; }
+^Warning { return T_HDR_WARNING; }
+^WWW-Authenticate { return T_HDR_WWW_AUTHENTICATE; }
+^{TOKEN_SYM}+ { yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_HDR_UNKNOWN; }
+
+ /* Token as define in RFC 3261 */
+{TOKEN_SYM}+ { yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_TOKEN; }
+
+ /* Switch to quoted string context */
+\" { yy_push_state(C_QSTRING); }
+
+ /* End of line */
+\r\n { return T_CRLF; }
+\n { return T_CRLF; }
+
+[[:blank:]] /* Skip white space */
+
+ /* Single character token */
+. { return yytext[0]; }
+
+ /* URI.
+ This context scans a URI including parameters.
+ The syntax of a URI will be checked outside the scanner
+ */
+<C_URI>\" { yy_push_state(C_QSTRING); }
+<C_URI>{TOKEN_SYM}({TOKEN_SYM}|[[:blank:]])*/< {
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_DISPLAY; }
+<C_URI>[^[:blank:]<>\r\n]+/[[:blank:]]*> {
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_URI; }
+<C_URI>\* { return T_URI_WILDCARD; }
+<C_URI>[^[:blank:]<>\"\r\n]+ {
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_URI; }
+<C_URI>[[:blank:]] /* Skip white space */
+<C_URI>. { return yytext[0]; }
+<C_URI>\n { return T_ERROR; }
+
+ /* URI special case.
+ In several headers (eg. From, To, Contact, Reply-To) the URI
+ can be enclosed by < and >
+ If it is enclosed then parameters belong to the URI, if it
+ is not enclosed then parameters belong to the header.
+ Parameters are seperated by a semi-colon.
+ For the URI special case, parameters belong to the header.
+ If the parser receives a < from the scanner, then the parser
+ will switch to the normal URI case.
+ The syntax of a URI will be checked outside the scanner
+ */
+<C_URI_SPECIAL>\" { yy_push_state(C_QSTRING); }
+<C_URI_SPECIAL>{TOKEN_SYM}({TOKEN_SYM}|[[:blank:]])*/< {
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_DISPLAY; }
+<C_URI_SPECIAL>\* { return T_URI_WILDCARD; }
+<C_URI_SPECIAL>[^[:blank:]<>;\"\r\n]+ {
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_URI; }
+<C_URI_SPECIAL>[[:blank:]] /* Skip white space */
+<C_URI_SPECIAL>. { return yytext[0]; }
+<C_URI_SPECIAL>\n { return T_ERROR; }
+
+ /* Quoted string (starting after open quote, closing quote
+ will be consumed but not returned. */
+<C_QSTRING>\\ { yymore(); }
+<C_QSTRING>[^\"\\\r\n]*\\\" { yymore(); }
+<C_QSTRING>[^\"\\\r\n]*\" { yy_pop_state();
+ yytext[strlen(yytext)-1] = '\0';
+ yylval.yyt_str = new string(unescape(string(yytext)));
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_QSTRING; }
+<C_QSTRING>[^\"\\\n]*\n { yy_pop_state(); return T_ERROR; }
+<C_QSTRING>. { yy_pop_state(); return T_ERROR; }
+
+ /* Comment (starting after LPAREN till RPAREN) */
+<C_COMMENT>\\ { yymore(); }
+<C_COMMENT>[^\(\)\\\r\n]*\\\) { yymore(); }
+<C_COMMENT>[^\(\)\\\r\n]*\\\( { yymore(); }
+<C_COMMENT>[^\(\)\\\r\n]*\( { t_parser::inc_comment_level(); yymore(); }
+<C_COMMENT>[^\(\)\\\r\n]*/\) { if (t_parser::dec_comment_level()) {
+ BEGIN(C_RPAREN);
+ yymore();
+ } else {
+ yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_COMMENT;
+ }
+ }
+<C_COMMENT>[^\(\)\\\n]*\n { return T_ERROR; }
+<C_COMMENT>. { return T_ERROR; }
+<C_RPAREN>\) { BEGIN(C_COMMENT); yymore(); }
+
+ /* Language tag */
+<C_LANG>{ALPHA}{1,8}(\-{ALPHA}{1,8})* { yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_LANG; }
+<C_LANG>[[:blank:]] /* Skip white space */
+<C_LANG>. { return yytext[0]; }
+<C_LANG>\r\n { return T_CRLF; }
+<C_LANG>\n { return T_CRLF; }
+
+ /* Word */
+<C_WORD>{WORD_SYM}+ { yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_WORD; }
+<C_WORD>[[:blank:]] /* Skip white space */
+<C_WORD>. { return yytext[0]; }
+<C_WORD>\r\n { return T_CRLF; }
+<C_WORD>\n { return T_CRLF; }
+
+ /* Number */
+<C_NUM>{DIGIT}+ { yylval.yyt_ulong = strtoul(yytext, NULL, 10); return T_NUM; }
+<C_NUM>[[:blank:]] /* Skip white space */
+<C_NUM>. { return yytext[0]; }
+<C_NUM>\r\n { return T_CRLF; }
+<C_NUM>\n { return T_CRLF; }
+
+ /* Date */
+<C_DATE>Mon { yylval.yyt_int = 1; return T_WKDAY; }
+<C_DATE>Tue { yylval.yyt_int = 2; return T_WKDAY; }
+<C_DATE>Wed { yylval.yyt_int = 3; return T_WKDAY; }
+<C_DATE>Thu { yylval.yyt_int = 4; return T_WKDAY; }
+<C_DATE>Fri { yylval.yyt_int = 5; return T_WKDAY; }
+<C_DATE>Sat { yylval.yyt_int = 6; return T_WKDAY; }
+<C_DATE>Sun { yylval.yyt_int = 0; return T_WKDAY; }
+<C_DATE>Jan { yylval.yyt_int = 0; return T_MONTH; }
+<C_DATE>Feb { yylval.yyt_int = 1; return T_MONTH; }
+<C_DATE>Mar { yylval.yyt_int = 2; return T_MONTH; }
+<C_DATE>Apr { yylval.yyt_int = 3; return T_MONTH; }
+<C_DATE>May { yylval.yyt_int = 4; return T_MONTH; }
+<C_DATE>Jun { yylval.yyt_int = 5; return T_MONTH; }
+<C_DATE>Jul { yylval.yyt_int = 6; return T_MONTH; }
+<C_DATE>Aug { yylval.yyt_int = 7; return T_MONTH; }
+<C_DATE>Sep { yylval.yyt_int = 8; return T_MONTH; }
+<C_DATE>Oct { yylval.yyt_int = 9; return T_MONTH; }
+<C_DATE>Nov { yylval.yyt_int = 10; return T_MONTH; }
+<C_DATE>Dec { yylval.yyt_int = 11; return T_MONTH; }
+<C_DATE>GMT { return T_GMT; }
+<C_DATE>{DIGIT}+ { yylval.yyt_ulong = strtoul(yytext, NULL, 10); return T_NUM; }
+<C_DATE>[[:blank:]] /* Skip white space */
+<C_DATE>. { return yytext[0]; }
+<C_DATE>\r\n { return T_CRLF; }
+<C_DATE>\n { return T_CRLF; }
+
+ /* Get all text till end of line */
+<C_LINE>[^\r\n]+ { yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_LINE; }
+<C_LINE>\r\n { return T_CRLF; }
+<C_LINE>\n { return T_CRLF; }
+<C_LINE>\r { return T_CRLF; }
+
+ /* Start of a new message */
+<C_NEW>SIP { return T_SIP; }
+<C_NEW>{CAPITALS}+ { yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_METHOD; }
+<C_NEW>[[:blank:]] /* Skip white space */
+<C_NEW>. { return T_ERROR; }
+<C_NEW>\r\n { return T_CRLF; }
+<C_NEW>\n { return T_CRLF; }
+
+ /* Authorization scheme */
+<C_AUTH_SCHEME>Digest { return T_AUTH_DIGEST; }
+<C_AUTH_SCHEME>{TOKEN_SYM}+ { yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_AUTH_OTHER; }
+<C_AUTH_SCHEME>[[:blank:]] /* Skip white space */
+<C_AUTH_SCHEME>. { return T_ERROR; }
+<C_AUTH_SCHEME>\r\n { return T_CRLF; }
+<C_AUTH_SCHEME>\n { return T_CRLF; }
+
+ /* IPv6 address
+ * NOTE: the validity of the format is not checked here.
+ */
+<C_IPV6ADDR>({HEXDIG}|[:\.])+ { yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_IPV6ADDR; }
+<C_IPV6ADDR>[[:blank:]] /* Skip white space */
+<C_IPV6ADDR>. { return T_ERROR; }
+<C_IPV6ADDR>\r\n { return T_CRLF; }
+<C_IPV6ADDR>\n { return T_CRLF; }
+
+ /* Parameter values may contain an IPv6 address or reference. */
+<C_PARAMVAL>({TOKEN_SYM}|[:\[\]])+ { yylval.yyt_str = new string(yytext);
+ MEMMAN_NEW(yylval.yyt_str);
+ return T_PARAMVAL; }
+<C_PARAMVAL>\" { yy_push_state(C_QSTRING); }
+<C_PARAMVAL>[[:blank:]] /* Skip white space */
+<C_PARAMVAL>. { return T_ERROR; }
+<C_PARAMVAL>\r\n { return T_CRLF; }
+<C_PARAMVAL>\n { return T_CRLF; }
diff --git a/src/parser/sip_body.cpp b/src/parser/sip_body.cpp
new file mode 100644
index 0000000..cc95f85
--- /dev/null
+++ b/src/parser/sip_body.cpp
@@ -0,0 +1,326 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 "sip_body.h"
+
+#include <list>
+#include <cassert>
+#include <cstdlib>
+#include "log.h"
+#include "protocol.h"
+#include "sip_message.h"
+#include "util.h"
+#include "audits/memman.h"
+#include "audio/rtp_telephone_event.h"
+
+////////////////////////////////////
+// class t_sip_body
+////////////////////////////////////
+
+t_sip_body::t_sip_body() {
+ invalid = false;
+}
+
+bool t_sip_body::local_ip_check(void) const {
+ return true;
+}
+
+size_t t_sip_body::get_encoded_size(void) const {
+ return encode().size();
+}
+
+////////////////////////////////////
+// class t_sip_xml_body
+////////////////////////////////////
+
+void t_sip_body_xml::create_xml_doc(const string &xml_version, const string &charset) {
+ clear_xml_doc();
+
+ // XML doc
+ xml_doc = xmlNewDoc(BAD_CAST xml_version.c_str());
+ MEMMAN_NEW(xml_doc);
+ xml_doc->encoding = xmlCharStrdup(charset.c_str());
+}
+
+void t_sip_body_xml::clear_xml_doc(void) {
+ if (xml_doc) {
+ MEMMAN_DELETE(xml_doc);
+ xmlFreeDoc(xml_doc);
+ xml_doc = NULL;
+ }
+}
+
+void t_sip_body_xml::copy_xml_doc(t_sip_body_xml *to_body) const {
+ if (to_body->xml_doc) {
+ to_body->clear_xml_doc();
+ }
+
+ if (xml_doc) {
+ to_body->xml_doc = xmlCopyDoc(xml_doc, 1);
+ if (!to_body->xml_doc) {
+ log_file->write_report("Failed to copy xml document.",
+ "t_sip_body_xml::copy",
+ LOG_NORMAL, LOG_CRITICAL);
+ } else {
+ MEMMAN_NEW(to_body->xml_doc);
+ }
+ }
+}
+
+t_sip_body_xml::t_sip_body_xml() : t_sip_body(),
+ xml_doc(NULL)
+{}
+
+t_sip_body_xml::~t_sip_body_xml() {
+ clear_xml_doc();
+}
+
+string t_sip_body_xml::encode(void) const {
+ if (!xml_doc) {
+ t_sip_body_xml *self = const_cast<t_sip_body_xml *>(this);
+ self->create_xml_doc();
+ }
+ assert(xml_doc);
+
+ xmlChar *buf;
+ int buf_size;
+
+ xmlDocDumpMemory(xml_doc, &buf, &buf_size);
+ string result((char*)buf);
+ xmlFree(buf);
+
+ return result;
+}
+
+bool t_sip_body_xml::parse(const string &s) {
+ assert(xml_doc == NULL);
+
+ xml_doc = xmlReadMemory(s.c_str(), s.size(), "noname.xml", NULL,
+ XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
+ if (!xml_doc) {
+ log_file->write_report("Failed to parse xml document.",
+ "t_sip_body_xml::parse",
+ LOG_NORMAL, LOG_WARNING);
+ } else {
+ MEMMAN_NEW(xml_doc);
+ }
+
+ return (xml_doc != NULL);
+}
+
+////////////////////////////////////
+// class t_sip_body_opaque
+////////////////////////////////////
+
+t_sip_body_opaque::t_sip_body_opaque() : t_sip_body()
+{}
+
+t_sip_body_opaque::t_sip_body_opaque(string s) :
+ t_sip_body(),
+ opaque(s)
+{}
+
+string t_sip_body_opaque::encode(void) const {
+ return opaque;
+}
+
+t_sip_body *t_sip_body_opaque::copy(void) const {
+ t_sip_body_opaque *sb = new t_sip_body_opaque(*this);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_opaque::get_type(void) const {
+ return BODY_OPAQUE;
+}
+
+t_media t_sip_body_opaque::get_media(void) const {
+ return t_media("application", "octet-stream");
+}
+
+size_t t_sip_body_opaque::get_encoded_size(void) const {
+ return opaque.size();
+}
+
+////////////////////////////////////
+// class t_sip_body_sipfrag
+////////////////////////////////////
+
+t_sip_body_sipfrag::t_sip_body_sipfrag(t_sip_message *m) : t_sip_body() {
+ sipfrag = m->copy();
+}
+
+t_sip_body_sipfrag::~t_sip_body_sipfrag() {
+ MEMMAN_DELETE(sipfrag);
+ delete sipfrag;
+}
+
+string t_sip_body_sipfrag::encode(void) const {
+ return sipfrag->encode(false);
+}
+
+t_sip_body *t_sip_body_sipfrag::copy(void) const {
+ t_sip_body_sipfrag *sb = new t_sip_body_sipfrag(sipfrag);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_sipfrag::get_type(void) const {
+ return BODY_SIPFRAG;
+}
+
+t_media t_sip_body_sipfrag::get_media(void) const {
+ return t_media("message", "sipfrag");
+}
+
+////////////////////////////////////
+// class t_sip_body_dtmf_relay
+////////////////////////////////////
+
+t_sip_body_dtmf_relay::t_sip_body_dtmf_relay() : t_sip_body() {
+ signal = '0';
+ duration = 250;
+}
+
+t_sip_body_dtmf_relay::t_sip_body_dtmf_relay(char _signal, uint16 _duration) :
+ signal(_signal), duration(_duration)
+{}
+
+string t_sip_body_dtmf_relay::encode(void) const {
+ string s = "Signal=";
+ s += signal;
+ s += CRLF;
+
+ s += "Duration=";
+ s += int2str(duration);
+ s += CRLF;
+
+ return s;
+}
+
+t_sip_body *t_sip_body_dtmf_relay::copy(void) const {
+ t_sip_body_dtmf_relay *sb = new t_sip_body_dtmf_relay(*this);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_dtmf_relay::get_type(void) const {
+ return BODY_DTMF_RELAY;
+}
+
+t_media t_sip_body_dtmf_relay::get_media(void) const {
+ return t_media("application", "dtmf-relay");
+}
+
+bool t_sip_body_dtmf_relay::parse(const string &s) {
+ signal = 0;
+ duration = 250;
+
+ bool valid = false;
+ vector<string> lines = split_linebreak(s);
+
+ for (vector<string>::iterator i = lines.begin(); i != lines.end(); i++) {
+ string line = trim(*i);
+ if (line.empty()) continue;
+
+ vector<string> l = split_on_first(line, '=');
+ if (l.size() != 2) continue;
+
+ string parameter = tolower(trim(l[0]));
+ string value = tolower(trim(l[1]));
+
+ if (value.empty()) continue;
+
+ if (parameter == "signal") {
+ if (!VALID_DTMF_SYM(value[0])) return false;
+ signal = value[0];
+ valid = true;
+ } else if (parameter == "duration") {
+ duration = atoi(value.c_str());
+ if (duration == 0) return false;
+ }
+ }
+
+ return valid;
+}
+
+////////////////////////////////////
+// class t_sip_body_plain_text
+////////////////////////////////////
+
+t_sip_body_plain_text::t_sip_body_plain_text() :
+ t_sip_body()
+{}
+
+t_sip_body_plain_text::t_sip_body_plain_text(const string &_text) :
+ t_sip_body(),
+ text(_text)
+{}
+
+string t_sip_body_plain_text::encode(void) const {
+ return text;
+}
+
+t_sip_body *t_sip_body_plain_text::copy(void) const {
+ t_sip_body *sb = new t_sip_body_plain_text(*this);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_plain_text::get_type(void) const {
+ return BODY_PLAIN_TEXT;
+}
+
+t_media t_sip_body_plain_text::get_media(void) const {
+ return t_media("text", "plain");
+}
+
+size_t t_sip_body_plain_text::get_encoded_size(void) const {
+ return text.size();
+}
+
+////////////////////////////////////
+// class t_sip_body_html_text
+////////////////////////////////////
+
+t_sip_body_html_text::t_sip_body_html_text(const string &_text) :
+ t_sip_body(),
+ text(_text)
+{}
+
+string t_sip_body_html_text::encode(void) const {
+ return text;
+}
+
+t_sip_body *t_sip_body_html_text::copy(void) const {
+ t_sip_body *sb = new t_sip_body_html_text(*this);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_html_text::get_type(void) const {
+ return BODY_HTML_TEXT;
+}
+
+t_media t_sip_body_html_text::get_media(void) const {
+ return t_media("text", "html");
+}
+
+size_t t_sip_body_html_text::get_encoded_size(void) const {
+ return text.size();
+}
diff --git a/src/parser/sip_body.h b/src/parser/sip_body.h
new file mode 100644
index 0000000..88c93a7
--- /dev/null
+++ b/src/parser/sip_body.h
@@ -0,0 +1,260 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// SIP bodies
+#ifndef _H_SIP_BODY
+#define _H_SIP_BODY
+
+#include <cc++/config.h>
+#include <string>
+#include <libxml/tree.h>
+
+#include "media_type.h"
+
+//@{
+/** @name Utilies for XML body parsing */
+/**
+ * Check the tag name of an XML node.
+ * @param node [in] (xmlNode *) The XML node to check.
+ * @param tag [in] (const char *) The tag name.
+ * @param namespace [in] (const char *) The namespace of the tag.
+ * @return true if the node has the tag name within the name space.
+ */
+#define IS_XML_TAG(node, tag, namespace)\
+ ((node)->type == XML_ELEMENT_NODE &&\
+ (node)->ns &&\
+ xmlStrEqual((node)->ns->href, BAD_CAST (namespace)) &&\
+ xmlStrEqual((node)->name, BAD_CAST (tag)))
+
+/**
+ * Check the attribute name of an XML attribute.
+ */
+#define IS_XML_ATTR(attr, attr_name, namespace)\
+ ((attr)->type == XML_ATTRIBUTE_NODE &&\
+ (attr)->ns &&\
+ xmlStrEqual((attr)->ns->href, BAD_CAST (namespace)) &&\
+ xmlStrEqual((attr)->name, BAD_CAST (attr_name)))
+//@}
+
+class t_sip_message;
+
+using namespace std;
+
+/** Body type. */
+enum t_body_type {
+ BODY_OPAQUE, /**< Opaque body. */
+ BODY_SDP, /**< SDP */
+ BODY_SIPFRAG, /**< message/sipfrag RFC 3420 */
+ BODY_DTMF_RELAY, /**< DTMF relay as defined by Cisco */
+ BODY_SIMPLE_MSG_SUM, /**< Simple message summary RFC 3842 */
+ BODY_PLAIN_TEXT, /**< Plain text for messaging */
+ BODY_HTML_TEXT, /**< HTML text for messaging */
+ BODY_PIDF_XML, /**< pidf+xml RFC 3863 */
+ BODY_IM_ISCOMPOSING_XML /**< im-iscomposing+xml RFC 3994 */
+};
+
+/** Abstract base class for SIP bodies. */
+class t_sip_body {
+public:
+ /**
+ * Indicates if the body content is invalid.
+ * This will be set by the body parser.
+ */
+ bool invalid;
+
+ /** Constructor. */
+ t_sip_body();
+
+ virtual ~t_sip_body() {}
+
+ /**
+ * Encode the body.
+ * @return Text encoded body.
+ */
+ virtual string encode(void) const = 0;
+
+ /**
+ * Create a copy of the body.
+ * @return Copy of the body.
+ */
+ virtual t_sip_body *copy(void) const = 0;
+
+ /**
+ * Get type of body.
+ * @return body type.
+ */
+ virtual t_body_type get_type(void) const = 0;
+
+ /**
+ * Get content type for this type of body.
+ * @return Content type.
+ */
+ virtual t_media get_media(void) const = 0;
+
+ /**
+ * Check if all local IP address are correctly filled in. This
+ * check is an integrity check to help debugging the auto IP
+ * discover feature.
+ */
+ virtual bool local_ip_check(void) const;
+
+ /**
+ * Return the size of the encoded body. This method encodes the body
+ * to calculate the size. When a more efficient algorithm is available
+ * a sub class may override this method.
+ * @return The size of the encoded body in bytes.
+ */
+ virtual size_t get_encoded_size(void) const;
+};
+
+/** Abstract base class for XML formatted bodies. */
+class t_sip_body_xml : public t_sip_body {
+protected:
+ xmlDoc *xml_doc; /**< XML document */
+
+ /**
+ * Create an empty XML document.
+ * Override this method to create the specific XML document.
+ * @param xml_version [in] The XML version of the document.
+ * @param charset [in] The character set of the document.
+ */
+ virtual void create_xml_doc(const string &xml_version = "1.0", const string &charset = "UTF-8");
+
+ /** Remove the XML document */
+ virtual void clear_xml_doc(void);
+
+ /**
+ * Copy the XML document from this body to another body.
+ * @param to_body [in] The body to copy the XML body to.
+ */
+ virtual void copy_xml_doc(t_sip_body_xml *to_body) const;
+
+public:
+ /** Constructor */
+ t_sip_body_xml();
+
+ /** Destructor */
+ virtual ~t_sip_body_xml();
+
+ virtual string encode(void) const;
+
+ /**
+ * Parse a text representation of the body.
+ * The result is stored in @ref xml_doc
+ * @param s [in] Text to parse.
+ * @return True if parsing and state extracting succeeded, false otherwise.
+ * @pre xml_doc == NULL
+ * @post If parsing succeeds then xml_doc != NULL
+ */
+ virtual bool parse(const string &s);
+};
+
+
+/**
+ * This body can contain any type of body. The contents are
+ * unparsed and thus opaque.
+ */
+class t_sip_body_opaque : public t_sip_body {
+public:
+ string opaque; /**< The body contents. */
+
+ /** Construct body with empty content. */
+ t_sip_body_opaque();
+
+ /**
+ * Construct a body with opaque content.
+ * @param s [in] The content.
+ */
+ t_sip_body_opaque(string s);
+
+ string encode(void) const;
+ t_sip_body *copy(void) const;
+ t_body_type get_type(void) const;
+ t_media get_media(void) const;
+ virtual size_t get_encoded_size(void) const;
+};
+
+// RFC 3420
+// sipfrag body
+class t_sip_body_sipfrag : public t_sip_body {
+public:
+ t_sip_message *sipfrag;
+
+ t_sip_body_sipfrag(t_sip_message *m);
+ ~t_sip_body_sipfrag();
+ string encode(void) const;
+ t_sip_body *copy(void) const;
+ t_body_type get_type(void) const;
+ t_media get_media(void) const;
+};
+
+// application/dtmf-relay body
+class t_sip_body_dtmf_relay : public t_sip_body {
+public:
+ char signal;
+ uint16 duration; // ms
+
+ t_sip_body_dtmf_relay();
+ t_sip_body_dtmf_relay(char _signal, uint16 _duration);
+ string encode(void) const;
+ t_sip_body *copy(void) const;
+ t_body_type get_type(void) const;
+ t_media get_media(void) const;
+ bool parse(const string &s);
+};
+
+/** Plain text body. */
+class t_sip_body_plain_text : public t_sip_body {
+public:
+ string text; /**< The text */
+
+ /** Construct a body with empty text. */
+ t_sip_body_plain_text();
+
+ /**
+ * Constructor.
+ * @param _text [in] The body text.
+ */
+ t_sip_body_plain_text(const string &_text);
+
+ string encode(void) const;
+ t_sip_body *copy(void) const;
+ t_body_type get_type(void) const;
+ t_media get_media(void) const;
+ virtual size_t get_encoded_size(void) const;
+};
+
+/** Html text body. */
+class t_sip_body_html_text : public t_sip_body {
+public:
+ string text; /**< The text */
+
+ /**
+ * Constructor.
+ * @param _text [in] The body text.
+ */
+ t_sip_body_html_text(const string &_text);
+
+ string encode(void) const;
+ t_sip_body *copy(void) const;
+ t_body_type get_type(void) const;
+ t_media get_media(void) const;
+ virtual size_t get_encoded_size(void) const;
+};
+
+#endif
diff --git a/src/parser/sip_message.cpp b/src/parser/sip_message.cpp
new file mode 100644
index 0000000..85cda18
--- /dev/null
+++ b/src/parser/sip_message.cpp
@@ -0,0 +1,476 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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 <fstream>
+#include <iostream>
+#include <sstream>
+
+#include "sip_message.h"
+#include "util.h"
+#include "parse_ctrl.h"
+#include "sdp/sdp.h"
+#include "audits/memman.h"
+
+////////////////////////////////////
+// class t_sip_message
+////////////////////////////////////
+
+t_sip_message::t_sip_message() :
+ local_ip_(0)
+{
+ src_ip_port.clear();
+ version = SIP_VERSION;
+ body = NULL;
+}
+
+t_sip_message::t_sip_message(const t_sip_message& m) :
+ local_ip_(m.local_ip_),
+ src_ip_port(m.src_ip_port),
+ version(m.version),
+ hdr_accept(m.hdr_accept),
+ hdr_accept_encoding(m.hdr_accept_encoding),
+ hdr_accept_language(m.hdr_accept_language),
+ hdr_alert_info(m.hdr_alert_info),
+ hdr_allow(m.hdr_allow),
+ hdr_allow_events(m.hdr_allow_events),
+ hdr_auth_info(m.hdr_auth_info),
+ hdr_authorization(m.hdr_authorization),
+ hdr_call_id(m.hdr_call_id),
+ hdr_call_info(m.hdr_call_info),
+ hdr_contact(m.hdr_contact),
+ hdr_content_disp(m.hdr_content_disp),
+ hdr_content_encoding(m.hdr_content_encoding),
+ hdr_content_language(m.hdr_content_language),
+ hdr_content_length(m.hdr_content_length),
+ hdr_content_type(m.hdr_content_type),
+ hdr_cseq(m.hdr_cseq),
+ hdr_date(m.hdr_date),
+ hdr_error_info(m.hdr_error_info),
+ hdr_event(m.hdr_event),
+ hdr_expires(m.hdr_expires),
+ hdr_from(m.hdr_from),
+ hdr_in_reply_to(m.hdr_in_reply_to),
+ hdr_max_forwards(m.hdr_max_forwards),
+ hdr_min_expires(m.hdr_min_expires),
+ hdr_mime_version(m.hdr_mime_version),
+ hdr_organization(m.hdr_organization),
+ hdr_p_asserted_identity(m.hdr_p_asserted_identity),
+ hdr_p_preferred_identity(m.hdr_p_preferred_identity),
+ hdr_priority(m.hdr_priority),
+ hdr_privacy(m.hdr_privacy),
+ hdr_proxy_authenticate(m.hdr_proxy_authenticate),
+ hdr_proxy_authorization(m.hdr_proxy_authorization),
+ hdr_proxy_require(m.hdr_proxy_require),
+ hdr_rack(m.hdr_rack),
+ hdr_record_route(m.hdr_record_route),
+ hdr_refer_sub(m.hdr_refer_sub),
+ hdr_refer_to(m.hdr_refer_to),
+ hdr_referred_by(m.hdr_referred_by),
+ hdr_replaces(m.hdr_replaces),
+ hdr_reply_to(m.hdr_reply_to),
+ hdr_require(m.hdr_require),
+ hdr_request_disposition(m.hdr_request_disposition),
+ hdr_retry_after(m.hdr_retry_after),
+ hdr_route(m.hdr_route),
+ hdr_rseq(m.hdr_rseq),
+ hdr_server(m.hdr_server),
+ hdr_service_route(m.hdr_service_route),
+ hdr_sip_etag(m.hdr_sip_etag),
+ hdr_sip_if_match(m.hdr_sip_if_match),
+ hdr_subject(m.hdr_subject),
+ hdr_subscription_state(m.hdr_subscription_state),
+ hdr_supported(m.hdr_supported),
+ hdr_timestamp(m.hdr_timestamp),
+ hdr_to(m.hdr_to),
+ hdr_unsupported(m.hdr_unsupported),
+ hdr_user_agent(m.hdr_user_agent),
+ hdr_via(m.hdr_via),
+ hdr_warning(m.hdr_warning),
+ hdr_www_authenticate(m.hdr_www_authenticate),
+ unknown_headers(m.unknown_headers)
+{
+ if (m.body) {
+ body = m.body->copy();
+ } else {
+ body = NULL;
+ }
+}
+
+t_sip_message::~t_sip_message() {
+ if (body) {
+ MEMMAN_DELETE(body);
+ delete body;
+ }
+}
+
+t_msg_type t_sip_message::get_type(void) const {
+ return MSG_SIPFRAG;
+}
+
+void t_sip_message::add_unknown_header(const string &name,
+ const string &value) {
+ t_parameter h(name, value);
+ unknown_headers.push_back(h);
+}
+
+bool t_sip_message::is_valid(bool &fatal, string &reason) const {
+
+ // RFC 3261 8.1.1
+ // Mandatory headers
+ if (!hdr_to.is_populated()) {
+ fatal = true;
+ reason = "To-header missing";
+ return false;
+ }
+
+ if (!hdr_from.is_populated()) {
+ fatal = true;
+ reason = "From header missing";
+ return false;
+ }
+
+ if (!hdr_cseq.is_populated()) {
+ fatal = true;
+ reason = "CSeq header missing";
+ return false;
+ }
+
+ if (!hdr_call_id.is_populated()) {
+ fatal = true;
+ reason = "Call-ID header missing";
+ return false;
+ }
+
+ if (!hdr_via.is_populated()) {
+ fatal = true;
+ reason = "Via header missing";
+ return false;
+ }
+
+ // RFC 3261 20.15
+ // Content-Type MUST be present if body is not empty
+ if (body && !hdr_content_type.is_populated()) {
+ fatal = false;
+ reason = "Content-Type header missing";
+ return false;
+ }
+
+ // RFC 3261 18.4
+ // The Content-Length header field MUST be used with stream oriented transports.
+ if (cmp_nocase(hdr_via.via_list.front().transport, "tcp") == 0 &&
+ !hdr_content_length.is_populated())
+ {
+ fatal = false;
+ reason = "Content-Length header missing";
+ return false;
+ }
+
+ return true;
+}
+
+string t_sip_message::encode(bool add_content_length) {
+ string s;
+ string encoded_body;
+
+ // RFC 3261 7.3.1
+ // Headers needed by a proxy should be on top
+ s += hdr_via.encode();
+ s += hdr_route.encode();
+ s += hdr_record_route.encode();
+ s += hdr_service_route.encode();
+ s += hdr_proxy_require.encode();
+ s += hdr_max_forwards.encode();
+ s += hdr_proxy_authenticate.encode();
+ s += hdr_proxy_authorization.encode();
+
+ // Order as in many examples
+ s += hdr_to.encode();
+ s += hdr_from.encode();
+ s += hdr_call_id.encode();
+ s += hdr_cseq.encode();
+ s += hdr_contact.encode();
+ s += hdr_content_type.encode();
+
+ // Privacy related headers
+ s += hdr_privacy.encode();
+ s += hdr_p_asserted_identity.encode();
+ s += hdr_p_preferred_identity.encode();
+
+ // Authentication headers
+ s += hdr_auth_info.encode();
+ s += hdr_authorization.encode();
+ s += hdr_www_authenticate.encode();
+
+ // Remaining headers in alphabetical order
+ s += hdr_accept.encode();
+ s += hdr_accept_encoding.encode();
+ s += hdr_accept_language.encode();
+ s += hdr_alert_info.encode();
+ s += hdr_allow.encode();
+ s += hdr_allow_events.encode();
+ s += hdr_call_info.encode();
+ s += hdr_content_disp.encode();
+ s += hdr_content_encoding.encode();
+ s += hdr_content_language.encode();
+ s += hdr_date.encode();
+ s += hdr_error_info.encode();
+ s += hdr_event.encode();
+ s += hdr_expires.encode();
+ s += hdr_in_reply_to.encode();
+ s += hdr_min_expires.encode();
+ s += hdr_mime_version.encode();
+ s += hdr_organization.encode();
+ s += hdr_priority.encode();
+ s += hdr_rack.encode();
+ s += hdr_refer_sub.encode();
+ s += hdr_refer_to.encode();
+ s += hdr_referred_by.encode();
+ s += hdr_replaces.encode();
+ s += hdr_reply_to.encode();
+ s += hdr_require.encode();
+ s += hdr_request_disposition.encode();
+ s += hdr_retry_after.encode();
+ s += hdr_rseq.encode();
+ s += hdr_server.encode();
+ s += hdr_sip_etag.encode();
+ s += hdr_sip_if_match.encode();
+ s += hdr_subject.encode();
+ s += hdr_subscription_state.encode();
+ s += hdr_supported.encode();
+ s += hdr_timestamp.encode();
+ s += hdr_unsupported.encode();
+ s += hdr_user_agent.encode();
+ s += hdr_warning.encode();
+
+ // Unknown headers
+ for (list<t_parameter>::const_iterator i = unknown_headers.begin();
+ i != unknown_headers.end(); i++)
+ {
+ s += i->name;
+ s += ": ";
+ s += i->value;
+ s += CRLF;
+ }
+
+ // Encode body if present. Set the content length.
+ if (body) {
+ encoded_body = body->encode();
+ hdr_content_length.set_length(encoded_body.size());
+ } else {
+ // RFC 3261 20.14
+ // If no body is present then Content-Length MUST be 0
+ hdr_content_length.set_length(0);
+ }
+
+ // Content-Length appears last in examples
+ if (add_content_length) {
+ s += hdr_content_length.encode();
+ }
+
+ // Blank line between headers and body
+ s += CRLF;
+
+ // Add body
+ if (body) s += encoded_body;
+
+ return s;
+}
+
+list<string> t_sip_message::encode_env(void) {
+ list<string> l;
+
+ // RFC 3261 7.3.1
+ // Headers needed by a proxy should be on top
+ l.push_back(hdr_via.encode_env());
+ l.push_back(hdr_route.encode_env());
+ l.push_back(hdr_record_route.encode_env());
+ l.push_back(hdr_service_route.encode_env());
+ l.push_back(hdr_proxy_require.encode_env());
+ l.push_back(hdr_max_forwards.encode_env());
+ l.push_back(hdr_proxy_authenticate.encode_env());
+ l.push_back(hdr_proxy_authorization.encode_env());
+
+ // Order as in many examples
+ l.push_back(hdr_to.encode_env());
+ l.push_back(hdr_from.encode_env());
+ l.push_back(hdr_call_id.encode_env());
+ l.push_back(hdr_cseq.encode_env());
+ l.push_back(hdr_contact.encode_env());
+ l.push_back(hdr_content_type.encode_env());
+
+ // Authentication headers
+ l.push_back(hdr_auth_info.encode_env());
+ l.push_back(hdr_authorization.encode_env());
+ l.push_back(hdr_www_authenticate.encode_env());
+
+ // Authentication headers
+ l.push_back(hdr_auth_info.encode_env());
+ l.push_back(hdr_authorization.encode_env());
+ l.push_back(hdr_www_authenticate.encode_env());
+
+ // Remaining headers in alphabetical order
+ l.push_back(hdr_accept.encode_env());
+ l.push_back(hdr_accept_encoding.encode_env());
+ l.push_back(hdr_accept_language.encode_env());
+ l.push_back(hdr_alert_info.encode_env());
+ l.push_back(hdr_allow.encode_env());
+ l.push_back(hdr_allow_events.encode_env());
+ l.push_back(hdr_call_info.encode_env());
+ l.push_back(hdr_content_disp.encode_env());
+ l.push_back(hdr_content_encoding.encode_env());
+ l.push_back(hdr_content_language.encode_env());
+ l.push_back(hdr_date.encode_env());
+ l.push_back(hdr_error_info.encode_env());
+ l.push_back(hdr_event.encode_env());
+ l.push_back(hdr_expires.encode_env());
+ l.push_back(hdr_in_reply_to.encode_env());
+ l.push_back(hdr_min_expires.encode_env());
+ l.push_back(hdr_mime_version.encode_env());
+ l.push_back(hdr_organization.encode_env());
+ l.push_back(hdr_priority.encode_env());
+ l.push_back(hdr_rack.encode_env());
+ l.push_back(hdr_refer_sub.encode_env());
+ l.push_back(hdr_refer_to.encode_env());
+ l.push_back(hdr_referred_by.encode_env());
+ l.push_back(hdr_replaces.encode_env());
+ l.push_back(hdr_reply_to.encode_env());
+ l.push_back(hdr_require.encode_env());
+ l.push_back(hdr_request_disposition.encode_env());
+ l.push_back(hdr_retry_after.encode_env());
+ l.push_back(hdr_rseq.encode_env());
+ l.push_back(hdr_server.encode_env());
+ l.push_back(hdr_sip_etag.encode_env());
+ l.push_back(hdr_sip_if_match.encode_env());
+ l.push_back(hdr_subject.encode_env());
+ l.push_back(hdr_subscription_state.encode_env());
+ l.push_back(hdr_supported.encode_env());
+ l.push_back(hdr_timestamp.encode_env());
+ l.push_back(hdr_unsupported.encode_env());
+ l.push_back(hdr_user_agent.encode_env());
+ l.push_back(hdr_warning.encode_env());
+
+ // Unknown headers
+ for (list<t_parameter>::const_iterator i = unknown_headers.begin();
+ i != unknown_headers.end(); i++)
+ {
+ string s = "SIP_";
+ s += toupper(replace_char(i->name, '-', '_'));
+ s += '=';
+ s += i->value;
+ l.push_back(s);
+ }
+
+ l.push_back(hdr_content_length.encode_env());
+
+ return l;
+}
+
+t_sip_message *t_sip_message::copy(void) const {
+ t_sip_message *m = new t_sip_message(*this);
+ MEMMAN_NEW(m);
+ return m;
+}
+
+void t_sip_message::set_body_plain_text(const string &text, const string &charset) {
+ // Content-Type header
+ t_media mime_type("text", "plain");
+ mime_type.charset = charset;
+ hdr_content_type.set_media(mime_type);
+
+ if (body) {
+ MEMMAN_DELETE(body);
+ delete body;
+ }
+
+ body = new t_sip_body_plain_text(text);
+ MEMMAN_NEW(body);
+}
+
+bool t_sip_message::set_body_from_file(const string &filename, const t_media &media) {
+ // Open file and set read pointer at end so we know the size.
+ ifstream f(filename.c_str(), ios::binary);
+ if (!f) return false;
+
+ ostringstream body_stream(ios::binary);
+
+ // Copy file into body
+ body_stream << f.rdbuf();
+
+ if (!f.good() || !body_stream.good()) {
+ return false;
+ }
+
+ // Create body of correct type
+ t_sip_body *new_body = NULL;
+ if (media.type == "text" && media.subtype == "plain") {
+ t_sip_body_plain_text *text_body = new t_sip_body_plain_text(body_stream.str());
+ MEMMAN_NEW(text_body);
+
+ new_body = text_body;
+ } else {
+ t_sip_body_opaque *opaque_body = new t_sip_body_opaque(body_stream.str());
+ MEMMAN_NEW(opaque_body);
+
+ new_body = opaque_body;
+ }
+
+ if (body) {
+ MEMMAN_DELETE(body);
+ delete body;
+ }
+ body = new_body;
+
+ // Content-Type header
+ hdr_content_type.set_media(media);
+
+ return true;
+}
+
+size_t t_sip_message::get_encoded_size(void) {
+ string s = encode();
+ return s.size();
+}
+
+bool t_sip_message::local_ip_check(void) const {
+ if (get_type() == MSG_REQUEST && hdr_via.is_populated()) {
+ const t_via &v = hdr_via.via_list.front();
+ if (v.host == "0.0.0.0") return false;
+ }
+
+ if (hdr_contact.is_populated()) {
+ if (!hdr_contact.any_flag && !hdr_contact.contact_list.empty()) {
+ const t_contact_param &c = hdr_contact.contact_list.front();
+ if (c.uri.get_host() == "0.0.0.0") return false;
+ }
+ }
+
+ if (body) {
+ return body->local_ip_check();
+ }
+
+ return true;
+}
+
+void t_sip_message::calc_local_ip(void) {
+ // Do nothing
+}
+
+unsigned long t_sip_message::get_local_ip(void) {
+ if (local_ip_ == 0) calc_local_ip();
+ return local_ip_;
+}
diff --git a/src/parser/sip_message.h b/src/parser/sip_message.h
new file mode 100644
index 0000000..6602438
--- /dev/null
+++ b/src/parser/sip_message.h
@@ -0,0 +1,270 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program 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.
+
+ This program 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
+*/
+
+// SIP message
+
+#ifndef _H_SIP_MESSAGE
+#define _H_SIP_MESSAGE
+
+#include <list>
+#include <string>
+#include "definitions.h"
+#include "hdr_accept.h"
+#include "hdr_accept_encoding.h"
+#include "hdr_accept_language.h"
+#include "hdr_alert_info.h"
+#include "hdr_allow.h"
+#include "hdr_allow_events.h"
+#include "hdr_auth_info.h"
+#include "hdr_authorization.h"
+#include "hdr_call_id.h"
+#include "hdr_call_info.h"
+#include "hdr_contact.h"
+#include "hdr_content_disp.h"
+#include "hdr_content_encoding.h"
+#include "hdr_content_language.h"
+#include "hdr_content_length.h"
+#include "hdr_content_type.h"
+#include "hdr_cseq.h"
+#include "hdr_date.h"
+#include "hdr_error_info.h"
+#include "hdr_event.h"
+#include "hdr_expires.h"
+#include "hdr_from.h"
+#include "hdr_in_reply_to.h"
+#include "hdr_max_forwards.h"
+#include "hdr_min_expires.h"
+#include "hdr_mime_version.h"
+#include "hdr_organization.h"
+#include "hdr_p_asserted_identity.h"
+#include "hdr_p_preferred_identity.h"
+#include "hdr_priority.h"
+#include "hdr_privacy.h"
+#include "hdr_proxy_authenticate.h"
+#include "hdr_proxy_authorization.h"
+#include "hdr_proxy_require.h"
+#include "hdr_rack.h"
+#include "hdr_record_route.h"
+#include "hdr_refer_sub.h"
+#include "hdr_refer_to.h"
+#include "hdr_referred_by.h"
+#include "hdr_replaces.h"
+#include "hdr_reply_to.h"
+#include "hdr_require.h"
+#include "hdr_request_disposition.h"
+#include "hdr_retry_after.h"
+#include "hdr_route.h"
+#include "hdr_rseq.h"
+#include "hdr_server.h"
+#include "hdr_service_route.h"
+#include "hdr_sip_etag.h"
+#include "hdr_sip_if_match.h"
+#include "hdr_subject.h"
+#include "hdr_subscription_state.h"
+#include "hdr_supported.h"
+#include "hdr_timestamp.h"
+#include "hdr_to.h"
+#include "hdr_unsupported.h"
+#include "hdr_user_agent.h"
+#include "hdr_via.h"
+#include "hdr_warning.h"
+#include "hdr_www_authenticate.h"
+#include "parameter.h"
+#include "sip_body.h"
+
+// Macro's to access the body of a message, eg msg.sdp_body
+#define SDP_BODY ((t_sdp *)body)
+#define OPAQUE_BODY ((t_sip_body_opaque)*body)
+
+using namespace std;
+
+enum t_msg_type {
+ MSG_REQUEST,
+ MSG_RESPONSE,
+ MSG_SIPFRAG, // Only a sequence of headers (RFC 3420)
+};
+
+
+class t_sip_message {
+protected:
+ /**
+ * Local IP address that will be uses for this SIP message.
+ * The local IP address can only be determined when the destination
+ * of a SIP message is known (because of multi homing).
+ */
+ unsigned long local_ip_;
+
+public:
+ // The source IP address and port are only set for messages
+ // received from the network. So the transaction user knows
+ // where a message comes from.
+ t_ip_port src_ip_port;
+
+ // SIP version
+ string version;
+
+ // All possible headers
+ t_hdr_accept hdr_accept;
+ t_hdr_accept_encoding hdr_accept_encoding;
+ t_hdr_accept_language hdr_accept_language;
+ t_hdr_alert_info hdr_alert_info;
+ t_hdr_allow hdr_allow;
+ t_hdr_allow_events hdr_allow_events;
+ t_hdr_auth_info hdr_auth_info;
+ t_hdr_authorization hdr_authorization;
+ t_hdr_call_id hdr_call_id;
+ t_hdr_call_info hdr_call_info;
+ t_hdr_contact hdr_contact;
+ t_hdr_content_disp hdr_content_disp;
+ t_hdr_content_encoding hdr_content_encoding;
+ t_hdr_content_language hdr_content_language;
+ t_hdr_content_length hdr_content_length;
+ t_hdr_content_type hdr_content_type;
+ t_hdr_cseq hdr_cseq;
+ t_hdr_date hdr_date;
+ t_hdr_error_info hdr_error_info;
+ t_hdr_event hdr_event;
+ t_hdr_expires hdr_expires;
+ t_hdr_from hdr_from;
+ t_hdr_in_reply_to hdr_in_reply_to;
+ t_hdr_max_forwards hdr_max_forwards;
+ t_hdr_min_expires hdr_min_expires;
+ t_hdr_mime_version hdr_mime_version;
+ t_hdr_organization hdr_organization;
+ t_hdr_p_asserted_identity hdr_p_asserted_identity;
+ t_hdr_p_preferred_identity hdr_p_preferred_identity;
+ t_hdr_priority hdr_priority;
+ t_hdr_privacy hdr_privacy;
+ t_hdr_proxy_authenticate hdr_proxy_authenticate;
+ t_hdr_proxy_authorization hdr_proxy_authorization;
+ t_hdr_proxy_require hdr_proxy_require;
+ t_hdr_rack hdr_rack;
+ t_hdr_record_route hdr_record_route;
+ t_hdr_refer_sub hdr_refer_sub;
+ t_hdr_refer_to hdr_refer_to;
+ t_hdr_referred_by hdr_referred_by;
+ t_hdr_replaces hdr_replaces;
+ t_hdr_reply_to hdr_reply_to;
+ t_hdr_require hdr_require;
+ t_hdr_request_disposition hdr_request_disposition;
+ t_hdr_retry_after hdr_retry_after;
+ t_hdr_route hdr_route;
+ t_hdr_rseq hdr_rseq;
+ t_hdr_server hdr_server;
+ t_hdr_service_route hdr_service_route;
+ t_hdr_sip_etag hdr_sip_etag;
+ t_hdr_sip_if_match hdr_sip_if_match;
+ t_hdr_subject hdr_subject;
+ t_hdr_subscription_state hdr_subscription_state;
+ t_hdr_supported hdr_supported;
+ t_hdr_timestamp hdr_timestamp;
+ t_hdr_to hdr_to;
+ t_hdr_unsupported hdr_unsupported;
+ t_hdr_user_agent hdr_user_agent;
+ t_hdr_via hdr_via;
+ t_hdr_warning hdr_warning;
+ t_hdr_www_authenticate hdr_www_authenticate;
+
+ // Unknown headers are represented by parameters.
+ // Parameter.name = header name
+ // Parameter.value = header value
+ list<t_parameter> unknown_headers;
+
+ // A SIP message can carry a body
+ t_sip_body *body;
+
+ t_sip_message();
+ t_sip_message(const t_sip_message& m);
+ virtual ~t_sip_message();
+
+ virtual t_msg_type get_type(void) const;
+ void add_unknown_header(const string &name, const string &value);
+
+ // Check if the message is valid. At this class the
+ // general rules applying to both requests and responses
+ // is checked.
+ // fatal is true if one of the headers mandatory for all
+ // messages is missing (to, from, cseq, call-id, via).
+ // reason contains a reason string if the message is invalid.
+ virtual bool is_valid(bool &fatal, string &reason) const;
+
+ // Return encoded headers
+ // The version should be encode by the subclasses.
+ // Parameter add_content_length indicates if a Content-Length
+ // header must be added. Usually it must, only for sipfrag bodies
+ // it may be omitted.
+ virtual string encode(bool add_content_length = true);
+
+ // Return list of environment variable settings for all headers
+ // (see header.h for the format)
+ // Besides the header variables the following variables will be
+ // returned as well:
+ //
+ // SIP_REQUEST_METHOD, for a request
+ // SIP_REQUEST_URI, for a request
+ // SIP_STATUS_CODE, for a response
+ // SIP_STATUS_REASON, for a response
+ virtual list<string> encode_env(void);
+
+ // Create a copy of the message
+ virtual t_sip_message *copy(void) const;
+
+ /**
+ * Set a plain text body in the message.
+ * @param text [in] The text.
+ * @param charset [in] The character set used for encoding.
+ * @post The Content-Type header is set to "text/plain".
+ * @post If a body was already present then it is deleted.
+ */
+ void set_body_plain_text(const string &text, const string &charset);
+
+ /**
+ * Set a body with the contents of a file.
+ * @param filename [in] The name of the file.
+ * @param media [in] The mime type of the contents.
+ * @return True of body is set, false if file could not be read.
+ */
+ bool set_body_from_file(const string &filename, const t_media &media);
+
+ /**
+ * Get the size of an encoded SIP message.
+ * @return Size in bytes.
+ */
+ size_t get_encoded_size(void);
+
+ /**
+ * Check if all local IP address are correctly filled in. This
+ * check is an integrity check to help debugging the auto IP
+ * discover feature.
+ */
+ bool local_ip_check(void) const;
+
+ /** Determine the local IP address for this SIP message. */
+ virtual void calc_local_ip(void);
+
+ /**
+ * Get the local IP address for this SIP message.
+ * The local IP address can be used as source address for sending
+ * the message.
+ * @return The local IP address.
+ * @return 0, if the local IP address is not determined yet.
+ */
+ unsigned long get_local_ip(void);
+};
+
+#endif