Beispiel #1
0
PassRefPtr<SecurityOrigin> SecurityOrigin::create(const KURL& url)
{
    if (shouldTreatAsUniqueOrigin(url)) {
        RefPtr<SecurityOrigin> origin = adoptRef(new SecurityOrigin());

        if (url.protocolIs("file")) {
            // Unfortunately, we can't represent all unique origins exactly
            // the same way because we need to produce a quirky database
            // identifier for file URLs due to persistent storage in some
            // embedders of WebKit.
            origin->m_needsDatabaseIdentifierQuirkForFiles = true;
        }

        return origin.release();
    }

    if (shouldUseInnerURL(url))
        return adoptRef(new SecurityOrigin(extractInnerURL(url)));

    return adoptRef(new SecurityOrigin(url));
}
Beispiel #2
0
void deleteCookie(const Document*, const KURL& url, const String& name)
{
    CFHTTPCookieStorageRef cookieStorage = currentCookieStorage();
    if (!cookieStorage)
        return;

    RetainPtr<CFURLRef> urlCF(AdoptCF, url.createCFURL());

    bool sendSecureCookies = url.protocolIs("https");
    RetainPtr<CFArrayRef> cookiesCF(AdoptCF, CFHTTPCookieStorageCopyCookiesForURL(cookieStorage, urlCF.get(), sendSecureCookies));

    CFIndex count = CFArrayGetCount(cookiesCF.get());
    for (CFIndex i = 0; i < count; i++) {
        CFHTTPCookieRef cookie = (CFHTTPCookieRef)CFArrayGetValueAtIndex(cookiesCF.get(), i);
        String cookieName = CFHTTPCookieGetName(cookie);
        if (cookieName == name) {
            CFHTTPCookieStorageDeleteCookie(cookieStorage, cookie);
            break;
        }
    }
}
bool DOMFileSystemBase::crackFileSystemURL(const KURL& url, FileSystemType& type, String& filePath)
{
    if (!url.protocolIs("filesystem"))
        return false;

    if (!url.innerURL())
        return false;

    String typeString = url.innerURL()->path().substring(1);
    if (typeString == temporaryPathPrefix)
        type = FileSystemTypeTemporary;
    else if (typeString == persistentPathPrefix)
        type = FileSystemTypePersistent;
    else if (typeString == externalPathPrefix)
        type = FileSystemTypeExternal;
    else
        return false;

    filePath = decodeURLEscapeSequences(url.path());
    return true;
}
void ResourceHandleManager::startJob(ResourceHandle* job)
{
    KURL kurl = job->request().url();

    if (kurl.protocolIs("data")) {
        parseDataUrl(job);
        return;
    }

    initializeHandle(job);

    m_runningJobs++;
    CURLMcode ret = curl_multi_add_handle(m_curlMultiHandle, job->getInternal()->m_handle);
    // don't call perform, because events must be async
    // timeout will occur and do curl_multi_perform
    if (ret && ret != CURLM_CALL_MULTI_PERFORM) {
#ifndef NDEBUG
        printf("Error %d starting job %s\n", ret, encodeWithURLEscapeSequences(job->request().url().string()).latin1().data());
#endif
        job->cancel();
        return;
    }
}
void ResourceHandleManager::dispatchSynchronousJob(ResourceHandle* job)
{
    KURL kurl = job->request().url();

    if (kurl.protocolIs("data")) {
        parseDataUrl(job);
        return;
    }

    initializeHandle(job);

    ResourceHandleInternal* handle = job->getInternal();

    // curl_easy_perform blocks until the transfert is finished.
    CURLcode ret =  curl_easy_perform(handle->m_handle);

    if (ret != 0) {
        ResourceError error(String(handle->m_url), ret, String(handle->m_url), String(curl_easy_strerror(ret)));
        handle->client()->didFail(job, error);
    }

    curl_easy_cleanup(handle->m_handle);
}
 void preconnectHost(const KURL& host, const CrossOriginAttributeValue crossOrigin) const override
 {
     m_didPreconnect = true;
     m_isHTTPS = host.protocolIs("https");
     m_isCrossOrigin = (crossOrigin == CrossOriginAttributeAnonymous);
 }
// We copied the KURL version here on Dec 4, 2009 while doing a WebKit
// merge.
//
// FIXME Somehow share this with KURL? Like we'd theoretically merge with
// decodeURLEscapeSequences below?
bool portAllowed(const KURL& url)
{
    unsigned short port = url.port();

    // Since most URLs don't have a port, return early for the "no port" case.
    if (!port)
        return true;

    // This blocked port list matches the port blocking that Mozilla implements.
    // See http://www.mozilla.org/projects/netlib/PortBanning.html for more information.
    static const unsigned short blockedPortList[] = {
        1,    // tcpmux
        7,    // echo
        9,    // discard
        11,   // systat
        13,   // daytime
        15,   // netstat
        17,   // qotd
        19,   // chargen
        20,   // FTP-data
        21,   // FTP-control
        22,   // SSH
        23,   // telnet
        25,   // SMTP
        37,   // time
        42,   // name
        43,   // nicname
        53,   // domain
        77,   // priv-rjs
        79,   // finger
        87,   // ttylink
        95,   // supdup
        101,  // hostriame
        102,  // iso-tsap
        103,  // gppitnp
        104,  // acr-nema
        109,  // POP2
        110,  // POP3
        111,  // sunrpc
        113,  // auth
        115,  // SFTP
        117,  // uucp-path
        119,  // nntp
        123,  // NTP
        135,  // loc-srv / epmap
        139,  // netbios
        143,  // IMAP2
        179,  // BGP
        389,  // LDAP
        465,  // SMTP+SSL
        512,  // print / exec
        513,  // login
        514,  // shell
        515,  // printer
        526,  // tempo
        530,  // courier
        531,  // Chat
        532,  // netnews
        540,  // UUCP
        556,  // remotefs
        563,  // NNTP+SSL
        587,  // ESMTP
        601,  // syslog-conn
        636,  // LDAP+SSL
        993,  // IMAP+SSL
        995,  // POP3+SSL
        2049, // NFS
        3659, // apple-sasl / PasswordServer [Apple addition]
        4045, // lockd
        6000, // X11
        6665, // Alternate IRC [Apple addition]
        6666, // Alternate IRC [Apple addition]
        6667, // Standard IRC [Apple addition]
        6668, // Alternate IRC [Apple addition]
        6669, // Alternate IRC [Apple addition]
        invalidPortNumber, // Used to block all invalid port numbers
    };
    const unsigned short* const blockedPortListEnd = blockedPortList + sizeof(blockedPortList) / sizeof(blockedPortList[0]);

#ifndef NDEBUG
    // The port list must be sorted for binary_search to work.
    static bool checkedPortList = false;
    if (!checkedPortList) {
        for (const unsigned short* p = blockedPortList; p != blockedPortListEnd - 1; ++p)
            ASSERT(*p < *(p + 1));
        checkedPortList = true;
    }
#endif

    // If the port is not in the blocked port list, allow it.
    if (!binary_search(blockedPortList, blockedPortListEnd, port))
        return true;

    // Allow ports 21 and 22 for FTP URLs, as Mozilla does.
    if ((port == 21 || port == 22) && url.protocolIs("ftp"))
        return true;

    // Allow any port number in a file URL, since the port number is ignored.
    if (url.protocolIs("file"))
        return true;

    return false;
}
Beispiel #8
0
bool parseManifest(const KURL& manifestURL, const char* data, int length, Manifest& manifest)
{
    ASSERT(manifest.explicitURLs.isEmpty());
    ASSERT(manifest.onlineWhitelistedURLs.isEmpty());
    ASSERT(manifest.fallbackURLs.isEmpty());
    manifest.allowAllNetworkRequests = false;

    Mode mode = Explicit;

    RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/cache-manifest", "UTF-8");
    String s = decoder->decode(data, length);
    s += decoder->flush();

    // Look for the magic signature: "^\xFEFF?CACHE MANIFEST[ \t]?" (the BOM is removed by TextResourceDecoder).
    // Example: "CACHE MANIFEST #comment" is a valid signature.
    // Example: "CACHE MANIFEST;V2" is not.
    if (!s.startsWith("CACHE MANIFEST"))
        return false;

    const UChar* end = s.characters() + s.length();
    const UChar* p = s.characters() + 14; // "CACHE MANIFEST" is 14 characters.

    if (p < end && *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r')
        return false;

    // Skip to the end of the line.
    while (p < end && *p != '\r' && *p != '\n')
        p++;

    while (1) {
        // Skip whitespace
        while (p < end && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
            p++;

        if (p == end)
            break;

        const UChar* lineStart = p;

        // Find the end of the line
        while (p < end && *p != '\r' && *p != '\n')
            p++;

        // Check if we have a comment
        if (*lineStart == '#')
            continue;

        // Get rid of trailing whitespace
        const UChar* tmp = p - 1;
        while (tmp > lineStart && (*tmp == ' ' || *tmp == '\t'))
            tmp--;

        String line(lineStart, tmp - lineStart + 1);

        if (line == "CACHE:")
            mode = Explicit;
        else if (line == "FALLBACK:")
            mode = Fallback;
        else if (line == "NETWORK:")
            mode = OnlineWhitelist;
        else if (line.endsWith(":"))
            mode = Unknown;
        else if (mode == Unknown)
            continue;
        else if (mode == Explicit || mode == OnlineWhitelist) {
            const UChar* p = line.characters();
            const UChar* lineEnd = p + line.length();

            // Look for whitespace separating the URL from subsequent ignored tokens.
            while (p < lineEnd && *p != '\t' && *p != ' ')
                p++;

            if (mode == OnlineWhitelist && p - line.characters() == 1 && *line.characters() == '*') {
                // Wildcard was found.
                manifest.allowAllNetworkRequests = true;
                continue;
            }

            KURL url(manifestURL, String(line.characters(), p - line.characters()));

            if (!url.isValid())
                continue;

            if (url.hasFragmentIdentifier())
                url.removeFragmentIdentifier();

            if (!equalIgnoringCase(url.protocol(), manifestURL.protocol()))
                continue;

            if (mode == Explicit && manifestURL.protocolIs("https") && !protocolHostAndPortAreEqual(manifestURL, url))
                continue;

            if (mode == Explicit)
                manifest.explicitURLs.add(url.string());
            else
                manifest.onlineWhitelistedURLs.append(url);

        } else if (mode == Fallback) {
            const UChar* p = line.characters();
            const UChar* lineEnd = p + line.length();

            // Look for whitespace separating the two URLs
            while (p < lineEnd && *p != '\t' && *p != ' ')
                p++;

            if (p == lineEnd) {
                // There was no whitespace separating the URLs.
                continue;
            }

            KURL namespaceURL(manifestURL, String(line.characters(), p - line.characters()));
            if (!namespaceURL.isValid())
                continue;
            if (namespaceURL.hasFragmentIdentifier())
                namespaceURL.removeFragmentIdentifier();

            if (!protocolHostAndPortAreEqual(manifestURL, namespaceURL))
                continue;

            // Skip whitespace separating fallback namespace from URL.
            while (p < lineEnd && (*p == '\t' || *p == ' '))
                p++;

            // Look for whitespace separating the URL from subsequent ignored tokens.
            const UChar* fallbackStart = p;
            while (p < lineEnd && *p != '\t' && *p != ' ')
                p++;

            KURL fallbackURL(manifestURL, String(fallbackStart, p - fallbackStart));
            if (!fallbackURL.isValid())
                continue;
            if (fallbackURL.hasFragmentIdentifier())
                fallbackURL.removeFragmentIdentifier();

            if (!protocolHostAndPortAreEqual(manifestURL, fallbackURL))
                continue;

            manifest.fallbackURLs.append(make_pair(namespaceURL, fallbackURL));
        } else
            ASSERT_NOT_REACHED();
    }

    return true;
}
Beispiel #9
0
PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, PassRefPtr<Event> event, bool lockHistory, FormSubmissionTrigger trigger)
{
    ASSERT(form);

    HTMLFormControlElement* submitButton = 0;
    if (event && event->target()) {
        for (Node* node = event->target()->toNode(); node; node = node->parentNode()) {
            if (node->isElementNode() && toElement(node)->isFormControlElement()) {
                submitButton = static_cast<HTMLFormControlElement*>(node);
                break;
            }
        }
    }

    FormSubmission::Attributes copiedAttributes;
    copiedAttributes.copyFrom(attributes);
    if (submitButton) {
        String attributeValue;
        if (!(attributeValue = submitButton->getAttribute(formactionAttr)).isNull())
            copiedAttributes.parseAction(attributeValue);
        if (!(attributeValue = submitButton->getAttribute(formenctypeAttr)).isNull())
            copiedAttributes.updateEncodingType(attributeValue);
        if (!(attributeValue = submitButton->getAttribute(formmethodAttr)).isNull())
            copiedAttributes.updateMethodType(attributeValue);
        if (!(attributeValue = submitButton->getAttribute(formtargetAttr)).isNull())
            copiedAttributes.setTarget(attributeValue);
    }
    
    Document* document = form->document();
    KURL actionURL = document->completeURL(copiedAttributes.action().isEmpty() ? document->url().string() : copiedAttributes.action());
    bool isMailtoForm = actionURL.protocolIs("mailto");
    bool isMultiPartForm = false;
    String encodingType = copiedAttributes.encodingType();

    if (copiedAttributes.method() == PostMethod) {
        isMultiPartForm = copiedAttributes.isMultiPartForm();
        if (isMultiPartForm && isMailtoForm) {
            encodingType = "application/x-www-form-urlencoded";
            isMultiPartForm = false;
        }
    }

    TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataBuilder::encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document);
    RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding.encodingForFormSubmission());
    Vector<pair<String, String> > formValues;

    bool containsPasswordData = false;
    for (unsigned i = 0; i < form->associatedElements().size(); ++i) {
        FormAssociatedElement* control = form->associatedElements()[i];
        HTMLElement* element = toHTMLElement(control);
        if (!element->isDisabledFormControl())
            control->appendFormData(*domFormData, isMultiPartForm);
        if (element->hasLocalName(inputTag)) {
            HTMLInputElement* input = static_cast<HTMLInputElement*>(control);
            if (input->isTextField()) {
                formValues.append(pair<String, String>(input->name().string(), input->value()));
                input->addSearchResult();
            }
            if (input->isPasswordField() && !input->value().isEmpty())
                containsPasswordData = true;
        }
    }

    RefPtr<FormData> formData;
    String boundary;

    if (isMultiPartForm) {
        formData = FormData::createMultiPart(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding(), document);
        boundary = formData->boundary().data();
    } else {
        formData = FormData::create(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding(), attributes.method() == GetMethod ? FormData::FormURLEncoded : FormData::parseEncodingType(encodingType));
        if (copiedAttributes.method() == PostMethod && isMailtoForm) {
            // Convert the form data into a string that we put into the URL.
            appendMailtoPostFormDataToURL(actionURL, *formData, encodingType);
            formData = FormData::create();
        }
    }

    formData->setIdentifier(generateFormDataIdentifier());
    formData->setContainsPasswordData(containsPasswordData);
    String targetOrBaseTarget = copiedAttributes.target().isEmpty() ? document->baseTarget() : copiedAttributes.target();
    RefPtr<FormState> formState = FormState::create(form, formValues, document, trigger);
    return adoptRef(new FormSubmission(copiedAttributes.method(), actionURL, targetOrBaseTarget, encodingType, formState.release(), formData.release(), boundary, lockHistory, event));
}
void PageSerializer::serializeFrame(Frame* frame)
{
    Document* document = frame->document();
    KURL url = document->url();
    if (!url.isValid() || url.protocolIs("about")) {
        // For blank frames we generate a fake URL so they can be referenced by their containing frame.
        url = urlForBlankFrame(frame);
    }

    if (m_resourceURLs.contains(url)) {
        // FIXME: We could have 2 frame with the same URL but which were dynamically changed and have now
        // different content. So we should serialize both and somehow rename the frame src in the containing
        // frame. Arg!
        return;
    }

    Vector<Node*> nodes;
    SerializerMarkupAccumulator accumulator(this, document, &nodes);
    TextEncoding textEncoding(document->charset());
    CString data;
    if (!textEncoding.isValid()) {
        // FIXME: iframes used as images trigger this. We should deal with them correctly.
        return;
    }
    String text = accumulator.serializeNodes(document->documentElement(), 0, IncludeNode);
    CString frameHTML = textEncoding.encode(text.characters(), text.length(), EntitiesForUnencodables);
    m_resources->append(Resource(url, document->suggestedMIMEType(), SharedBuffer::create(frameHTML.data(), frameHTML.length())));
    m_resourceURLs.add(url);

    for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter) {
        Node* node = *iter;
        if (!node->isElementNode())
            continue;

        Element* element = toElement(node);
        // We have to process in-line style as it might contain some resources (typically background images).
        if (element->isStyledElement())
            retrieveResourcesForCSSDeclaration(static_cast<StyledElement*>(element)->inlineStyleDecl(), document);

        if (element->hasTagName(HTMLNames::imgTag)) {
            HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(element);
            KURL url = document->completeURL(imageElement->getAttribute(HTMLNames::srcAttr));
            CachedImage* cachedImage = imageElement->cachedImage();
            addImageToResources(cachedImage, imageElement->renderer(), url);
        } else if (element->hasTagName(HTMLNames::linkTag)) {
            HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(element);
            if (CSSStyleSheet* sheet = linkElement->sheet()) {
                KURL url = document->completeURL(linkElement->getAttribute(HTMLNames::hrefAttr));
                serializeCSSStyleSheet(sheet, url);
                ASSERT(m_resourceURLs.contains(url));
            }
        } else if (element->hasTagName(HTMLNames::styleTag)) {
            HTMLStyleElement* styleElement = static_cast<HTMLStyleElement*>(element);
            if (CSSStyleSheet* sheet = styleElement->sheet())
                serializeCSSStyleSheet(sheet, KURL());
        }
    }

    for (Frame* childFrame = frame->tree()->firstChild(); childFrame; childFrame = childFrame->tree()->nextSibling())
        serializeFrame(childFrame);
}
Beispiel #11
0
void CookieManager::getRawCookies(Vector<ParsedCookie*> &stackOfCookies, const KURL& requestURL, CookieFilter filter) const
{
    if (!m_syncedWithDatabase && !m_privateMode) {
        LOG_ERROR("CookieManager is calling getRawCookies before database values are loaded.");
        return;
    }

    CookieLog("CookieManager - getRawCookies - processing url with domain - %s & protocol: %s & path: %s\n", requestURL.host().utf8().data(), requestURL.protocol().utf8().data(), requestURL.path().utf8().data());

    const bool invalidScheme = shouldIgnoreScheme(requestURL.protocol());
    const bool specialCaseForWebWorks = invalidScheme && m_shouldDumpAllCookies;
    const bool isConnectionSecure = requestURL.protocolIs("https") || requestURL.protocolIs("wss") || specialCaseForWebWorks;

    Vector<ParsedCookie*> cookieCandidates;
    Vector<CookieMap*> protocolsToSearch;

    // Special Case: If a server sets a "secure" cookie over a non-secure channel and tries to access the cookie
    // over a secure channel, it will not succeed because the secure protocol isn't mapped to the insecure protocol yet.
    // Set the map to the non-secure version, so it'll search the mapping for a secure cookie.
    CookieMap* targetMap = m_managerMap.get(requestURL.protocol());
    if (!targetMap && isConnectionSecure) {
        CookieLog("CookieManager - special case: secure protocol are not linked yet.");
        if (requestURL.protocolIs("https"))
            targetMap = m_managerMap.get("http");
        else if (requestURL.protocolIs("wss"))
            targetMap = m_managerMap.get("ws");
    }

    // Decide which scheme tree we should look at.
    // Return on invalid schemes. cookies are currently disabled on file and local.
    // We only want to enable them for WebWorks that enabled a special flag.
    if (specialCaseForWebWorks)
        copyValuesToVector(m_managerMap, protocolsToSearch);
    else if (invalidScheme)
        return;
    else {
        protocolsToSearch.append(targetMap);
        // FIXME: this is a hack for webworks apps; RFC 6265 says "Cookies do not provide isolation by scheme"
        // so we should not be checking protocols at all. See PR 135595
        if (m_shouldDumpAllCookies) {
            protocolsToSearch.append(m_managerMap.get("file"));
            protocolsToSearch.append(m_managerMap.get("local"));
       }
    }

    Vector<String> delimitedHost;

    // IP addresses are stored in a particular format (due to ipv6). Reduce the ip address so we can match
    // it with the one in memory.
    string canonicalIP = BlackBerry::Platform::getCanonicalIPFormat(requestURL.host().utf8().data());
    if (!canonicalIP.empty())
        delimitedHost.append(String(canonicalIP.c_str()));
    else
        requestURL.host().lower().split(".", true, delimitedHost);

    // Go through all the protocol trees that we need to search for
    // and get all cookies that are valid for this domain
    for (size_t k = 0; k < protocolsToSearch.size(); k++) {
        CookieMap* currentMap = protocolsToSearch[k];

        // if no cookies exist for this protocol, break right away
        if (!currentMap)
            continue;

        CookieLog("CookieManager - looking at protocol map %s \n", currentMap->getName().utf8().data());

        // Special case for local and files - because WebApps expect to get ALL cookies from the backing-store on local protocol
        if (specialCaseForWebWorks) {
            CookieLog("CookieManager - special case find in protocol map - %s\n", currentMap->getName().utf8().data());
            currentMap->getAllChildCookies(&cookieCandidates);
        } else {
            // Get cookies from the null domain map
            currentMap->getAllCookies(&cookieCandidates);

            // Get cookies from the valid domain maps
            int i = delimitedHost.size() - 1;
            while (i >= 0) {
                CookieLog("CookieManager - finding %s in currentmap\n", delimitedHost[i].utf8().data());
                currentMap = currentMap->getSubdomainMap(delimitedHost[i]);
                // if this subdomain/domain does not exist in our mapping then we simply exit
                if (!currentMap) {
                    CookieLog("CookieManager - cannot find next map exiting the while loop.\n");
                    break;
                }
                CookieLog("CookieManager - found the map, grabbing cookies from this map\n");
                currentMap->getAllCookies(&cookieCandidates);
                i--;
            }
        }
    }

    CookieLog("CookieManager - there are %d cookies in candidate\n", cookieCandidates.size());

    for (size_t i = 0; i < cookieCandidates.size(); ++i) {
        ParsedCookie* cookie = cookieCandidates[i];

        // According to the path-matches rules in RFC6265, section 5.1.4,
        // we should add a '/' at the end of cookie-path for comparison if the cookie-path is not end with '/'.
        String path = cookie->path();
        CookieLog("CookieManager - comparing cookie path %s (len %d) to request path %s (len %d)", path.utf8().data(), path.length(), requestURL.path().utf8().data(), path.length());
        if (!equalIgnoringCase(path, requestURL.path()) && !path.endsWith("/", false))
            path = path + "/";

        // Only secure connections have access to secure cookies. Unless specialCaseForWebWorks is true.
        // Get the cookies filtering out HttpOnly cookies if requested.
        if (requestURL.path().startsWith(path, false) && (isConnectionSecure || !cookie->isSecure()) && (filter == WithHttpOnlyCookies || !cookie->isHttpOnly())) {
            CookieLog("CookieManager - cookie chosen - %s\n", cookie->toString().utf8().data());
            cookie->setLastAccessed(currentTime());
            stackOfCookies.append(cookie);
        }
    }

    std::stable_sort(stackOfCookies.begin(), stackOfCookies.end(), cookieSorter);
}
Beispiel #12
0
void Loader::Host::servePendingRequests(RequestQueue& requestsPending, bool& serveLowerPriority)
{
    while (!requestsPending.isEmpty()) {        
        Request* request = requestsPending.first();
        DocLoader* docLoader = request->docLoader();
        bool resourceIsCacheValidator = request->cachedResource()->isCacheValidator();
        // If the document is fully parsed and there are no pending stylesheets there won't be any more 
        // resources that we would want to push to the front of the queue. Just hand off the remaining resources
        // to the networking layer.
        bool parsedAndStylesheetsKnown = !docLoader->doc()->parsing() && docLoader->doc()->haveStylesheetsLoaded();
        if (!parsedAndStylesheetsKnown && !resourceIsCacheValidator && m_requestsLoading.size() >= m_maxRequestsInFlight) {
            serveLowerPriority = false;
            return;
        }
        requestsPending.removeFirst();
        
        ResourceRequest resourceRequest(request->cachedResource()->url());
        
        if (!request->cachedResource()->accept().isEmpty())
            resourceRequest.setHTTPAccept(request->cachedResource()->accept());
        
        KURL referrer = docLoader->doc()->url();
        if ((referrer.protocolIs("http") || referrer.protocolIs("https")) && referrer.path().isEmpty())
            referrer.setPath("/");
        resourceRequest.setHTTPReferrer(referrer.string());
        FrameLoader::addHTTPOriginIfNeeded(resourceRequest, docLoader->doc()->securityOrigin()->toString());
        
        if (resourceIsCacheValidator) {
            CachedResource* resourceToRevalidate = request->cachedResource()->resourceToRevalidate();
            ASSERT(resourceToRevalidate->canUseCacheValidator());
            ASSERT(resourceToRevalidate->isLoaded());
            const String& lastModified = resourceToRevalidate->response().httpHeaderField("Last-Modified");
            const String& eTag = resourceToRevalidate->response().httpHeaderField("ETag");
            if (!lastModified.isEmpty() || !eTag.isEmpty()) {
                ASSERT(docLoader->cachePolicy() != CachePolicyReload);
                if (docLoader->cachePolicy() == CachePolicyRevalidate)
                    resourceRequest.setHTTPHeaderField("Cache-Control", "max-age=0");
                if (!lastModified.isEmpty())
                    resourceRequest.setHTTPHeaderField("If-Modified-Since", lastModified);
                if (!eTag.isEmpty())
                    resourceRequest.setHTTPHeaderField("If-None-Match", eTag);
            }
        }

        RefPtr<SubresourceLoader> loader = SubresourceLoader::create(docLoader->doc()->frame(),
                                                                     this, resourceRequest, request->shouldSkipCanLoadCheck(), request->sendResourceLoadCallbacks());
        if (loader) {
            m_requestsLoading.add(loader.release(), request);
            request->cachedResource()->setRequestedFromNetworkingLayer();
#if REQUEST_DEBUG
            printf("HOST %s COUNT %d LOADING %s\n", resourceRequest.url().host().latin1().data(), m_requestsLoading.size(), request->cachedResource()->url().latin1().data());
#endif
        } else {            
            docLoader->decrementRequestCount();
            docLoader->setLoadInProgress(true);
            request->cachedResource()->error();
            docLoader->setLoadInProgress(false);
            delete request;
        }
    }
}
PassRefPtrWillBeRawPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, PassRefPtrWillBeRawPtr<Event> event)
{
    ASSERT(form);

    HTMLFormControlElement* submitButton = 0;
    if (event && event->target()) {
        for (Node* node = event->target()->toNode(); node; node = node->parentOrShadowHostNode()) {
            if (node->isElementNode() && toElement(node)->isFormControlElement()) {
                submitButton = toHTMLFormControlElement(node);
                break;
            }
        }
    }

    FormSubmission::Attributes copiedAttributes;
    copiedAttributes.copyFrom(attributes);
    if (submitButton) {
        AtomicString attributeValue;
        if (!(attributeValue = submitButton->fastGetAttribute(formactionAttr)).isNull())
            copiedAttributes.parseAction(attributeValue);
        if (!(attributeValue = submitButton->fastGetAttribute(formenctypeAttr)).isNull())
            copiedAttributes.updateEncodingType(attributeValue);
        if (!(attributeValue = submitButton->fastGetAttribute(formmethodAttr)).isNull())
            copiedAttributes.updateMethodType(attributeValue);
        if (!(attributeValue = submitButton->fastGetAttribute(formtargetAttr)).isNull())
            copiedAttributes.setTarget(attributeValue);
    }

    if (copiedAttributes.method() == DialogMethod) {
        if (submitButton)
            return adoptRefWillBeNoop(new FormSubmission(submitButton->resultForDialogSubmit()));
        return adoptRefWillBeNoop(new FormSubmission(""));
    }

    Document& document = form->document();
    KURL actionURL = document.completeURL(copiedAttributes.action().isEmpty() ? document.url().string() : copiedAttributes.action());
    bool isMailtoForm = actionURL.protocolIs("mailto");
    bool isMultiPartForm = false;
    AtomicString encodingType = copiedAttributes.encodingType();

    if (copiedAttributes.method() == PostMethod) {
        isMultiPartForm = copiedAttributes.isMultiPartForm();
        if (isMultiPartForm && isMailtoForm) {
            encodingType = AtomicString("application/x-www-form-urlencoded", AtomicString::ConstructFromLiteral);
            isMultiPartForm = false;
        }
    }
    WTF::TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataEncoder::encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document.encoding());
    FormData* domFormData = FormData::create(dataEncoding.encodingForFormSubmission());

    bool containsPasswordData = false;
    for (unsigned i = 0; i < form->associatedElements().size(); ++i) {
        FormAssociatedElement* control = form->associatedElements()[i];
        ASSERT(control);
        HTMLElement& element = toHTMLElement(*control);
        if (!element.isDisabledFormControl())
            control->appendToFormData(*domFormData);
        if (isHTMLInputElement(element)) {
            HTMLInputElement& input = toHTMLInputElement(element);
            if (input.type() == InputTypeNames::password && !input.value().isEmpty())
                containsPasswordData = true;
        }
    }

    RefPtr<EncodedFormData> formData;
    String boundary;

    if (isMultiPartForm) {
        formData = domFormData->encodeMultiPartFormData();
        boundary = formData->boundary().data();
    } else {
        formData = domFormData->encodeFormData(attributes.method() == GetMethod ? EncodedFormData::FormURLEncoded : EncodedFormData::parseEncodingType(encodingType));
        if (copiedAttributes.method() == PostMethod && isMailtoForm) {
            // Convert the form data into a string that we put into the URL.
            appendMailtoPostFormDataToURL(actionURL, *formData, encodingType);
            formData = EncodedFormData::create();
        }
    }

    formData->setIdentifier(generateFormDataIdentifier());
    formData->setContainsPasswordData(containsPasswordData);
    AtomicString targetOrBaseTarget = copiedAttributes.target().isEmpty() ? document.baseTarget() : copiedAttributes.target();
    return adoptRefWillBeNoop(new FormSubmission(copiedAttributes.method(), actionURL, targetOrBaseTarget, encodingType, form, formData.release(), boundary, event));
}
Beispiel #14
0
void CookieManager::getRawCookies(Vector<ParsedCookie*> &stackOfCookies, const KURL& requestURL, CookieFilter filter) const
{
    CookieLog("CookieManager - getRawCookies - processing url with domain - %s & protocol: %s & path: %s\n", requestURL.host().utf8().data(), requestURL.protocol().utf8().data(), requestURL.path().utf8().data());

    bool specialCaseForLocal = (requestURL.protocolIs("local") || requestURL.protocolIs("file")) && m_shouldDumpAllCookies;
    bool isConnectionSecure = requestURL.protocolIs("https") || requestURL.protocolIs("wss") || specialCaseForLocal;

    Vector<ParsedCookie*> cookieCandidates;
    Vector<CookieMap*> protocolsToSearch;

    if (specialCaseForLocal)
        copyValuesToVector(m_managerMap, protocolsToSearch);
    else {
        protocolsToSearch.append(m_managerMap.get(requestURL.protocol()));
        // FIXME: this is a hack for webworks apps; RFC 6265 says "Cookies do not provide isolation by scheme"
        // so we should not be checking protocols at all. See PR 135595
        if (m_shouldDumpAllCookies) {
            protocolsToSearch.append(m_managerMap.get("file"));
            protocolsToSearch.append(m_managerMap.get("local"));
       }
    }

    Vector<String> delimitedHost;
    requestURL.host().lower().split(".", true, delimitedHost);

    // Go through all the protocol trees that we need to search for
    // and get all cookies that are valid for this domain
    for (size_t k = 0; k < protocolsToSearch.size(); k++) {
        CookieMap* currentMap = protocolsToSearch[k];

        // if no cookies exist for this protocol, break right away
        if (!currentMap)
            continue;

        CookieLog("CookieManager - looking at protocol map %s \n", currentMap->getName().utf8().data());

        // Special case for local and files - because WebApps expect to get ALL cookies from the backing-store on local protocol
        if (specialCaseForLocal) {
            CookieLog("CookieManager - special case find in protocol map - %s\n", currentMap->getName().utf8().data());
            currentMap->getAllChildCookies(&cookieCandidates);
        } else {
            // Get cookies from the null domain map
            currentMap->getAllCookies(&cookieCandidates);

            // Get cookies from the valid domain maps
            int i = delimitedHost.size() - 1;
            while (i >= 0) {
                CookieLog("CookieManager - finding %s in currentmap\n", delimitedHost[i].utf8().data());
                currentMap = currentMap->getSubdomainMap(delimitedHost[i]);
                // if this subdomain/domain does not exist in our mapping then we simply exit
                if (!currentMap) {
                    CookieLog("CookieManager - cannot find next map exiting the while loop.\n");
                    break;
                }
                CookieLog("CookieManager - found the map, grabbing cookies from this map\n");
                currentMap->getAllCookies(&cookieCandidates);
                i--;
            }
        }
    }

    CookieLog("CookieManager - there are %d cookies in candidate\n", cookieCandidates.size());

    for (size_t i = 0; i < cookieCandidates.size(); ++i) {
        ParsedCookie* cookie = cookieCandidates[i];

        // According to the path-matches rules in RFC6265, section 5.1.4,
        // we should add a '/' at the end of cookie-path for comparison if the cookie-path is not end with '/'.
        String path = cookie->path();
        CookieLog("CookieManager - comparing cookie path %s (len %d) to request path %s (len %d)", path.utf8().data(), path.length(), requestURL.path().utf8().data(), path.length());
        if (!equalIgnoringCase(path, requestURL.path()) && !path.endsWith("/", false))
            path += "/";

        // Only secure connections have access to secure cookies. Unless specialCaseForLocal is true
        // Get the cookies filtering out HttpOnly cookies if requested.
        if (requestURL.path().startsWith(path, false) && (isConnectionSecure || !cookie->isSecure()) && (filter == WithHttpOnlyCookies || !cookie->isHttpOnly())) {
            CookieLog("CookieManager - cookie chosen - %s\n", cookie->toString().utf8().data());
            cookie->setLastAccessed(currentTime());
            stackOfCookies.append(cookie);
        }
    }

    std::stable_sort(stackOfCookies.begin(), stackOfCookies.end(), cookieSorter);
}
void FrameFetchContext::upgradeInsecureRequest(FetchRequest& fetchRequest)
{
    KURL url = fetchRequest.resourceRequest().url();

    // Tack an 'Upgrade-Insecure-Requests' header to outgoing navigational requests, as described in
    // https://w3c.github.io/webappsec/specs/upgrade/#feature-detect
    if (fetchRequest.resourceRequest().frameType() != WebURLRequest::FrameTypeNone)
        fetchRequest.mutableResourceRequest().addHTTPHeaderField("Upgrade-Insecure-Requests", "1");

    if (m_document && m_document->insecureRequestsPolicy() == SecurityContext::InsecureRequestsUpgrade && url.protocolIs("http")) {
        ASSERT(m_document->insecureNavigationsToUpgrade());

        // We always upgrade requests that meet any of the following criteria:
        //
        // 1. Are for subresources (including nested frames).
        // 2. Are form submissions.
        // 3. Whose hosts are contained in the document's InsecureNavigationSet.
        const ResourceRequest& request = fetchRequest.resourceRequest();
        if (request.frameType() == WebURLRequest::FrameTypeNone
            || request.frameType() == WebURLRequest::FrameTypeNested
            || request.requestContext() == WebURLRequest::RequestContextForm
            || (!url.host().isNull() && m_document->insecureNavigationsToUpgrade()->contains(url.host().impl()->hash())))
        {
            UseCounter::count(m_document, UseCounter::UpgradeInsecureRequestsUpgradedRequest);
            url.setProtocol("https");
            if (url.port() == 80)
                url.setPort(443);
            fetchRequest.mutableResourceRequest().setURL(url);
        }
    }
}