// host = [ "*." ] 1*host-char *( "." 1*host-char ) // / "*" // host-char = ALPHA / DIGIT / "-" // bool CSPSourceList::parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard) { ASSERT(begin <= end); ASSERT(host.isEmpty()); ASSERT(!hostHasWildcard); if (begin == end) return false; const UChar* position = begin; if (skipExactly(position, end, '*')) { hostHasWildcard = true; if (position == end) return true; if (!skipExactly(position, end, '.')) return false; } const UChar* hostBegin = position; while (position < end) { if (!skipExactly<isHostCharacter>(position, end)) return false; skipWhile<isHostCharacter>(position, end); if (position < end && !skipExactly(position, end, '.')) return false; } ASSERT(position == end); host = String(hostBegin, end - hostBegin); return true; }
static bool skipQuotesIfNeeded(CharacterType*& position, CharacterType* const end, bool& completeQuotes) { ASSERT(position <= end); unsigned char quote; if (skipExactly<CharacterType>(position, end, '\'')) quote = '\''; else if (skipExactly<CharacterType>(position, end, '"')) quote = '"'; else return false; while (!completeQuotes && position < end) { skipUntil(position, end, static_cast<CharacterType>(quote)); if (*(position - 1) != '\\') completeQuotes = true; completeQuotes = skipExactly(position, end, static_cast<CharacterType>(quote)) && completeQuotes; } return true; }
// policy = directive-list // directive-list = [ directive *( ";" [ directive ] ) ] // void ContentSecurityPolicy::parse(const String& policy) { ASSERT(!m_havePolicy); if (policy.isEmpty()) return; const UChar* position = policy.characters(); const UChar* end = position + policy.length(); while (position < end) { const UChar* directiveBegin = position; skipUtil(position, end, ';'); String name, value; if (parseDirective(directiveBegin, position, name, value)) { ASSERT(!name.isEmpty()); addDirective(name, value); } ASSERT(position == end || *position == ';'); skipExactly(position, end, ';'); } }
// source = scheme ":" // / ( [ scheme "://" ] host [ port ] ) // / "'self'" // bool CSPSourceList::parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, bool& hostHasWildcard, bool& portHasWildcard) { if (begin == end) return false; if (equalIgnoringCase("'self'", begin, end - begin)) { addSourceSelf(); return false; } if (equalIgnoringCase("'unsafe-inline'", begin, end - begin)) { addSourceUnsafeInline(); return false; } if (equalIgnoringCase("'unsafe-eval'", begin, end - begin)) { addSourceUnsafeEval(); return false; } const UChar* position = begin; const UChar* beginHost = begin; skipUtil(position, end, ':'); if (position == end) { // This must be a host-only source. if (!parseHost(beginHost, position, host, hostHasWildcard)) return false; return true; } if (end - position == 1) { ASSERT(*position == ':'); // This must be a scheme-only source. if (!parseScheme(begin, position, scheme)) return false; return true; } ASSERT(end - position >= 2); if (position[1] == '/') { if (!parseScheme(begin, position, scheme) || !skipExactly(position, end, ':') || !skipExactly(position, end, '/') || !skipExactly(position, end, '/')) return false; beginHost = position; skipUtil(position, end, ':'); } if (position == beginHost) return false; if (!parseHost(beginHost, position, host, hostHasWildcard)) return false; if (position == end) { port = 0; return true; } if (!skipExactly(position, end, ':')) ASSERT_NOT_REACHED(); if (!parsePort(position, end, port, portHasWildcard)) return false; return true; }