/**
 * @brief   Set the AWS custom date header.
 *
 * If \a request does not already contain an `x-amz-date` header, then this function
 * will set a custom `x-amz-date` header to the value of \p dateTime formatted like
 * "Fri, 09 Sep 2011 23:36:00 GMT".
 *
 * @param   request   The network request to add the date header to.
 * @param   dateTime  The timestamp (in UTC) to set the date header's value to.
 */
void AwsSignatureV3Private::setDateHeader(QNetworkRequest &request, const QDateTime &dateTime) const
{
    Q_ASSERT(dateTime.timeSpec() == Qt::UTC);
    if (!request.hasRawHeader("x-amz-date")) {
        request.setRawHeader("x-amz-date", dateTime.toString(QLatin1String("ddd, dd MMM yyyy hh:mm:ss 'GMT'")).toUtf8());
    }
}
/**
 * @brief  Set authorization header on a network request.
 *
 * This function will calculate the authorization header value and set it as the `Authorization`
 * HTTP header on \p request.
 *
 * @param[in]     credentials  The AWS credentials to use to sign the request.
 * @param[in]     operation    The HTTP method being used for the request.
 * @param[in,out] request      The network request to add the authorization header to.
 * @param[in]     payload      Optional data being submitted in the request (eg for `PUT` and `POST` operations).
 *
 * @see    http://docs.aws.amazon.com/general/latest/gr/sigV3-signed-request-examples.html
 * @see    authorizationHeaderValue
 */
void AwsSignatureV3Private::setAuthorizationHeader(const AwsAbstractCredentials &credentials,
                                                   const QNetworkAccessManager::Operation operation,
                                                   QNetworkRequest &request, const QByteArray &payload) const
{
    Q_ASSERT(!request.hasRawHeader("Authorization"));
    request.setRawHeader("Authorization", authorizationHeaderValue(credentials, operation, request, payload));
}
Exemple #3
0
void DeleteJob::dispatchRequest(QNetworkAccessManager* accessManager, const QNetworkRequest& request, const QByteArray& data, const QString& contentType)
{
    Q_UNUSED(data)
    Q_UNUSED(contentType)

    QNetworkRequest r = request;
    if (!r.hasRawHeader("If-Match")) {
        r.setRawHeader("If-Match", "*");
    }

    accessManager->deleteResource(r);
}
/**
 * @brief  Create an AWS V3 Signature canonical request.
 *
 * Note, this function implments both `AWS3` and `AWS3-HTTPS` variants of the
 * AWS Signature version 3 - which are quite different.
 *
 * @param[in]  operation      The HTTP method being used for the request.
 * @param[in]  request        The network request to generate a canonical request for.
 * @param[in]  payload        Optional data being submitted in the request (eg for `PUT` and `POST` operations).
 * @param[out] signedHeaders  A semi-colon separated list of the names of all headers
 *                            included in the result.
 *
 * @return  An AWS V3 Signature canonical request.
 *
 * @see  http://docs.aws.amazon.com/amazonswf/latest/developerguide/HMACAuth-swf.html (AWS3)
 * @see  http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/RESTAuthentication.html (AWS3-HTTPS)
 */
QByteArray AwsSignatureV3Private::canonicalRequest(const QNetworkAccessManager::Operation operation,
                                                   const QNetworkRequest &request, const QByteArray &payload,
                                                   QByteArray * const signedHeaders) const
{
    // AWS3-HTTPS
    if (isHttps(request)) {
        Q_ASSERT((request.hasRawHeader("x-amz-date")) || (request.hasRawHeader("Date")));
        QByteArray canonicalRequest = request.rawHeader(request.hasRawHeader("x-amz-date") ? "x-amz-date" : "Date");
        if (request.hasRawHeader("x-amz-nonce")) {
            canonicalRequest += request.rawHeader("x-amz-nonce");
        }
        return canonicalRequest;
    }

    // AWS3
    return httpMethod(operation).toUtf8() + '\n' +
           canonicalPath(request.url()).toUtf8() + '\n' +
           canonicalQuery(QUrlQuery(request.url()))  + '\n' +
           canonicalHeaders(request, signedHeaders) + '\n' +
           payload;
}
QNetworkRequest ResourceRequest::toNetworkRequest(QObject* originatingFrame) const
{
    QNetworkRequest request;
    request.setUrl(url());
    request.setOriginatingObject(originatingFrame);

    const HTTPHeaderMap &headers = httpHeaderFields();
    for (HTTPHeaderMap::const_iterator it = headers.begin(), end = headers.end();
         it != end; ++it) {
        QByteArray name = QString(it->first).toAscii();
        QByteArray value = QString(it->second).toAscii();
        // QNetworkRequest::setRawHeader() would remove the header if the value is null
        // Make sure to set an empty header instead of null header.
        if (!value.isNull())
            request.setRawHeader(name, value);
        else
            request.setRawHeader(name, "");
    }

    // Make sure we always have an Accept header; some sites require this to
    // serve subresources
    if (!request.hasRawHeader("Accept"))
        request.setRawHeader("Accept", "*/*");

    switch (cachePolicy()) {
    case ReloadIgnoringCacheData:
        request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
        break;
    case ReturnCacheDataElseLoad:
        request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
        break;
    case ReturnCacheDataDontLoad:
        request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
        break;
    case UseProtocolCachePolicy:
        // QNetworkRequest::PreferNetwork
    default:
        break;
    }

    if (!allowCookies() || !thirdPartyCookiePolicyPermitsForFrame(originatingFrame, url(), firstPartyForCookies())) {
        request.setAttribute(QNetworkRequest::CookieSaveControlAttribute, QNetworkRequest::Manual);
        request.setAttribute(QNetworkRequest::CookieLoadControlAttribute, QNetworkRequest::Manual);
    }

    if (!allowCookies())
        request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual);

    return request;
}
void AwsSignatureV3::sign(const AwsAbstractCredentials &credentials,
                          const QNetworkAccessManager::Operation operation,
                          QNetworkRequest &request, const QByteArray &data) const
{
    Q_D(const AwsSignatureV3);

    // Note, the use of a nonce value with AWS3-HTTPS is undocumented, but done by the
    // official Java SDK, and worth copying for additional security.
    if ((d->isHttps(request)) && (!request.hasRawHeader("x-amz-nonce"))) {
        request.setRawHeader("x-amz-nonce", QUuid::createUuid().toByteArray().mid(1,36));
    }

    d->setDateHeader(request);
    d->setAuthorizationHeader(credentials, operation, request, data);
}
Exemple #7
0
QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
{
    // copy the request, we probably need to add some headers
    QNetworkRequest newRequest(request);

    // add Content-Type header if not there already
    if (!request.header(QNetworkRequest::ContentTypeHeader).isValid()) {
        QByteArray contentType;
        contentType.reserve(34 + multiPart->d_func()->boundary.count());
        contentType += "multipart/";
        switch (multiPart->d_func()->contentType) {
        case QHttpMultiPart::RelatedType:
            contentType += "related";
            break;
        case QHttpMultiPart::FormDataType:
            contentType += "form-data";
            break;
        case QHttpMultiPart::AlternativeType:
            contentType += "alternative";
            break;
        default:
            contentType += "mixed";
            break;
        }
        // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1
        contentType += "; boundary=\"" + multiPart->d_func()->boundary + "\"";
        newRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType));
    }

    // add MIME-Version header if not there already (we must include the header
    // if the message conforms to RFC 2045, see section 4 of that RFC)
    QByteArray mimeHeader("MIME-Version");
    if (!request.hasRawHeader(mimeHeader))
        newRequest.setRawHeader(mimeHeader, QByteArray("1.0"));

    QIODevice *device = multiPart->d_func()->device;
    if (!device->isReadable()) {
        if (!device->isOpen()) {
            if (!device->open(QIODevice::ReadOnly))
                qWarning("could not open device for reading");
        } else {
            qWarning("device is not readable");
        }
    }

    return newRequest;
}
Exemple #8
0
void AccessManager::AccessManagerPrivate::setMetaDataForRequest(QNetworkRequest request, KIO::MetaData& metaData)
{
    // Add any meta data specified within request...
    QVariant userMetaData = request.attribute (static_cast<QNetworkRequest::Attribute>(MetaData));
    if (userMetaData.isValid() && userMetaData.type() == QVariant::Map)
        metaData += userMetaData.toMap();

    metaData.insert(QL1S("PropagateHttpHeader"), QL1S("true"));

    if (request.hasRawHeader("User-Agent")) {
        metaData.insert(QL1S("UserAgent"), request.rawHeader("User-Agent"));
        request.setRawHeader("User-Agent", QByteArray());
    }

    if (request.hasRawHeader("Accept")) {
        metaData.insert(QL1S("accept"), request.rawHeader("Accept"));
        request.setRawHeader("Accept", QByteArray());
    }

    if (request.hasRawHeader("Accept-Charset")) {
        metaData.insert(QL1S("Charsets"), request.rawHeader("Accept-Charset"));
        request.setRawHeader("Accept-Charset", QByteArray());
    }

    if (request.hasRawHeader("Accept-Language")) {
        metaData.insert(QL1S("Languages"), request.rawHeader("Accept-Language"));
        request.setRawHeader("Accept-Language", QByteArray());
    }

    if (request.hasRawHeader("Referer")) {
        metaData.insert(QL1S("referrer"), request.rawHeader("Referer"));
        request.setRawHeader("Referer", QByteArray());
    }

    if (request.hasRawHeader("Content-Type")) {
        metaData.insert(QL1S("content-type"), request.rawHeader("Content-Type"));
        request.setRawHeader("Content-Type", QByteArray());
    }

    if (request.attribute(QNetworkRequest::AuthenticationReuseAttribute) == QNetworkRequest::Manual) {
        metaData.insert(QL1S("no-preemptive-auth-reuse"), QL1S("true"));
    }

    request.setRawHeader("Content-Length", QByteArray());
    request.setRawHeader("Connection", QByteArray());
    request.setRawHeader("If-None-Match", QByteArray());
    request.setRawHeader("If-Modified-Since", QByteArray());
    request.setRawHeader("x-kdewebkit-ignore-disposition", QByteArray());

    QStringList customHeaders;
    Q_FOREACH(const QByteArray &key, request.rawHeaderList()) {
        const QByteArray value = request.rawHeader(key);
        if (value.length())
            customHeaders << (key + QL1S(": ") + value);
    }

    if (!customHeaders.isEmpty()) {
        metaData.insert(QL1S("customHTTPHeader"), customHeaders.join("\r\n"));
    }

    // Append per request meta data, if any...
    if (!requestMetaData.isEmpty()) {
        metaData += requestMetaData;
        // Clear per request meta data...
        requestMetaData.clear();
    }

    // Append per session meta data, if any...
    if (!sessionMetaData.isEmpty()) {
        metaData += sessionMetaData;
    }
}
/**
 * @brief   Set the AWS custom date header.
 *
 * This function will set a custom `x-amz-date` header to the value of \p dateTime
 * formatted to AwsSignatureV4Private::DateTimeFormat.
 *
 * @note    Although Amazon labels this as a "date", it is in fact a full timestamp.
 *
 * @param   request   The network request to add the date header to.
 * @param   dateTime  The timestamp to set the date header's value to.
 *
 * @return  \p dateTime verbatim (just a convenience for some callers).
 */
QDateTime AwsSignatureV4Private::setDateHeader(QNetworkRequest &request, const QDateTime &dateTime) const
{
    Q_ASSERT(!request.hasRawHeader("x-amz-date"));
    request.setRawHeader("x-amz-date", dateTime.toString(DateTimeFormat).toUtf8());
    return dateTime;
}