#include #include #include #include #include #include "obs-app.hpp" #include "qt-wrappers.hpp" #define LOGO_URL "https://obsproject.com/assets/images/new_icon_small-r.png" static const QString serverResponseHeader = QStringLiteral("HTTP/1.0 200 OK\n" "Connection: close\n" "Content-Type: text/html; charset=UTF-8\n" "Server: OBS Studio\n" "\n" "OBS Studio" ""); static const QString responseTemplate = "
" "\"OBS\"" "
" "

%1

"; AuthListener::AuthListener(QObject *parent) : QObject(parent) { server = new QTcpServer(this); connect(server, &QTcpServer::newConnection, this, &AuthListener::NewConnection); if (!server->listen(QHostAddress::LocalHost, 0)) { blog(LOG_DEBUG, "Server could not start"); emit fail(); } else { blog(LOG_DEBUG, "Server started at port %d", server->serverPort()); } } quint16 AuthListener::GetPort() { return server ? server->serverPort() : 0; } void AuthListener::SetState(QString state) { this->state = state; } void AuthListener::NewConnection() { QTcpSocket *socket = server->nextPendingConnection(); if (socket) { connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater); connect(socket, &QTcpSocket::readyRead, socket, [&, socket]() { QByteArray buffer; while (socket->bytesAvailable() > 0) { buffer.append(socket->readAll()); } socket->write(QT_TO_UTF8(serverResponseHeader)); QString redirect = QString::fromLatin1(buffer); blog(LOG_DEBUG, "redirect: %s", QT_TO_UTF8(redirect)); QRegularExpression re_state( "(&|\\?)state=(?[^&]+)"); QRegularExpression re_code( "(&|\\?)code=(?[^&]+)"); QRegularExpressionMatch match = re_state.match(redirect); QString code; if (match.hasMatch()) { if (state == match.captured("state")) { match = re_code.match(redirect); if (!match.hasMatch()) blog(LOG_DEBUG, "no 'code' " "in server " "redirect"); code = match.captured("code"); } else { blog(LOG_WARNING, "state mismatch " "while handling " "redirect"); } } else { blog(LOG_DEBUG, "no 'state' in " "server redirect"); } if (code.isEmpty()) { auto data = responseTemplate.arg( QTStr("YouTube.Auth.NoCode")); socket->write(QT_TO_UTF8(data)); emit fail(); } else { auto data = responseTemplate.arg( QTStr("YouTube.Auth.Ok")); socket->write(QT_TO_UTF8(data)); emit ok(code); } socket->flush(); socket->close(); }); } else { emit fail(); } }