void GoogleDocumentService::downloadDocument(const QString & _url, const QString & _type)
{
    authToken = docAuthToken;
    QString url = _url;
    QString type = _type;
    url.replace("docId", "docID", Qt::CaseInsensitive);
    QString exportFormat = "";

    if(QString::compare(type, "spreadsheet", Qt::CaseInsensitive) == 0) {
        exportFormat = "&exportFormat=ods&format=ods";
        authToken = spreadAuthToken;
    } else if(QString::compare(type, "presentation", Qt::CaseInsensitive) == 0) {
        exportFormat = "&exportFormat=ppt&format=ppt";
    }
    else if(QString::compare(type, "document", Qt::CaseInsensitive) == 0) {
        exportFormat = "&exportFormat=odt&format=odt";
    }

    qDebug() << "URL = " <<  url + exportFormat;
    QUrl documentUrl(url + exportFormat);

    QNetworkRequest requestHeader(documentUrl);
    requestHeader.setRawHeader("User-Agent", "Calligra");
    requestHeader.setRawHeader("GData-Version", "3.0");
    requestHeader.setRawHeader("Authorization", authToken.toUtf8());

    QList<QByteArray> headerlist = requestHeader.rawHeaderList();
    foreach (const QByteArray &element, headerlist)
        qDebug() << element << requestHeader.rawHeader(element);

    networkManager.get(requestHeader);

    waitingForDoc = true;

}
void GoogleDocumentService::listDocuments()
{
    authToken = docAuthToken;
    QString url;
    switch (m_type) {
    case OnlineDocument::WORDS:
        url = "https://docs.google.com/feeds/default/private/full/-/document";
        break;
    case OnlineDocument::STAGE:
        url = "https://docs.google.com/feeds/default/private/full/-/presentation";
        break;
    case OnlineDocument::SHEETS:
        url = "https://docs.google.com/feeds/default/private/full/-/spreadsheet";
        break;
    }

    QNetworkRequest requestHeader(QUrl(url.toUtf8()));
    requestHeader.setRawHeader("Host", "docs.google.com");
    requestHeader.setRawHeader("User-Agent", "Calligra");
    requestHeader.setRawHeader("GData-Version", "3.0");
    requestHeader.setRawHeader("Content-Type", "application/atom+xml");
    requestHeader.setRawHeader("Authorization", authToken.toUtf8());

    networkManager.get(requestHeader);
    emit progressUpdate("Successfully authenticated!!! Retreiving document list...");
}
Example #3
0
int HttpClient::requestHeader(Url &url, HttpHeader &header) {
    string headStr;
    int ret = requestHeader(url, headStr);
    header.setHeaderStr(headStr);
    return ret;

}
Example #4
0
QList<FormData> HTTPConnection::parseFormData() const {
    // make sure we have the correct MIME type
    QList<QByteArray> elements = requestHeader("Content-Type").split(';');

    QString contentType = elements.at(0).trimmed();

    if (contentType != "multipart/form-data") {
        return QList<FormData>();
    }

    // retrieve the boundary marker
    QByteArray boundary;
    for (int ii = 1, nn = elements.size(); ii < nn; ii++) {
        QByteArray element = elements.at(ii).trimmed();
        if (element.startsWith("boundary")) {
            boundary = element.mid(element.indexOf('=') + 1).trimmed();
            break;
        }
    }
    
    QByteArray start = "--" + boundary;
    QByteArray end = "\r\n--" + boundary + "--\r\n";

    QList<FormData> data;
    QBuffer buffer(const_cast<QByteArray*>(&_requestContent->content()));
    buffer.open(QIODevice::ReadOnly);
    while (buffer.canReadLine()) {
        QByteArray line = buffer.readLine().trimmed();
        if (line == start) {
            FormData datum;
            while (buffer.canReadLine()) {
                QByteArray line = buffer.readLine().trimmed();
                if (line.isEmpty()) {
                    // content starts after this line
                    int idx = _requestContent->content().indexOf(end, buffer.pos());
                    if (idx == -1) {
                        qWarning() << "Missing end boundary." << _address;
                        return data;
                    }
                    datum.second = QByteArray::fromRawData(_requestContent->content().data() + buffer.pos(),
                                                           idx - buffer.pos());
                    data.append(datum);
                    buffer.seek(idx + end.length());

                } else {
                    // it's a header element
                    int idx = line.indexOf(':');
                    if (idx == -1) {
                        qWarning() << "Invalid header line." << _address << line;
                        continue;
                    }
                    datum.first.insert(line.left(idx).trimmed(), line.mid(idx + 1).trimmed());
                }
            }
        }
    }

    return data;
}
Example #5
0
void HTTPConnection::readHeaders() {
    while (_socket->canReadLine()) {
        QByteArray line = _socket->readLine();
        QByteArray trimmed = line.trimmed();
        if (trimmed.isEmpty()) {
            _socket->disconnect(this, SLOT(readHeaders()));

            QByteArray clength = requestHeader("Content-Length");
            if (clength.isEmpty()) {
                _parentManager->handleHTTPRequest(this, _requestUrl);

            } else {
                bool success = false;
                auto length = clength.toInt(&success);
                if (!success) {
                    qWarning() << "Invalid header." << _address << trimmed;
                    respond("400 Bad Request", "The header was malformed.");
                    return;
                }

                // Storing big requests in memory gets expensive, especially on servers
                // with limited memory. So we store big requests in a temporary file on disk
                // and map it to faster read/write access.
                static const int MAX_CONTENT_SIZE_IN_MEMORY = 10 * 1000 * 1000;
                if (length < MAX_CONTENT_SIZE_IN_MEMORY) {
                    _requestContent = MemoryStorage::make(length);
                } else {
                    _requestContent = FileStorage::make(length);
                }

                connect(_socket, SIGNAL(readyRead()), SLOT(readContent()));

                // read any content immediately available
                readContent();
            }
            return;
        }
        char first = line.at(0);
        if (first == ' ' || first == '\t') { // continuation
            _requestHeaders[_lastRequestHeader].append(trimmed);
            continue;
        }
        int idx = trimmed.indexOf(':');
        if (idx == -1) {
            qWarning() << "Invalid header." << _address << trimmed;
            respond("400 Bad Request", "The header was malformed.");
            return;
        }
        _lastRequestHeader = trimmed.left(idx).toLower();
        QByteArray& value = _requestHeaders[_lastRequestHeader];
        if (!value.isEmpty()) {
            value.append(", ");
        }
        value.append(trimmed.mid(idx + 1).trimmed());
    }
}
Example #6
0
QHash<QString, QString> HTTPConnection::parseUrlEncodedForm() {
    // make sure we have the correct MIME type
    QList<QByteArray> elements = requestHeader("Content-Type").split(';');

    QString contentType = elements.at(0).trimmed();
    if (contentType != "application/x-www-form-urlencoded") {
        return QHash<QString, QString>();
    }

    QUrlQuery form { _requestContent->content() };
    QHash<QString, QString> pairs;
    for (auto pair : form.queryItems()) {
        auto key = QUrl::fromPercentEncoding(pair.first.toLatin1().replace('+', ' '));
        auto value = QUrl::fromPercentEncoding(pair.second.toLatin1().replace('+', ' '));
        pairs[key] = value;
    }

    return pairs;
}
Example #7
0
/** serializes the HTTP response status line plus headers into a byte-stream.
 *
 * This method is invoked right before the response content is written or the
 * response is flushed at all.
 *
 * It first sets the status code (if not done yet), invoked post_process callback,
 * performs connection-level response header modifications and then
 * builds the response chunk for status line and headers.
 *
 * Post-modification done <b>after</b> the post_process hook has been invoked:
 * <ol>
 *   <li>set status code to 200 (Ok) if not set yet.</li>
 *   <li>set Content-Type header to a default if not set yet.</li>
 *   <li>set Connection header to keep-alive or close (computed value)</li>
 *   <li>append Transfer-Encoding chunked if no Content-Length header is set.</li>
 *   <li>optionally enable TCP_CORK if this is no keep-alive connection and the administrator allows it.</li>
 * </ol>
 *
 * \note this does not serialize the message body.
 */
Source* HttpRequest::serialize()
{
	Buffer buffers;

	if (expectingContinue)
		status = HttpStatus::ExpectationFailed;
	else if (status == static_cast<HttpStatus>(0))
		status = HttpStatus::Ok;

	if (!responseHeaders.contains("Content-Type")) {
		responseHeaders.push_back("Content-Type", "text/plain"); //!< \todo pass "default" content-type instead!
	}

	if (connection.worker().server().advertise() && !connection.worker().server().tag().empty()) {
		if (!responseHeaders.contains("Server")) {
			responseHeaders.push_back("Server", connection.worker().server().tag());
		} else {
			responseHeaders.push_back("Via", connection.worker().server().tag());
		}
	}

	// post-response hook
	connection.worker().server().onPostProcess(this);

	// setup (connection-level) response transfer
	if (supportsProtocol(1, 1)
		&& !responseHeaders.contains("Content-Length")
		&& !responseHeaders.contains("Transfer-Encoding")
		&& !isResponseContentForbidden())
	{
		responseHeaders.push_back("Transfer-Encoding", "chunked");
		outputFilters.push_back(std::make_shared<ChunkedEncoder>());
	}

	bool keepalive = connection.shouldKeepAlive();
	if (!connection.worker().server().maxKeepAlive())
		keepalive = false;

	// remaining request count, that is allowed on a persistent connection
	std::size_t rlim = connection.worker().server().maxKeepAliveRequests();
	if (rlim) {
		rlim = connection.requestCount_ <= rlim
			? rlim - connection.requestCount_ + 1
			: 0;

		if (rlim == 0)
			// disable keep-alive, if max request count has been reached
			keepalive = false;
	}

	// only set Connection-response-header if found as request-header, too
	if (!requestHeader("Connection").empty() || keepalive != connection.shouldKeepAlive()) {
		if (keepalive) {
			responseHeaders.overwrite("Connection", "keep-alive");

			if (rlim) {
				// sent keep-alive timeout and remaining request count
				char buf[80];
				snprintf(buf, sizeof(buf), "timeout=%ld, max=%ld",
					static_cast<time_t>(connection.worker().server().maxKeepAlive().value()), rlim);
				responseHeaders.overwrite("Keep-Alive", buf);
			} else {
				// sent keep-alive timeout only (infinite request count)
				char buf[80];
				snprintf(buf, sizeof(buf), "timeout=%ld",
					static_cast<time_t>(connection.worker().server().maxKeepAlive().value()));
				responseHeaders.overwrite("Keep-Alive", buf);
			}
		} else
			responseHeaders.overwrite("Connection", "close");
	}

	connection.setShouldKeepAlive(keepalive);

	if (!connection.worker().server().tcpCork())
		connection.socket()->setTcpCork(true);

	if (supportsProtocol(1, 1))
		buffers.push_back("HTTP/1.1 ");
	else if (supportsProtocol(1, 0))
		buffers.push_back("HTTP/1.0 ");
	else
		buffers.push_back("HTTP/0.9 ");

	buffers.push_back(statusCodes_[static_cast<int>(status)]);
	buffers.push_back(' ');
	buffers.push_back(statusStr(status));
	buffers.push_back("\r\n");

	for (auto& i: responseHeaders) {
		buffers.push_back(i.name.data(), i.name.size());
		buffers.push_back(": ");
		buffers.push_back(i.value.data(), i.value.size());
		buffers.push_back("\r\n");
	};

	buffers.push_back("\r\n");

	return new BufferSource(std::move(buffers));
}