source: trunk/ETSI-Testsuites/ETSI_auto_IOT/codec/c++/sip_codets.cpp @ 40

Last change on this file since 40 was 22, checked in by rings, 14 years ago
  • Property svn:executable set to *
File size: 99.4 KB
Line 
1#include "gen_classes.h"
2#include "Regex.h"
3
4namespace t3devlib { namespace gen {
5
6
7//
8// Implementation of the decoder for SDP
9//
10
11// SIP quoted strings messages allow multiple ways of representing
12// some characters (raw unicode or escaped). This function is used
13// to normalise the content so that two equivalent representation
14// will result in the same TTCN-3 charstring.
15//
16void normalise_quoted_string (Charstring& cs, bool remove_quotes = false) throw (DecodeError)
17{
18        std::string result;
19
20        //FIXME: how LWS shall be normalised ?
21       
22        const unsigned char* p   = cs.GetValueBin();
23        const unsigned char* end = p + (cs.GetLength() / 8);
24
25        if (remove_quotes)
26        {
27                if ((end - p) < 2)
28                        goto error_malformed;
29
30                if ((*p++ != '"') | (*--end != '"'))
31                        goto error_malformed;
32        }
33
34        for ( ; p!=end ; p++)
35        {
36                switch (*p) {
37                case '\r': //LWS
38                case '\n':
39
40                case ' ': //WSP
41                case '\v':
42                case '\t':
43                case '\f':
44
45                case 0x21: //!
46                        // plain text
47                        result += *p;
48                        break;
49
50                case '\\':
51                        // escaped character
52                        p++;
53                        if ((p == end) || ((*p == '\r') | (*p == '\n'))) {
54                                // cannot be escaped
55                                // (should never happen since we checked it wit a regex before)
56                                DecodeError e (&cs);
57                                e.Msg() << "Invalid escaped sequence in quoted string: \\\\x" << std::hex << ((int) *p) << std::endl;
58                                throw e;
59                        }
60
61                        // valid escaped character
62                        result += *p;
63                        break;
64
65                default:
66                        if ((*p >= 0x23) && (*p <= 0x7e))
67                        {
68                                // plain text
69                                result += *p;
70
71                        } else if (*p > 127) {
72                                // UTF-8 character
73                                //
74                                // FIXME: how to represent UTF-8 chars ? ('%xx' escape sequences are not used here)
75                                result += *p;
76
77                        } else {
78                                // non allowed character
79                                // (should never happen since we checked it wit a regex before)
80                                DecodeError e (&cs);
81                                e.Msg() << "Invalid character in quoted string: \\x" << std::hex << ((int) *p) << std::endl;
82                                throw e;
83                        }
84                }
85        }
86
87        // replace the string with the quoted string
88        {
89                Bytestring& bs = cs;
90                bs.SetValue (result);
91        }
92        return;
93
94error_malformed:
95        DecodeError e(&cs);
96        e.Msg() << "Malformed quoted string: " << cs.GetValue() << endl;
97        throw e;
98}
99
100static inline bool asciichar_is_displayable (char c)
101{
102        if ((c >= 32) && (c<127))
103                return true;
104        return (c == '\r') | (c == '\n') | (c == '\t') | (c == '%');
105}
106
107// SIP tokens allow multiple ways of representing some characters (raw
108// unicode or escaped). This function is used to normalise the content so
109// that two equivalent representation will result in the same TTCN-3
110// charstring.
111//
112void normalise_escaped_string (Charstring& cs) throw (DecodeError)
113{
114        std::string result;
115
116        const unsigned char* p   = cs.GetValueBin();
117        const unsigned char* end = p + (cs.GetLength() / 8);
118
119        for ( ; p!=end ; p++)
120        {
121                unsigned char c;
122
123                if (*p == '%') {
124                        // escaped char %xx
125
126                        if ((end - p) < 3)
127                                goto error_malformed;
128
129                        char buff[3] = { p[1], p[2], '\0'};
130                        p += 2;
131
132                        char* next;
133                        c = strtol(buff, &next, 16);
134
135                        if (next != &buff[2])
136                                goto error_malformed;
137                        //TODO: check that the result is UTF-8 valid ?
138                } else {
139                        c = *p;
140                }
141
142                if (asciichar_is_displayable(c))
143                {
144                        // 7-bit character
145                        result += c;
146                } else {
147                        // 8-bit character and control characters
148                        // -> escape it
149                        char buff[4];
150                        sprintf (buff, "%%%02x", c);
151                        result += buff;
152                }
153        }
154
155        // replace the string with the quoted string
156        {
157                Bytestring& bs = cs;
158                bs.SetValue (result);
159        }
160        return;
161
162error_malformed:
163        DecodeError e(&cs);
164        e.Msg() << "Malformed string: " << cs.GetValue() << endl;
165        throw e;
166}
167
168//WSP: space, htab, vtab, form feed
169#define SIPCHARS_WSP            " \t\v\f"
170#define SIPREG_LWS              "(?:[" SIPCHARS_WSP "]*\\r\\n)?[" SIPCHARS_WSP "]+"
171#define SIPREG_SWS              "(?:" SIPREG_LWS ")?"
172
173// move past the possible leading linear whitespaces in the buffer
174void remove_whitespace (Buffer & buffer) {
175        static Regex reg_ws ("^" SIPREG_LWS);
176        if (reg_ws.Match (buffer)) {
177                int nPos = buffer.GetPosition() + reg_ws.GetMatchedLength();
178                buffer.SetPosition (nPos);
179        }
180}
181
182void read_sp (Buffer & buffer, Variable* v) {
183        static Regex reg_ws ("^[ \t]+");
184        reg_ws.AssertMatch (buffer, v);
185        int nPos = buffer.GetPosition() + reg_ws.GetMatchedLength();
186        buffer.SetPosition (nPos);
187}
188
189bool is_sip_scheme (const char * pszScheme) {
190        return strncasecmp(pszScheme, "sip", 3) == 0 || strncasecmp(pszScheme, "sips", 4) == 0;
191}
192
193bool is_tel_scheme (const char * pszScheme) {
194        return strncasecmp(pszScheme, "tel", 3) == 0 || strncasecmp(pszScheme, "fax", 3) == 0 ||
195                strncasecmp(pszScheme, "modem", 5) == 0;
196}
197
198
199
200// Definition of character classes used to be used in the regular expressions
201// (within [])
202#define SIPCHARS_MARK           "\\-_.!~*'()"
203#define SIPCHARS_ALFA           "A-Za-z"
204#define SIPCHARS_ALFANUM        "0-9" SIPCHARS_ALFA
205#define SIPCHARS_HEXA   "0-9A-Fa-f"
206#define SIPCHARS_UNRESERVED     SIPCHARS_ALFANUM SIPCHARS_MARK
207#define SIPCHARS_RESERVED       ";/?:@&=+$,"
208#define SIPCHARS_USER_UNRESERVED "&=+$,;?/"
209#define SIPCHARS_UTF8_NONASCII  "\x80-\xFD"
210#define SIPCHARS_TEXT_UTF8CHAR  "\x21-\xFD"
211
212
213// Definition of common regular expression reused many times within the
214// decoder
215//
216// Note: these definitions shall not contain any group match '(' ')' to avoid
217// side effect (the index of the subsequent group match would be shifted)
218// -> all parenthesis group needed should be implemented with '(?:' ')' so
219//    that they are not indexed
220//
221#define SIPREG_ESCAPED  "(%[0-9A-Fa-f]{2})"
222#define SIPREG_TOKEN "[" SIPCHARS_ALFANUM ".!%*_+`'~\\-]+"
223#define SIPREG_TOKEN_NODOT "[" SIPCHARS_ALFANUM "!%*_+`'~\\-]+"
224#define SIPREG_WORD "(?:[][" SIPCHARS_ALFANUM "\\-.!%*_+`'~()<>:\\\\\"/?{}])+"
225#define SIPREG_ASCII_WITHOUT_COMMA "[\\x21-\\x2B\\x2D-\\x7E]+"
226#define SIPREG_TEXT_UTF8_TRIM   "[\x21-\xFD]([\x21-\xFD]|(" SIPREG_LWS "))*"
227
228// sip version
229#define SIPREG_SIP_VERSION "SIP/[0-9]\\.[0-9]"
230
231// header name
232#define SIPREG_HNAME "(?:[][/?:+$" SIPCHARS_UNRESERVED "]|" SIPREG_ESCAPED ")+"
233
234// host name
235#define SIPREG_TOPLABEL "[" SIPCHARS_ALFA "]([" SIPCHARS_ALFANUM "\\-]*[" SIPCHARS_ALFANUM "])?"
236#define SIPREG_DOMAINLABEL      "[" SIPCHARS_ALFANUM "]([" SIPCHARS_ALFANUM "\\-]*[" SIPCHARS_ALFANUM "])?"
237#define SIPREG_HOSTNAME "(" SIPREG_DOMAINLABEL "\\.)*" SIPREG_TOPLABEL "\\.?"
238
239#define SIPREG_HCOLON           "[      ]*:" SIPREG_SWS
240#define SIPREG_COMMA            SIPREG_SWS "[,]" SIPREG_SWS
241#define SIPREG_SEMI                     SIPREG_SWS "[;]" SIPREG_SWS
242#define SIPREG_EQUAL            SIPREG_SWS "[=]" SIPREG_SWS
243#define SIPREG_SLASH            SIPREG_SWS "[/]" SIPREG_SWS
244
245// without leading and trailing whitespace
246#define SIPREG_QUOTED_PAIR      "[\\x5C][\\x00-\\x09\\x0B\\x0C\\x0E-\\x7F]"
247#define SIPREG_QUOTED_STRING    "[\"]((" SIPREG_LWS ")|[]!#-[^-~" SIPCHARS_UTF8_NONASCII"]|(" SIPREG_QUOTED_PAIR "))*[\"]"
248#define SIPREG_DISPLAY_NAME "((" SIPREG_TOKEN "(" SIPREG_LWS SIPREG_TOKEN ")*)|(" SIPREG_QUOTED_STRING "))"
249
250#define SIPREG_COMMENT  "[(]((" SIPREG_LWS ")|[\\x21-\\x5B]|[\\x5D-\\xFD]|(" SIPREG_QUOTED_PAIR "))*[)]"
251
252// IPv4
253#define SIPREG_IP4      "([0-9]{1,3}\\.){3}[0-9]{1,3}"
254
255// IPv6
256#define SIPREG_HEX4             "[" SIPCHARS_HEXA "]{1,4}"
257#define SIPREG_HEXSEQ           SIPREG_HEX4 "([:]" SIPREG_HEX4 ")*"
258#define SIPREG_HEXPART  "(((" SIPREG_HEXSEQ ")?[:]{2}(" SIPREG_HEXSEQ ")?)|(" SIPREG_HEXSEQ  "))"
259#define SIPREG_IP6              "[[]" SIPREG_HEXPART "([:]" SIPREG_IP4 ")?[]]"
260
261// host
262#define SIPREG_HOST             "((" SIPREG_HOSTNAME ")|(" SIPREG_IP4 ")|(" SIPREG_IP6 "))"
263#define SIPREG_ABSOLUTE_URI     "([" SIPCHARS_UNRESERVED "/;?:@&=+$,]|" SIPREG_ESCAPED ")+"
264
265// phone number (global or local)
266#define SIPREG_PHONE_NUMBER "(([+][\\-0-9.()]+)|[\\-0-9()*#A-Da-dPpWw]+)"
267
268#define SIPCHARS_PPARAM_UNRESERVED "][/:&+$"
269#define SIPREG_PPARAM           "([" SIPCHARS_PPARAM_UNRESERVED SIPCHARS_UNRESERVED "]|" SIPREG_ESCAPED ")"
270#define SIPREG_PPARAM_ALLOWED   "[" SIPCHARS_PPARAM_UNRESERVED SIPCHARS_UNRESERVED ";=%]+"
271
272#define SIPCHARS_HPARAM_UNRESERVED "][/?:+$"
273#define SIPREG_HPARAM           "([" SIPCHARS_HPARAM_UNRESERVED SIPCHARS_UNRESERVED "]|" SIPREG_ESCAPED ")"
274#define SIPREG_HPARAM_ALLOWED   "[" SIPCHARS_HPARAM_UNRESERVED SIPCHARS_UNRESERVED ";=%]+"
275
276#define SIPREG_TELPARAM_NAME    "[!#$%&'*+\\-.0-9A-Z^_`a-z|~]+"
277#define SIPREG_TELPARAM_VALUE   "([\\x21\\x23-\\x3A\\x3C-\\x7E]+|(" SIPREG_QUOTED_STRING "))"
278#define SIPREG_TELPARAMS                "([;]" SIPREG_TELPARAM_NAME "([=]" SIPREG_TELPARAM_VALUE ")?)+"
279
280#define SIPREG_GPARAM_VALUE "(([" SIPCHARS_ALFANUM ".!%*_+`'~\\-:]+)|(" SIPREG_QUOTED_STRING "))"
281
282// content type parameter
283#define SIPREG_M_PARAMETER      SIPREG_TOKEN SIPREG_EQUAL "(?:" SIPREG_TOKEN "|" SIPREG_QUOTED_STRING ")"
284
285
286bool detect_separator(Regex & reg_separator, Buffer & buffer)
287{
288        bool bRes;
289        if (bRes = reg_separator.Match(buffer))
290                reg_separator.MovePast(buffer);
291        return bRes;
292}
293bool detect_comma(Buffer & buffer)
294{
295        Regex reg_comma ("^" SIPREG_COMMA);
296        return detect_separator(reg_comma, buffer);
297}
298
299bool detect_semi(Buffer & buffer) throw (DecodeError)
300{
301        Regex reg_semi ("^" SIPREG_SEMI);
302        return detect_separator(reg_semi, buffer);
303}
304
305void SipUrl::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
306{
307        Charstring csSemi;
308        csSemi.SetValue(";");
309
310        if(field_id == id_urlParameters && IsPresent(id_urlParameters)) {
311                csSemi.Encode(buffer);
312        }
313}
314
315void SipUrl::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
316{
317        Charstring csColon;
318        csColon.SetValue(":");
319
320        switch(field_id) {
321        case id_scheme:
322                csColon.Encode(buffer);
323                break;
324        default:
325                break;
326        }
327}
328
329void SipUrl::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
330{
331
332        static Regex reg_scheme ("^[" SIPCHARS_ALFA "][" SIPCHARS_ALFANUM "+.\\-]*");
333        static Regex reg_colon ("^[:]");
334        static Regex reg_userinfo ("^(?:[" SIPCHARS_UNRESERVED SIPCHARS_USER_UNRESERVED "]|" SIPREG_ESCAPED ")+(?::(?:[" SIPCHARS_UNRESERVED "&=+$,]|"SIPREG_ESCAPED")*)?[@]");
335        static Regex reg_phone ("^" SIPREG_PHONE_NUMBER);
336        static Regex reg_hostport ("^[][" SIPCHARS_ALFANUM ":.\\-]+");
337        static Regex reg_absolute_uri ("^" SIPREG_ABSOLUTE_URI);
338        static Regex reg_urlParams ("^;" SIPREG_PPARAM_ALLOWED);       
339        static Regex reg_headers ("^[?]" SIPREG_PPARAM_ALLOWED);
340        static Regex reg_telParams ("^" SIPREG_TELPARAMS);
341
342        const char * pszScheme;
343        switch (id) {
344        case id_scheme:
345                reg_scheme.AssertMatch (buffer, this);
346                SetHypFieldLength (id, reg_scheme.GetMatchedLength());
347                break;
348
349        case id_userInfo:
350                reg_colon.AssertMatch(buffer, this);
351                buffer.SetPosition(buffer.GetPosition() + 8);
352                pszScheme = Get_scheme().GetValue();
353                SetHypFieldIsPresent (id,  0);
354                // user-info is not decoded in case of absoluteURI
355                if (is_sip_scheme(pszScheme)) {
356                        if (reg_userinfo.Match (buffer)) {
357                                SetHypFieldIsPresent (id,  1);
358                                SetHypFieldLength (id, reg_userinfo.GetMatchedLength() - 8);
359                        }
360                }
361                // telephone numbers are decoded to the userInfo field
362                else if (is_tel_scheme(pszScheme)){
363                        reg_phone.AssertMatch(buffer, this);
364                        SetHypFieldIsPresent (id,  1);
365                        SetHypFieldLength (id, reg_phone.GetMatchedLength());
366                }
367                else { // absoluteURI
368                        if (reg_absolute_uri.Match (buffer)) {
369                                SetHypFieldIsPresent (id,  1);
370                                SetHypFieldLength(id, reg_absolute_uri.GetMatchedLength());
371                        }
372                }
373                break;
374
375        case id_hostPort:
376                pszScheme = Get_scheme().GetValue();
377                if (is_sip_scheme(pszScheme)) {
378                        // remove '@'
379                        if (IsPresent (id_userInfo)) {
380                                buffer.SetPosition(buffer.GetPosition() + 8);
381                        }
382                        if (reg_hostport.Match (buffer)) {
383                                SetHypFieldIsPresent (id,  1);
384                                SetHypFieldLength(id, reg_hostport.GetMatchedLength());
385                        } else if (IsPresent (id_userInfo)) {
386                                reg_hostport.Error(this, buffer);
387                        } else {
388                                SetHypFieldIsPresent (id,  0);
389                        }
390                } else { // tel or absoluteURI
391                        SetHypFieldIsPresent(id, 0);
392                }
393                break;
394
395        case id_urlParameters:
396                pszScheme = Get_scheme().GetValue();
397                if (is_sip_scheme(pszScheme) && reg_urlParams.Match (buffer)){
398                        SetHypFieldIsPresent (id,  1);
399                        SetHypFieldLength(id, reg_urlParams.GetMatchedLength());
400                } else if (is_tel_scheme(pszScheme)) {
401                        // "tel" parameters have a different syntax (e.g. & is allowed within both id and values)
402                        if (reg_telParams.Match (buffer)) {
403                                SetHypFieldIsPresent (id,  1);
404                                SetHypFieldLength(id, reg_telParams.GetMatchedLength());
405                        } else {
406                                SetHypFieldIsPresent(id, 0);
407                        }
408                }
409                else {
410                        SetHypFieldIsPresent(id, 0);
411                }
412                break;
413        case id_headers:
414                pszScheme = Get_scheme().GetValue();
415                if (is_sip_scheme(pszScheme) && reg_headers.Match (buffer)){
416                        SetHypFieldIsPresent (id,  1);
417                        SetHypFieldLength(id, reg_headers.GetMatchedLength());
418                } else {
419                        SetHypFieldIsPresent(id, 0);
420                }
421                break;
422        }
423}
424
425void UserInfo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
426{
427        Charstring csColon;
428        csColon.SetValue(":");
429       
430        switch(field_id) {
431        case id_password:
432                csColon.Encode(buffer);
433                break;
434        default:
435                break;
436        }
437}
438
439void UserInfo::PostEncode (Buffer& buffer) throw (EncodeError)
440{
441        Charstring csAt;
442        csAt.SetValue("@");
443
444        csAt.Encode(buffer);
445}
446
447void UserInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
448{
449        static Regex reg_username ("^([" SIPCHARS_UNRESERVED SIPCHARS_USER_UNRESERVED "]|" SIPREG_ESCAPED ")+");
450        static Regex reg_colon ("^[:]");
451        static Regex reg_password ("^([&=+$," SIPCHARS_UNRESERVED "]|" SIPREG_ESCAPED ")*");
452        static Regex reg_absolute_uri ("^" SIPREG_ABSOLUTE_URI);
453
454        // absoluteURI is mapped into SipUrl.userInfo.userOrTelephoneSubscriber and requires special handling
455        Variable* parent = GetParent();
456        bool bRequestUri = false;
457        if (parent != NULL) {
458                const char * pszParName = parent->GetTypeName();
459                if (strcmp(pszParName, "SipUrl") == 0) {
460                        SipUrl * pSipUrl = dynamic_cast<SipUrl*>(parent);
461                        const char * pszScheme = pSipUrl->Get_scheme().GetValue();
462                        bRequestUri = !is_sip_scheme(pszScheme);
463                }
464        }
465        Regex * pRegex;
466        switch (id) {
467        case id_userOrTelephoneSubscriber:
468                pRegex = bRequestUri ? &reg_absolute_uri : &reg_username;
469                pRegex->AssertMatch (buffer, this);
470                SetHypFieldLength(id, pRegex->GetMatchedLength());
471                break;
472        case id_password:
473                if(!bRequestUri && reg_colon.Match(buffer)) {
474                        buffer.SetPosition(buffer.GetPosition() + 8);
475                        SetHypFieldIsPresent (id, 1);
476                        reg_password.AssertMatch (buffer, this);
477                } else {
478                        SetHypFieldIsPresent (id, 0);
479                }
480                break;
481        }
482}
483
484void UserInfo::PostDecode (Buffer& buffer) throw (DecodeError)
485{
486        if (IsPresent (id_userOrTelephoneSubscriber))
487                normalise_escaped_string (Get_userOrTelephoneSubscriber());
488        if (IsPresent (id_password))
489                normalise_escaped_string (Get_password());
490}
491
492void HostPort::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
493{
494        Charstring csColon;
495        csColon.SetValue(":");
496
497        switch(field_id) {
498        case id_portField:
499                if(IsPresent(field_id)) {
500                        Get_portField().SetFormat(Integer::AsciiDecimal);
501                        csColon.Encode(buffer);
502                }
503                break;
504        default:
505                break;
506        }
507}
508
509void HostPort::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
510{
511        static Regex reg_host ("^" SIPREG_HOST);
512        static Regex reg_colon ("^:");
513
514        switch (id) {
515        case id_host:
516                // host is always present
517                SetHypFieldIsPresent(id, 1);
518                reg_host.AssertMatch (buffer, this);
519                SetHypFieldLength(id, reg_host.GetMatchedLength());
520                break;
521
522        case id_portField:
523                if(reg_colon.Match (buffer)) {
524                        buffer.SetPosition(buffer.GetPosition() + 8);
525                        SetHypFieldIsPresent (id, 1);
526                        Get_portField().SetFormat(Integer::AsciiDecimal);
527                } else {
528                        SetHypFieldIsPresent (id, 0);
529                }
530                break;
531        }
532}
533
534void SemicolonParam_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
535{
536        Charstring csSemi;
537        csSemi.SetValue(";");
538
539        if(field_id != 0) {
540                csSemi.Encode(buffer);
541        }
542}
543
544void SemicolonParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
545{
546        static Regex reg_separator ("^" SIPREG_SEMI);
547        if (reg_separator.Match(buffer)) // the separator can be in the beginning
548                reg_separator.MovePast(buffer);
549}
550
551void SemicolonParam_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
552{
553        if (detect_semi (buffer))
554                SetHypSize (GetSize() + 1);
555        else
556                SetHypSize (-2);
557}
558
559void AmpersandParam_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
560{
561        Charstring csAmpersand, csQuestion;
562        csAmpersand.SetValue("&");
563        csQuestion.SetValue("?");
564
565        if(field_id == 0) {
566                csQuestion.Encode(buffer);
567        }
568        else {         
569                csAmpersand.Encode(buffer);
570        }
571}
572
573void AmpersandParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
574{
575        static Regex reg_start ("^[?]");
576        static Regex reg_separator ("^[&]");
577
578        if (!buffer.GetBitsLeft())
579                return;
580        if (GetSize() == 0){
581                reg_start.AssertMatch(buffer, this);
582                buffer.SetPosition(buffer.GetPosition() + 8);
583        }
584        else if (reg_separator.Match(buffer))
585                buffer.SetPosition(buffer.GetPosition() + 8);
586        else
587                SetHypSize(-2);
588}
589
590void CommaParam_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
591{
592        Charstring csComma;
593        csComma.SetValue(",");
594
595        if(field_id != 0) {
596                csComma.Encode(buffer);
597        }
598}
599
600void CommaParam_List::PreDecode (Buffer& buffer) throw (DecodeError)
601{
602        Variable* parent = GetParent();
603        if (parent != NULL) {           
604                const char * pszParName = parent->GetTypeName();
605                if (strcmp(pszParName, "Credentials") == 0 ||
606                        strcmp(pszParName, "AuthenticationInfo") == 0){
607                        SetHypSize (GetSize() + 1);
608                        SetHypAppend (1);
609                }
610        }
611}
612
613void CommaParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
614{
615        static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA);
616        if (GetSize() > 0 && !reg_content.Match(buffer)) {
617                SetHypSize(-2);
618        }
619}
620
621void CommaParam_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
622{
623        static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA);
624        if (detect_comma (buffer) && reg_content.Match (buffer))
625                SetHypSize (GetSize() + 1);
626        else
627                SetHypSize (-2);
628}
629
630
631void GenericParam::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
632{
633        Charstring csEqual;
634        csEqual.SetValue("=");
635
636        switch(field_id) {
637        case id_paramValue:
638                if(IsPresent(field_id)) {
639                        csEqual.Encode(buffer);
640                }
641                break;
642        default:
643                break;
644        }
645}
646
647void GenericParam::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
648{
649        static Regex reg_equal ("^" SIPREG_EQUAL);
650
651        static Regex reg_pparname ("^" SIPREG_PPARAM "+");
652        static Regex reg_pparvalue ("^" SIPREG_PPARAM "*");
653
654        static Regex reg_hparname ("^" SIPREG_HPARAM "+");
655        static Regex reg_hparvalue ("^" SIPREG_HPARAM "*");
656
657        static Regex reg_telparname ("^" SIPREG_TELPARAM_NAME);
658        static Regex reg_telparvalue ("^" SIPREG_TELPARAM_VALUE);
659
660        static Regex reg_gparname ("^" SIPREG_TOKEN);
661        static Regex reg_gparvalue ("^" SIPREG_GPARAM_VALUE);
662
663        Regex * preg_name = NULL;
664        Regex * preg_value;
665        bool bMandatoryParam = false;
666
667        Variable* parent = GetParent();
668        if (parent == NULL)
669                throw DecodeError (this, "Parent type cannot be null\n");
670        const char * pszParName = parent->GetTypeName();
671        if (strcmp(pszParName, "SemicolonParam_List") == 0){
672                parent = parent->GetParent();
673                if (parent != NULL && strcmp (parent->GetTypeName(), "SipUrl") == 0) {
674                        SipUrl * pSipUrl = dynamic_cast<SipUrl*>(parent);
675                        const char * pszScheme = pSipUrl->Get_scheme().GetValue();
676                        if (is_sip_scheme(pszScheme)) {
677                                preg_name = &reg_pparname;
678                                preg_value = &reg_pparvalue;
679                        }
680                        else if (is_tel_scheme(pszScheme)) {
681                                preg_name = &reg_telparname;
682                                preg_value = &reg_telparvalue;
683                        }
684                }
685                if (preg_name == NULL) {
686                        preg_name = &reg_gparname;
687                        preg_value = &reg_gparvalue;
688                }
689        }
690        else if (strcmp(pszParName, "AmpersandParam_List") == 0){
691                preg_name = &reg_hparname;
692                preg_value = &reg_hparvalue;
693                bMandatoryParam = true;
694        }
695        else if (strcmp(pszParName, "CommaParam_List") == 0){
696                preg_name = &reg_gparname;
697                preg_value = &reg_gparvalue;
698        }
699        else {
700                std::string message ("Unexpected parent type of parameter record: '");
701                message += pszParName;
702                message += '\n';
703                throw DecodeError (this, message);
704        }
705       
706        char c;
707        switch (id) {
708        case id_id:
709                preg_name->AssertMatch (buffer, this);
710                SetHypFieldLength (id, preg_name->GetMatchedLength());
711                break;
712        case id_paramValue:
713                if (bMandatoryParam)
714                        reg_equal.AssertMatch(buffer, this);
715                if(bMandatoryParam || (buffer.GetBitsLeft() && reg_equal.Match(buffer))) {
716                        buffer.SetPosition(buffer.GetPosition() + reg_equal.GetMatchedLength());
717                        preg_value->AssertMatch (buffer, this);
718                        SetHypFieldIsPresent (id, 1);
719                        SetHypFieldLength (id, preg_value->GetMatchedLength());
720                } else {
721                        SetHypFieldIsPresent (id, 0);
722                }
723                break;
724        }
725}
726
727
728void RequestLine::PostEncode (Buffer& buffer) throw (EncodeError)
729{
730        Charstring cs;
731
732        cs.SetValue("\r\n");
733        cs.Encode(buffer);
734}
735
736void RequestLine::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
737{
738        Charstring cs;
739
740        cs.SetValue(" ");
741
742        switch(field_id) {
743        case id_method:
744        case id_requestUri:
745                cs.Encode(buffer);
746                break;
747        default:
748                break;
749        }
750}
751
752void GenericParam::PostDecode (Buffer& buffer) throw (DecodeError)
753{
754        Variable* param_list = GetParent();
755        if (!param_list)
756                return;
757       
758        Variable* parent = param_list->GetParent();
759        if (!parent)
760                return;
761        const char* parent_type = parent->GetTypeName();
762
763        if (strcmp (parent_type, "SipUrl") == 0) {
764                normalise_escaped_string (Get_id());
765        }
766
767        if (IsPresent (id_paramValue))
768        {
769                Charstring& value = Get_paramValue();
770
771                if (value.GetLength() &&
772                    (*value.GetValueBin() == '"')) {
773                        normalise_quoted_string (value, true);
774                } else {
775                        const char* par_name = Get_id().GetValue();
776                       
777                        //TODO: add other unescaped params
778                        if (strcmp (parent_type, "ViaBody") == 0) {
779                                if ((strcmp (par_name, "branch") == 0)
780                                 || (strcmp (par_name, "ttl") == 0)
781                                 || (strcmp (par_name, "maddr") == 0)
782                                 || (strcmp (par_name, "received") == 0))
783                                        goto skip_escape;
784                        } else if (strcmp (parent_type, "From") == 0) {
785                                if (strcmp (par_name, "tag") == 0)
786                                        goto skip_escape;
787                        }
788                        else if (strcmp (parent_type, "PChargingVector") == 0) {
789                          if (strcmp (par_name, "icid-value") == 0)
790                                        goto skip_escape;
791                        }
792do_escape:
793                        normalise_escaped_string (value);
794skip_escape: ;
795
796                }
797        }
798}
799
800void RequestLine::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
801{
802        static Regex reg_method ("^" SIPREG_TOKEN);
803        static Regex reg_request_uri ("[^ \t\n\r]+");
804        static Regex reg_sip_version (SIPREG_SIP_VERSION);
805        switch (id) {
806                case id_method:
807                        reg_method.AssertMatch (buffer, this);
808                        SetHypFieldLength (id, reg_method.GetMatchedLength());
809                        break;
810                case id_requestUri:
811                        read_sp (buffer, this);
812                        reg_request_uri.AssertMatch (buffer, this);
813                        SetHypFieldLength (id, reg_request_uri.GetMatchedLength());
814                        break;
815                case id_sipVersion:
816                        read_sp (buffer, this);
817                        reg_sip_version.AssertMatch (buffer, this);
818                        SetHypFieldLength (id, reg_sip_version.GetMatchedLength());
819                        break;
820        }
821}
822
823void RequestLine::PostDecode (Buffer& buffer) throw (DecodeError)
824{
825        static Regex reg_crlf ("^\r\n");
826
827        reg_crlf.AssertMatch (buffer, this);
828        buffer.SetPosition(buffer.GetPosition() + reg_crlf.GetMatchedLength());
829}
830
831const char* Method::msSipMethods[] = {
832        "ACK_E",
833        "BYE_E",
834        "CANCEL_E",
835        "INVITE_E",
836        "OPTIONS_E",
837        "REGISTER_E",
838        "PRACK_E",
839        "SUBSCRIBE_E",
840        "NOTIFY_E",
841        "PUBLISH_E",
842        "REFER_E",
843        "UPDATE_E",
844        "MESSAGE_E",
845        "INFO_E",
846        "UNKNOWN_METHOD_E"
847        , "" };
848
849const char* Method::msMethodValues[] = {
850        "ACK",
851        "BYE",
852        "CANCEL",
853        "INVITE",
854        "OPTIONS",
855        "REGISTER",
856        "PRACK",
857        "SUBSCRIBE",
858        "NOTIFY",
859        "PUBLISH",
860        "REFER",
861        "UPDATE",
862        "MESSAGE",
863        "INFO"
864        "UNKNOWN_METHOD"
865        , "" };
866
867void Method::Encode (Buffer& buffer) throw (EncodeError)
868{
869        Charstring c;
870        const char ** ppMethod = msSipMethods;
871        const std::string & val = GetValueString();
872
873        int i = 0;
874        while (*(ppMethod[i]) && strcmp(ppMethod[i], val.c_str()) != 0)
875                i++;
876
877        if (*(ppMethod[i]) == 0) {
878                std::string message ("unsupported enum value '");
879                message += val;
880                message += '\n';
881                throw EncodeError (this, message);
882        }
883
884        c.SetValue(msMethodValues[i]);
885        c.Encode(buffer);
886}
887
888void Method::Decode (Buffer& buffer) throw (DecodeError)
889{
890        static Regex reg_method ("^" SIPREG_TOKEN);
891
892        reg_method.AssertMatch (buffer, this);
893
894        const char ** ppValue = msMethodValues;
895        const std::string & val = reg_method.GetMatchedString();
896
897        int i = 0;
898        while (*(ppValue[i]) && strcmp(ppValue[i], val.c_str()) != 0) // case sensitive!!!
899                i++;
900
901        if (*(ppValue[i]) == 0) {
902                SetValueString ("UNKNOWN_METHOD_E");
903        } else {
904                SetValueString (msSipMethods[i]);
905        }
906        buffer.SetPosition(buffer.GetPosition() + reg_method.GetMatchedLength());
907}
908
909void StatusLine::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
910{
911        Charstring csWS;
912        csWS.SetValue(" ");
913
914        switch(field_id) {
915        case id_statusCode:
916                Get_statusCode().SetFormat(Integer::AsciiDecimal);
917        case id_reasonPhrase:
918                csWS.Encode(buffer);
919                break;
920        default:
921                break;
922        }
923}
924
925void StatusLine::PostEncode (Buffer& buffer) throw (EncodeError)
926{
927        Charstring csCRLF;
928        csCRLF.SetValue("\r\n");
929
930        csCRLF.Encode(buffer);
931}
932
933void StatusLine::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
934{
935        static Regex reg_sip_version (SIPREG_SIP_VERSION);
936        static Regex reg_status_code ("^[0-9]{3}");
937        static Regex reg_phrase ("([" SIPCHARS_RESERVED SIPCHARS_UNRESERVED SIPCHARS_UTF8_NONASCII " \t]|" SIPREG_ESCAPED ")*");
938
939        switch (id) {
940                case id_sipVersion:
941                        reg_sip_version.AssertMatch (buffer, this);
942                        SetHypFieldLength (id, reg_sip_version.GetMatchedLength());
943                        break;
944                case id_statusCode:
945                        read_sp (buffer, this);
946                        reg_status_code.AssertMatch (buffer, this);
947                        SetHypFieldLength (id, reg_status_code.GetMatchedLength());
948                        Get_statusCode().SetFormat(Integer::AsciiDecimal);
949                        break;
950                case id_reasonPhrase:
951                        read_sp (buffer, this);
952                        reg_phrase.AssertMatch (buffer, this);
953                        SetHypFieldLength (id, reg_phrase.GetMatchedLength());                 
954                        break;
955        }
956}
957
958void StatusLine::PostDecode (Buffer& buffer) throw (DecodeError)
959{
960        static Regex reg_crlf ("^\r\n");
961
962        reg_crlf.AssertMatch(buffer, this);
963        reg_crlf.MovePast(buffer);
964
965        normalise_escaped_string (Get_reasonPhrase());
966}
967
968class SipHeaderMap {
969public:
970        struct Entry {
971                Entry (const char* name, const char* abbrev, int id_msg_hdr, const char* id_fdn)
972                 : mName (name), mAbbrev (abbrev), mIdMessageHeader (id_msg_hdr), mIdFieldName (id_fdn)
973                {}
974                const std::string       mName;
975                const std::string       mAbbrev;
976                const int               mIdMessageHeader;
977                const std::string       mIdFieldName;
978        };
979
980        static const Entry& GetByName (const std::string& key)
981        {
982                const mMapName_t& m = msInstance.mMapName;
983                mMapName_t::const_iterator it = m.find (key);
984                if (it != m.end()) {
985                        return *it->second;
986                } else {
987                        return *msInstance.mUndef;
988                }
989        }
990       
991        static const Entry& GetByIdFieldName (const std::string& key)
992        {
993                const std::map<std::string, Entry*>& m = msInstance.mMapIdFieldName;
994                std::map <std::string, Entry*>::const_iterator it = m.find (key);
995                if (it != m.end()) {
996                        return *it->second;
997                } else {
998                        return *msInstance.mUndef;
999                }
1000        }
1001       
1002        static const Entry& GetByIdMessageHeader (int key)
1003        {
1004                const std::map<int, Entry*>& m = msInstance.mMapIdMessageHeader;
1005                std::map <int, Entry*>::const_iterator it = m.find (key);
1006                if (it != m.end()) {
1007                        return *it->second;
1008                } else {
1009                        return *msInstance.mUndef;
1010                }
1011        }
1012
1013
1014private:
1015        void AddEntry (const Entry& entry) {
1016                mEntries.push_back(entry);
1017                Entry& e = *mEntries.rbegin();
1018               
1019                //TODO: check unicity
1020                mMapName[e.mName] = &e;
1021                mMapName[e.mAbbrev] = &e;
1022                mMapIdMessageHeader[e.mIdMessageHeader] = &e;
1023                mMapIdFieldName[e.mIdFieldName] = &e;
1024        }
1025
1026        SipHeaderMap() {
1027
1028#define SIP_HEADER_ADD(name, abbr, msghdr, fdname)      AddEntry (Entry (#name, #abbr, MessageHeader::id_ ## msghdr, #fdname));
1029
1030                //              Name            Abbrev  MessageHeader   FieldName
1031                //                                      field id        field id
1032                SIP_HEADER_ADD (From,           f,      fromField,      FROM_E);
1033                SIP_HEADER_ADD (Via,            v,      via,            VIA_E);
1034                SIP_HEADER_ADD (Accept,          ,      accept,         ACCEPT_E);
1035                SIP_HEADER_ADD (Call-ID,        i,      callId,         CALL_ID_E);
1036                SIP_HEADER_ADD (CSeq,            ,      cSeq,           CSEQ_E);
1037                SIP_HEADER_ADD (Content-Length, l,      contentLength,  CONTENT_LENGTH_E);
1038                SIP_HEADER_ADD (Content-Type,   c,      contentType,    CONTENT_TYPE_E);
1039                SIP_HEADER_ADD (Contact,        m,      contact,                CONTACT_E);
1040                SIP_HEADER_ADD (To,                     t,      toField,                TO_E);
1041                SIP_HEADER_ADD (Accept-Encoding,        ,       acceptEncoding, ACCEPT_ENCODING_E);
1042                SIP_HEADER_ADD (Accept-Language,        ,       acceptLanguage, ACCEPT_LANGUAGE_E);
1043                SIP_HEADER_ADD (Max-Forwards,   ,       maxForwards,    MAX_FORWARDS_E);
1044                SIP_HEADER_ADD (Alert-Info,             ,       alertInfo,      ALERT_INFO_E);
1045                SIP_HEADER_ADD (Require,        ,       require,        REQUIRE_E);
1046                SIP_HEADER_ADD (Proxy-Require,  ,       proxyRequire,   PROXY_REQUIRE_E);
1047                SIP_HEADER_ADD (Record-Route,   ,       recordRoute,    RECORD_ROUTE_E);
1048                SIP_HEADER_ADD (Allow,           ,      allow,          ALLOW_E);
1049                SIP_HEADER_ADD (Authentication-Info,    ,       authenticationInfo,     AUTHENTICATION_INFO_E);
1050                SIP_HEADER_ADD (Authorization,  ,       authorization,  AUTHORIZATION_E);
1051                SIP_HEADER_ADD (Call-Info,              ,       callInfo,               CALL_INFO_E);
1052                SIP_HEADER_ADD (Content-Disposition,    ,       contentDisposition,     CONTENT_DISPOSITION_E);
1053                SIP_HEADER_ADD (Content-Encoding,       e,      contentEncoding,        CONTENT_ENCODING_E);
1054                SIP_HEADER_ADD (Content-Language,       ,       contentLanguage,        CONTENT_LANGUAGE_E);
1055                SIP_HEADER_ADD (Date,            ,      date,           DATE_E);
1056                SIP_HEADER_ADD (Error-Info,             ,       errorInfo,      ERROR_INFO_E);
1057                SIP_HEADER_ADD (Expires,        ,       expires,        EXPIRES_E);
1058                SIP_HEADER_ADD (In-Reply-To,    ,       inReplyTo,      IN_REPLY_TO_E);
1059                SIP_HEADER_ADD (MIME-Version,   ,       mimeVersion,    MIME_VERSION_E);
1060                SIP_HEADER_ADD (Min-Expires,    ,       minExpires,     MIN_EXPIRES_E);
1061                SIP_HEADER_ADD (Organization,   ,       organization,   ORGANIZATION_E);
1062                SIP_HEADER_ADD (Priority,       ,       priority,       PRIORITY_E);
1063                SIP_HEADER_ADD (Proxy-Authenticate,             ,       proxyAuthenticate,      PROXY_AUTHENTICATE_E);
1064                SIP_HEADER_ADD (Proxy-Authorization,    ,       proxyAuthorization,     PROXY_AUTHORIZATION_E);
1065                SIP_HEADER_ADD (Reply-To,       ,       replyTo,        REPLY_TO_E);
1066                SIP_HEADER_ADD (Retry-After,    ,       retryAfter,     RETRY_AFTER_E);
1067                SIP_HEADER_ADD (Route,          ,       route,          ROUTE_E);
1068                SIP_HEADER_ADD (Server,         ,       server,         SERVER_E);
1069                SIP_HEADER_ADD (Supported,      ,       supported,      SUPPORTED_E);
1070                SIP_HEADER_ADD (Subject,        s,      subject,        SUBJECT_E);
1071                SIP_HEADER_ADD (Timestamp,      ,       timestamp,      TIMESTAMP_E);
1072                SIP_HEADER_ADD (Unsupported,    ,       unsupported,    UNSUPPORTED_E);
1073                SIP_HEADER_ADD (User-Agent,     ,       userAgent,      USER_AGENT_E);
1074                SIP_HEADER_ADD (Warning,        ,       warning,        WARNING_E);
1075                SIP_HEADER_ADD (WWW-Authenticate,               ,       wwwAuthenticate,        WWW_AUTHENTICATE_E);
1076                SIP_HEADER_ADD (RSeq,           ,       rSeq,           RSEQ_E);
1077                SIP_HEADER_ADD (RAck,           ,       rAck,           RACK_E);
1078                SIP_HEADER_ADD (Allow-Events,   u,      allowEvents,    ALLOW_EVENTS_E);
1079                SIP_HEADER_ADD (Event,          o,      event,          EVENT_E);
1080                SIP_HEADER_ADD (Subscription-State,             ,       subscriptionState,      SUBSCRIPTION_STATE_E);
1081                SIP_HEADER_ADD (P-Media-Authorization,  ,       pMediaAuthorization,    P_MEDIA_AUTHORIZATION_E);
1082                SIP_HEADER_ADD (Privacy,        ,       privacy,        PRIVACY_E);
1083                SIP_HEADER_ADD (P-Asserted-Identity,    ,       pAssertedID,    P_ASSERTED_ID_E);
1084                SIP_HEADER_ADD (P-Preferred-Identity,   ,       pPreferredID,   P_PREFERRED_ID_E);
1085                SIP_HEADER_ADD (Reason,         ,       reason,         REASON_E);
1086                SIP_HEADER_ADD (Path,           ,       path,           PATH_E);
1087                SIP_HEADER_ADD (Security-Client,                ,       securityClient,         SECURITY_CLIENT_E);
1088                SIP_HEADER_ADD (Security-Server,                ,       securityServer,         SECURITY_SERVER_E);
1089                SIP_HEADER_ADD (Security-Verify,                ,       securityVerify,         SECURITY_VERIFY_E);
1090                SIP_HEADER_ADD (P-Associated-URI,               ,       pAssociatedURI,         P_ASSOCIATED_URI_E);
1091                SIP_HEADER_ADD (P-Called-Party-ID,              ,       pCalledPartyID,         P_CALLED_PARTY_E);
1092                SIP_HEADER_ADD (P-Visited-Network-ID,   ,       pVisitedNetworkID,      P_VISITED_NETWORK_E);
1093                SIP_HEADER_ADD (P-Access-Network-Info,  ,       pAccessNetworkInfo,     P_ACCESS_NETWORK_INFO_E);
1094                SIP_HEADER_ADD (P-Charging-Function-Addresses,  ,       pChargingFunctionAddresses,             P_CHARGING_FUNCTION_ADDRESSES_E);
1095                SIP_HEADER_ADD (P-Charging-Vector,              ,       pChargingVector,        P_CHARGING_VECTOR_E);
1096                SIP_HEADER_ADD (Refer-To,       r,      referTo,        REFER_TO_E);
1097                SIP_HEADER_ADD (Replaces,               ,       replaces,       REPLACES_E);
1098                SIP_HEADER_ADD (Service-Route,                  ,       serviceRoute,           SERVICE_ROUTE_E);
1099                SIP_HEADER_ADD (Accept-Contact,                 a,      acceptContact,          ACCEPT_CONTACT_E);
1100                SIP_HEADER_ADD (Referred-By,    b,      referredBy,     REFERRED_BY_E);
1101                SIP_HEADER_ADD (Session-Expires,                ,       sessionExpires,         SESSION_EXPIRES_E);
1102                SIP_HEADER_ADD (Min-SE,         ,       minSE,          MIN_SE_E);
1103                SIP_HEADER_ADD (History-Info,                   ,       historyInfo,            HISTORY_INFO_E);
1104                SIP_HEADER_ADD (P-Early-Media,                  ,       pEarlyMedia,            P_EARLY_MEDIA_E);
1105                SIP_HEADER_ADD (UserToUser,             ,       userToUser,     USER_TO_USER_E);
1106                SIP_HEADER_ADD (P-Asserted-Service,             ,       pAssertedService,               P_ASSERTED_SERVICE_E);         
1107                {
1108                        mEntries.push_back(Entry("", "", MessageHeader::id_undefinedHeader_List, ""));
1109                        Entry& e = *mEntries.rbegin();
1110                        mMapIdMessageHeader[e.mIdMessageHeader] = &e;
1111                        mUndef = &e;
1112                }
1113        }
1114
1115        static SipHeaderMap             msInstance;
1116
1117        std::list<Entry>                mEntries;
1118        Entry*                          mUndef;
1119
1120        class StringCaseInsensitiveComparator
1121        {
1122        public:
1123                bool operator() (const std::string& a, const std::string& b) const
1124                {
1125                        return (strcasecmp (a.c_str(), b.c_str()) < 0);
1126                }
1127        };
1128
1129        typedef std::map <std::string, Entry*, StringCaseInsensitiveComparator> mMapName_t;
1130        mMapName_t                      mMapName;
1131        std::map <std::string, Entry*>  mMapIdFieldName;
1132        std::map <int, Entry*>          mMapIdMessageHeader;
1133
1134};
1135
1136SipHeaderMap SipHeaderMap::msInstance;
1137
1138void MessageHeader::PostEncode (Buffer& buffer) throw (EncodeError)
1139{
1140        Charstring csCRLF;
1141        csCRLF.SetValue("\r\n");
1142
1143        csCRLF.Encode(buffer); 
1144}
1145
1146void MessageHeader::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1147{
1148        Charstring csCRLF;
1149        csCRLF.SetValue("\r\n");
1150
1151        if(IsPresent(field_id) && field_id != id_undefinedHeader_List) {
1152                csCRLF.Encode(buffer);
1153        }
1154}
1155
1156void MessageHeader::PreDecodeField (Buffer& buffer) throw (DecodeError)
1157{
1158        static Regex reg_header_name ("^(" SIPREG_TOKEN ")" SIPREG_HCOLON);
1159        static Regex reg_crlf ("^\r\n");
1160
1161        if (reg_crlf.Match (buffer)) {
1162                reg_crlf.MovePast (buffer);
1163                SetHypNextField (-2); // end of the headers
1164        } else {
1165                reg_header_name.AssertMatch (buffer, this);
1166
1167                const SipHeaderMap::Entry& hdr = SipHeaderMap::GetByName(reg_header_name.GetMatchedString (1));
1168                int id = hdr.mIdMessageHeader;
1169
1170                std::cerr << "biiiiiip " << reg_header_name.GetMatchedString(1) << std::endl;
1171
1172
1173
1174                // check that this field is not duplicated
1175                if (IsPresent(id)) {
1176                        switch (id) {
1177                        case id_accept:
1178                        case id_acceptEncoding:
1179                        case id_acceptLanguage:
1180                        case id_alertInfo:
1181                        case id_allow:
1182                        case id_authorization:
1183                        case id_contact:
1184                        case id_contentEncoding:
1185                        case id_contentLanguage:
1186                        case id_errorInfo:
1187                        case id_inReplyTo:
1188                        case id_proxyAuthorization:
1189                        case id_proxyRequire:
1190                        case id_recordRoute:
1191                        case id_require:
1192                        case id_route:
1193                        case id_supported:
1194                        case id_unsupported:
1195                        case id_via:
1196                        case id_warning:
1197                        case id_allowEvents:
1198                        case id_pMediaAuthorization:
1199                        case id_pAssertedID:
1200                        case id_pPreferredID:
1201                        case id_reason:
1202                        case id_path:
1203                        case id_securityClient:
1204                        case id_securityServer:
1205                        case id_securityVerify:
1206                        case id_pAssociatedURI:
1207                        case id_pCalledPartyID:
1208                        case id_pVisitedNetworkID:
1209                        case id_acceptContact:
1210                        case id_historyInfo:
1211                        case id_pEarlyMedia:
1212                        case id_undefinedHeader_List:
1213                                // these fields can appear multiple times
1214                                break;
1215                        default:
1216                                DecodeError e (this);
1217                                e.Msg() << "Duplicated field in the message: "
1218                                        << hdr.mName << std::endl;
1219                                throw (e);
1220                        }
1221                }
1222                SetHypNextField (id);
1223        }
1224}
1225
1226void MessageHeader::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
1227{
1228        static Regex reg_crlf ("^\r\n");
1229        reg_crlf.AssertMatch (buffer, this);
1230        buffer.SetPosition(buffer.GetPosition() + reg_crlf.GetMatchedLength());
1231}
1232
1233
1234const char* FieldName::msFields[] = {
1235        "ACCEPT_E",
1236        "ACCEPT_ENCODING_E",
1237        "ACCEPT_LANGUAGE_E",
1238        "ALERT_INFO_E",
1239        "ALLOW_E",
1240        "AUTHENTICATION_INFO_E",
1241        "AUTHORIZATION_E",
1242        "CALL_ID_E",
1243        "CALL_INFO_E",
1244        "CONTACT_E",
1245        "CONTENT_DISPOSITION_E",
1246        "CONTENT_ENCODING_E",
1247        "CONTENT_LANGUAGE_E",
1248        "CONTENT_LENGTH_E",
1249        "CONTENT_TYPE_E",
1250        "CSEQ_E",
1251        "DATE_E",
1252        "ERROR_INFO_E",
1253        "EXPIRES_E",
1254        "FROM_E",
1255        "IN_REPLY_TO_E",
1256        "MAX_FORWARDS_E",
1257        "MIME_VERSION_E",
1258        "MIN_EXPIRES_E",
1259        "ORGANIZATION_E",
1260        "PRIORITY_E",
1261        "PROXY_AUTHENTICATE_E",
1262        "PROXY_AUTHORIZATION_E",
1263        "PROXY_REQUIRE_E",
1264        "RECORD_ROUTE_E",
1265        "REPLY_TO_E",
1266        "REQUIRE_E",
1267        "RETRY_AFTER_E",
1268        "ROUTE_E",
1269        "SERVER_E",
1270        "SUBJECT_E",
1271        "SUPPORTED_E",
1272        "TIMESTAMP_E",
1273        "TO_E",
1274        "UNSUPPORTED_E",
1275        "USER_AGENT_E",
1276        "VIA_E",
1277        "WARNING_E",
1278        "WWW_AUTHENTICATE_E",
1279        "RACK_E",
1280        "RSEQ_E",
1281        "ALLOW_EVENTS_E",
1282        "EVENT_E",
1283        "SUBSCRIPTION_STATE_E",
1284        "P_MEDIA_AUTHORIZATION_E",
1285        "PRIVACY_E",
1286        "P_ASSERTED_ID_E",
1287        "P_PREFERRED_ID_E",
1288        "REASON_E",
1289        "REFER_TO_E",
1290        "REFERRED_BY_E",
1291        "HISTORY_INFO_E",
1292        "P_MEDIA_AUTH_E",
1293        "PATH_E",       
1294        "SECURITY_CLIENT_E",   
1295        "SECURITY_SERVER_E",
1296        "SECURITY_VERIFY_E", 
1297        "P_ACCESS_NETWORK_INFO_E",
1298        "P_ASSOCIATED_URI_E",
1299        "P_CALLED_PARTY_E",
1300        "P_CHARGING_FUNCTION_ADDRESSES_E",
1301        "P_CHARGING_VECTOR_E",
1302        "P_VISITED_NETWORK_E",
1303        "SERVICE_ROUTE_E",
1304        "ACCEPT_CONTACT_E",
1305        "MIN_SE_E",
1306        "SESSION_EXPIRES_E",
1307        "P_ASSERTED_SERVICE_E",
1308        "P_EARLY_MEDIA_E"
1309        , "" };
1310
1311void FieldName::Encode (Buffer& buffer) throw (EncodeError)
1312{
1313        Charstring c;
1314
1315        c.SetValue ((SipHeaderMap::GetByIdFieldName(GetValueString()).mName + ": ").c_str());
1316        c.Encode(buffer);
1317}
1318
1319void FieldName::Decode (Buffer& buffer) throw (DecodeError)
1320{
1321        static Regex reg_header_name ("^([A-Za-z\\-]+)" SIPREG_HCOLON);
1322
1323        reg_header_name.AssertMatch (buffer, this);
1324        SetValueString (SipHeaderMap::GetByName(reg_header_name.GetMatchedString (1)).mIdFieldName.c_str());
1325       
1326        buffer.SetPosition(buffer.GetPosition() + reg_header_name.GetMatchedLength());
1327}
1328
1329void Addr_Union::PreDecode (Buffer& buffer) throw (DecodeError)
1330{
1331        static Regex reg_name_addr ("^" SIPREG_DISPLAY_NAME "?" SIPREG_SWS "<[^\\r\\n]*>");
1332       
1333        mPosition = buffer.GetPosition();
1334
1335        SetHypChosenId (
1336                reg_name_addr.Match (buffer)
1337                        ? id_nameAddr
1338                        : id_addrSpecUnion
1339        );
1340}
1341
1342void Addr_Union::PostDecode (Buffer& buffer) throw (DecodeError)
1343{
1344        if (GetChosenId() == id_addrSpecUnion) {
1345                Variable* parent = GetParent();
1346                if (parent && (
1347                        (strcmp (parent->GetTypeName(), "From") == 0) ||
1348                        (strcmp (parent->GetTypeName(), "ContactAddress") == 0) ||
1349                        (strcmp (parent->GetTypeName(), "ReplyTo") == 0) ||
1350                        (strcmp (parent->GetTypeName(), "To") == 0) ))
1351                {
1352                        // in the case we decoded an address not enclosed in <> in a
1353                        // From, Contact, Reply-To or To header, then we must ensure
1354                        // that it does not contain comma, semicolon or question mark
1355
1356                        const unsigned char* start = buffer.GetValueBin() + (mPosition/8);
1357                        const unsigned char* end   = buffer.GetValueBin() + (buffer.GetPosition()/8);
1358                       
1359                        for (const unsigned char* p=start ; p!=end ; p++) {
1360                                switch (*p) {
1361                                case ';':
1362                                        Get_addrSpecUnion().SetField (SipUrl::id_urlParameters, new Undef);
1363                                case '?':
1364                                        Get_addrSpecUnion().SetField (SipUrl::id_headers, new Undef);
1365                                        buffer.SetPosition ((p-start) * 8 + mPosition);
1366                                        goto finished;
1367                                case ',':
1368                                        throw DecodeError (this, "Url must not contain unescaped comma, semicolor or question mark if it is not enclosed with <>\n");
1369                                default: ;
1370                                }
1371                        }
1372                        finished: ;
1373                }
1374        }
1375}
1376
1377void ContactBody::PreDecode (Buffer& buffer) throw (DecodeError)
1378{
1379        static Regex reg_asterisk ("^[*]");
1380        if (reg_asterisk.Match (buffer)) {
1381                if (GetChosenId() == id_contactAddresses)
1382                        throw DecodeError (this, "cannot process wildcard; contactAddresses option is already selected\n");
1383                SetHypChosenId (id_wildcard);
1384                SetHypFieldLength(id_wildcard, 8);
1385        } else {
1386                if (GetChosenId() == id_wildcard)
1387                        throw DecodeError (this, "cannot process address list; wildcart option is already selected\n");
1388                SetHypChosenId (id_contactAddresses);
1389        }
1390}
1391
1392void ContactAddress_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1393{
1394        Charstring csComma;
1395        csComma.SetValue(",");
1396
1397        if(field_id != 0) {
1398                csComma.Encode(buffer);
1399        }
1400}
1401
1402void ContactAddress_List::PreDecode (Buffer& buffer) throw (DecodeError)
1403{
1404        SetHypSize (GetSize() + 1);
1405        SetHypAppend (1);
1406}
1407
1408void ContactAddress_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
1409{
1410        if (detect_comma (buffer))
1411                SetHypSize (GetSize() + 1);
1412        else
1413                SetHypSize (-2);
1414}
1415
1416void ContactAddress::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1417{
1418        Charstring csSemi;
1419        csSemi.SetValue(";");
1420
1421        if(field_id == id_contactParams && IsPresent(id_contactParams)) {
1422                csSemi.Encode(buffer);
1423        }
1424}
1425
1426void ContactAddress::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1427{
1428        static Regex reg_semicolon ("^" SIPREG_SEMI);
1429        if (id == id_contactParams) {
1430                if(reg_semicolon.Match(buffer)) {
1431                        SetHypFieldIsPresent (id, 1);
1432                } else {
1433                        SetHypFieldIsPresent (id, 0);
1434                }
1435        }
1436}
1437
1438void From::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1439{
1440        Charstring csSemi;
1441        csSemi.SetValue(";");
1442
1443        if(field_id == id_fromParams && IsPresent(id_fromParams)) {
1444                csSemi.Encode(buffer);
1445        }
1446}
1447
1448void From::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1449{
1450        static Regex reg_semicolon ("^;");
1451        if (id == id_fromParams) {
1452                if(reg_semicolon.Match(buffer)) {
1453                        SetHypFieldIsPresent (id, 1);
1454                } else {
1455                        SetHypFieldIsPresent (id, 0);
1456                }
1457        }
1458}
1459
1460void To::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1461{
1462        Charstring csSemi;
1463        csSemi.SetValue(";");
1464
1465        if(field_id == id_toParams && IsPresent(id_toParams)) {
1466                csSemi.Encode(buffer);
1467        }
1468}
1469
1470void To::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1471{
1472        static Regex reg_semicolon ("^;");
1473        if (id == id_toParams) {
1474                if(reg_semicolon.Match(buffer)) {
1475                        SetHypFieldIsPresent (id, 1);
1476                } else {
1477                        SetHypFieldIsPresent (id, 0);
1478                }
1479        }
1480}
1481
1482void ReplyTo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1483{
1484        Charstring csSemi;
1485        csSemi.SetValue(";");
1486
1487        if(field_id == id_replyToParams && IsPresent(id_replyToParams)) {
1488                csSemi.Encode(buffer);
1489        }
1490}
1491
1492void ReplyTo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1493{
1494        static Regex reg_semicolon ("^;");
1495        if (id == id_replyToParams) {
1496                if(reg_semicolon.Match(buffer)) {
1497                        SetHypFieldIsPresent (id, 1);
1498                } else {
1499                        SetHypFieldIsPresent (id, 0);
1500                }
1501        }
1502}
1503
1504void Accept::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){
1505        static Regex reg_accept_args ("^[^;,\\r\\n]");
1506        if (id == id_acceptArgs){
1507                if(reg_accept_args.Match(buffer) || Get_acceptArgs().GetSize() > 0) {
1508                        SetHypFieldIsPresent (id, 1);
1509                } else if (Get_acceptArgs().GetSize() == 0){
1510                        SetHypFieldIsPresent (id, 0);
1511                }
1512        }
1513}
1514
1515void AcceptBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1516{
1517        Charstring csSemi;
1518        csSemi.SetValue(";");
1519
1520        if(field_id == id_acceptParam && IsPresent(id_acceptParam)) {
1521                csSemi.Encode(buffer);
1522        }
1523}
1524
1525void AcceptBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1526{
1527        static Regex reg_media_range ("^[^" SIPCHARS_WSP ";,\\r\\n]+");
1528        static Regex reg_semicolon ("^" SIPREG_SEMI);
1529        switch (id){
1530                case id_mediaRange:
1531                        reg_media_range.AssertMatch (buffer, this);
1532                        SetHypFieldLength(id, reg_media_range.GetMatchedLength());
1533                        break;
1534                case id_acceptParam:
1535                        if (reg_semicolon.Match (buffer) ) {
1536                                SetHypFieldIsPresent(id, 1);
1537                        } else {
1538                                SetHypFieldIsPresent(id, 0);
1539                        }
1540        }
1541}
1542
1543void AcceptBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1544{
1545        Charstring csComma;
1546        csComma.SetValue(",");
1547
1548        if(field_id != 0) {
1549                csComma.Encode(buffer);
1550        }
1551}
1552
1553void AcceptBody_List::PreDecode (Buffer& buffer) throw (DecodeError)
1554{
1555        // we assume that we are decoding one field at onece
1556        // multiple fields are handled by successively decoding
1557        // the via field several times in MessageHeader
1558        SetHypSize (GetSize() + 1);
1559        SetHypAppend (1);
1560}
1561
1562void AcceptBody_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1563{
1564        static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA);
1565        if (GetSize() > 0 && !reg_content.Match(buffer)) {
1566                SetHypSize(-2);
1567        }
1568}
1569
1570void AcceptBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
1571{
1572        static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA);
1573        if (detect_comma (buffer) && reg_content.Match (buffer))
1574                SetHypSize (GetSize() + 1);
1575        else
1576                SetHypSize (-2);
1577}
1578
1579void AcceptEncoding::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){
1580        static Regex reg_content_coding ("^[^,\\r\\n]");
1581        if (id == id_contentCoding){
1582                if(reg_content_coding.Match(buffer) ||
1583                        Get_contentCoding().GetSize() > 0) {
1584                        SetHypFieldIsPresent (id, 1);
1585                } else {
1586                        SetHypFieldIsPresent (id, 0);
1587                }
1588        }
1589}
1590
1591void ContentCoding_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1592{
1593        Charstring csComma;
1594        csComma.SetValue(",");
1595
1596        if(field_id != 0) {
1597                csComma.Encode(buffer);
1598        }
1599}
1600
1601void ContentCoding_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1602{
1603        static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA);
1604        if (GetSize() == 0)
1605                reg_content.AssertMatch(buffer, this);
1606        else if (!reg_content.Match(buffer)) {
1607                SetHypSize(-2);
1608                return;
1609        }
1610        SetHypFieldLength(reg_content.GetMatchedLength());
1611}
1612
1613
1614void ContentCoding_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
1615{
1616        static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA);
1617        if (detect_comma (buffer) && reg_content.Match (buffer))
1618                SetHypSize (GetSize() + 1);
1619        else
1620                SetHypSize (-2);
1621}
1622
1623void AcceptLanguage::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){
1624        static Regex reg_language_body ("^[^;,\\r\\n]");
1625        if (id == id_languageBody){
1626                if(reg_language_body.Match(buffer) ||
1627                        Get_languageBody().GetSize() > 0) {
1628                        SetHypFieldIsPresent (id, 1);
1629                } else {
1630                        SetHypFieldIsPresent (id, 0);
1631                }
1632        }
1633}
1634
1635void LanguageBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1636{
1637        Charstring csSemi;
1638        csSemi.SetValue(";");
1639
1640        if(field_id == id_acceptParam && IsPresent(id_acceptParam)) {
1641                csSemi.Encode(buffer);
1642        }
1643}
1644
1645void LanguageBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1646{
1647        static Regex reg_language_range ("^[^" SIPCHARS_WSP ";,\\r\\n]+");
1648        static Regex reg_semicolon ("^" SIPREG_SEMI);
1649        switch (id){
1650                case id_languageRange:
1651                        reg_language_range.AssertMatch (buffer, this);
1652                        SetHypFieldLength(id, reg_language_range.GetMatchedLength());
1653                        break;
1654                case id_acceptParam:
1655                        if (reg_semicolon.Match (buffer)) {
1656                                SetHypFieldIsPresent(id, 1);
1657                        } else {
1658                                SetHypFieldIsPresent(id, 0);
1659                        }
1660        }
1661}
1662
1663void LanguageBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1664{
1665        Charstring csComma;
1666        csComma.SetValue(",");
1667
1668        if(field_id != 0) {
1669                csComma.Encode(buffer);
1670        }
1671}
1672
1673void LanguageBody_List::PreDecode (Buffer& buffer) throw (DecodeError)
1674{
1675        // we assume that we are decoding one field at onece
1676        // multiple fields are handled by successively decoding
1677        // the via field several times in MessageHeader
1678        SetHypSize (GetSize() + 1);
1679        SetHypAppend (1);
1680}
1681
1682void LanguageBody_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) {
1683        static Regex reg_language ("^[^" SIPCHARS_WSP ";,\\r\\n]+");
1684        if (!reg_language.Match(buffer)) {
1685                SetHypSize(-2);
1686                return;
1687        }
1688}
1689
1690void LanguageBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
1691{
1692        static Regex reg_language ("^[^" SIPCHARS_WSP ";,\\r\\n]+");
1693        if (detect_comma (buffer) && reg_language.Match (buffer))
1694                SetHypSize (GetSize() + 1);
1695        else
1696                SetHypSize (-2);
1697}
1698
1699void MaxForwards::PreEncode (Buffer& buffer) throw (EncodeError)
1700{
1701        Get_forwards().SetFormat(Integer::AsciiDecimal);
1702}
1703
1704void MaxForwards::PreDecode (Buffer& buffer) throw (DecodeError)
1705{
1706        Get_forwards().SetFormat(Integer::AsciiDecimal);
1707}
1708
1709void AlertInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){
1710        static Regex reg_alert_info ("^[^;,\\r\\n]");
1711        if (id == id_alertInfoBody){
1712                if(reg_alert_info.Match(buffer) || Get_alertInfoBody().GetSize() > 0) {
1713                        SetHypFieldIsPresent (id, 1);
1714                } else {
1715                        SetHypFieldIsPresent (id, 0);
1716                }
1717        }
1718}
1719
1720void AlertInfoBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1721{
1722        Charstring csLeftAngle, csSemi;
1723        csLeftAngle.SetValue("<");
1724        csSemi.SetValue(";");
1725
1726        if(field_id == id_url) {
1727                csLeftAngle.Encode(buffer);
1728        }
1729
1730        if(field_id == id_genericParams && IsPresent(id_genericParams)) {
1731                csSemi.Encode(buffer);
1732        }
1733}
1734
1735void AlertInfoBody::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1736{
1737        Charstring csRightAngle;
1738        csRightAngle.SetValue(">");
1739
1740        if(field_id == id_url) {
1741                csRightAngle.Encode(buffer);
1742        }
1743}
1744
1745void AlertInfoBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1746{
1747        static Regex reg_url ("^<" SIPREG_ABSOLUTE_URI ">");
1748        static Regex reg_semicolon ("^" SIPREG_SEMI);
1749        switch (id){
1750                case id_url:
1751                        reg_url.AssertMatch (buffer, this);
1752                        buffer.SetPosition(buffer.GetPosition() + 8);
1753                        SetHypFieldLength(id, reg_url.GetMatchedLength() - 16);
1754                        break;
1755                case id_genericParams:
1756                        if (reg_semicolon.Match (buffer)) {
1757                                SetHypFieldIsPresent(id, 1);
1758                        } else {
1759                                SetHypFieldIsPresent(id, 0);
1760                        }
1761        }
1762}
1763
1764void AlertInfoBody::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
1765{
1766        switch (id){
1767                case id_url:
1768                        buffer.SetPosition(buffer.GetPosition() + 8);
1769                        break;
1770        }
1771}
1772
1773void AlertInfoBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1774{
1775        Charstring csComma;
1776        csComma.SetValue(",");
1777
1778        if(field_id != 0) {
1779                csComma.Encode(buffer);
1780        }
1781}
1782
1783void AlertInfoBody_List::PreDecode (Buffer& buffer) throw (DecodeError)
1784{
1785        // we assume that we are decoding one field at onece
1786        // multiple fields are handled by successively decoding
1787        // the via field several times in MessageHeader
1788        SetHypSize (GetSize() + 1);
1789        SetHypAppend (1);
1790}
1791
1792void AlertInfoBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
1793{
1794        if (detect_comma (buffer))
1795                SetHypSize (GetSize() + 1);
1796        else
1797                SetHypSize (-2);
1798}
1799
1800void Allow::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){
1801        static Regex reg_allow ("^[^,\\r\\n]");
1802        if (id == id_methods){
1803                if(reg_allow.Match(buffer) || Get_methods().GetSize() > 0) {
1804                        SetHypFieldIsPresent (id, 1);
1805                } else {
1806                        SetHypFieldIsPresent (id, 0);
1807                }
1808        }
1809}
1810
1811void Method_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1812{
1813        Charstring csComma;
1814        csComma.SetValue(",");
1815
1816        if(field_id != 0) {
1817                csComma.Encode(buffer);
1818        }
1819}
1820
1821void Method_List::PreDecode (Buffer& buffer) throw (DecodeError)
1822{
1823        // we assume that we are decoding one field at onece
1824        // multiple fields are handled by successively decoding
1825        // the via field several times in MessageHeader
1826        SetHypSize (GetSize() + 1);
1827        SetHypAppend (1);
1828}
1829
1830void Method_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) {
1831        static Regex reg_content ("^" SIPREG_TOKEN);
1832       
1833        if (reg_content.Match (buffer)) {
1834                SetHypFieldLength(reg_content.GetMatchedLength());
1835        } else {
1836                SetHypSize(-2);
1837                return;
1838        }
1839}
1840
1841void Method_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
1842{
1843        static Regex reg_content ("^" SIPREG_TOKEN);
1844
1845        if (detect_comma (buffer) && reg_content.Match (buffer))
1846                SetHypSize (GetSize() + 1);
1847        else
1848                SetHypSize (-2);
1849}
1850
1851
1852void CredentialsList::PreDecode (Buffer& buffer) throw (DecodeError) {
1853  SetHypSize (GetSize() + 1);
1854  SetHypAppend (1);
1855}
1856
1857void CredentialsList::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) {
1858 
1859}
1860
1861// TODO: Add CredentialsList PreEncode
1862
1863/*      type record Authorization
1864      {
1865        FieldName               fieldName (AUTHORIZATION_E),
1866                CredentialsList body // changed from Credentials to allow multiple Authorization headers
1867      }*/
1868/*      type record ProxyAuthorization
1869      {
1870        FieldName               fieldName (PROXY_AUTHORIZATION_E),
1871        CredentialsList         credentials // changed from Credentials to allow multiple Authorization headers
1872      }*/
1873
1874
1875void Credentials::PreEncode (Buffer& buffer) throw (EncodeError)
1876{
1877        Charstring csDigestWS;
1878        csDigestWS.SetValue("Digest ");
1879       
1880        if(GetChosenId() == id_digestResponse) {
1881                csDigestWS.Encode(buffer);
1882        }
1883}
1884
1885void Credentials::PreDecode (Buffer& buffer) throw (DecodeError)
1886{
1887        static Regex reg_digest ("^[Dd][Ii][Gg][Ee][Ss][Tt]" SIPREG_LWS);
1888        if (reg_digest.Match (buffer)) {
1889                if (GetChosenId() == id_otherResponse)
1890                        throw DecodeError (this, "cannot process digest credentials; otherResponse option is already selected\n");
1891                buffer.SetPosition(buffer.GetPosition() + reg_digest.GetMatchedLength());
1892                SetHypChosenId (id_digestResponse);             
1893        } else {
1894                if (GetChosenId() == id_digestResponse)
1895                        throw DecodeError (this, "cannot process custom credentials; digestResponse option is already selected\n");
1896                SetHypChosenId (id_otherResponse);
1897        }
1898}
1899
1900void Challenge::PreEncode (Buffer& buffer) throw (EncodeError)
1901{
1902        Charstring csDigestWS;
1903        csDigestWS.SetValue("Digest ");
1904       
1905        if(GetChosenId() == id_digestCln) {
1906                csDigestWS.Encode(buffer);
1907        }
1908}
1909
1910void Challenge::PreDecode (Buffer& buffer) throw (DecodeError)
1911{
1912        static Regex reg_digest ("^[Dd][Ii][Gg][Ee][Ss][Tt]" SIPREG_LWS);
1913        if (reg_digest.Match (buffer)) {
1914                buffer.SetPosition(buffer.GetPosition() + reg_digest.GetMatchedLength());
1915                SetHypChosenId (id_digestCln);
1916        } else {
1917                SetHypChosenId (id_otherChallenge);
1918        }
1919}
1920
1921void OtherAuth::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1922{
1923        Charstring csWS;
1924        csWS.SetValue(" ");
1925
1926        switch(field_id) {
1927        case id_authScheme:
1928                csWS.Encode(buffer);
1929                break;
1930        default:
1931                break;
1932        }
1933}
1934
1935void OtherAuth::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1936{
1937        static Regex reg_auth_scheme ("^" SIPREG_TOKEN);
1938        static Regex reg_separator ("^" SIPREG_LWS);
1939
1940        switch (id){
1941                case id_authScheme:
1942                        reg_auth_scheme.AssertMatch (buffer, this);
1943                        SetHypFieldLength (id, reg_auth_scheme.GetMatchedLength());
1944                        break;
1945                case id_authParams:
1946                        reg_separator.AssertMatch(buffer, this);
1947                        buffer.SetPosition(buffer.GetPosition() + reg_separator.GetMatchedLength());
1948                        Get_authParams().SetHypSize (GetSize() + 1);
1949                        Get_authParams().SetHypAppend (1);
1950                        break;
1951        }
1952}
1953
1954void CallInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){
1955        static Regex reg_call_info ("^[^;,\\r\\n]");
1956        if (id == id_callInfoBody){
1957                if(reg_call_info.Match(buffer)) {
1958                        SetHypFieldIsPresent (id, 1);
1959                } else {
1960                        SetHypFieldIsPresent (id, 0);
1961                }
1962        }
1963}
1964
1965void CallInfoBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1966{
1967        Charstring csLeftAngle, csSemi;
1968        csLeftAngle.SetValue("<");
1969        csSemi.SetValue(";");
1970
1971        if(field_id == id_url) {
1972                csLeftAngle.Encode(buffer);
1973        }
1974
1975        if(field_id == id_infoParams && IsPresent(id_infoParams)) {
1976                csSemi.Encode(buffer);
1977        }
1978}
1979
1980void CallInfoBody::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1981{
1982        Charstring csRightAngle;
1983        csRightAngle.SetValue(">");
1984
1985        if(field_id == id_url) {
1986                csRightAngle.Encode(buffer);
1987        }
1988}
1989
1990void CallInfoBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
1991{
1992        static Regex reg_url ("^<" SIPREG_ABSOLUTE_URI ">");
1993        static Regex reg_semicolon ("^" SIPREG_SEMI);
1994        switch (id){
1995                case id_url:
1996                        reg_url.AssertMatch (buffer, this);
1997                        buffer.SetPosition(buffer.GetPosition() + 8);
1998                        SetHypFieldLength(id, reg_url.GetMatchedLength() - 16);
1999                        break;
2000                case id_infoParams:
2001                        if (reg_semicolon.Match (buffer)) {
2002                                SetHypFieldIsPresent(id, 1);
2003                        } else {
2004                                SetHypFieldIsPresent(id, 0);
2005                        }
2006        }
2007}
2008
2009void CallInfoBody::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2010{
2011        switch (id){
2012                case id_url:
2013                        buffer.SetPosition(buffer.GetPosition() + 8);
2014                        break;
2015        }
2016}
2017
2018void CallInfoBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2019{
2020        Charstring csComma;
2021        csComma.SetValue(",");
2022
2023        if(field_id != 0) {
2024                csComma.Encode(buffer);
2025        }
2026}
2027
2028void CallInfoBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2029{
2030        if (detect_comma (buffer))
2031                SetHypSize (GetSize() + 1);
2032        else
2033                SetHypSize (-2);
2034}
2035
2036void ContentDisposition::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2037{
2038        Charstring csSemi;
2039        csSemi.SetValue(";");
2040
2041        if(field_id == id_dispositionParams && IsPresent(id_dispositionParams)) {
2042                csSemi.Encode(buffer);
2043        }
2044}
2045
2046
2047void ContentDisposition::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2048{
2049        static Regex reg_disposition_type ("^" SIPREG_TOKEN);
2050        static Regex reg_semicolon ("^" SIPREG_SEMI);
2051        switch (id){
2052                case id_dispositionType:
2053                        reg_disposition_type.AssertMatch (buffer, this);
2054                        SetHypFieldLength(id, reg_disposition_type.GetMatchedLength());
2055                        break;
2056                case id_dispositionParams:
2057                        if (reg_semicolon.Match (buffer)) {
2058                                SetHypFieldIsPresent(id, 1);
2059                        } else {
2060                                SetHypFieldIsPresent(id, 0);
2061                        }
2062        }
2063}
2064
2065void LanguageTag_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2066{
2067        Charstring csComma;
2068        csComma.SetValue(",");
2069
2070        if(field_id != 0) {
2071                csComma.Encode(buffer);
2072        }
2073}
2074
2075void LanguageTag_List::PreDecode (Buffer& buffer) throw (DecodeError)
2076{
2077        SetHypSize (GetSize() + 1);
2078        SetHypAppend (1);
2079}
2080
2081void LanguageTag_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2082{
2083        static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA);
2084        reg_content.AssertMatch(buffer, this);
2085        SetHypFieldLength(reg_content.GetMatchedLength());     
2086}
2087
2088void LanguageTag_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2089{
2090        if (detect_comma (buffer))
2091                SetHypSize (GetSize() + 1);
2092        else
2093                SetHypSize (-2);
2094}
2095
2096void Date::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){
2097        static Regex reg_date ("^[^\\r\\n]+");
2098        if (id == id_sipDate){
2099                reg_date.AssertMatch(buffer, this);
2100                SetHypFieldLength(id, reg_date.GetMatchedLength());
2101        }
2102}
2103
2104void ErrorInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){
2105        static Regex reg_error_info ("^[^;,\\r\\n]");
2106        if (id == id_errorInfo){
2107                if(reg_error_info.Match(buffer) || Get_errorInfo().GetSize() > 0) {
2108                        SetHypFieldIsPresent (id, 1);
2109                } else {
2110                        SetHypFieldIsPresent (id, 0);
2111                }
2112        }
2113}
2114
2115void ErrorInfoBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2116{
2117        Charstring csLeftAngle, csSemi;
2118        csLeftAngle.SetValue("<");
2119        csSemi.SetValue(";");
2120
2121        if(field_id == id_uri) {
2122                csLeftAngle.Encode(buffer);
2123        }
2124
2125        if(field_id == id_genericParams && IsPresent(id_genericParams)) {
2126                csSemi.Encode(buffer);
2127        }
2128}
2129
2130void ErrorInfoBody::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2131{
2132        Charstring csRightAngle;
2133        csRightAngle.SetValue(">");
2134
2135        if(field_id == id_uri) {
2136                csRightAngle.Encode(buffer);
2137        }
2138}
2139
2140void ErrorInfoBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2141{
2142        static Regex reg_uri ("^<" SIPREG_ABSOLUTE_URI ">");
2143        static Regex reg_semicolon ("^" SIPREG_SEMI);
2144        switch (id){
2145                case id_uri:
2146                        reg_uri.AssertMatch (buffer, this);
2147                        buffer.SetPosition(buffer.GetPosition() + 8);
2148                        SetHypFieldLength(id, reg_uri.GetMatchedLength() - 16);
2149                        break;
2150                case id_genericParams:
2151                        if (reg_semicolon.Match (buffer)) {
2152                                SetHypFieldIsPresent(id, 1);
2153                        } else {
2154                                SetHypFieldIsPresent(id, 0);
2155                        }
2156        }
2157}
2158
2159void ErrorInfoBody::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2160{
2161        switch (id){
2162                case id_uri:
2163                        buffer.SetPosition(buffer.GetPosition() + 8);
2164                        break;
2165        }
2166}
2167
2168void ErrorInfoBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2169{
2170        Charstring csComma;
2171        csComma.SetValue(",");
2172
2173        if(field_id != 0) {
2174                csComma.Encode(buffer);
2175        }
2176}
2177
2178void ErrorInfoBody_List::PreDecode (Buffer& buffer) throw (DecodeError)
2179{
2180        SetHypSize (GetSize() + 1);
2181        SetHypAppend (1);
2182}
2183
2184void ErrorInfoBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2185{
2186        if (detect_comma (buffer))
2187                SetHypSize (GetSize() + 1);
2188        else
2189                SetHypSize (-2);
2190}
2191
2192void Expires::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2193{
2194        static Regex reg_delta_sec ("^[0-9]+");
2195
2196        switch (id) {
2197        case id_deltaSec:
2198                reg_delta_sec.AssertMatch (buffer, this);
2199                SetHypFieldLength (id, reg_delta_sec.GetMatchedLength());
2200                break;
2201        }
2202}
2203
2204void CallidString_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2205{
2206        Charstring csComma;
2207        csComma.SetValue(",");
2208
2209        if(field_id != 0) {
2210                csComma.Encode(buffer);
2211        }
2212}
2213
2214void CallidString_List::PreDecode (Buffer& buffer) throw (DecodeError)
2215{
2216        SetHypSize (GetSize() + 1);
2217        SetHypAppend (1);
2218}
2219
2220void CallidString_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2221{
2222        static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA);
2223        reg_content.AssertMatch(buffer, this);
2224        SetHypFieldLength(reg_content.GetMatchedLength());
2225}
2226
2227
2228void CallidString_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2229{
2230        if (detect_comma (buffer))
2231                SetHypSize (GetSize() + 1);
2232        else
2233                SetHypSize (-2);
2234}
2235
2236void MimeVersion::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2237{
2238        Charstring csDot;
2239        csDot.SetValue(".");
2240
2241        switch(field_id) {
2242        case id_majorNumber:
2243                Get_majorNumber().SetFormat(Integer::AsciiDecimal);
2244                break;
2245        case id_minorNumber:
2246                Get_minorNumber().SetFormat(Integer::AsciiDecimal);
2247                csDot.Encode(buffer);
2248                break;
2249        default:
2250                break;
2251        }
2252}
2253
2254void MimeVersion::PreDecode (Buffer& buffer) throw (DecodeError)
2255{
2256        Get_majorNumber().SetFormat(Integer::AsciiDecimal);
2257        Get_minorNumber().SetFormat(Integer::AsciiDecimal);
2258}
2259void MimeVersion::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2260{
2261        static Regex reg_separator ("^[.]");
2262        if (id == id_minorNumber) {
2263                reg_separator.AssertMatch (buffer, this);
2264                buffer.SetPosition(buffer.GetPosition() + 8);
2265        }
2266}
2267void MinExpires::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2268{
2269        static Regex reg_delta_sec ("^[0-9]+");
2270
2271        switch (id) {
2272        case id_deltaSec:
2273                reg_delta_sec.AssertMatch (buffer, this);
2274                SetHypFieldLength (id, reg_delta_sec.GetMatchedLength());
2275                break;
2276        }
2277}
2278
2279void Organization::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2280{
2281        static Regex reg_organization ("^(" SIPREG_TEXT_UTF8_TRIM ")*");
2282
2283        switch (id) {
2284        case id_organization:
2285                reg_organization.AssertMatch (buffer, this);
2286                SetHypFieldLength (id, reg_organization.GetMatchedLength());
2287                break;
2288        }
2289}
2290
2291void Priority::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){
2292        static Regex reg_priority ("^" SIPREG_TOKEN);
2293        if (id == id_priorityValue){
2294                reg_priority.AssertMatch(buffer, this);
2295                SetHypFieldLength(id, reg_priority.GetMatchedLength());
2296        }
2297}
2298
2299void RetryAfter::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2300{
2301        Charstring csLeftPar, csSemi;
2302        csLeftPar.SetValue("(");
2303        csSemi.SetValue(";");
2304
2305        if(field_id == id_comment && IsPresent(id_comment)) {
2306                csLeftPar.Encode(buffer);
2307        }
2308
2309        if(field_id == id_retryParams && IsPresent(id_retryParams)) {
2310                csSemi.Encode(buffer);
2311        }
2312}
2313
2314void RetryAfter::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2315{
2316        Charstring csRightPar;
2317        csRightPar.SetValue(")");
2318
2319        if(field_id == id_comment && IsPresent(id_comment)) {
2320                csRightPar.Encode(buffer);
2321        }
2322}
2323
2324void RetryAfter::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2325{
2326        static Regex reg_delta_sec ("^[0-9]+");
2327        static Regex reg_comment ("^" SIPREG_COMMENT);
2328        static Regex reg_separator ("^" SIPREG_SEMI);
2329
2330        switch (id) {
2331                case id_deltaSec:
2332                        reg_delta_sec.AssertMatch (buffer, this);
2333                        SetHypFieldLength (id, reg_delta_sec.GetMatchedLength());
2334                        break;
2335                case id_comment:
2336                        remove_whitespace(buffer);
2337                        if (reg_comment.Match (buffer)) {
2338                                SetHypFieldIsPresent(id, 1);
2339                                SetHypFieldLength (id, reg_comment.GetMatchedLength() - 16);
2340                                buffer.SetPosition(buffer.GetPosition() + 8);
2341                        }
2342                        else
2343                                SetHypFieldIsPresent(id, 0);
2344                        break;
2345                case id_retryParams:
2346                        if (reg_separator.Match (buffer))
2347                                SetHypFieldIsPresent(id, 1);
2348                        else
2349                                SetHypFieldIsPresent(id, 0);
2350                        break;
2351        }
2352}
2353
2354void RetryAfter::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2355{
2356        static Regex reg_parenthesis ("^[)]");
2357        if (id == id_comment && IsPresent(id))
2358        {
2359                reg_parenthesis.AssertMatch (buffer, this);
2360                buffer.SetPosition(buffer.GetPosition() + 8);
2361                remove_whitespace(buffer);
2362        }
2363}
2364
2365void Subject::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2366{
2367        static Regex reg_summary ("^(" SIPREG_TEXT_UTF8_TRIM ")*");
2368
2369        switch (id) {
2370        case id_summary:
2371                reg_summary.AssertMatch (buffer, this);
2372                SetHypFieldLength (id, reg_summary.GetMatchedLength());
2373                break;
2374        }
2375}
2376
2377
2378void ServerVal_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2379{
2380        Charstring csWS;
2381        csWS.SetValue(" ");
2382
2383        if(field_id != 0) {
2384                csWS.Encode(buffer);
2385        }
2386}
2387
2388void ServerVal_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2389{
2390        static Regex reg_content ("^((?:" SIPREG_TOKEN "(?:" SIPREG_SLASH SIPREG_TOKEN ")?)|" SIPREG_COMMENT ")");
2391        reg_content.AssertMatch(buffer, this);
2392        SetHypFieldLength(reg_content.GetMatchedLength());
2393}
2394
2395void ServerVal_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2396{
2397        static Regex reg_separator ("^" SIPREG_LWS);
2398        if (reg_separator.Match (buffer)) {
2399                reg_separator.MovePast (buffer);
2400                SetHypSize (GetSize() + 1);
2401        }
2402        else
2403                SetHypSize (-2);
2404}
2405
2406void Supported::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2407{
2408        static Regex reg_content ("^" SIPREG_TOKEN);
2409
2410        switch (id){
2411                case id_optionsTags:
2412                        if (reg_content.Match (buffer) || Get_optionsTags().GetSize() > 0)
2413                                SetHypFieldIsPresent(id, 1);
2414                        else
2415                                SetHypFieldIsPresent(id, 0);
2416                        break;
2417        }
2418}
2419
2420void NameAddr::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2421{
2422        Charstring csLeftAngle;
2423        csLeftAngle.SetValue("<");
2424
2425        if(field_id == id_addrSpec) {
2426                csLeftAngle.Encode(buffer);
2427        }
2428}
2429
2430void NameAddr::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2431{
2432        Charstring csWS, csRightAngle;
2433        csWS.SetValue(" ");
2434        csRightAngle.SetValue(">");
2435
2436        switch(field_id) {
2437        case id_displayName:
2438                if(IsPresent(id_displayName)) {
2439                        csWS.Encode(buffer);
2440                }
2441                break;
2442        case id_addrSpec:
2443                csRightAngle.Encode(buffer);
2444                break;
2445        default:
2446                break;
2447        }
2448}
2449
2450void NameAddr::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2451{
2452        static Regex reg_display_name ("^" SIPREG_DISPLAY_NAME);
2453        static Regex reg_laquot = ("^<");
2454        static Regex reg_uri = ("^[^\\r\\n]+");
2455
2456        remove_whitespace(buffer);
2457        switch (id){
2458                case id_displayName:
2459                        if (reg_display_name.Match(buffer)) {
2460                                SetHypFieldIsPresent (id, 1);
2461                                SetHypFieldLength (id, reg_display_name.GetMatchedLength());
2462                        } else {
2463                                SetHypFieldIsPresent (id, 0);
2464                        }
2465                        break;
2466                case id_addrSpec:
2467                        reg_laquot.AssertMatch (buffer, this);
2468                        buffer.SetPosition(buffer.GetPosition() + 8);
2469                        reg_uri.AssertMatch(buffer, this);
2470                        SetHypFieldLength (id, reg_uri.GetMatchedLength());
2471                        break;
2472        }
2473}
2474
2475void NameAddr::PostDecode (Buffer& buffer) throw (DecodeError)
2476{
2477        static Regex reg_raquot ("^>");
2478
2479        reg_raquot.AssertMatch (buffer, this);
2480        buffer.SetPosition(buffer.GetPosition() + 8);
2481        remove_whitespace(buffer);
2482       
2483        if (IsPresent (id_displayName)) {
2484                if (Get_displayName().GetLength() &&
2485                    (*Get_displayName().GetValueBin() == '"'))
2486                        normalise_quoted_string (Get_displayName(), true);
2487        }
2488}
2489
2490void SentProtocol::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2491{
2492        Charstring csSlash;
2493        csSlash.SetValue("/");
2494
2495        if(field_id != id_protocolName) {
2496                csSlash.Encode(buffer);
2497        }
2498}
2499
2500void SentProtocol::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2501{
2502
2503        if (id) {
2504                static Regex reg_slash ("^/");
2505                reg_slash.AssertMatch (buffer, this);
2506                reg_slash.MovePast (buffer);
2507        }
2508
2509        static Regex reg_sp ("^" SIPREG_TOKEN);
2510
2511        reg_sp.AssertMatch (buffer, this);
2512
2513        SetHypFieldLength (id, reg_sp.GetMatchedLength());
2514}
2515
2516void ViaBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2517{
2518        Charstring csSemi;
2519        csSemi.SetValue(";");
2520
2521        if(field_id == id_viaParams && IsPresent(id_viaParams)) {
2522                csSemi.Encode(buffer);
2523        }
2524}
2525
2526void ViaBody::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2527{
2528        Charstring csWS;
2529        csWS.SetValue(" ");
2530
2531        if(field_id == id_sentProtocol) {
2532                csWS.Encode(buffer);
2533        }
2534}
2535
2536void ViaBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2537{
2538        static Regex reg_lws ("^" SIPREG_LWS);
2539        static Regex reg_semi ("^;");
2540
2541        switch (id) {
2542        case id_sentBy:
2543                reg_lws.AssertMatch (buffer, this);
2544                reg_lws.MovePast (buffer);
2545                break;
2546        case id_viaParams:
2547                SetHypFieldIsPresent (id, reg_semi.Match (buffer) ? 1 : 0);
2548                break;
2549        default:
2550                ;
2551        }
2552}
2553
2554void ViaBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2555{
2556        Charstring csComma;
2557        csComma.SetValue(",");
2558
2559        if(field_id != 0) {
2560                csComma.Encode(buffer);
2561        }
2562}
2563
2564void ViaBody_List::PreDecode (Buffer& buffer) throw (DecodeError)
2565{
2566        // we assume that we are decoding one field at once
2567        // multiple fields are handled by successively decoding
2568        // the via field several times in MessageHeader
2569        SetHypSize (GetSize() + 1);
2570        SetHypAppend (1);
2571}
2572
2573void ViaBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2574{
2575        Regex reg_comma ("^" SIPREG_COMMA);
2576
2577        if (reg_comma.Match(buffer)) {
2578                reg_comma.MovePast(buffer);
2579
2580                SetHypSize (GetSize() + 1);
2581        }
2582}
2583
2584void UndefinedHeader_List::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2585{
2586        Charstring csCRLF;
2587        csCRLF.SetValue("\r\n");
2588
2589        csCRLF.Encode(buffer);
2590}
2591
2592void UndefinedHeader_List::PreDecode (Buffer& buffer) throw (DecodeError)
2593{
2594        // we assume that we are decoding one field at once
2595        // multiple fields are handled by successively decoding
2596        // the via field several times in MessageHeader
2597        SetHypSize (GetSize() + 1);
2598        SetHypAppend (1);
2599}
2600
2601void UndefinedHeader::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2602{
2603        Charstring csColon;
2604        csColon.SetValue(": ");
2605
2606        if(field_id == id_headerName) {
2607                csColon.Encode(buffer);
2608        }
2609}
2610
2611void UndefinedHeader::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2612{
2613        static Regex reg_header_name ("^" SIPREG_TOKEN);
2614
2615        // TODO: match properly UTF-8 characters
2616        // TODO: normalise the value ?...
2617        static Regex reg_header_value ("^" SIPREG_HCOLON "(([^\\r\\n]|" SIPREG_SWS ")*)");
2618
2619        switch (id) {
2620        case id_headerName:
2621                reg_header_name.AssertMatch (buffer, this);
2622                SetHypFieldLength (id, reg_header_name.GetMatchedLength());
2623                break;
2624        case id_headerValue:
2625                reg_header_value.AssertMatch (buffer, this);
2626                reg_header_value.MoveAt (buffer, 1);
2627                SetHypFieldLength (id, reg_header_value.GetMatchedLength(1));
2628                break;
2629        default:
2630                ;
2631        }
2632}
2633
2634void UndefinedHeader::PostDecode (Buffer& buffer) throw (DecodeError)
2635{
2636        normalise_escaped_string (Get_headerValue());
2637}
2638
2639void CallId::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2640{
2641        if (id == id_callid) {
2642                static Regex reg_cid ("^" SIPREG_WORD "(@" SIPREG_WORD ")*" );
2643
2644                reg_cid.AssertMatch(buffer, this);
2645                SetHypFieldLength (id, reg_cid.GetMatchedLength());
2646        }
2647}
2648
2649void CSeq::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2650{
2651        Charstring csWS;
2652        csWS.SetValue(" ");
2653       
2654        switch(field_id) {
2655        case id_method:
2656                csWS.Encode(buffer);
2657                break;
2658        case id_seqNumber:
2659                Get_seqNumber().SetFormat(Integer::AsciiDecimal);
2660                break;
2661        default:
2662                break;
2663        }
2664}
2665
2666void CSeq::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2667{
2668        static Regex reg_method ("^" SIPREG_LWS "(" SIPREG_TOKEN ")");
2669
2670        switch (id) {
2671        case id_seqNumber:
2672                Get_seqNumber().SetFormat(Integer::AsciiDecimal);
2673                break;
2674        case id_method:
2675                reg_method.AssertMatch (buffer, this);
2676                reg_method.MoveAt (buffer, 1);
2677                SetHypFieldLength (id, reg_method.GetMatchedLength(1));
2678                break;
2679        }
2680}
2681
2682void ContentLength::PreEncode (Buffer& buffer) throw (EncodeError)
2683{
2684        Get_len().SetFormat(Integer::AsciiDecimal);
2685}
2686
2687void ContentLength::PreDecode (Buffer& buffer) throw (DecodeError)
2688{
2689        Get_len().SetFormat(Integer::AsciiDecimal);
2690}
2691
2692void ContentType::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2693{
2694        static Regex reg_ctype ("^" SIPREG_TOKEN "/" SIPREG_TOKEN "(" SIPREG_SEMI SIPREG_M_PARAMETER ")*");
2695        if (id == id_mediaType)
2696        {
2697                reg_ctype.AssertMatch (buffer, this);
2698                SetHypFieldLength (id, reg_ctype.GetMatchedLength());
2699        }
2700       
2701}
2702
2703#define SIP_MESSAGE_CODET(msgname) \
2704void msgname::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) \
2705{ \
2706        switch (id) { \
2707        case id_msgHeader: \
2708          { \
2709                /* decide if we have to decode the message body and how to decode it */ \
2710                MessageHeader& hdr = Get_msgHeader(); \
2711                int content_length = hdr.IsPresent (MessageHeader::id_contentLength) ? hdr.Get_contentLength().Get_len().GetValue() : 0; \
2712                if (content_length == 0) { \
2713                        /* no message body */ \
2714                        if (hdr.IsPresent (MessageHeader::id_contentType)) \
2715                                throw DecodeError (this, "the Content-Type field must not be present if the content length is null\n"); \
2716 \
2717                        SetHypFieldIsPresent (id_messageBody, 0); \
2718                } else if (content_length > 0) { \
2719                        /* message body present */ \
2720                        if (!hdr.IsPresent (MessageHeader::id_contentType)) \
2721                                throw DecodeError (this, "the Content-Type field must be present if the content length is not null\n"); \
2722 \
2723                        SetHypFieldIsPresent (id_messageBody, 1); \
2724                        MessageBody::SetHypLength (content_length * 8); \
2725                        const char* content_type = hdr.Get_contentType().Get_mediaType().GetValue(); \
2726                        if (strcmp (content_type, "application/sdp") == 0) { \
2727                                MessageBody::SetHypChosenId (MessageBody::id_sdpMessageBody); \
2728                        } else { \
2729                                /* decode as plain text by default */ \
2730                                MessageBody::SetHypChosenId (MessageBody::id_textplain); \
2731                        } \
2732                } else { \
2733                        throw DecodeError (this, "Content-Length must not be a negative number\n"); \
2734                } \
2735                SetHypFieldIsPresent (id_payload, 0); \
2736                break; \
2737          } \
2738        case id_payload: \
2739                if (buffer.GetBitsLeft()) { \
2740                        DecodeError ex(this); \
2741                        ex.Msg() << "buffer not fully decoded (" << buffer.GetBitsLeft()/8 << " remaining bytes)" << std::endl; \
2742                        throw ex; \
2743                } \
2744                Get_payload().Get_payloadlength().SetValue(buffer.GetLength() / 8); \
2745                Get_payload().Get_payloadvalue().SetValueBin(buffer.GetValueBin(), buffer.GetLength()); \
2746 \
2747                /* replace undisplayable characters with '?' */ \
2748                Charstring& payload = Get_payload().Get_payloadvalue(); \
2749                int byte_length = buffer.GetLength() / 8; \
2750                for (int  i=0 ; i<byte_length ; i++) { \
2751                        if (!asciichar_is_displayable (payload[i])) \
2752                                payload[i] = '?'; \
2753                } \
2754                break; \
2755        } \
2756}
2757
2758#define SIP_MESSAGE_CODET_ERROR(msgname) \
2759void msgname::PostDecode (Buffer& buffer, DecodeError& e) throw (DecodeError) \
2760{ \
2761        std::cerr << "###################################################################################" << std::endl; \
2762        std::cerr << "###  INVALID SIP MESSAGE RECEIVED                                               ###" << std::endl; \
2763        std::cerr << "###                                                                             ###" << std::endl; \
2764        e.Dump(std::cerr); \
2765        std::cerr << "###-----------------------------------------------------------------------------###" << std::endl; \
2766        std::cerr.write (reinterpret_cast<const char*>(buffer.GetValueBin()), buffer.GetLength()/8); \
2767        std::cerr << "###################################################################################" << std::endl; \
2768        /* tell t3devkit to ignore silently the message */ \
2769        throw DecodeIgnoreMessage(e.mVar); \
2770}
2771
2772SIP_MESSAGE_CODET (Response)
2773SIP_MESSAGE_CODET_ERROR (Response)
2774SIP_MESSAGE_CODET (Request)
2775SIP_MESSAGE_CODET_ERROR (Request)
2776SIP_MESSAGE_CODET (REGISTER_Request)
2777SIP_MESSAGE_CODET_ERROR (REGISTER_Request)
2778SIP_MESSAGE_CODET (INVITE_Request)
2779SIP_MESSAGE_CODET_ERROR (INVITE_Request)
2780SIP_MESSAGE_CODET (OPTIONS_Request)
2781SIP_MESSAGE_CODET_ERROR (OPTIONS_Request)
2782SIP_MESSAGE_CODET (BYE_Request)
2783SIP_MESSAGE_CODET_ERROR (BYE_Request)
2784SIP_MESSAGE_CODET (CANCEL_Request)
2785SIP_MESSAGE_CODET_ERROR (CANCEL_Request)
2786SIP_MESSAGE_CODET (ACK_Request)
2787SIP_MESSAGE_CODET_ERROR (ACK_Request)
2788SIP_MESSAGE_CODET (PRACK_Request)
2789SIP_MESSAGE_CODET_ERROR (PRACK_Request)
2790SIP_MESSAGE_CODET (NOTIFY_Request)
2791SIP_MESSAGE_CODET_ERROR (NOTIFY_Request)
2792SIP_MESSAGE_CODET (SUBSCRIBE_Request)
2793SIP_MESSAGE_CODET_ERROR (SUBSCRIBE_Request)
2794SIP_MESSAGE_CODET (PUBLISH_Request)
2795SIP_MESSAGE_CODET_ERROR (PUBLISH_Request)
2796SIP_MESSAGE_CODET (UPDATE_Request)
2797SIP_MESSAGE_CODET_ERROR (UPDATE_Request)
2798SIP_MESSAGE_CODET (REFER_Request)
2799SIP_MESSAGE_CODET_ERROR (REFER_Request)
2800SIP_MESSAGE_CODET (MESSAGE_Request)
2801SIP_MESSAGE_CODET_ERROR (MESSAGE_Request)
2802SIP_MESSAGE_CODET (INFO_Request)
2803SIP_MESSAGE_CODET_ERROR (INFO_Request)
2804
2805void OptionTag_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2806{
2807        Charstring csComma;
2808        csComma.SetValue(",");
2809
2810        if(field_id != 0) {
2811                csComma.Encode(buffer);
2812        }
2813}
2814
2815void OptionTag_List::PreDecode (Buffer& buffer) throw (DecodeError)
2816{
2817        SetHypSize (GetSize() + 1);
2818        SetHypAppend (1);
2819}
2820
2821void OptionTag_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2822{
2823        static Regex reg_content ("^" SIPREG_TOKEN);
2824       
2825        bool bMandatory = true;
2826        Variable* parent = GetParent();
2827        if (parent != NULL) {
2828                const char * pszParName = parent->GetTypeName();
2829                if (strcmp(pszParName, "Supported") == 0)
2830                        bMandatory = false;
2831        }
2832
2833        if (bMandatory || GetSize() == 0)
2834                reg_content.AssertMatch(buffer, this);
2835        else if (!reg_content.Match (buffer)) {
2836                SetHypSize (-2);
2837                return;
2838        }
2839        SetHypFieldLength(reg_content.GetMatchedLength());     
2840}
2841
2842void OptionTag_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2843{
2844        static Regex reg_content ("^" SIPREG_TOKEN);
2845        if (detect_comma (buffer) && reg_content.Match (buffer))
2846                SetHypSize (GetSize() + 1);
2847        else
2848                SetHypSize (-2);
2849}
2850
2851void RouteBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2852{
2853        Charstring csComma;
2854        csComma.SetValue(",");
2855
2856        if(field_id != 0) {
2857                csComma.Encode(buffer);
2858        }
2859}
2860
2861void RouteBody_List::PreDecode (Buffer& buffer) throw (DecodeError)
2862{
2863        SetHypSize (GetSize() + 1);
2864        SetHypAppend (1);
2865}
2866
2867void RouteBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2868{
2869        if (detect_comma (buffer))
2870                SetHypSize (GetSize() + 1);
2871        else
2872                SetHypSize (-2);
2873}
2874
2875void RouteBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2876{
2877        Charstring csSemi;
2878        csSemi.SetValue(";");
2879
2880        if(field_id == id_rrParam && IsPresent(id_rrParam)) {
2881                csSemi.Encode(buffer);
2882        }
2883}
2884
2885void RouteBody::PreDecodeField(int id, Buffer& buffer) throw (DecodeError)
2886{
2887        static Regex reg_semi ("^;");
2888
2889        if (id == id_rrParam) {
2890                SetHypFieldIsPresent (id, reg_semi.Match(buffer) ? 1 : 0);
2891        }
2892}
2893
2894void Timestamp::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2895{
2896        Charstring csWS;
2897        csWS.SetValue(" ");
2898       
2899        switch(field_id) {
2900        case id_delay:
2901                if(IsPresent(id_delay)) {
2902                        csWS.Encode(buffer);
2903                }
2904                break;
2905        default:
2906                break;
2907        }
2908}
2909
2910void Timestamp::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2911{
2912        static Regex reg_separator ("^" SIPREG_LWS);
2913
2914        switch (id) {
2915        case id_timeValue:
2916                SetHypFieldIsPresent (id, 1); //always present (mandatory in BNF)
2917                break;
2918        case id_delay:
2919                if (reg_separator.Match (buffer)) {
2920                        reg_separator.MovePast (buffer);
2921                        SetHypFieldIsPresent (id, 1);
2922                } else
2923                        SetHypFieldIsPresent (id, 0);
2924                break;
2925        }
2926}
2927
2928void TimeValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2929{
2930        Charstring csDot;
2931        csDot.SetValue(".");
2932
2933        switch(field_id) {
2934        case id_majorDigit:
2935                Get_majorDigit().SetFormat(Integer::AsciiDecimal);
2936                break;
2937        case id_minorDigit:
2938                Get_minorDigit().SetFormat(Integer::AsciiDecimal);
2939                csDot.Encode(buffer);
2940                break;
2941        default:
2942                break;
2943        }
2944}
2945
2946void TimeValue::PreDecode (Buffer& buffer) throw (DecodeError)
2947{
2948        Get_majorDigit().SetFormat(Integer::AsciiDecimal);
2949        Get_minorDigit().SetFormat(Integer::AsciiDecimal);
2950}
2951
2952void TimeValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
2953{
2954        static Regex reg_separator ("^[.]");
2955        static Regex reg_digits ("^[0-9]+");
2956        switch (id) {
2957                case id_minorDigit:
2958                        SetHypFieldIsPresent (id,  0);
2959                        if (reg_separator.Match (buffer)) {
2960                                reg_separator.MovePast( buffer);
2961                                if (reg_digits.Match (buffer))
2962                                        SetHypFieldIsPresent(id, 1);
2963                        }                       
2964                        break;
2965        }
2966}
2967
2968void WarningValue_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2969{
2970        Charstring csComma;
2971        csComma.SetValue(",");
2972
2973        if(field_id != 0) {
2974                csComma.Encode(buffer);
2975        }
2976}
2977
2978void WarningValue_List::PreDecode (Buffer& buffer) throw (DecodeError)
2979{
2980        SetHypSize (GetSize() + 1);
2981        SetHypAppend (1);
2982}
2983
2984void WarningValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
2985{
2986        if (detect_comma (buffer))
2987                SetHypSize (GetSize() + 1);
2988        else
2989                SetHypSize (-2);
2990}
2991
2992void WarningValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
2993{
2994        Charstring csWS, csDoubleQuote;
2995        csWS.SetValue(" ");
2996        csDoubleQuote.SetValue("\"");
2997
2998        switch(field_id) {
2999        case id_warnCode:
3000                Get_warnCode().SetFormat(Integer::AsciiDecimal);
3001                break;
3002        case id_warnText:
3003                csWS.Encode(buffer);
3004                csDoubleQuote.Encode(buffer);
3005                break;
3006        case id_warnAgent:
3007                csWS.Encode(buffer);
3008                break;
3009        }
3010}
3011
3012void WarningValue::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3013{
3014        Charstring csDoubleQuote;
3015        csDoubleQuote.SetValue("\"");
3016
3017        if(field_id == id_warnText) {
3018                csDoubleQuote.Encode(buffer);
3019        }
3020}
3021
3022void WarningValue::PreDecode (Buffer& buffer) throw (DecodeError)
3023{
3024        Get_warnCode().SetFormat(Integer::AsciiDecimal);
3025}
3026
3027void WarningValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3028{
3029        static Regex reg_separator ("^[ ]");
3030        static Regex reg_text ("^" SIPREG_QUOTED_STRING);
3031        switch (id) {
3032                case id_warnAgent:
3033                        reg_separator.AssertMatch (buffer, this);
3034                        reg_separator.MovePast (buffer);
3035                        break;
3036                case id_warnText:
3037                        reg_separator.AssertMatch (buffer, this);
3038                        reg_separator.MovePast (buffer);
3039                        reg_text.AssertMatch (buffer, this);
3040                        buffer.SetPosition(buffer.GetPosition() + 8); // remove starting quota
3041                        SetHypFieldLength (id, reg_text.GetMatchedLength() - 16);
3042                        break;
3043        }
3044}
3045
3046void WarningValue::PostDecode (Buffer& buffer) throw (DecodeError)
3047{
3048        buffer.SetPosition(buffer.GetPosition() + 8); // remove ending quota
3049
3050        normalise_quoted_string (Get_warnText());
3051}
3052
3053void WarnAgent::PreDecode (Buffer& buffer) throw (DecodeError)
3054{
3055        static Regex reg_host ("^" SIPREG_HOST "([:][0-9]+)?");
3056        static Regex reg_pseudonym ("^" SIPREG_TOKEN);
3057        int nLen1 = -1;
3058        int nLen2 = -1;
3059        if (reg_host.Match (buffer))
3060                nLen1 = reg_host.GetMatchedLength();
3061        if (reg_pseudonym.Match (buffer))
3062                nLen2 = reg_pseudonym.GetMatchedLength();
3063        if (nLen2 > nLen1) {
3064                SetHypChosenId (id_pseudonym);
3065                SetHypFieldLength (id_pseudonym, nLen2);
3066        } else
3067                SetHypChosenId (id_hostPort);
3068}
3069
3070void RSeq::PreEncode (Buffer& buffer) throw (EncodeError)
3071{
3072        Get_responseNum().SetFormat(Integer::AsciiDecimal);
3073}
3074
3075void RSeq::PreDecode (Buffer& buffer) throw (DecodeError)
3076{
3077        Get_responseNum().SetFormat(Integer::AsciiDecimal);
3078}
3079
3080void RAck::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3081{
3082        Charstring csWS;
3083        csWS.SetValue(" ");
3084
3085
3086        switch(field_id) {
3087        case id_responseNum:
3088                Get_responseNum().SetFormat(Integer::AsciiDecimal);
3089                break;
3090        case id_seqNumber:
3091                Get_seqNumber().SetFormat(Integer::AsciiDecimal);
3092        case id_method:
3093                csWS.Encode(buffer);
3094                break;
3095        default:
3096                break;
3097        }
3098}
3099
3100void RAck::PreDecode (Buffer& buffer) throw (DecodeError)
3101{
3102        Get_responseNum().SetFormat(Integer::AsciiDecimal);
3103        Get_seqNumber().SetFormat(Integer::AsciiDecimal);
3104}
3105
3106void RAck::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3107{
3108        static Regex reg_separator ("^[ ]");
3109        static Regex reg_method ("^" SIPREG_TOKEN);
3110        switch (id) {
3111                case id_seqNumber:
3112                        reg_separator.AssertMatch (buffer, this);
3113                        reg_separator.MovePast (buffer);
3114                        break;
3115                case id_method:
3116                        reg_separator.AssertMatch (buffer, this);
3117                        reg_separator.MovePast (buffer);
3118                        reg_method.AssertMatch (buffer, this);
3119                        SetHypFieldLength (id, reg_method.GetMatchedLength());
3120                        break;
3121        }
3122}
3123
3124void EventType_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3125{
3126        Charstring csComma;
3127        csComma.SetValue(",");
3128
3129        if(field_id != 0) {
3130                csComma.Encode(buffer);
3131        }
3132}
3133
3134void EventType_List::PreDecode (Buffer& buffer) throw (DecodeError)
3135{
3136        SetHypSize (GetSize() + 1);
3137        SetHypAppend (1);
3138}
3139
3140void EventType_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3141{
3142        static Regex reg_event ("^" SIPREG_TOKEN);
3143        reg_event.AssertMatch (buffer, this);
3144        SetHypFieldLength (reg_event.GetMatchedLength());
3145}
3146
3147void EventType_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3148{
3149        if (detect_comma (buffer))
3150                SetHypSize (GetSize() + 1);
3151        else
3152                SetHypSize (-2);
3153}
3154
3155void Event::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3156{
3157        Charstring csSemi;
3158        csSemi.SetValue(";");
3159
3160        if(field_id == id_eventParams && IsPresent(id_eventParams)) {
3161                csSemi.Encode(buffer);
3162        }
3163}
3164
3165void Event::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3166{
3167        static Regex reg_event ("^" SIPREG_TOKEN);
3168        static Regex reg_separator ("^" SIPREG_SEMI);
3169
3170        switch (id) {
3171                case id_eventType:
3172                        reg_event.AssertMatch (buffer, this);
3173                        SetHypFieldLength (id, reg_event.GetMatchedLength());
3174                        break;
3175                case id_eventParams:
3176                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3177                        break;
3178        }
3179}
3180
3181void SubscriptionState::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3182{
3183        Charstring csSemi;
3184        csSemi.SetValue(";");
3185
3186        if(field_id == id_substateParams && IsPresent(id_substateParams)) {
3187                csSemi.Encode(buffer);
3188        }
3189}
3190
3191void SubscriptionState::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3192{
3193        static Regex reg_substate ("^" SIPREG_TOKEN);
3194        static Regex reg_separator ("^" SIPREG_SEMI);
3195
3196        switch (id) {
3197                case id_subState:
3198                        reg_substate.AssertMatch (buffer, this);
3199                        SetHypFieldLength (id, reg_substate.GetMatchedLength());
3200                        break;
3201                case id_substateParams:
3202                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3203                        break;
3204        }
3205}
3206
3207void PMediaAuthorization_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3208{
3209        Charstring csComma;
3210        csComma.SetValue(",");
3211
3212        if(field_id != 0) {
3213                csComma.Encode(buffer);
3214        }
3215}
3216
3217void PMediaAuthorization_List::PreDecode (Buffer& buffer) throw (DecodeError)
3218{
3219        SetHypSize (GetSize() + 1);
3220        SetHypAppend (1);
3221}
3222
3223void PMediaAuthorization_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3224{
3225        static Regex reg_media_authorization ("^[" SIPCHARS_HEXA "]+");
3226        reg_media_authorization.AssertMatch (buffer, this);
3227        SetHypFieldLength (reg_media_authorization.GetMatchedLength());
3228}
3229
3230void PMediaAuthorization_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3231{
3232        if (detect_comma (buffer))
3233                SetHypSize (GetSize() + 1);
3234        else
3235                SetHypSize (-2);
3236}
3237
3238void PrivacyValue_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3239{
3240        Charstring csSemi;
3241        csSemi.SetValue(";");
3242
3243        if(field_id != 0) {
3244                csSemi.Encode(buffer);
3245        }
3246}
3247
3248void PrivacyValue_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3249{
3250        static Regex reg_privacy ("^" SIPREG_TOKEN);
3251        reg_privacy.AssertMatch (buffer, this);
3252        SetHypFieldLength (reg_privacy.GetMatchedLength());
3253}
3254
3255void PrivacyValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3256{
3257        if (detect_semi (buffer))
3258                SetHypSize (GetSize() + 1);
3259        else
3260                SetHypSize (-2);
3261}
3262
3263void PAssertedIDValue_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3264{
3265        Charstring csComma;
3266        csComma.SetValue(",");
3267
3268        if(field_id != 0) {
3269                csComma.Encode(buffer);
3270        }
3271}
3272
3273void PAssertedIDValue_List::PreDecode (Buffer& buffer) throw (DecodeError)
3274{
3275        SetHypSize (GetSize() + 1);
3276        SetHypAppend (1);
3277}
3278
3279void PAssertedIDValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3280{
3281        if (detect_comma (buffer))
3282                SetHypSize (GetSize() + 1);
3283        else
3284                SetHypSize (-2);
3285}
3286
3287void PPreferredIDValue_List::PreDecode (Buffer& buffer) throw (DecodeError)
3288{
3289        SetHypSize (GetSize() + 1);
3290        SetHypAppend (1);
3291}
3292
3293void PPreferredIDValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3294{
3295        if (detect_comma (buffer))
3296                SetHypSize (GetSize() + 1);
3297        else
3298                SetHypSize (-2);
3299}
3300
3301void ReasonValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3302{
3303        Charstring csSemi;
3304        csSemi.SetValue(";");
3305
3306        if(field_id == id_reasonParams && IsPresent(id_reasonParams)) {
3307                csSemi.Encode(buffer);
3308        }
3309}
3310
3311void ReasonValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3312{
3313        static Regex reg_token ("^" SIPREG_TOKEN);
3314        static Regex reg_separator ("^" SIPREG_SEMI);
3315
3316        switch (id) {
3317                case id_token:
3318                        reg_token.AssertMatch (buffer, this);
3319                        SetHypFieldLength (id, reg_token.GetMatchedLength());
3320                        break;
3321                case id_reasonParams:
3322                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3323                        break;
3324        }
3325}
3326
3327void ReasonValues::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3328{
3329        Charstring csComma;
3330        csComma.SetValue(",");
3331
3332        if(field_id != 0) {
3333                csComma.Encode(buffer);
3334        }
3335}
3336
3337void PathValues::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3338{
3339        Charstring csComma;
3340        csComma.SetValue(",");
3341
3342        if(field_id != 0) {
3343                csComma.Encode(buffer);
3344        }
3345}
3346
3347void ReasonValues::PreDecode (Buffer& buffer) throw (DecodeError)
3348{
3349        SetHypSize (GetSize() + 1);
3350        SetHypAppend (1);
3351}
3352
3353void ReasonValues::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3354{
3355        if (detect_comma (buffer))
3356                SetHypSize (GetSize() + 1);
3357        else
3358                SetHypSize (-2);
3359}
3360
3361void PathValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3362{
3363        Charstring csSemi;
3364        csSemi.SetValue(";");
3365
3366        if(field_id == id_rrParam && IsPresent(id_rrParam)) {
3367                csSemi.Encode(buffer);
3368        }
3369}
3370
3371void PathValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3372{
3373        static Regex reg_separator ("^" SIPREG_SEMI);
3374
3375        switch (id) {
3376                case id_rrParam:
3377                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3378                        break;
3379        }
3380}
3381
3382void PathValues::PreDecode (Buffer& buffer) throw (DecodeError)
3383{
3384        SetHypSize (GetSize() + 1);
3385        SetHypAppend (1);
3386}
3387
3388void PathValues::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3389{
3390        if (detect_comma (buffer))
3391                SetHypSize (GetSize() + 1);
3392        else
3393                SetHypSize (-2);
3394}
3395
3396void SecurityMechanism::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3397{
3398        Charstring csSemi;
3399        csSemi.SetValue(";");
3400
3401        if(field_id == id_mechParams && IsPresent(id_mechParams)) {
3402                csSemi.Encode(buffer);
3403        }
3404}
3405
3406void SecurityMechanism::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3407{
3408        static Regex reg_token ("^" SIPREG_TOKEN);
3409        static Regex reg_separator ("^" SIPREG_SEMI);
3410
3411        switch (id) {
3412                case id_mechName:
3413                        reg_token.AssertMatch (buffer, this);
3414                        SetHypFieldLength (id, reg_token.GetMatchedLength());
3415                        break;
3416                case id_mechParams:
3417                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3418                        break;
3419        }
3420}
3421
3422void SecurityMechanism_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3423{
3424        Charstring csComma;
3425        csComma.SetValue(",");
3426
3427        if(field_id != 0) {
3428                csComma.Encode(buffer);
3429        }
3430}
3431
3432void SecurityMechanism_List::PreDecode (Buffer& buffer) throw (DecodeError)
3433{
3434        SetHypSize (GetSize() + 1);
3435        SetHypAppend (1);
3436}
3437
3438void SecurityMechanism_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3439{
3440        if (detect_comma (buffer))
3441                SetHypSize (GetSize() + 1);
3442        else
3443                SetHypSize (-2);
3444}
3445
3446void NameAddrParam::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3447{
3448        Charstring csSemi;
3449        csSemi.SetValue(";");
3450
3451        if(field_id == id_genericParams && IsPresent(id_genericParams)) {
3452                csSemi.Encode(buffer);
3453        }
3454}
3455
3456void NameAddrParam::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3457{
3458        static Regex reg_separator ("^" SIPREG_SEMI);
3459
3460        switch (id) {
3461                case id_genericParams:
3462                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3463                        break;
3464        }
3465}
3466
3467void NameAddrParam_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3468{
3469        Charstring csComma;
3470        csComma.SetValue(",");
3471
3472        if(field_id != 0) {
3473                csComma.Encode(buffer);
3474        }
3475}
3476
3477void NameAddrParam_List::PreDecode (Buffer& buffer) throw (DecodeError)
3478{
3479        SetHypSize (GetSize() + 1);
3480        SetHypAppend (1);
3481}
3482
3483void NameAddrParam_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3484{
3485        if (detect_comma (buffer))
3486                SetHypSize (GetSize() + 1);
3487        else
3488                SetHypSize (-2);
3489}
3490
3491void VnetworkSpec::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3492{
3493        Charstring csSemi;
3494        csSemi.SetValue(";");
3495
3496        if(field_id == id_genericParams && IsPresent(id_genericParams)) {
3497                csSemi.Encode(buffer);
3498        }
3499}
3500
3501void VnetworkSpec::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3502{
3503        static Regex reg_token ("^(" SIPREG_TOKEN ")|(" SIPREG_QUOTED_STRING ")");
3504        static Regex reg_separator ("^" SIPREG_SEMI);
3505
3506        switch (id) {
3507                case id_vNetworkSpecToken:
3508                        reg_token.AssertMatch (buffer, this);
3509                        SetHypFieldLength (id, reg_token.GetMatchedLength());
3510                        break;
3511                case id_genericParams:
3512                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3513                        break;
3514        }
3515}
3516
3517void VnetworkSpec_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3518{
3519        Charstring csComma;
3520        csComma.SetValue(",");
3521
3522        if(field_id != 0) {
3523                csComma.Encode(buffer);
3524        }
3525}
3526
3527void VnetworkSpec_List::PreDecode (Buffer& buffer) throw (DecodeError)
3528{
3529        SetHypSize (GetSize() + 1);
3530        SetHypAppend (1);
3531}
3532
3533void VnetworkSpec_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3534{
3535        if (detect_comma (buffer))
3536                SetHypSize (GetSize() + 1);
3537        else
3538                SetHypSize (-2);
3539}
3540
3541void PAccessNetworkInfo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3542{
3543        Charstring csSemi;
3544        csSemi.SetValue(";");
3545
3546        if(field_id == id_genericParams && IsPresent(id_genericParams)) {
3547                csSemi.Encode(buffer);
3548        }
3549}
3550
3551void PAccessNetworkInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3552{
3553        static Regex reg_token ("^" SIPREG_TOKEN);
3554        static Regex reg_separator ("^" SIPREG_SEMI);
3555
3556        switch (id) {
3557                case id_accessType:
3558                        reg_token.AssertMatch (buffer, this);
3559                        SetHypFieldLength (id, reg_token.GetMatchedLength());
3560                        break;
3561                case id_genericParams:
3562                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3563                        break;
3564        }
3565}
3566
3567void PChargingFunctionAddresses::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3568{
3569        static Regex reg_token ("^" SIPREG_TOKEN);
3570        switch (id) {
3571                case id_chargeAddrParams:
3572                        SetHypFieldIsPresent (id, reg_token.Match (buffer) ? 1 : 0);
3573                        break;
3574        }
3575}
3576
3577void PChargingVector::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3578{
3579        static Regex reg_token ("^" SIPREG_TOKEN);
3580        switch (id) {
3581                case id_chargeParams:
3582                        SetHypFieldIsPresent (id, reg_token.Match (buffer) ? 1 : 0);
3583                        break;
3584        }
3585}
3586
3587void ReferTo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3588{
3589        Charstring csSemi;
3590        csSemi.SetValue(";");
3591
3592        if(field_id == id_referToParams && IsPresent(id_referToParams)) {
3593                csSemi.Encode(buffer);
3594        }
3595}
3596
3597void ReferTo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3598{
3599        static Regex reg_separator ("^" SIPREG_SEMI);
3600
3601        switch (id) {
3602                case id_referToParams:
3603                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3604                        break;
3605        }
3606}
3607
3608void AcRcValue_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3609{
3610        Charstring csComma;
3611        csComma.SetValue(",");
3612
3613        if(field_id != 0) {
3614                csComma.Encode(buffer);
3615        }
3616}
3617
3618void AcRcValue_List::PreDecode (Buffer& buffer) throw (DecodeError)
3619{
3620        SetHypSize (GetSize() + 1);
3621        SetHypAppend (1);
3622}
3623
3624void AcRcValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3625{
3626        if (detect_comma (buffer))
3627                SetHypSize (GetSize() + 1);
3628        else
3629                SetHypSize (-2);
3630}
3631
3632void AcRcValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3633{
3634        Charstring csSemi;
3635        csSemi.SetValue(";");
3636
3637        if(field_id == id_acRcParams && IsPresent(id_acRcParams)) {
3638                csSemi.Encode(buffer);
3639        }
3640}
3641
3642void AcRcValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3643{
3644        static Regex reg_wildcard ("^[*]");
3645        static Regex reg_separator ("^" SIPREG_SEMI);
3646
3647        switch (id) {
3648                case id_wildcard:
3649                        reg_wildcard.AssertMatch (buffer, this);
3650                        SetHypFieldLength (id, reg_wildcard.GetMatchedLength());
3651                        break;
3652                case id_acRcParams:
3653                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3654                        break;
3655        }
3656}
3657
3658void Replaces::PreEncodeField   (int field_id, Buffer& buffer) throw (EncodeError)
3659{
3660        Charstring csSemi;
3661        csSemi.SetValue(";");
3662
3663        if(field_id     == id_fieldName &&      IsPresent(id_fieldName))        {
3664                csSemi.Encode(buffer);
3665        }
3666}
3667
3668void Replaces::PreDecodeField   (int id, Buffer& buffer) throw (DecodeError)
3669{
3670        static Regex reg_separator ("^" SIPREG_SEMI);
3671
3672        switch (id) {
3673                case id_fieldName:
3674                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3675                        break;
3676        }
3677}
3678
3679void ReferredBy::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3680{
3681        Charstring csSemi;
3682        csSemi.SetValue(";");
3683
3684        if(field_id     == id_referredbyIdParams &&     IsPresent(id_referredbyIdParams))       {
3685                csSemi.Encode(buffer);
3686        }
3687}
3688
3689void ReferredBy::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3690{
3691        static Regex reg_separator ("^" SIPREG_SEMI);
3692
3693        switch (id) {
3694                case id_referredbyIdParams:
3695                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3696                        break;
3697        }
3698}
3699
3700/* Nothing to do
3701void UserToUser::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3702{
3703}
3704
3705void UserToUser::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3706{
3707}*/
3708
3709void MinSE::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3710{
3711        Charstring csSemi;
3712        csSemi.SetValue(";");
3713
3714        if(field_id == id_minSeParam && IsPresent(id_minSeParam)) {
3715                csSemi.Encode(buffer);
3716        }
3717}
3718
3719
3720void MinSE::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3721{
3722        static Regex reg_delta_sec ("^[0-9]+");
3723        static Regex reg_separator ("^" SIPREG_SEMI);
3724
3725        switch (id) {
3726                case id_deltaSec:
3727                        reg_delta_sec.AssertMatch (buffer, this);
3728                        SetHypFieldLength (id, reg_delta_sec.GetMatchedLength());
3729                        break;
3730                case id_minSeParam:
3731                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3732                        break;
3733        }
3734}
3735
3736void IntegerList::PreEncode (Buffer& buffer) throw (EncodeError)
3737{
3738        Charstring csIndexEqual;
3739        csIndexEqual.SetValue("index=");
3740
3741        csIndexEqual.Encode(buffer);
3742}
3743
3744void IntegerList::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3745{
3746        Charstring csDot;
3747        csDot.SetValue(".");
3748
3749        if(field_id != 0) {
3750                csDot.Encode(buffer);
3751        }
3752        GetField(field_id).SetFormat(Integer::AsciiDecimal);
3753}
3754
3755void IntegerList::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3756{
3757        SetSize (GetSize() + 1);
3758        GetField(id).SetFormat(Integer::AsciiDecimal);
3759}
3760
3761void IntegerList::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3762{
3763        Regex reg_dot ("^[\\x2E]");
3764
3765        if (detect_separator(reg_dot, buffer))
3766                SetHypSize (GetSize() + 1);
3767        else
3768                SetHypSize (-2);
3769}
3770
3771void HistoryInfoEntry::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3772{
3773        Charstring csSemi;
3774        csSemi.SetValue(";");
3775
3776        if(field_id == id_hiIndex && IsPresent(id_hiIndex)) {
3777                csSemi.Encode(buffer);
3778        }
3779
3780        if(field_id == id_hiExtention && IsPresent(id_hiExtention)) {
3781                csSemi.Encode(buffer);
3782        }
3783}
3784
3785void HistoryInfoEntry::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3786{
3787        static Regex reg_index ("^" SIPREG_SEMI "[Ii][Nn][Dd][Ee][Xx][=]");
3788        static Regex reg_separator ("^" SIPREG_SEMI);
3789
3790        switch (id) {
3791                case id_hiIndex:
3792                        if (reg_index.Match (buffer)) {                         
3793                                reg_index.MovePast (buffer);
3794                                SetHypFieldIsPresent (id, 1);
3795                        } else
3796                                SetHypFieldIsPresent (id, 0);
3797                        break;
3798                case id_hiExtention:
3799                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3800                        break;
3801        }
3802}
3803
3804void HistoryInfo_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3805{
3806        Charstring csComma;
3807        csComma.SetValue(",");
3808
3809        if(field_id != 0) {
3810                csComma.Encode(buffer);
3811        }
3812}
3813
3814void HistoryInfo_List::PreDecode (Buffer& buffer) throw (DecodeError)
3815{
3816        SetHypSize (GetSize() + 1);
3817        SetHypAppend (1);
3818}
3819
3820void HistoryInfo_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
3821{
3822        if (detect_comma (buffer))
3823                SetHypSize (GetSize() + 1);
3824        else
3825                SetHypSize (-2);
3826}
3827
3828void EM_List::PreEncodeField    (int field_id, Buffer& buffer) throw (EncodeError)
3829{
3830        Charstring csComma;
3831        csComma.SetValue(",");
3832
3833        if(field_id != 0) {
3834                csComma.Encode(buffer);
3835        }
3836}
3837
3838void EM_List::PreDecodeField    (int id, Buffer& buffer) throw (DecodeError) {
3839        static Regex reg_token ("^" SIPREG_TOKEN);
3840        if (GetSize() == 0)
3841                reg_token.AssertMatch(buffer, this);
3842        else if (!reg_token.Match(buffer)) {
3843                SetHypSize(-2);
3844                return;
3845        }
3846        SetHypFieldLength(reg_token.GetMatchedLength());
3847}
3848
3849void EM_List::PreDecode (Buffer&        buffer) throw   (DecodeError)
3850{
3851        SetHypSize (GetSize() + 1);
3852        SetHypAppend (1);
3853}
3854
3855void EM_List::PostDecodeField (int      id,     Buffer& buffer) throw   (DecodeError)
3856{
3857        if (detect_comma (buffer))
3858                SetHypSize (GetSize() + 1);
3859        else
3860                SetHypSize (-2);
3861}
3862
3863void PEarlyMedia::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3864{
3865        static Regex reg_token ("^" SIPREG_TOKEN);
3866
3867        switch (id) {
3868                case id_em_param:
3869                        if (reg_token.Match (buffer) || Get_em_param().GetSize() > 0) {                         
3870                                SetHypFieldIsPresent (id, 1);
3871                        } else
3872                                SetHypFieldIsPresent (id, 0);
3873                        break;
3874        }
3875}
3876
3877/* UserToUser: Nothing to do
3878void UserToUser::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
3879{
3880
3881}
3882
3883void UserToUser::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3884{
3885
3886}*/
3887
3888void PAssertedService::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3889{
3890        static Regex reg_token ("^" SIPREG_TOKEN);
3891
3892        switch (id) {
3893                case id_pAssertedServiceValue:
3894                        reg_token.AssertMatch (buffer, this);
3895                        SetHypFieldLength(id, reg_token.GetMatchedLength());
3896                        break;
3897        }
3898}
3899
3900
3901void MessageBody::PreEncode     (Buffer& buffer) throw (EncodeError)
3902{
3903  switch (GetChosenId())
3904  {
3905    case id_xmlBody:
3906    case id_xmlMessage:
3907    case id_mimeMessageBody:
3908      {
3909        std::string message ("unsupported field '");
3910        message += GetChosenFieldName();
3911        message += '\n';
3912        throw EncodeError (this, message);
3913      }
3914      break;
3915  }
3916}
3917
3918
3919void SessionExpires::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
3920{
3921        static Regex reg_delta_sec ("^[0-9]+");
3922        static Regex reg_separator ("^" SIPREG_SEMI);
3923
3924        switch (id) {
3925                case id_deltaSec:
3926                        reg_delta_sec.AssertMatch (buffer, this);
3927                        SetHypFieldLength (id, reg_delta_sec.GetMatchedLength());
3928                        break;
3929                case id_seParam:
3930                        SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0);
3931                        break;
3932        }
3933}
3934
3935
3936}} // namespaces
Note: See TracBrowser for help on using the repository browser.