// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial #include "axivionresultparser.h" #include #include #include #include #include namespace Axivion::Internal { static std::pair splitHeaderAndBody(const QByteArray &input) { QByteArray header; QByteArray json; int emptyLine = input.indexOf("\r\n\r\n"); // we always get \r\n as line separator if (emptyLine != -1) { header = input.left(emptyLine); json = input.mid(emptyLine + 4); } else { json = input; } return {header, json}; } static int httpStatus(const QByteArray &header) { int firstHeaderEnd = header.indexOf("\r\n"); if (firstHeaderEnd == -1) return 600; // unexpected header const QString firstLine = QString::fromUtf8(header.first(firstHeaderEnd)); static const QRegularExpression regex(R"(^HTTP/\d\.\d (\d{3}) .*$)"); const QRegularExpressionMatch match = regex.match(firstLine); return match.hasMatch() ? match.captured(1).toInt() : 601; } static std::pair prehandleHeaderAndBody(const QByteArray &header, const QByteArray &body) { BaseResult result; if (header.isEmpty()) { result.error = QString::fromUtf8(body); // we likely had a curl problem return {result, {}}; } int status = httpStatus(header); if ((status > 399) || (status > 299 && body.isEmpty())) { // FIXME handle some explicitly? const QString statusStr = QString::number(status); if (body.isEmpty() || body.startsWith('<')) // likely an html response or redirect result.error = QLatin1String("(%1)").arg(statusStr); else result.error = QLatin1String("%1 (%2)").arg(QString::fromUtf8(body)).arg(statusStr); return {result, {}}; } QJsonParseError error; const QJsonDocument doc = QJsonDocument::fromJson(body, &error); if (error.error != QJsonParseError::NoError) { result.error = error.errorString(); return {result, doc}; } if (!doc.isObject()) { result.error = "Not an object."; return {result, {}}; } return {result, doc}; } namespace ResultParser { DashboardInfo parseDashboardInfo(const QByteArray &input) { DashboardInfo result; auto [header, body] = splitHeaderAndBody(input); auto [error, doc] = prehandleHeaderAndBody(header, body); if (!error.error.isEmpty()) { result.error = error.error; return result; } const QJsonObject object = doc.object(); result.mainUrl = object.value("mainUrl").toString(); if (!object.contains("projects")) { result.error = "Missing projects information."; return result; } const QJsonValue projects = object.value("projects"); if (!projects.isArray()) { result.error = "Projects information not an array."; return result; } const QJsonArray array = projects.toArray(); for (const QJsonValue &val : array) { if (!val.isObject()) continue; const QJsonObject projectObject = val.toObject(); Project project; project.name = projectObject.value("name").toString(); project.url = projectObject.value("url").toString(); if (project.name.isEmpty() || project.url.isEmpty()) continue; result.projects.append(project); } return result; } } // ResultParser } // Axivion::Internal