summaryrefslogtreecommitdiffstats
path: root/java/gov/nist/javax/sip/parser/UserAgentParser.java
blob: e96ff93c6175b14c3bd1796539586c7f5ddfaa17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain.  As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
package gov.nist.javax.sip.parser;

import gov.nist.core.Token;
import gov.nist.javax.sip.header.*;
import java.text.ParseException;

/**
 * Parser for UserAgent header.
 *
 * @version 1.2 $Revision: 1.15 $ $Date: 2009/07/17 18:58:07 $
 *
 * @author Olivier Deruelle  <br/>
 * @author M. Ranganathan  <br/>
 *
 *
 */
public class UserAgentParser extends HeaderParser {

    /**
     * Constructor
     *
     * @param userAgent -
     *            UserAgent header to parse
     */
    public UserAgentParser(String userAgent) {
        super(userAgent);
    }

    /**
     * Constructor
     *
     * @param lexer -
     *            the lexer to use.
     */
    protected UserAgentParser(Lexer lexer) {
        super(lexer);
    }

    /**
     * parse the message. Note that we have losened up on the parsing quite a bit because
     * user agents tend to be very bad about specifying the user agent according to RFC.
     *
     * @return SIPHeader (UserAgent object)
     * @throws SIPParseException
     *             if the message does not respect the spec.
     */
    public SIPHeader parse() throws ParseException {
        if (debug)
            dbg_enter("UserAgentParser.parse");
        UserAgent userAgent = new UserAgent();
        try {
            headerName(TokenTypes.USER_AGENT);
            if (this.lexer.lookAhead(0) == '\n')
                throw createParseException("empty header");

            /*
             * BNF User-Agent = "User-Agent" HCOLON server-val *(LWS server-val)
             * server-val = product / comment product = token [SLASH
             * product-version] product-version = token
             */
            while (this.lexer.lookAhead(0) != '\n'
                    && this.lexer.lookAhead(0) != '\0') {

                if (this.lexer.lookAhead(0) == '(') {
                    String comment = this.lexer.comment();
                    userAgent.addProductToken('(' + comment + ')');
                } else {
                    // product = token [SLASHproduct-version]
                    // product-version = token
                    // The RFC Does NOT allow this space but we are generous in what we accept

                    this.getLexer().SPorHT();


                    String product = this.lexer.byteStringNoSlash();
                    if ( product == null ) throw createParseException("Expected product string");

                    StringBuffer productSb = new StringBuffer(product);
                    // do we possibily have the optional product-version?
                    if (this.lexer.peekNextToken().getTokenType() == TokenTypes.SLASH) {
                        // yes
                        this.lexer.match(TokenTypes.SLASH);
                        // product-version
                        // The RFC Does NOT allow this space but we are generous in what we accept
                        this.getLexer().SPorHT();

                        String productVersion = this.lexer.byteStringNoSlash();

                        if ( productVersion == null ) throw createParseException("Expected product version");

                        productSb.append("/");

                        productSb.append(productVersion);
                    }

                    userAgent.addProductToken(productSb.toString());
                }
                // LWS
                this.lexer.SPorHT();
            }
        } finally {
            if (debug)
                dbg_leave("UserAgentParser.parse");
        }

        return userAgent;
    }


      public static void main(String args[]) throws ParseException { String
      userAgent[] = { "User-Agent: Softphone/Beta1.5 \n", "User-Agent:Nist/Beta1 (beta version) \n", "User-Agent: Nist UA (beta version)\n",
      "User-Agent: Nist1.0/Beta2 Ubi/vers.1.0 (very cool) \n" ,
      "User-Agent: SJphone/1.60.299a/L (SJ Labs)\n",
      "User-Agent: sipXecs/3.5.11 sipXecs/sipxbridge (Linux)\n"};

      for (int i = 0; i < userAgent.length; i++ ) { UserAgentParser parser =
      new UserAgentParser(userAgent[i]); UserAgent ua= (UserAgent)
      parser.parse(); System.out.println("encoded = " + ua.encode()); }
       }

}