2008-05-14 Julien Chaffraix <jchaffraix@webkit.org>
[WebKit-https.git] / WebCore / xml / AccessItemRule.cpp
1 /*
2  * Copyright (C) 2008 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "AccessItemRule.h"
28
29 #include "PlatformString.h"
30 #include "ParserUtilities.h"
31 #include <stdio.h>
32
33 namespace WebCore {
34
35 AccessItemRule::AccessItemRule(const String& rule)
36 {
37     parseAccessItemRule(rule);
38 }
39
40 static inline bool skipLWS(const UChar*& ptr, const UChar* end)
41 {
42     // LWS as defined by RFC 2616:
43     // LWS = [CRLF] 1*( SP | HT )
44
45     if (ptr + 1 < end && *ptr == '\r' && *(ptr + 1) == '\n')
46         ptr += 2;
47
48     const UChar* start = ptr;
49     while (ptr < end && (*ptr == ' ' || *ptr == '\t'))
50         ptr++;
51     return ptr != start;
52 }
53
54 void AccessItemRule::parseAccessItemRule(const String& rule)
55 {
56     // Parse the rule according to Section 4.2 (Access-Control HTTP Response Header) of the 
57     // Access Control for Cross-site Requests spec.
58     // W3C Working Draft 14 February 2008
59
60     //   Access-Control = "Access-Control" ":" 1#rule
61     //   rule           = "allow" 1*(LWS pattern) [LWS "exclude" 1*(LWS pattern)]
62     //   pattern        = "<" access item ">"
63
64     if (rule.isEmpty())
65         return;
66
67     const UChar* ptr = rule.characters();
68     const UChar* end = ptr + rule.length();
69
70     // Skip leading whitespace
71     skipLWS(ptr, end);
72     if (ptr == end)
73         return;
74
75     if (!skipString(ptr, end, "allow"))
76         return;
77
78     parsePatternList(ptr, end, m_allowList);
79     if (m_allowList.isEmpty())
80         return;
81
82     if (!skipString(ptr, end, "exclude")) {
83         if (ptr != end)
84             invalidate();
85         return;
86     }
87
88     parsePatternList(ptr, end, m_excludeList);
89     if (m_excludeList.isEmpty()) {
90         invalidate();
91         return;
92     }
93
94     if (ptr != end)
95         invalidate();
96 }
97
98 void AccessItemRule::parsePatternList(const UChar*& ptr, const UChar* end, Vector<AccessItem>& list)
99 {
100     while (ptr < end) {
101         if (!skipLWS(ptr, end) || ptr == end) {
102             invalidate();
103             return;
104         }
105
106         if (*ptr != '<')
107             return;
108
109         ptr++;
110
111         bool sawEndTag = false;
112         const UChar* start = ptr;
113         while (ptr < end) {
114             if (*ptr == '>') {
115                 sawEndTag = true;
116                 break;
117             }
118             ptr++;
119         }
120         if (!sawEndTag) {
121             invalidate();
122             return;
123         }
124         
125         AccessItem accessItem(String(start, ptr - start));
126         if (!accessItem.isValid()) {
127             invalidate();
128             return;
129         }
130
131         list.append(accessItem);
132         ptr++;
133     }
134 }
135
136 void AccessItemRule::invalidate()
137 {
138     m_allowList.clear();
139     m_excludeList.clear();
140 }
141
142 #ifndef NDEBUG
143 void AccessItemRule::show()
144 {
145     printf("  AccessItemRule::show\n");
146
147     printf("  AllowList count: %d\n", static_cast<int>(m_allowList.size()));
148     for (size_t i = 0; i < m_allowList.size(); ++i)
149         m_allowList[i].show();
150
151     printf("  ExludeList count: %d\n", static_cast<int>(m_excludeList.size()));
152     for (size_t i = 0; i < m_excludeList.size(); ++i)
153         m_excludeList[i].show();
154 }
155 #endif
156
157 } // namespace WebCore