/* Copyright (C) 2022 The Qt Company Ltd. * * SPDX-License-Identifier: GPL-3.0-only WITH Qt-GPL-exception-1.0 */ #include "clienthandler.h" #include "commonsetup.h" #include "jsonhandler.h" #include "utils.h" namespace QLicenseService { bool ClientHandler::checkLicenseExpiryTime(std::string &reply) { if (m_floatingLicense) { // No checking from stored files in case of floating license return false; } std::cout << "Offline - checking validity from license file " << m_request.licenseFile << std::endl; // Open the license file std::string data; if (utils::readFile(data, m_request.licenseFile) != 0) { std::cout << "No license file - rejecting license " << m_request.licenseFile << std::endl; reply = replyString[e_bad_connection]; return false; } JsonHandler license(data); // Check license status if (license.get("status") != "true") { std::cout << "License status = false: Rejecting license\n"; reply = replyString[e_bad_connection]; return false; } // Expiry date. Add 1 day to expiry date to get the end actually at the beginning of the next day std::string expDate = license.get("expiry_date"); std::time_t expEpoch = utils::stringToEpoch(expDate.c_str()) + SECS_IN_DAY; // Current date std::time_t current = std::time(0); // See if the time has expire if (current > expEpoch) { // Store the leeway time if applicable if (license.get("leeway_hours") != "") { m_license.leeway_hours = license.getInt("leeway_hours"); m_license.current_timestamp = current; m_license.expiry_epoch = expEpoch; } return false; } std::cout << "License granted, expires at " << expDate << std::endl; reply = replyString[e_license_granted]; return true; } int ClientHandler::parseRequest() { // First find out the command, and drop it out from the list std::string cmd = utils::trimStr(params[0]); params.erase(params.begin()); m_request.reqType = RequestType::no_request; if (cmd == LICENSE_REQUEST_CMD) { m_request.reqType = RequestType::license_request; m_request.accessPoint = m_settings.get("reservation_access_point"); } else if (cmd ==PERMANENT_REQUEST_CMD) { m_request.reqType = RequestType::long_term_request; m_request.accessPoint = m_settings.get("permanent_access_point"); // find either 'add' or 'remove' if (params.size() > 0) { if (params[0] != OP_ADD_RESERVATION && params[0] != OP_REMOVE_RESERVATION) { std::cout << "Invalid operation for permanent request: " << params[0] << std::endl; return e_bad_request; } m_request.operation = params[0]; } else { std::cout << "No operation for permanent request: 'add' or 'remove' needed\n"; return e_bad_request; } // Found and operation: Not needed in the list any more params.erase(params.begin()); } else if (cmd == SERVER_VERSION_CMD) { m_request.reqType = RequestType::server_version; m_request.accessPoint = m_settings.get("version_query_access_point"); } else if (cmd == DAEMON_VERSION_CMD) { m_request.reqType = RequestType::daemon_version; } else if (cmd == RESERVATION_QUERY_CMD) { m_request.reqType = RequestType::reservation_query; } else { std::cout << "Invalid command: " << cmd << std::endl; return e_bad_request; } bool argFound = false; std::string arg; for (const std::string &item : params) { if (item.empty()) { continue; } if (!argFound) { if (item[0] == '-') { arg = item; argFound = true; continue; } else { std::cout << "Not a valid argument: \"" << item << "\"\n"; return e_bad_request; } } else { if (arg == "-a") m_request.appName = utils::strToLower(item); else if (arg == "-v") m_request.appVersion = item; else if (arg == "-u") m_request.userId = item; else if (arg == "-i") m_request.licenseId = item; else if (arg == "-p") m_request.parentReservationId = item; else if (arg == "-r") m_request.runnerType = item; else if (arg == "-e") m_request.email = item; else if (arg == "-l") m_request.serverAddr = item; else { std::cout << "Invalid argument: \"" << arg << "\"\n"; return e_bad_request; } argFound = false; arg = ""; } } // Check if we're run out of items in argument list without getting the value: if (argFound) { std::cout << "No value for argument: \"" << arg << "\"\n"; return e_bad_request; } if (!m_request.parentReservationId.empty()) { m_hasParent = true; } std::stringstream ss; ss << WORKING_DIR << DIR_SEPARATOR << LICENSE_FILE_PREFIX; ss << m_request.userId << "_" << m_request.licenseId << LICENSE_FILE_EXTENSION; m_request.licenseFile += ss.str(); buildRequestJson(); return 0; } bool ClientHandler::checkLeewayTime(std::string &reply) { // Leeway time granted? if (m_license.leeway_hours == 0) { return false; } // License expired and offline: Allow some leeway time int leewayTimeLeft = m_license.expiry_epoch + (m_license.leeway_hours * SECS_IN_HOUR) - m_license.current_timestamp; if (leewayTimeLeft > 0) { std::stringstream ss; ss << replyString[e_no_conn_leeway] << std::fixed << std::setprecision(1) << (float)leewayTimeLeft / SECS_IN_DAY << " days"; reply = ss.str(); return true; } return false; } void ClientHandler::updateLicense(const std::string &responseJson) { JsonHandler json(responseJson); m_license.status = json.getBool("status"); m_license.message = json.get("message"); m_license.leeway_hours = json.getInt("leeway_hours"); m_license.last_timestamp = utils::getTimestampNow(); m_license.expiry_date = json.get("expiry_date"); m_license.license_key = json.get("license_key"); m_license.license_id = json.get("license_number"); m_license.reservation_id = json.get("reservation_id"); m_license.user_id = json.get("user_id"); } void ClientHandler::addChildClient(ClientHandler *client) { m_childClients[client->getSocketId()] = client; } void ClientHandler::removeCachedFile() { utils::deleteFile(m_request.licenseFile); } void ClientHandler::resetTime() { m_license.last_timestamp = utils::getTimestampNow(); } bool ClientHandler::removeChildClient(uint16_t socketId) { if (m_childClients.find(socketId) != m_childClients.end()) { ClientHandler *client = m_childClients[socketId]; m_childClients.erase(socketId); delete client; return true; } return false; } bool ClientHandler::clientInStorage(uint16_t socketId) { if (m_childClients.find(socketId) != m_childClients.end()) { return true; } return false; } } // namespace QLicenseService