Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / websockets / WebSocketExtensionParser.cpp
1 /*
2  * Copyright (C) 2012 Google Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #include "modules/websockets/WebSocketExtensionParser.h"
34
35 #include "wtf/ASCIICType.h"
36 #include "wtf/text/CString.h"
37
38 namespace blink {
39
40 WebSocketExtensionParser::ParserStateBackup::~ParserStateBackup()
41 {
42     if (!m_isDisposed) {
43         m_parser->m_current = m_current;
44     }
45 }
46
47 bool WebSocketExtensionParser::finished()
48 {
49     return m_current >= m_end;
50 }
51
52 bool WebSocketExtensionParser::parsedSuccessfully()
53 {
54     return m_current == m_end;
55 }
56
57 static bool isSeparator(char character)
58 {
59     static const char* separatorCharacters = "()<>@,;:\\\"/[]?={} \t";
60     const char* p = strchr(separatorCharacters, character);
61     return p && *p;
62 }
63
64 void WebSocketExtensionParser::skipSpaces()
65 {
66     while (m_current < m_end && (*m_current == ' ' || *m_current == '\t'))
67         ++m_current;
68 }
69
70 bool WebSocketExtensionParser::consumeToken()
71 {
72     ParserStateBackup backup(this);
73     skipSpaces();
74     const char* start = m_current;
75     while (m_current < m_end && isASCIIPrintable(*m_current) && !isSeparator(*m_current))
76         ++m_current;
77     if (start < m_current) {
78         m_currentToken = String(start, m_current - start);
79         backup.dispose();
80         return true;
81     }
82     return false;
83 }
84
85 bool WebSocketExtensionParser::consumeQuotedString()
86 {
87     ParserStateBackup backup(this);
88     skipSpaces();
89     if (m_current >= m_end || *m_current != '"')
90         return false;
91
92     Vector<char> buffer;
93     ++m_current;
94     while (m_current < m_end && *m_current != '"') {
95         if (*m_current == '\\' && ++m_current >= m_end)
96             return false;
97         // RFC6455 requires that the value after quoted-string unescaping
98         // MUST conform to the 'token' ABNF.
99         if (!isASCIIPrintable(*m_current) || isSeparator(*m_current))
100             return false;
101         buffer.append(*m_current);
102         ++m_current;
103     }
104     if (m_current >= m_end || *m_current != '"' || buffer.isEmpty())
105         return false;
106     m_currentToken = String::fromUTF8(buffer.data(), buffer.size());
107     ++m_current;
108     backup.dispose();
109     return true;
110 }
111
112 bool WebSocketExtensionParser::consumeQuotedStringOrToken()
113 {
114     // This is ok because consumeQuotedString() restores m_current
115     // on failure.
116     return consumeQuotedString() || consumeToken();
117 }
118
119 bool WebSocketExtensionParser::consumeCharacter(char character)
120 {
121     ParserStateBackup backup(this);
122     skipSpaces();
123     if (m_current < m_end && *m_current == character) {
124         ++m_current;
125         backup.dispose();
126         return true;
127     }
128     return false;
129 }
130
131 bool WebSocketExtensionParser::parseExtension(String& extensionToken, HashMap<String, String>& extensionParameters)
132 {
133     ParserStateBackup backup(this);
134     // Parse extension-token.
135     if (!consumeToken())
136         return false;
137
138     extensionToken = currentToken();
139
140     // Parse extension-parameters if exists.
141     while (consumeCharacter(';')) {
142         if (!consumeToken())
143             return false;
144
145         String parameterToken = currentToken();
146         if (consumeCharacter('=')) {
147             if (consumeQuotedStringOrToken())
148                 extensionParameters.add(parameterToken, currentToken());
149             else
150                 return false;
151         } else {
152             extensionParameters.add(parameterToken, String());
153         }
154     }
155     skipSpaces();
156     if (!finished() && !consumeCharacter(','))
157         return false;
158
159     backup.dispose();
160     return true;
161 }
162
163 } // namespace blink