ResourceError ResourceError::tlsError(SoupRequest* request, unsigned tlsErrors, GTlsCertificate* certificate)
{
    ResourceError resourceError(g_quark_to_string(SOUP_HTTP_ERROR), SOUP_STATUS_SSL_FAILED,
        failingURI(request), unacceptableTLSCertificate());
    resourceError.setTLSErrors(tlsErrors);
    resourceError.setCertificate(certificate);
    return resourceError;
}
bool ResourceHandle::startHttp(String urlString)
{
    SoupSession* session = defaultSession();
    ensureSessionIsInitialized(session);

    d->m_msg = request().toSoupMessage();
    g_signal_connect(d->m_msg, "restarted", G_CALLBACK(restartedCallback), this);
    g_signal_connect(d->m_msg, "got-headers", G_CALLBACK(gotHeadersCallback), this);
    g_signal_connect(d->m_msg, "content-sniffed", G_CALLBACK(contentSniffedCallback), this);
    g_signal_connect(d->m_msg, "got-chunk", G_CALLBACK(gotChunkCallback), this);

    g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(this));

    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) {
                        ResourceError resourceError(g_quark_to_string(SOUP_HTTP_ERROR),
                                                    d->m_msg->status_code,
                                                    urlString,
                                                    String::fromUTF8(error->message));
                        g_error_free(error);

                        d->client()->didFail(this, resourceError);

                        g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
                                                             0, 0, 0, 0, this);
                        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);
                }
            }
        }
    }