1231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block/*
2dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *
4231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Redistribution and use in source and binary forms, with or without
5231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * modification, are permitted provided that the following conditions
6231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * are met:
7231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * 1. Redistributions of source code must retain the above copyright
8231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *    notice, this list of conditions and the following disclaimer.
9231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * 2. Redistributions in binary form must reproduce the above copyright
10231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *    notice, this list of conditions and the following disclaimer in the
11231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *    documentation and/or other materials provided with the distribution.
12231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *
13231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block */
25231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
26231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "config.h"
27231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "UserContentURLPattern.h"
28231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "KURL.h"
29231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/StdLibExtras.h>
30231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
31231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocknamespace WebCore {
32231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool UserContentURLPattern::matchesPatterns(const KURL& url, const Vector<String>* whitelist, const Vector<String>* blacklist)
34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
35231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // In order for a URL to be a match it has to be present in the whitelist and not present in the blacklist.
36231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // If there is no whitelist at all, then all URLs are assumed to be in the whitelist.
37231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool matchesWhitelist = !whitelist || whitelist->isEmpty();
38231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!matchesWhitelist) {
39231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        for (unsigned i = 0; i < whitelist->size(); ++i) {
40231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            UserContentURLPattern contentPattern(whitelist->at(i));
41231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (contentPattern.matches(url)) {
42231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                matchesWhitelist = true;
43231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
44231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            }
45231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
46231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
47231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
48231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool matchesBlacklist = false;
49231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (blacklist) {
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        for (unsigned i = 0; i < blacklist->size(); ++i) {
51231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            UserContentURLPattern contentPattern(blacklist->at(i));
52231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (contentPattern.matches(url)) {
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                matchesBlacklist = true;
54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            }
56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
57231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
58231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
59231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return matchesWhitelist && !matchesBlacklist;
60231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
61231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool UserContentURLPattern::parse(const String& pattern)
63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
64231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DEFINE_STATIC_LOCAL(const String, schemeSeparator, ("://"));
65231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
66f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    size_t schemeEndPos = pattern.find(schemeSeparator);
67f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (schemeEndPos == notFound)
68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
69231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_scheme = pattern.left(schemeEndPos);
71231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
72f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned hostStartPos = schemeEndPos + schemeSeparator.length();
73f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (hostStartPos >= pattern.length())
74231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
75231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
76231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    int pathStartPos = 0;
77231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (equalIgnoringCase(m_scheme, "file"))
79231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        pathStartPos = hostStartPos;
80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    else {
81f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        size_t hostEndPos = pattern.find("/", hostStartPos);
82f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (hostEndPos == notFound)
83231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
84dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
85231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_host = pattern.substring(hostStartPos, hostEndPos - hostStartPos);
86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_matchSubdomains = false;
87231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (m_host == "*") {
89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // The pattern can be just '*', which means match all domains.
90231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_host = "";
91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_matchSubdomains = true;
92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else if (m_host.startsWith("*.")) {
93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // The first component can be '*', which means to match all subdomains.
94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_host = m_host.substring(2); // Length of "*."
95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_matchSubdomains = true;
96231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // No other '*' can occur in the host.
99f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (m_host.find("*") != notFound)
100231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
101231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        pathStartPos = hostEndPos;
103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
104231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
105231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_path = pattern.right(pattern.length() - pathStartPos);
106231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
107231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return true;
108231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
109231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
110231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool UserContentURLPattern::matches(const KURL& test) const
111231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
112231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_invalid)
113231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
114231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!equalIgnoringCase(test.protocol(), m_scheme))
116231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!equalIgnoringCase(m_scheme, "file") && !matchesHost(test))
119231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
120231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return matchesPath(test);
122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool UserContentURLPattern::matchesHost(const KURL& test) const
125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    const String& host = test.host();
127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (equalIgnoringCase(host, m_host))
128231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
129231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
130231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_matchSubdomains)
131231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
132231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
133231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // If we're matching subdomains, and we have no host, that means the pattern
134231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // was <scheme>://*/<whatever>, so we match anything.
135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_host.length())
136231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
137231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Check if the domain is a subdomain of our host.
139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!host.endsWith(m_host, false))
140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return false;
141dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(host.length() > m_host.length());
143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Check that the character before the suffix is a period.
145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return host[host.length() - m_host.length() - 1] == '.';
146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
148231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstruct MatchTester
149231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
150231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    const String m_pattern;
151231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    unsigned m_patternIndex;
152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
153231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    const String m_test;
154231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    unsigned m_testIndex;
155231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
156231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MatchTester(const String& pattern, const String& test)
157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    : m_pattern(pattern)
158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_patternIndex(0)
159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_test(test)
160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_testIndex(0)
161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
162231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
163231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool testStringFinished() const { return m_testIndex >= m_test.length(); }
165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool patternStringFinished() const { return m_patternIndex >= m_pattern.length(); }
166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    void eatWildcard()
168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        while (!patternStringFinished()) {
170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (m_pattern[m_patternIndex] != '*')
171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return;
172231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_patternIndex++;
173231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
174231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
175231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
176231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    void eatSameChars()
177231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
178231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        while (!patternStringFinished() && !testStringFinished()) {
179231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (m_pattern[m_patternIndex] == '*')
180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return;
181231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (m_pattern[m_patternIndex] != m_test[m_testIndex])
182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return;
183231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_patternIndex++;
184231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_testIndex++;
185231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
186231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
187231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
188231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool test()
189231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Eat all the matching chars.
191231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        eatSameChars();
192231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
193231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // If the string is finished, then the pattern must be empty too, or contains
194231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // only wildcards.
195231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (testStringFinished()) {
196231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            eatWildcard();
197231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (patternStringFinished())
198231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return true;
199231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
200231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
201231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
202231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Pattern is empty but not string, this is not a match.
203231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (patternStringFinished())
204231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
205231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
206231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // If we don't encounter a *, then we're hosed.
207231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (m_pattern[m_patternIndex] != '*')
208231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
209231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
210231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        while (!testStringFinished()) {
211231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            MatchTester nextMatch(*this);
212231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            nextMatch.m_patternIndex++;
213231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (nextMatch.test())
214231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return true;
215231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_testIndex++;
216231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
217231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
218231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // We reached the end of the string.  Let's see if the pattern contains only
219231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // wildcards.
220231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        eatWildcard();
221231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return patternStringFinished();
222231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
223231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block};
224231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
225231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool UserContentURLPattern::matchesPath(const KURL& test) const
226231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
227231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MatchTester match(m_path, test.path());
228231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return match.test();
229231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
230231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
231231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} // namespace WebCore
232