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); }