void ResourceRequest::updateSoupMessageMembers(SoupMessage* soupMessage) const { updateSoupMessageHeaders(soupMessage->request_headers); String firstPartyString = firstPartyForCookies().string(); if (!firstPartyString.isEmpty()) { GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data())); soup_message_set_first_party(soupMessage, firstParty.get()); } soup_message_set_flags(soupMessage, m_soupFlags); if (!acceptEncoding()) soup_message_disable_feature(soupMessage, SOUP_TYPE_CONTENT_DECODER); }
/* Downloads a feed specified in the request structure, returns the downloaded data or NULL in the request structure. If the webserver reports a permanent redirection, the feed url will be modified and the old URL 'll be freed. The request structure will also contain the HTTP status and the last modified string. */ void network_process_request (const updateJobPtr job) { SoupMessage *msg; SoupDate *date; gboolean do_not_track = FALSE; g_assert (NULL != job->request); debug1 (DEBUG_NET, "downloading %s", job->request->source); if (job->request->postdata && (debug_level & DEBUG_VERBOSE) && (debug_level & DEBUG_NET)) debug1 (DEBUG_NET, " postdata=>>>%s<<<", job->request->postdata); /* Prepare the SoupMessage */ msg = soup_message_new (job->request->postdata ? SOUP_METHOD_POST : SOUP_METHOD_GET, job->request->source); if (!msg) { g_warning ("The request for %s could not be parsed!", job->request->source); return; } /* Set the postdata for the request */ if (job->request->postdata) { soup_message_set_request (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_STATIC, /* libsoup won't free the postdata */ job->request->postdata, strlen (job->request->postdata)); } /* Set the If-Modified-Since: header */ if (job->request->updateState && update_state_get_lastmodified (job->request->updateState)) { gchar *datestr; date = soup_date_new_from_time_t (update_state_get_lastmodified (job->request->updateState)); datestr = soup_date_to_string (date, SOUP_DATE_HTTP); soup_message_headers_append (msg->request_headers, "If-Modified-Since", datestr); g_free (datestr); soup_date_free (date); } /* Set the If-None-Match header */ if (job->request->updateState && update_state_get_etag (job->request->updateState)) { soup_message_headers_append(msg->request_headers, "If-None-Match", update_state_get_etag (job->request->updateState)); } /* Set the I-AM header */ if (job->request->updateState && (update_state_get_lastmodified (job->request->updateState) || update_state_get_etag (job->request->updateState))) { soup_message_headers_append(msg->request_headers, "A-IM", "feed"); } /* Support HTTP content negotiation */ soup_message_headers_append(msg->request_headers, "Accept", "application/atom+xml,application/xml;q=0.9,text/xml;q=0.8,*/*;q=0.7"); /* Set the authentication */ if (!job->request->authValue && job->request->options && job->request->options->username && job->request->options->password) { SoupURI *uri = soup_message_get_uri (msg); soup_uri_set_user (uri, job->request->options->username); soup_uri_set_password (uri, job->request->options->password); } if (job->request->authValue) { soup_message_headers_append (msg->request_headers, "Authorization", job->request->authValue); } /* Add requested cookies */ if (job->request->updateState && job->request->updateState->cookies) { soup_message_headers_append (msg->request_headers, "Cookie", job->request->updateState->cookies); soup_message_disable_feature (msg, SOUP_TYPE_COOKIE_JAR); } /* TODO: Right now we send the msg, and if it requires authentication and * we didn't provide one, the petition fails and when the job is processed * it sees it needs authentication and displays a dialog, and if credentials * are entered, it queues a new job with auth credentials. Instead of that, * we should probably handle authentication directly here, connecting the * msg to a callback in case of 401 (see soup_message_add_status_code_handler()) * displaying the dialog ourselves, and requeing the msg if we get credentials */ /* Add Do Not Track header according to settings */ conf_get_bool_value (DO_NOT_TRACK, &do_not_track); if (do_not_track) soup_message_headers_append (msg->request_headers, "DNT", "1"); /* If the feed has "dont use a proxy" selected, use 'session2' which is non-proxy */ if (job->request->options && job->request->options->dontUseProxy) soup_session_queue_message (session2, msg, network_process_callback, job); else soup_session_queue_message (session, msg, network_process_callback, job); }
static bool startHttp(ResourceHandle* handle) { ASSERT(handle); SoupSession* session = handle->defaultSession(); ensureSessionIsInitialized(session); ResourceHandleInternal* d = handle->getInternal(); ResourceRequest request(handle->request()); KURL url(request.url()); url.removeFragmentIdentifier(); request.setURL(url); d->m_msg = request.toSoupMessage(); if (!d->m_msg) return false; if(!handle->shouldContentSniff()) soup_message_disable_feature(d->m_msg, SOUP_TYPE_CONTENT_SNIFFER); g_signal_connect(d->m_msg, "restarted", G_CALLBACK(restartedCallback), handle); g_signal_connect(d->m_msg, "got-headers", G_CALLBACK(gotHeadersCallback), handle); g_signal_connect(d->m_msg, "content-sniffed", G_CALLBACK(contentSniffedCallback), handle); g_signal_connect(d->m_msg, "got-chunk", G_CALLBACK(gotChunkCallback), handle); g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(handle)); FormData* httpBody = d->m_request.httpBody(); if (httpBody && !httpBody->isEmpty()) { size_t numElements = httpBody->elements().size(); // handle the most common case (i.e. no file upload) if (numElements < 2) { Vector<char> body; httpBody->flatten(body); soup_message_set_request(d->m_msg, d->m_request.httpContentType().utf8().data(), SOUP_MEMORY_COPY, body.data(), body.size()); } else { /* * we have more than one element to upload, and some may * be (big) files, which we will want to mmap instead of * copying into memory; TODO: support upload of non-local * (think sftp://) files by using GIO? */ soup_message_body_set_accumulate(d->m_msg->request_body, FALSE); for (size_t i = 0; i < numElements; i++) { const FormDataElement& element = httpBody->elements()[i]; if (element.m_type == FormDataElement::data) soup_message_body_append(d->m_msg->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size()); else { /* * mapping for uploaded files code inspired by technique used in * libsoup's simple-httpd test */ GError* error = 0; gchar* fileName = filenameFromString(element.m_filename); GMappedFile* fileMapping = g_mapped_file_new(fileName, false, &error); g_free(fileName); if (error) { g_error_free(error); g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, handle); g_object_unref(d->m_msg); d->m_msg = 0; return false; } SoupBuffer* soupBuffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(fileMapping), g_mapped_file_get_length(fileMapping), fileMapping, #if GLIB_CHECK_VERSION(2, 21, 3) reinterpret_cast<GDestroyNotify>(g_mapped_file_unref)); #else reinterpret_cast<GDestroyNotify>(g_mapped_file_free)); #endif soup_message_body_append_buffer(d->m_msg->request_body, soupBuffer); soup_buffer_free(soupBuffer); } } } }
/* Downloads a feed specified in the request structure, returns the downloaded data or NULL in the request structure. If the the webserver reports a permanent redirection, the feed url will be modified and the old URL 'll be freed. The request structure will also contain the HTTP status and the last modified string. */ void network_process_request (const updateJobPtr const job) { SoupMessage *msg; SoupDate *date; g_assert (NULL != job->request); debug1 (DEBUG_NET, "downloading %s", job->request->source); /* Prepare the SoupMessage */ msg = soup_message_new (job->request->postdata ? SOUP_METHOD_POST : SOUP_METHOD_GET, job->request->source); if (!msg) { g_warning ("The request for %s could not be parsed!", job->request->source); return; } /* Set the postdata for the request */ if (job->request->postdata) { soup_message_set_request (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_STATIC, /* libsoup won't free the postdata */ job->request->postdata, strlen (job->request->postdata)); } /* Set the If-Modified-Since: header */ if (job->request->updateState && job->request->updateState->lastModified) { gchar *datestr; date = soup_date_new_from_time_t (job->request->updateState->lastModified); datestr = soup_date_to_string (date, SOUP_DATE_HTTP); soup_message_headers_append (msg->request_headers, "If-Modified-Since", datestr); g_free (datestr); soup_date_free (date); } /* Set the authentication */ if (!job->request->authValue && job->request->options && job->request->options->username && job->request->options->password) { SoupURI *uri = soup_message_get_uri (msg); soup_uri_set_user (uri, job->request->options->username); soup_uri_set_password (uri, job->request->options->password); } if (job->request->authValue) { soup_message_headers_append (msg->request_headers, "Authorization", job->request->authValue); } /* Add requested cookies */ if (job->request->updateState && job->request->updateState->cookies) { soup_message_headers_append (msg->request_headers, "Cookie", job->request->updateState->cookies); soup_message_disable_feature (msg, SOUP_TYPE_COOKIE_JAR); } /* TODO: Right now we send the msg, and if it requires authentication and * we didn't provide one, the petition fails and when the job is processed * it sees it needs authentication and displays a dialog, and if credentials * are entered, it queues a new job with auth credentials. Instead of that, * we should probably handle authentication directly here, connecting the * msg to a callback in case of 401 (see soup_message_add_status_code_handler()) * displaying the dialog ourselves, and requeing the msg if we get credentials */ /* If the feed has "dont use a proxy" selected, disable the proxy for the msg */ if ((job->request->options && job->request->options->dontUseProxy) || (network_get_proxy_host () == NULL)) soup_message_disable_feature (msg, SOUP_TYPE_PROXY_URI_RESOLVER); soup_session_queue_message (session, msg, network_process_callback, job); }