QFilef(QDir(m_installDir).filePath("config/manifest_public_key.pem"));if(!f.open(QIODevice::ReadOnly)){m_error="device public key missing";returnfalse;}
QByteArraykd=f.readAll();BIO*b=BIO_new_mem_buf(kd.constData(),kd.size());EVP_PKEY*k=b?PEM_read_bio_PUBKEY(b,nullptr,nullptr,nullptr):nullptr;if(b)BIO_free(b);if(!k){m_error="device public key invalid";returnfalse;}
if(trimmedBase.isEmpty()||trimmedBase.contains("YOUR_SERVER_IP",Qt::CaseInsensitive)){m_error="api_base_url is not configured. Set config/server_config.json before building the client, for example http://192.168.229.128:8000";returnfalse;}
if(token.trimmed().isEmpty()){m_error="client_token is empty in config/app_config.json";returnfalse;}
if(licenseKey.trimmed().isEmpty()){m_error="license_key is empty. Create a License in the admin page and paste the generated key into config/app_config.json";returnfalse;}
ConfigHelper&config=ConfigHelper::instance();
QStringinstallation=config.getValue("Device","installation_id");if(installation.isEmpty()){installation=QUuid::createUuid().toString(QUuid::WithoutBraces);if(!config.setValue("Device","installation_id",installation)){m_error=QString("cannot save installation id to %1: %2").arg(config.configPath(),config.lastError());returnfalse;}}
QNetworkAccessManagermanager;QNetworkRequestreq{QUrl(trimmedBase+"/api/v1/device/issue")};req.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");req.setRawHeader("X-Client-Token",token.toUtf8());QNetworkReply*reply=manager.post(req,QJsonDocument(body).toJson(QJsonDocument::Compact));QEventLooploop;booltimeoutOk=false;inttimeoutMs=ConfigHelper::instance().getValue("Update","request_timeout_ms").toInt(&timeoutOk);if(!timeoutOk||timeoutMs<1000)timeoutMs=5000;QTimertimer;timer.setSingleShot(true);QObject::connect(&timer,&QTimer::timeout,[&](){if(reply&&reply->isRunning())reply->abort();});QObject::connect(reply,&QNetworkReply::finished,&loop,&QEventLoop::quit);timer.start(timeoutMs);loop.exec();timer.stop();intstatus=reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();QByteArrayraw=reply->readAll();reply->deleteLater();if(status!=200){m_error=QString("device issue failed (HTTP %1): %2").arg(status).arg(QString::fromUtf8(raw));returnfalse;}autoresponse=QJsonDocument::fromJson(raw).object();QJsonObjectwrapper{{"identity_text",response.value("identity_text")},{"signature",response.value("signature")}};QStringpath=QDir(m_installDir).filePath("config/client_identity.dat");QByteArraybytes=QJsonDocument(wrapper).toJson(QJsonDocument::Compact);QStringwriteError;if(!ConfigHelper::writeFileWithElevationIfNeeded(path,bytes,&writeError)){m_error=QString("cannot save device credential to %1: %2").arg(path,writeError);returnfalse;}if(!loadAndVerify(appId,channel))returnfalse;if(!config.setValue("Update","device_id",m_deviceId)){m_error=QString("cannot save server device id to %1: %2").arg(config.configPath(),config.lastError());returnfalse;}returntrue;