/* Copyright (C) 2022 The Qt Company Ltd. * * SPDX-License-Identifier: GPL-3.0-only WITH Qt-GPL-exception-1.0 */ #include "licdsetup.h" #include "commonsetup.h" #include "utils.h" namespace QLicenseService { LicdSetup::LicdSetup(int type, const std::string &settingsFilePath, const std::string &callerBinaryPath) : m_settingsFilePath(settingsFilePath) , m_setType(type) { if (m_setType == e_set_type_moc) m_tag = parseSettingTag(callerBinaryPath); else if (m_setType != e_set_type_daemon) m_tag = DEFAULT_USER_SETTINGS_TAG; } std::string LicdSetup::get(const std::string &item) { try { auto x = m_settings.at(item); } catch (...) { std::cout << "Warning: No settings item '" << item << "' found\n"; return ""; } return m_settings[item]; } void LicdSetup::set(const std::string &item, const std::string &value) { //std::cout << "Setting '" << item << "' to '" << value << "'\n"; m_settings[item] = value; } int LicdSetup::initSettings() { int result = 0; if (m_setType == e_set_type_daemon) { // read daemon info result = getDaemonInfo(); // Check if our setup already has some hw id - generate one if not if (get("hw_id").empty()) setHwId(); } else { // Read user info result = getUserInfo(); if (result == e_file_not_present) { // No settings file found: Create it if (createUserSettingsFile() != 0) { std::cout << "WARNING! Not able to create settings file\n"; } return e_file_not_present; } else if (result == e_no_settings_tag && m_setType != e_set_type_licensetool) { std::string content = getTaggedSettingsSkeleton(); if (appendNewSection(content) != 0) { std::cout << "WARNING! Not able to write into settings file\n"; } } } if (result == e_general_file_error) { std::cout << "Error reading file:\n"; return e_general_file_error; } else if (result == e_file_invalid_content) { std::cout << "Error somewhere in settings:\n"; for (auto& item: m_settings) { std::cout << item.first << ": " << item.second << '\n'; } return e_file_invalid_content; } return e_settings_ok; } void LicdSetup::setHwId() { std::cout << "No HW ID found, generating it ... "; const std::string hwInfo = utils::getSystemHwInfoString(); std::string hash; utils::doHmacHashSha256(hwInfo, get("server_secret"), hash); std::string settingsString; utils::readFile(settingsString, m_settingsFilePath); std::vector lines = utils::splitStr(settingsString, '\n'); settingsString = ""; std::string wanted = "hw_id="; for (std::string line : lines) { if (line.substr(0, wanted.length()) == wanted) { line = wanted + hash; } line += '\n'; settingsString += line; } utils::writeToFile(m_settingsFilePath, settingsString); set("hw_id", hash); } int LicdSetup::getUserInfo() { if (!utils::fileExists(m_settingsFilePath)) { return e_file_not_present; } std::ifstream file; bool defaultFound = false; bool inDefault = false; bool inTag = false; bool tagFound = false; try { file.open(m_settingsFilePath, std::ios::in); if (file.is_open()) { std::string line; while (getline(file, line)) { line = utils::trimStr(line); // Continue until correct tag is found: if (line.length() < 1) continue; // omit empty lines if (line[0] == '#') continue; // omit comment line if (line[0] == '[' && line[line.length()-1] == ']') { inTag = false; inDefault = false; if (!tagFound && !inTag) { if (line.compare(m_tag) == 0) { tagFound = true; inTag = true; inDefault = false; } } if (!defaultFound && !inDefault && !tagFound) { if (line == DEFAULT_USER_SETTINGS_TAG) { // Pick default settings only if correct tag is not found yet defaultFound = true; inDefault = true; inTag = false; } } continue; } if (inTag || inDefault) { std::string item; std::string value; std::vector data = utils::splitStr(line, '='); if (data.size() > 0) { item = data[0]; if (data.size() > 1) { value = data[1]; } else { value = ""; } m_settings[item] = value; } } } file.close(); } else { std::cout << "\nERROR not able to open the settings file, check " << m_settingsFilePath << std::endl; file.close(); return e_general_file_error; } } catch (...) { std::cout << "\nERROR reading the settings file, check " << m_settingsFilePath << std::endl; file.close(); return e_general_file_error; } if (!tagFound) { if (!defaultFound) { return e_file_invalid_content; } return e_no_settings_tag; } // Everything is in place? if (m_settings["user_id"].length() == 0 || m_settings["license_id"].length() == 0) { return e_file_invalid_content; } std::string addr = m_settings["licd_addr"]; uint16_t port = utils::strToInt(m_settings["licd_port"]); if (port == 0) { return e_file_invalid_content; } return e_settings_ok; } int LicdSetup::getDaemonInfo() { m_settings["host_os"] = utils::getOsName(); std::cout << "Host: " << m_settings["host_os"] << std::endl; std::ifstream file; try { std::cout << "Opening file " << m_settingsFilePath << std::endl; file.open(m_settingsFilePath, std::ios::in); if (file.is_open()) { std::string line; while (getline(file, line)) { line = utils::trimStr(line); if (line.length() > 0) { if (line[0] == '#' || line[0] == '[') continue; // omit these lines std::string item; std::string value; std::vector data = utils::splitStr(line, '='); if (data.size() > 0) { item = data[0]; if (data.size() > 1) { value = data[1]; } else { value = ""; } m_settings[item] = value; std::cout << "Setting '" << item << "' to '" << value <<"'\n"; } } } } else { std::cout << "ERROR opening the settings file" << std::endl; file.close(); return e_general_file_error; } } catch (...) { std::cout << "ERROR opening/reading the settings file" << std::endl; file.close(); return e_general_file_error; } file.close(); return e_settings_ok; } std::string LicdSetup::parseSettingTag(const std::string &callerBinaryPath) { // Qt uses absolute paths, like: (linux example): // "/home//Qt/6.3.1/gcc_64/./libexec/moc" size_t loc = callerBinaryPath.rfind(DIR_SEPARATOR); loc = callerBinaryPath.rfind(DIR_SEPARATOR, loc-1); std::string tag = "[" + callerBinaryPath.substr(0, loc); while (tag[tag.length()-1] == DIR_SEPARATOR || tag[tag.length()-1] == '.' ) { tag.erase(tag.length() -1); } tag += "]"; std::replace(tag.begin(), tag.end(), DIR_SEPARATOR, '_'); return tag; } int LicdSetup::createUserSettingsFile() { if (!utils::fileExists(m_settingsFilePath)) { std::cout << "Settings file does not exist." << std::endl; if (utils::writeToFile(m_settingsFilePath, getUserFileSkeleton(), false) != 0) { std::cout << "Failed to create file " << m_settingsFilePath << std::endl; return -1; } std::cout << "New settings file created in " << m_settingsFilePath.c_str() << "\nCheck and edit the " << DEFAULT_USER_SETTINGS_TAG << " section\n"; } return 0; } int LicdSetup::appendNewSection(const std::string &contentStr) { // Append new section in the file if (utils::writeToFile(m_settingsFilePath, contentStr, true) != 0) { return -1; } std::cout << "Note! Default settings copied under section:\n" << m_tag << std::endl; return 0; } std::string LicdSetup::getUserFileSkeleton() { std::stringstream ss; ss << "#" << std::endl; ss << "# User settings for Qt licensing tools" << std::endl; ss << "# Please fill up, and note that at least user_id" << std::endl; ss << "# and license id MUST be set here correctly" << std::endl; ss << "#\n" << "# Required fields:" << std::endl; ss << "# user_id: Your Qt license username" << std::endl; ss << "# license_id: Your Qt license ID" << std::endl; ss << "# licd_addr: URL of the qt license daemon." << std::endl; ss << "# licd_port: TCP/IP port of the qt license daemon" << std::endl; ss << "#\n" << "# Optional fields:" << std::endl; ss << "# user_email: For cloud usage" << std::endl; ss << "# license_server_addr: If your setup differs from system default license server" << std::endl; ss << "# license_server_port: If your setup differs from system default license server" << std::endl; ss << "\n\n# Default settings section (do not remove):" << std::endl; ss << DEFAULT_USER_SETTINGS_TAG << std::endl; ss << "user_id=foobar" << std::endl; ss << "user_email=foobar@foo.bar" << std::endl; ss << "license_id=12345678" << std::endl; ss << "licd_addr=" << DAEMON_ADDR << std::endl; ss << "licd_port=" << DAEMON_PORT << std::endl; ss << "license_server_addr=" << std::endl; ss << "license_server_port=" << std::endl; ss << std::endl; return ss.str(); } std::string LicdSetup::getTaggedSettingsSkeleton() { std::stringstream ss; ss << std::endl << m_tag << std::endl; ss << "user_id=" << m_settings["user_id"] << std::endl; ss << "user_email=" << m_settings["user_email"] << std::endl; ss << "license_id=" << m_settings["license_id"] << std::endl; ss << "licd_addr=" << m_settings["licd_addr"] << std::endl; ss << "licd_port=" << m_settings["licd_port"] << std::endl; ss << "license_server_addr=" << m_settings["license_server_addr"] << std::endl; ss << "license_server_port=" << m_settings["license_server_port"] << std::endl; ss << std::endl; return ss.str(); } std::string LicdSetup::getQtAppDataLocation() { std::string retVal = utils::getUserHomeDir(); retVal += DIR_SEPARATOR; retVal += USER_SETTINGS_DIR; retVal += DIR_SEPARATOR; return retVal; } } // namespace QLicenseService