/* SPDX-FileCopyrightText: 2026 Project Tick * SPDX-FileContributor: Project Tick * SPDX-License-Identifier: GPL-3.0-or-later * * MeshMC - A Custom Launcher for Minecraft * Copyright (C) 2026 Project Tick * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "Application.h" #include "AuthRequest.h" #include "katabasis/Globals.h" AuthRequest::AuthRequest(QObject* parent) : QObject(parent) {} AuthRequest::~AuthRequest() {} void AuthRequest::get(const QNetworkRequest& req, int timeout /* = 60*1000*/) { setup(req, QNetworkAccessManager::GetOperation); reply_ = APPLICATION->network()->get(request_); status_ = Requesting; timedReplies_.add(new Katabasis::Reply(reply_, timeout)); connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError))); connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished())); connect(reply_, &QNetworkReply::sslErrors, this, &AuthRequest::onSslErrors); } void AuthRequest::post(const QNetworkRequest& req, const QByteArray& data, int timeout /* = 60*1000*/) { setup(req, QNetworkAccessManager::PostOperation); data_ = data; status_ = Requesting; reply_ = APPLICATION->network()->post(request_, data_); timedReplies_.add(new Katabasis::Reply(reply_, timeout)); connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError))); connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished())); connect(reply_, &QNetworkReply::sslErrors, this, &AuthRequest::onSslErrors); connect(reply_, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(onUploadProgress(qint64, qint64))); } void AuthRequest::onRequestFinished() { if (status_ == Idle) { return; } if (reply_ != qobject_cast(sender())) { return; } httpStatus_ = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); finish(); } void AuthRequest::onRequestError(QNetworkReply::NetworkError error) { qWarning() << "AuthRequest::onRequestError: Error" << (int)error; if (status_ == Idle) { return; } if (reply_ != qobject_cast(sender())) { return; } errorString_ = reply_->errorString(); httpStatus_ = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); error_ = error; qWarning() << "AuthRequest::onRequestError: Error string: " << errorString_; qWarning() << "AuthRequest::onRequestError: HTTP status" << httpStatus_ << reply_->attribute(QNetworkRequest::HttpReasonPhraseAttribute) .toString(); // QTimer::singleShot(10, this, SLOT(finish())); } void AuthRequest::onSslErrors(QList errors) { int i = 1; for (auto error : errors) { qCritical() << "LOGIN SSL Error #" << i << " : " << error.errorString(); auto cert = error.certificate(); qCritical() << "Certificate in question:\n" << cert.toText(); i++; } } void AuthRequest::onUploadProgress(qint64 uploaded, qint64 total) { if (status_ == Idle) { qWarning() << "AuthRequest::onUploadProgress: No pending request"; return; } if (reply_ != qobject_cast(sender())) { return; } // Restart timeout because request in progress Katabasis::Reply* o2Reply = timedReplies_.find(reply_); if (o2Reply) { o2Reply->start(); } emit uploadProgress(uploaded, total); } void AuthRequest::setup(const QNetworkRequest& req, QNetworkAccessManager::Operation operation, const QByteArray& verb) { request_ = req; operation_ = operation; url_ = req.url(); QUrl url = url_; request_.setUrl(url); if (!verb.isEmpty()) { request_.setRawHeader(Katabasis::HTTP_HTTP_HEADER, verb); } status_ = Requesting; error_ = QNetworkReply::NoError; errorString_.clear(); httpStatus_ = 0; } void AuthRequest::finish() { QByteArray data; if (status_ == Idle) { qWarning() << "AuthRequest::finish: No pending request"; return; } data = reply_->readAll(); status_ = Idle; timedReplies_.remove(reply_); reply_->disconnect(this); reply_->deleteLater(); QList headers = reply_->rawHeaderPairs(); emit finished(error_, data, headers); }