static void populateHeadersObject(ScriptObject* object, const HTTPHeaderMap& headers)
{
    HTTPHeaderMap::const_iterator end = headers.end();
    for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it) {
        object->set(it->first.string(), it->second);
    }
}
bool WebSocketHandshake::processHeaders(const HTTPHeaderMap& headers)
{
    for (HTTPHeaderMap::const_iterator it = headers.begin(); it != headers.end(); ++it) {
        switch (m_mode) {
        case Normal:
            if (it->first == "websocket-origin")
                m_wsOrigin = it->second;
            else if (it->first == "websocket-location")
                m_wsLocation = it->second;
            else if (it->first == "websocket-protocol")
                m_wsProtocol = it->second;
            else if (it->first == "set-cookie")
                m_setCookie = it->second;
            else if (it->first == "set-cookie2")
                m_setCookie2 = it->second;
            continue;
        case Incomplete:
        case Failed:
        case Connected:
            ASSERT_NOT_REACHED();
        }
        ASSERT_NOT_REACHED();
    }
    return true;
}
示例#3
0
void WebSocketServerConnection::upgradeToWebSocketServerConnection(PassRefPtr<HTTPRequest> request)
{
    ASSERT(request);
    ASSERT(m_mode == HTTP);
    m_mode = WebSocket;
    RefPtr<HTTPRequest> protectedRequest(request);

    // Ask the client if we should upgrade for this or not.
    if (!m_client->didReceiveWebSocketUpgradeHTTPRequest(this, protectedRequest)) {
        shutdownNow();
        return;
    }

    // Build and send the WebSocket handshake response.
    const HTTPHeaderMap& requestHeaders = protectedRequest->headerFields();
    String accept = WebSocketHandshake::getExpectedWebSocketAccept(requestHeaders.get("Sec-WebSocket-Key"));
    HTTPHeaderMap responseHeaders;
    responseHeaders.add("Upgrade", requestHeaders.get("Upgrade"));
    responseHeaders.add("Connection", requestHeaders.get("Connection"));
    responseHeaders.add("Sec-WebSocket-Accept", accept);

    sendHTTPResponseHeader(101, "WebSocket Protocol Handshake", responseHeaders);

    m_client->didEstablishWebSocketConnection(this, protectedRequest);
}
示例#4
0
void CurlDownload::addHeaders(const ResourceRequest& request)
{
    if (request.httpHeaderFields().size() > 0) {
        struct curl_slist* headers = 0;

        HTTPHeaderMap customHeaders = request.httpHeaderFields();
        HTTPHeaderMap::const_iterator end = customHeaders.end();
        for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) {
            const String& value = it->value;
            String headerString(it->key);
            if (value.isEmpty())
                // Insert the ; to tell curl that this header has an empty value.
                headerString.append(";");
            else {
                headerString.append(": ");
                headerString.append(value);
            }
            CString headerLatin1 = headerString.latin1();
            headers = curl_slist_append(headers, headerLatin1.data());
        }

        if (headers) {
            curl_easy_setopt(m_curlHandle, CURLOPT_HTTPHEADER, headers);
            m_customHeaders = headers;
        }
    }
}
示例#5
0
void WebInspectorServer::didReceiveUnrecognizedHTTPRequest(WebSocketServerConnection* connection, PassRefPtr<HTTPRequest> request)
{
    // request->url() contains only the path extracted from the HTTP request line
    // and URL is poor at parsing incomplete URLs, so extract the interesting parts manually.
    String path = request->url();
    size_t pathEnd = path.find('?');
    if (pathEnd == notFound)
        pathEnd = path.find('#');
    if (pathEnd != notFound)
        path.truncate(pathEnd);

    // Ask for the complete payload in memory for the sake of simplicity. A more efficient way would be
    // to ask for header data and then let the platform abstraction write the payload straight on the connection.
    Vector<char> body;
    String contentType;
    bool found = platformResourceForPath(path, body, contentType);

    HTTPHeaderMap headerFields;
    headerFields.set("Connection", "close");
    headerFields.set("Content-Length", String::number(body.size()));
    if (found)
        headerFields.set("Content-Type", contentType);

    // Send when ready and close immediately afterwards.
    connection->sendHTTPResponseHeader(found ? 200 : 404, found ? "OK" : "Not Found", headerFields);
    connection->sendRawData(body.data(), body.size());
    connection->shutdownAfterSendOrNow();
}
示例#6
0
bool ArgumentCoder<ResourceResponse>::decode(ArgumentDecoder* decoder, ResourceResponse& resourceResponse)
{
    if (kShouldSerializeWebCoreData) {
        bool responseIsNull;
        if (!decoder->decode(responseIsNull))
            return false;
        if (responseIsNull) {
            resourceResponse = ResourceResponse();
            return true;
        }

        ResourceResponse response;

        String url;
        if (!decoder->decode(url))
            return false;
        response.setURL(KURL(KURL(), url));

        int32_t httpStatusCode;
        if (!decoder->decode(httpStatusCode))
            return false;
        response.setHTTPStatusCode(httpStatusCode);

        HTTPHeaderMap headers;
        if (!decoder->decode(headers))
            return false;
        for (HTTPHeaderMap::const_iterator it = headers.begin(), end = headers.end(); it != end; ++it)
            response.setHTTPHeaderField(it->key, it->value);

        String mimeType;
        if (!decoder->decode(mimeType))
            return false;
        response.setMimeType(mimeType);

        String textEncodingName;
        if (!decoder->decode(textEncodingName))
            return false;
        response.setTextEncodingName(textEncodingName);

        int64_t contentLength;
        if (!decoder->decode(contentLength))
            return false;
        response.setExpectedContentLength(contentLength);

        String httpStatusText;
        if (!decoder->decode(httpStatusText))
            return false;
        response.setHTTPStatusText(httpStatusText);

        String suggestedFilename;
        if (!decoder->decode(suggestedFilename))
            return false;
        response.setSuggestedFilename(suggestedFilename);

        resourceResponse = response;
    }

    return decodePlatformData(decoder, resourceResponse);
}
void InspectorResourceAgent::willLoadXHR(ThreadableLoaderClient* client, const String& method, const KURL& url, bool async, PassRefPtr<FormData> formData, const HTTPHeaderMap& headers, bool includeCredentials)
{
    RefPtr<XHRReplayData> xhrReplayData = XHRReplayData::create(method, url, async, formData, includeCredentials);
    HTTPHeaderMap::const_iterator end = headers.end();
    for (HTTPHeaderMap::const_iterator it = headers.begin(); it!= end; ++it)
        xhrReplayData->addHeader(it->key, it->value);
    m_pendingXHRReplayData.set(client, xhrReplayData);
}
示例#8
0
static PassRefPtr<InspectorObject> buildObjectForHeaders(const HTTPHeaderMap& headers)
{
    RefPtr<InspectorObject> headersObject = InspectorObject::create();
    HTTPHeaderMap::const_iterator end = headers.end();
    for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
        headersObject->setString(it->first.string(), it->second);
    return headersObject;
}
示例#9
0
bool PreflightResultCacheItem::allowsCrossSiteHeaders(const HTTPHeaderMap& requestHeaders) const
{
    HTTPHeaderMap::const_iterator end = requestHeaders.end();
    for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) {
        if (!m_headers.contains(it->first) && !isOnAccessControlSimpleRequestHeaderWhitelist(it->first))
            return false;
    }
    return true;
}
示例#10
0
NPError PluginView::handlePost(const char* url, const char* target, uint32 len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders)
{
    if (!url || !len || !buf)
        return NPERR_INVALID_PARAM;

    FrameLoadRequest frameLoadRequest;

    HTTPHeaderMap headerFields;
    Vector<char> buffer;
    
    if (file) {
        NPError readResult = handlePostReadFile(buffer, len, buf);
        if(readResult != NPERR_NO_ERROR)
            return readResult;
    } else {
        buffer.resize(len);
        memcpy(buffer.data(), buf, len);
    }

    const char* postData = buffer.data();
    int postDataLength = buffer.size();

    if (allowHeaders) {
        if (startsWithBlankLine(buffer)) {
            postData++;
            postDataLength--;
        } else {
            int location = locationAfterFirstBlankLine(buffer);
            if (location != -1) {
                // If the blank line is somewhere in the middle of the buffer, everything before is the header
                headerFields = parseRFC822HeaderFields(buffer, location);
                unsigned dataLength = buffer.size() - location;

                // Sometimes plugins like to set Content-Length themselves when they post,
                // but WebFoundation does not like that. So we will remove the header
                // and instead truncate the data to the requested length.
                String contentLength = headerFields.get("Content-Length");

                if (!contentLength.isNull())
                    dataLength = min(contentLength.toInt(), (int)dataLength);
                headerFields.remove("Content-Length");

                postData += location;
                postDataLength = dataLength;
            }
        }
    }

    frameLoadRequest.resourceRequest().setHTTPMethod("POST");
    frameLoadRequest.resourceRequest().setURL(makeURL(m_baseURL, url));
    frameLoadRequest.resourceRequest().addHTTPHeaderFields(headerFields);
    frameLoadRequest.resourceRequest().setHTTPBody(FormData::create(postData, postDataLength));
    frameLoadRequest.setFrameName(target);

    return load(frameLoadRequest, sendNotification, notifyData);
}
bool CrossOriginPreflightResultCacheItem::allowsCrossOriginHeaders(const HTTPHeaderMap& requestHeaders, String& errorDescription) const
{
    HTTPHeaderMap::const_iterator end = requestHeaders.end();
    for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) {
        if (!m_headers.contains(it->first) && !isOnAccessControlSimpleRequestHeaderWhitelist(it->first, it->second)) {
            errorDescription = "Request header field " + it->first.string() + " is not allowed by Access-Control-Allow-Headers.";
            return false;
        }
    }
    return true;
}
示例#12
0
static NPError parsePostBuffer(bool isFile, const char *buffer, uint32_t length, bool parseHeaders, HTTPHeaderMap& headerFields, Vector<uint8_t>& bodyData)
{
    RefPtr<SharedBuffer> fileContents;
    const char* postBuffer = 0;
    uint32_t postBufferSize = 0;

    if (isFile) {
        fileContents = SharedBuffer::createWithContentsOfFile(String::fromUTF8(buffer));
        if (!fileContents)
            return NPERR_FILE_NOT_FOUND;

        postBuffer = fileContents->data();
        postBufferSize = fileContents->size();

        // FIXME: The NPAPI spec states that the file should be deleted here.
    } else {
        postBuffer = buffer;
        postBufferSize = length;
    }

    if (parseHeaders) {
        if (startsWithBlankLine(postBuffer, postBufferSize)) {
            postBuffer++;
            postBufferSize--;
        } else {
            int location = locationAfterFirstBlankLine(postBuffer, postBufferSize);
            if (location != -1) {
                // If the blank line is somewhere in the middle of the buffer, everything before is the header
                headerFields = parseRFC822HeaderFields(postBuffer, location);
                unsigned dataLength = postBufferSize - location;
                
                // Sometimes plugins like to set Content-Length themselves when they post,
                // but WebFoundation does not like that. So we will remove the header
                // and instead truncate the data to the requested length.
                String contentLength = headerFields.get("Content-Length");
                
                if (!contentLength.isNull())
                    dataLength = min(contentLength.toInt(), (int)dataLength);
                headerFields.remove("Content-Length");
                
                postBuffer += location;
                postBufferSize = dataLength;
                
            }
        }
    }

    ASSERT(bodyData.isEmpty());
    bodyData.append(postBuffer, postBufferSize);

    return NPERR_NO_ERROR;
}
示例#13
0
bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap& headerMap)
{
    if (!isOnAccessControlSimpleRequestMethodWhitelist(method))
        return false;

    HTTPHeaderMap::const_iterator end = headerMap.end();
    for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) {
        if (!isOnAccessControlSimpleRequestHeaderWhitelist(it->first, it->second))
            return false;
    }

    return true;
}
示例#14
0
bool FetchUtils::isSimpleOrForbiddenRequest(const String& method, const HTTPHeaderMap& headerMap)
{
    if (!isSimpleMethod(method))
        return false;

    HTTPHeaderMap::const_iterator end = headerMap.end();
    for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) {
        if (!isSimpleHeader(it->key, it->value) && !isForbiddenHeaderName(it->key))
            return false;
    }

    return true;
}
bool ResourceHandle::startHttp(String urlString)
{
    if (!session) {
        session = soup_session_async_new();

        soup_session_add_feature(session, SOUP_SESSION_FEATURE(getCookieJar()));

        const char* soup_debug = g_getenv("WEBKIT_SOUP_LOGGING");
        if (soup_debug) {
            int soup_debug_level = atoi(soup_debug);

            SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(soup_debug_level), -1);
            soup_logger_attach(logger, session);
            g_object_unref(logger);
        }
    }

    SoupMessage* msg;
    msg = soup_message_new(request().httpMethod().utf8().data(), urlString.utf8().data());
    g_signal_connect(msg, "restarted", G_CALLBACK(restartedCallback), this);

    g_signal_connect(msg, "got-headers", G_CALLBACK(gotHeadersCallback), this);
    g_signal_connect(msg, "got-chunk", G_CALLBACK(gotChunkCallback), this);

    HTTPHeaderMap customHeaders = d->m_request.httpHeaderFields();
    if (!customHeaders.isEmpty()) {
        HTTPHeaderMap::const_iterator end = customHeaders.end();
        for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it)
            soup_message_headers_append(msg->request_headers, it->first.utf8().data(), it->second.utf8().data());
    }

    FormData* httpBody = d->m_request.httpBody();
    if (httpBody && !httpBody->isEmpty()) {
        // Making a copy of the request body isn't the most efficient way to
        // serialize it, but by far the most simple. Dealing with individual
        // FormData elements and shared buffers should be more memory
        // efficient.
        //
        // This possibly isn't handling file uploads/attachments, for which
        // shared buffers or streaming should definitely be used.
        Vector<char> body;
        httpBody->flatten(body);
        soup_message_set_request(msg, d->m_request.httpContentType().utf8().data(),
                                 SOUP_MEMORY_COPY, body.data(), body.size());
    }

    d->m_msg = static_cast<SoupMessage*>(g_object_ref(msg));
    soup_session_queue_message(session, d->m_msg, finishedCallback, this);

    return true;
}
static void addHeadersFromHashMap(CFMutableURLRequestRef request, const HTTPHeaderMap& requestHeaders)
{
    if (!requestHeaders.size())
        return;

    HTTPHeaderMap::const_iterator end = requestHeaders.end();
    for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) {
        CFStringRef key = it->first.createCFString();
        CFStringRef value = it->second.createCFString();
        CFURLRequestSetHTTPHeaderFieldValue(request, key, value);
        CFRelease(key);
        CFRelease(value);
    }
}
示例#17
0
static void addHeaders(JSContextRef context, JSObjectRef object, const HTTPHeaderMap& headers)
{
    ASSERT_ARG(context, context);
    ASSERT_ARG(object, object);
    
    HTTPHeaderMap::const_iterator end = headers.end();
    for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it) {
        JSStringRef field = JSStringCreateWithCharacters(it->first.characters(), it->first.length());
        JSStringRef valueString = JSStringCreateWithCharacters(it->second.characters(), it->second.length());
        JSValueRef value = JSValueMakeString(context, valueString);
        JSObjectSetProperty(context, object, field, value, kJSPropertyAttributeNone, 0);
        JSStringRelease(field);
        JSStringRelease(valueString);
    }
}
示例#18
0
static inline void setHeaderFields(CFMutableURLRequestRef request, const HTTPHeaderMap& requestHeaders) 
{
    // Remove existing headers first, as some of them may no longer be present in the map.
    RetainPtr<CFDictionaryRef> oldHeaderFields(AdoptCF, CFURLRequestCopyAllHTTPHeaderFields(request));
    CFIndex oldHeaderFieldCount = CFDictionaryGetCount(oldHeaderFields.get());
    if (oldHeaderFieldCount) {
        Vector<CFStringRef> oldHeaderFieldNames(oldHeaderFieldCount);
        CFDictionaryGetKeysAndValues(oldHeaderFields.get(), reinterpret_cast<const void**>(&oldHeaderFieldNames[0]), 0);
        for (CFIndex i = 0; i < oldHeaderFieldCount; ++i)
            CFURLRequestSetHTTPHeaderFieldValue(request, oldHeaderFieldNames[i], 0);
    }

    for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(), end = requestHeaders.end(); it != end; ++it)
        CFURLRequestSetHTTPHeaderFieldValue(request, it->key.string().createCFString().get(), it->value.createCFString().get());
}
示例#19
0
bool FetchUtils::isSimpleRequest(const String& method, const HTTPHeaderMap& headerMap)
{
    if (!isSimpleMethod(method))
        return false;

    HTTPHeaderMap::const_iterator end = headerMap.end();
    for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) {
        // Preflight is required for MIME types that can not be sent via form
        // submission.
        if (!isSimpleHeader(it->key, it->value))
            return false;
    }

    return true;
}
示例#20
0
static bool canSkipPrelight(PreflightResultCache::iterator cacheIt, bool includeCredentials, const String& method, const HTTPHeaderMap& requestHeaders)
{
    PreflightResultCacheItem* item = cacheIt->second;
    if (item->m_absoluteExpiryTime < currentTime())
        return false;
    if (includeCredentials && !item->m_credentials)
        return false;
    if (!item->m_methods->contains(method) && method != "GET" && method != "POST")
        return false;
    HTTPHeaderMap::const_iterator end = requestHeaders.end();
    for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) {
        if (!item->m_headers->contains(it->first) && !isOnAccessControlSimpleRequestHeaderWhitelist(it->first))
            return false;
    }

    return true;
}
示例#21
0
static ParsedContentRange parseContentRangeInHeader(const HTTPHeaderMap& headers)
{
    String contentRangeValue = headers.get(HTTPHeaderName::ContentRange);
    if (contentRangeValue.isEmpty())
        return ParsedContentRange();

    return ParsedContentRange(contentRangeValue);
}
示例#22
0
void WebSocketServerConnection::sendHTTPResponseHeader(int statusCode, const String& statusText, const HTTPHeaderMap& headerFields)
{
    StringBuilder builder;
    builder.append("HTTP/1.1 ");
    builder.append(String::number(statusCode));
    builder.append(" ");
    builder.append(statusText);
    builder.append("\r\n");
    HTTPHeaderMap::const_iterator end = headerFields.end();
    for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it) {
        builder.append(it->first);
        builder.append(": ");
        builder.append(it->second + "\r\n");
    }
    builder.append("\r\n");

    CString header = builder.toString().latin1();
    m_socket->send(header.data(), header.length());
}
SoupMessage* ResourceRequest::toSoupMessage() const
{
    SoupMessage* soupMessage = soup_message_new(httpMethod().utf8().data(), url().string().utf8().data());
    if (!soupMessage)
        return 0;

    HTTPHeaderMap headers = httpHeaderFields();
    SoupMessageHeaders* soupHeaders = soupMessage->request_headers;
    if (!headers.isEmpty()) {
        HTTPHeaderMap::const_iterator end = headers.end();
        for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
            soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data());
    }

    // Body data is only handled at ResourceHandleSoup::startHttp for
    // now; this is because this may not be a good place to go
    // openning and mmapping files. We should maybe revisit this.
    return soupMessage;
}
示例#24
0
static std::optional<std::chrono::system_clock::time_point> parseDateValueInHeader(const HTTPHeaderMap& headers, HTTPHeaderName headerName)
{
    String headerValue = headers.get(headerName);
    if (headerValue.isEmpty())
        return { };
    // This handles all date formats required by RFC2616:
    // Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
    // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
    // Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
    return parseHTTPDate(headerValue);
}
SoupMessage* ResourceResponse::toSoupMessage() const
{
    // This GET here is just because SoupMessage wants it, we dn't really know.
    SoupMessage* soupMessage = soup_message_new("GET", url().string().utf8().data());
    if (!soupMessage)
        return 0;

    soupMessage->status_code = httpStatusCode();

    HTTPHeaderMap headers = httpHeaderFields();
    SoupMessageHeaders* soupHeaders = soupMessage->response_headers;
    if (!headers.isEmpty()) {
        HTTPHeaderMap::const_iterator end = headers.end();
        for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
            soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data());
    }

    // Body data is not in the message.
    return soupMessage;
}
static double parseDateValueInHeader(const HTTPHeaderMap& headers, const AtomicString& headerName)
{
    const AtomicString& headerValue = headers.get(headerName);
    if (headerValue.isEmpty())
        return std::numeric_limits<double>::quiet_NaN();
    // This handles all date formats required by RFC2616:
    // Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
    // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
    // Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
    double dateInMilliseconds = parseDate(headerValue);
    if (!std::isfinite(dateInMilliseconds))
        return std::numeric_limits<double>::quiet_NaN();
    return dateInMilliseconds / 1000;
}
示例#27
0
void ResourceHandleManager::initializeHandle(ResourceHandle* job)
{
    KURL kurl = job->request().url();

    // Remove any fragment part, otherwise curl will send it as part of the request.
    kurl.setRef("");

    ResourceHandleInternal* d = job->getInternal();
    String url = kurl.string();

    if (kurl.isLocalFile()) {
        String query = kurl.query();
        // Remove any query part sent to a local file.
        if (!query.isEmpty())
            url = url.left(url.find(query));
        // Determine the MIME type based on the path.
        d->m_response.setMimeType(MIMETypeRegistry::getMIMETypeForPath(url));
    }

    d->m_handle = curl_easy_init();
#ifndef NDEBUG
    if (getenv("DEBUG_CURL"))
        curl_easy_setopt(d->m_handle, CURLOPT_VERBOSE, 1);
#endif
    curl_easy_setopt(d->m_handle, CURLOPT_PRIVATE, job);
    curl_easy_setopt(d->m_handle, CURLOPT_ERRORBUFFER, m_curlErrorBuffer);
    curl_easy_setopt(d->m_handle, CURLOPT_WRITEFUNCTION, writeCallback);
    curl_easy_setopt(d->m_handle, CURLOPT_WRITEDATA, job);
    curl_easy_setopt(d->m_handle, CURLOPT_HEADERFUNCTION, headerCallback);
    curl_easy_setopt(d->m_handle, CURLOPT_WRITEHEADER, job);
    curl_easy_setopt(d->m_handle, CURLOPT_AUTOREFERER, 1);
    curl_easy_setopt(d->m_handle, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(d->m_handle, CURLOPT_MAXREDIRS, 10);
    curl_easy_setopt(d->m_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    curl_easy_setopt(d->m_handle, CURLOPT_SHARE, m_curlShareHandle);
    curl_easy_setopt(d->m_handle, CURLOPT_DNS_CACHE_TIMEOUT, 60 * 5); // 5 minutes
    // FIXME: Enable SSL verification when we have a way of shipping certs
    // and/or reporting SSL errors to the user.
    if (ignoreSSLErrors)
        curl_easy_setopt(d->m_handle, CURLOPT_SSL_VERIFYPEER, false);
    // enable gzip and deflate through Accept-Encoding:
    curl_easy_setopt(d->m_handle, CURLOPT_ENCODING, "");

    // url must remain valid through the request
    ASSERT(!d->m_url);

    // url is in ASCII so latin1() will only convert it to char* without character translation.
    d->m_url = strdup(url.latin1().data());
    curl_easy_setopt(d->m_handle, CURLOPT_URL, d->m_url);

    if (m_cookieJarFileName) {
        curl_easy_setopt(d->m_handle, CURLOPT_COOKIEFILE, m_cookieJarFileName);
        curl_easy_setopt(d->m_handle, CURLOPT_COOKIEJAR, m_cookieJarFileName);
    }

    struct curl_slist* headers = 0;
    if (job->request().httpHeaderFields().size() > 0) {
        HTTPHeaderMap customHeaders = job->request().httpHeaderFields();
        HTTPHeaderMap::const_iterator end = customHeaders.end();
        for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) {
            String key = it->first;
            String value = it->second;
            String headerString(key);
            headerString.append(": ");
            headerString.append(value);
            CString headerLatin1 = headerString.latin1();
            headers = curl_slist_append(headers, headerLatin1.data());
        }
    }

    if ("GET" == job->request().httpMethod())
        curl_easy_setopt(d->m_handle, CURLOPT_HTTPGET, TRUE);
    else if ("POST" == job->request().httpMethod())
        setupPOST(job, &headers);
    else if ("PUT" == job->request().httpMethod())
        setupPUT(job, &headers);
    else if ("HEAD" == job->request().httpMethod())
        curl_easy_setopt(d->m_handle, CURLOPT_NOBODY, TRUE);

    if (headers) {
        curl_easy_setopt(d->m_handle, CURLOPT_HTTPHEADER, headers);
        d->m_customHeaders = headers;
    }
}
void ResourceRequestBase::addHTTPHeaderFields(const HTTPHeaderMap& headerFields)
{
    HTTPHeaderMap::const_iterator end = headerFields.end();
    for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it)
        addHTTPHeaderField(it->first, it->second);
}
示例#29
0
static HTTPHeaderMap parseRFC822HeaderFields(const char* bytes, unsigned length)
{
    String lastHeaderKey;
    HTTPHeaderMap headerFields;

    // Loop over lines until we're past the header, or we can't find any more end-of-lines
    while (const char* endOfLine = findEndOfLine(bytes, length)) {
        const char* line = bytes;
        int lineLength = endOfLine - bytes;

        // Move bytes to the character after the terminator as returned by findEndOfLine.
        bytes = endOfLine + 1;
        if ((*endOfLine == '\r') && (*bytes == '\n'))
            bytes++; // Safe since findEndOfLine won't return a spanning CRLF.

        length -= (bytes - line);
        if (!lineLength) {
            // Blank line; we're at the end of the header
            break;
        }

        if (*line == ' ' || *line == '\t') {
            // Continuation of the previous header
            if (lastHeaderKey.isNull()) {
                // malformed header; ignore it and continue
                continue;
            } 
            
            // Merge the continuation of the previous header
            String currentValue = headerFields.get(lastHeaderKey);
            String newValue(line, lineLength);
            
            headerFields.set(lastHeaderKey, currentValue + newValue);
        } else {
            // Brand new header
            const char* colon = line;
            while (*colon != ':' && colon != endOfLine)
                colon++;

            if (colon == endOfLine) {
                // malformed header; ignore it and continue
                continue;
            }

            lastHeaderKey = capitalizeRFC822HeaderFieldName(String(line, colon - line));
            String value;
            
            for (colon++; colon != endOfLine; colon++) {
                if (*colon != ' ' && *colon != '\t')
                    break;
            }
            if (colon == endOfLine)
                value = "";
            else
                value = String(colon, endOfLine - colon);
            
            String oldValue = headerFields.get(lastHeaderKey);
            if (!oldValue.isNull())
                value = oldValue + ", " + value;
            
            headerFields.set(lastHeaderKey, value);
        }
    }

    return headerFields;
}
void ResourceRequest::addHTTPHeaderFields(const HTTPHeaderMap& headerFields)
{
    HTTPHeaderMap::const_iterator end = headerFields.end();
    for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it)
        addHTTPHeaderField(it->key, it->value);
}