Exemple #1
0
void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cachedStyleSheet, const SecurityOrigin* securityOrigin)
{
    // Check to see if we should enforce the MIME type of the CSS resource in strict mode.
    // Running in iWeb 2 is one example of where we don't want to - <rdar://problem/6099748>
    bool enforceMIMEType = isStrictParserMode(m_parserContext.mode) && m_parserContext.enforcesCSSMIMETypeInNoQuirksMode;
    bool hasValidMIMEType = false;
    String sheetText = cachedStyleSheet->sheetText(enforceMIMEType, &hasValidMIMEType);

    CSSParser p(parserContext());
    p.parseSheet(this, sheetText, 0);

    // If we're loading a stylesheet cross-origin, and the MIME type is not standard, require the CSS
    // to at least start with a syntactically valid CSS rule.
    // This prevents an attacker playing games by injecting CSS strings into HTML, XML, JSON, etc. etc.
    if (!hasValidMIMEType && !hasSyntacticallyValidCSSHeader()) {
        bool isCrossOriginCSS = !securityOrigin || !securityOrigin->canRequest(finalURL());
        if (isCrossOriginCSS) {
            clearRules();
            return;
        }
    }
    if (m_parserContext.needsSiteSpecificQuirks && isStrictParserMode(m_parserContext.mode)) {
        // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>.
        DEFINE_STATIC_LOCAL(const String, slashKHTMLFixesDotCss, ("/KHTMLFixes.css"));
        DEFINE_STATIC_LOCAL(const String, mediaWikiKHTMLFixesStyleSheet, ("/* KHTML fix stylesheet */\n/* work around the horizontal scrollbars */\n#column-content { margin-left: 0; }\n\n"));
        // There are two variants of KHTMLFixes.css. One is equal to mediaWikiKHTMLFixesStyleSheet,
        // while the other lacks the second trailing newline.
        if (finalURL().string().endsWith(slashKHTMLFixesDotCss) && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.startsWith(sheetText)
            && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1)
            clearRules();
    }
PassRefPtr<CSSRuleList> CSSStyleSheet::cssRules(bool omitCharsetRules)
{
    KURL url = finalURL();
    if (!url.isEmpty() && document() && !document()->securityOrigin()->canRequest(url))
        return 0;
    return CSSRuleList::create(this, omitCharsetRules);
}
void ProcessingInstruction::process(const String& href, const String& charset)
{
    if (href.length() > 1 && href[0] == '#') {
        m_localHref = href.substring(1);
        // We need to make a synthetic XSLStyleSheet that is embedded.
        // It needs to be able to kick off import/include loads that
        // can hang off some parent sheet.
        if (m_isXSL) {
            KURL finalURL(ParsedURLString, m_localHref);
            m_sheet = XSLStyleSheet::createEmbedded(this, finalURL);
            m_loading = false;
        }
        return;
    }

    clearResource();

    String url = document().completeURL(href).string();

    ResourcePtr<StyleSheetResource> resource;
    FetchRequest request(ResourceRequest(document().completeURL(href)), FetchInitiatorTypeNames::processinginstruction);
    if (m_isXSL) {
        resource = document().fetcher()->fetchXSLStyleSheet(request);
    } else {
        request.setCharset(charset.isEmpty() ? document().charset() : charset);
        resource = document().fetcher()->fetchCSSStyleSheet(request);
    }

    if (resource) {
        m_loading = true;
        document().styleEngine()->addPendingSheet();
        setResource(resource);
    }
}
PassRefPtr<CSSRuleList> CSSStyleSheet::cssRules()
{
    KURL url = finalURL();
    Document* document = findDocument();
    if (!url.isEmpty() && document && !document->securityOrigin()->canRequest(url))
        return 0;
    if (!m_ruleListCSSOMWrapper)
        m_ruleListCSSOMWrapper = adoptPtr(new StyleSheetCSSRuleList(this));
    return m_ruleListCSSOMWrapper.get();
}
void XSLStyleSheet::loadChildSheets()
{
    if (!document())
        return;

    xmlNodePtr stylesheetRoot = document()->children;

    // Top level children may include other things such as DTD nodes, we ignore
    // those.
    while (stylesheetRoot && stylesheetRoot->type != XML_ELEMENT_NODE)
        stylesheetRoot = stylesheetRoot->next;

    if (m_embedded) {
        // We have to locate (by ID) the appropriate embedded stylesheet
        // element, so that we can walk the import/include list.
        xmlAttrPtr idNode = xmlGetID(document(), (const xmlChar*)(finalURL().string().utf8().data()));
        if (!idNode)
            return;
        stylesheetRoot = idNode->parent;
    } else {
        // FIXME: Need to handle an external URI with a # in it. This is a
        // pretty minor edge case, so we'll deal with it later.
    }

    if (stylesheetRoot) {
        // Walk the children of the root element and look for import/include
        // elements. Imports must occur first.
        xmlNodePtr curr = stylesheetRoot->children;
        while (curr) {
            if (curr->type != XML_ELEMENT_NODE) {
                curr = curr->next;
                continue;
            }
            if (IS_XSLT_ELEM(curr) && IS_XSLT_NAME(curr, "import")) {
                xmlChar* uriRef = xsltGetNsProp(curr, (const xmlChar*)"href", XSLT_NAMESPACE);
                loadChildSheet(String::fromUTF8((const char*)uriRef));
                xmlFree(uriRef);
            } else {
                break;
            }
            curr = curr->next;
        }

        // Now handle includes.
        while (curr) {
            if (curr->type == XML_ELEMENT_NODE && IS_XSLT_ELEM(curr) && IS_XSLT_NAME(curr, "include")) {
                xmlChar* uriRef = xsltGetNsProp(curr, (const xmlChar*)"href", XSLT_NAMESPACE);
                loadChildSheet(String::fromUTF8((const char*)uriRef));
                xmlFree(uriRef);
            }
            curr = curr->next;
        }
    }
}
PassRefPtr<CSSRuleList> CSSStyleSheet::cssRules(bool omitCharsetRules)
{

#if 1
    // modified at webkit.org trunk r61391
    KURL url = finalURL();
    if (!url.isEmpty() && doc() && !doc()->securityOrigin()->canRequest(url))
#else
    if (doc() && !doc()->securityOrigin()->canRequest(baseURL()))
#endif
        return 0;
    return CSSRuleList::create(this, omitCharsetRules);
}
bool XSLStyleSheet::parseString(const String& string)
{
    // Parse in a single chunk into an xmlDocPtr
    const UChar BOM = 0xFEFF;
    const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
    if (!m_stylesheetDocTaken)
        xmlFreeDoc(m_stylesheetDoc);
    m_stylesheetDocTaken = false;

    PageConsoleClient* console = nullptr;
    Frame* frame = ownerDocument()->frame();
    if (frame && frame->page())
        console = &frame->page()->console();

    XMLDocumentParserScope scope(cachedResourceLoader(), XSLTProcessor::genericErrorFunc, XSLTProcessor::parseErrorFunc, console);

    auto upconvertedCharacters = StringView(string).upconvertedCharacters();
    const char* buffer = reinterpret_cast<const char*>(upconvertedCharacters.get());
    int size = string.length() * sizeof(UChar);

    xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(buffer, size);
    if (!ctxt)
        return 0;

    if (m_parentStyleSheet) {
        // The XSL transform may leave the newly-transformed document
        // with references to the symbol dictionaries of the style sheet
        // and any of its children. XML document disposal can corrupt memory
        // if a document uses more than one symbol dictionary, so we
        // ensure that all child stylesheets use the same dictionaries as their
        // parents.
        xmlDictFree(ctxt->dict);
        ctxt->dict = m_parentStyleSheet->m_stylesheetDoc->dict;
        xmlDictReference(ctxt->dict);
    }

    m_stylesheetDoc = xmlCtxtReadMemory(ctxt, buffer, size,
        finalURL().string().utf8().data(),
        BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE",
        XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);
    xmlFreeParserCtxt(ctxt);

    loadChildSheets();

    return m_stylesheetDoc;
}
PassRefPtr<CSSRuleList> CSSStyleSheet::rules()
{
    KURL url = finalURL();
    Document* document = findDocument();
    if (!url.isEmpty() && document && !document->securityOrigin()->canRequest(url))
        return 0;
    // IE behavior.
    RefPtr<StaticCSSRuleList> nonCharsetRules = StaticCSSRuleList::create();
    unsigned ruleCount = length();
    for (unsigned i = 0; i < ruleCount; ++i) {
        CSSRule* rule = item(i);
        if (rule->isCharsetRule())
            continue;
        nonCharsetRules->rules().append(rule);
    }
    return nonCharsetRules.release();
}
bool XSLStyleSheet::parseString(const String& source)
{
    // Parse in a single chunk into an xmlDocPtr
    if (!m_stylesheetDocTaken)
        xmlFreeDoc(m_stylesheetDoc);
    m_stylesheetDocTaken = false;

    PageConsole* console = 0;
    Frame* frame = ownerDocument()->frame();
    if (frame && frame->host())
        console = &frame->host()->console();

    XMLDocumentParserScope scope(fetcher(), XSLTProcessor::genericErrorFunc, XSLTProcessor::parseErrorFunc, console);
    XMLParserInput input(source);

    xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(input.data(), input.size());
    if (!ctxt)
        return 0;

    if (m_parentStyleSheet) {
        // The XSL transform may leave the newly-transformed document
        // with references to the symbol dictionaries of the style sheet
        // and any of its children. XML document disposal can corrupt memory
        // if a document uses more than one symbol dictionary, so we
        // ensure that all child stylesheets use the same dictionaries as their
        // parents.
        xmlDictFree(ctxt->dict);
        ctxt->dict = m_parentStyleSheet->m_stylesheetDoc->dict;
        xmlDictReference(ctxt->dict);
    }

    m_stylesheetDoc = xmlCtxtReadMemory(ctxt, input.data(), input.size(),
        finalURL().string().utf8().data(), input.encoding(),
        XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);

    xmlFreeParserCtxt(ctxt);
    loadChildSheets();
    return m_stylesheetDoc;
}
void ProcessingInstruction::checkStyleSheet()
{
    if (m_target == "xml-stylesheet" && document().frame() && parentNode() == &document()) {
        // see http://www.w3.org/TR/xml-stylesheet/
        // ### support stylesheet included in a fragment of this (or another) document
        // ### make sure this gets called when adding from javascript
        bool attrsOk;
        const HashMap<String, String> attrs = parseAttributes(data(), attrsOk);
        if (!attrsOk)
            return;
        HashMap<String, String>::const_iterator i = attrs.find("type");
        String type;
        if (i != attrs.end())
            type = i->value;

        m_isCSS = type.isEmpty() || type == "text/css";
#if ENABLE(XSLT)
        m_isXSL = (type == "text/xml" || type == "text/xsl" || type == "application/xml" ||
                   type == "application/xhtml+xml" || type == "application/rss+xml" || type == "application/atom+xml");
        if (!m_isCSS && !m_isXSL)
#else
        if (!m_isCSS)
#endif
            return;

        String href = attrs.get("href");
        String alternate = attrs.get("alternate");
        m_alternate = alternate == "yes";
        m_title = attrs.get("title");
        m_media = attrs.get("media");

        if (m_alternate && m_title.isEmpty())
            return;

        if (href.length() > 1 && href[0] == '#') {
            m_localHref = href.substring(1);
#if ENABLE(XSLT)
            // We need to make a synthetic XSLStyleSheet that is embedded.  It needs to be able
            // to kick off import/include loads that can hang off some parent sheet.
            if (m_isXSL) {
                URL finalURL(ParsedURLString, m_localHref);
                m_sheet = XSLStyleSheet::createEmbedded(this, finalURL);
                m_loading = false;
            }
#endif
        } else {
            if (m_cachedSheet) {
                m_cachedSheet->removeClient(this);
                m_cachedSheet = 0;
            }
            
            String url = document().completeURL(href).string();
            if (!dispatchBeforeLoadEvent(url))
                return;
            
            m_loading = true;
            document().styleSheetCollection().addPendingSheet();
            
            CachedResourceRequest request(ResourceRequest(document().completeURL(href)));
#if ENABLE(XSLT)
            if (m_isXSL)
                m_cachedSheet = document().cachedResourceLoader()->requestXSLStyleSheet(request);
            else
#endif
            {
                String charset = attrs.get("charset");
                if (charset.isEmpty())
                    charset = document().charset();
                request.setCharset(charset);

                m_cachedSheet = document().cachedResourceLoader()->requestCSSStyleSheet(request);
            }
            if (m_cachedSheet)
                m_cachedSheet->addClient(this);
            else {
                // The request may have been denied if (for example) the stylesheet is local and the document is remote.
                m_loading = false;
                document().styleSheetCollection().removePendingSheet();
            }
        }
    }
}
 void registerFinalResource(const WebString& url) {
     KURL finalURL(ParsedURLString, url);
     URLTestHelpers::registerMockedURLLoad(finalURL, testImageFilename);
 }