File indexing completed on 2024-12-22 04:57:54

0001 /*
0002     SPDX-License-Identifier: BSD-2-Clause
0003 */
0004 
0005 #include "debug.h"
0006 #include <QPair>
0007 #include <QTcpSocket>
0008 #include <QUrl>
0009 #if QT_VERSION >= 0x050000
0010 #include <QUrlQuery>
0011 #endif
0012 
0013 #include "o2/o2replyserver.h"
0014 
0015 O2ReplyServer::O2ReplyServer(QObject *parent)
0016     : QTcpServer(parent)
0017 {
0018     connect(this, &QTcpServer::newConnection, this, &O2ReplyServer::onIncomingConnection);
0019     replyContent_ = QByteArrayLiteral("<HTML></HTML>");
0020 }
0021 
0022 void O2ReplyServer::onIncomingConnection()
0023 {
0024     QTcpSocket *socket = nextPendingConnection();
0025     connect(socket, &QIODevice::readyRead, this, &O2ReplyServer::onBytesReady, Qt::UniqueConnection);
0026     connect(socket, &QAbstractSocket::disconnected, socket, &QObject::deleteLater);
0027 }
0028 
0029 void O2ReplyServer::onBytesReady()
0030 {
0031     qCDebug(TOMBOYNOTESRESOURCE_LOG) << "O2ReplyServer::onBytesReady";
0032     auto socket = qobject_cast<QTcpSocket *>(sender());
0033     if (!socket) {
0034         return;
0035     }
0036     QByteArray reply;
0037     reply.append("HTTP/1.0 200 OK \r\n");
0038     reply.append("Content-Type: text/html; charset=\"utf-8\"\r\n");
0039     reply.append(QByteArray("Content-Length: ") + QByteArray::number(replyContent_.size()) + "\r\n\r\n");
0040     reply.append(replyContent_);
0041     socket->write(reply);
0042 
0043     QByteArray data = socket->readAll();
0044     QMultiMap<QString, QString> queryParams = parseQueryParams(&data);
0045     socket->disconnectFromHost();
0046     close();
0047     Q_EMIT verificationReceived(queryParams);
0048 }
0049 
0050 QMultiMap<QString, QString> O2ReplyServer::parseQueryParams(QByteArray *data)
0051 {
0052     qCDebug(TOMBOYNOTESRESOURCE_LOG) << "O2ReplyServer::parseQueryParams";
0053 
0054     QString splitGetLine = QString::fromLatin1(*data).split(QStringLiteral("\r\n")).first();
0055     splitGetLine.remove(QStringLiteral("GET "));
0056     splitGetLine.remove(QStringLiteral("HTTP/1.1"));
0057     splitGetLine.remove(QStringLiteral("\r\n"));
0058     splitGetLine.prepend(QStringLiteral("http://localhost"));
0059     QUrl getTokenUrl(splitGetLine);
0060 
0061     QList<QPair<QString, QString>> tokens;
0062 #if QT_VERSION < 0x050000
0063     tokens = getTokenUrl.queryItems();
0064 #else
0065     QUrlQuery query(getTokenUrl);
0066     tokens = query.queryItems();
0067 #endif
0068     QMultiMap<QString, QString> queryParams;
0069     for (const auto &tokenPair : std::as_const(tokens)) {
0070         // FIXME: We are decoding key and value again. This helps with Google OAuth, but is it mandated by the standard?
0071         const QString key = QUrl::fromPercentEncoding(tokenPair.first.trimmed().toLatin1());
0072         const QString value = QUrl::fromPercentEncoding(tokenPair.second.trimmed().toLatin1());
0073         queryParams.insert(key, value);
0074     }
0075     return queryParams;
0076 }
0077 
0078 QByteArray O2ReplyServer::replyContent() const
0079 {
0080     return replyContent_;
0081 }
0082 
0083 void O2ReplyServer::setReplyContent(const QByteArray &value)
0084 {
0085     replyContent_ = value;
0086 }
0087 
0088 #include "moc_o2replyserver.cpp"