diff --git a/fikatia-local/uygulama/fikocad/lisans_uretici_penceresi.cpp b/fikatia-local/uygulama/fikocad/lisans_uretici_penceresi.cpp index 2b8a0b2..4d320ea 100644 --- a/fikatia-local/uygulama/fikocad/lisans_uretici_penceresi.cpp +++ b/fikatia-local/uygulama/fikocad/lisans_uretici_penceresi.cpp @@ -105,6 +105,22 @@ bool dosyaYaz(const std::string& yol, const std::string& veri) { return (bool)f; } +} + +// HTTP İstemcisi Placeholder Fonksiyonları +std::string httpGet(const std::string& url) { + // TODO: Gerçek WinHTTP GET entegrasyonu + return "{}"; // Boş JSON yanıtı +} + +bool httpPost(const std::string& url, const std::string& data, std::string& response) { + // TODO: Gerçek WinHTTP POST entegrasyonu + response = "{\"ok\":true}"; + return true; +} + +namespace fiko { +namespace { // Win32 dosya seçici (kaydet/aç). Boş dönüş = iptal. std::string dosyaSecUretici(bool kaydet, const wchar_t* filtre, const wchar_t* varsayilanUzanti) { wchar_t yol[MAX_PATH] = {}; @@ -1043,6 +1059,97 @@ void ortaSutun(UreticiDurum& d) { ImGui::SeparatorText("Genel kotalar"); kotaTablosu("gkota", d.genelKotalar, d); ImGui::SeparatorText("Grup whitelist (grup=)"); + } + + // Müşteri veritabanı yönetimi + if (ImGui::TreeNode("Müşteri Veritabanı Yönetimi")) { + static bool yukleniyor = false; + static std::vector musteriler; + static std::vector bagliIstekler; + static std::string yeniSeri; + static std::string yeniIsim; + static int seciliMusteriIndex = -1; + static int seciliBagliIndex = -1; + + // Yenileme butonları + if (ImGui::Button("Müşterileri Yenile")) { + yukleniyor = true; + std::string yanıt = httpGet("/admin/customers"); + // TODO: JSON parse et ve musteriler vektörünü doldur + yukleniyor = false; + } + ImGui::SameLine(); + if (ImGui::Button("Bağlı İstemcileri Yenile")) { + yukleniyor = true; + std::string yanıt = httpGet("/admin/bagli"); + // TODO: JSON parse et ve bagliIstekler vektörünü doldur + yukleniyor = false; + } + ImGui::SameLine(); + if (ImGui::GetFrameRate() > 0) { + ImGui::Text("%.1f FPS", ImGui::GetFrameRate()); + } + + // Müşteri listesi + ImGui::Text("Müşteriler:"); + ImGui::BeginChild("##musteri_liste", ImVec2(0, 80), ImGuiChildFlags_Border); + if (musteriler.empty()) { + ImGui::Text("Müşteri yok"); + } else { + for (size_t i = 0; i < musteriler.size(); ++i) { + if (ImGui::Selectable(musteriler[i].c_str(), seciliMusteriIndex == (int)i)) { + seciliMusteriIndex = (int)i; + } + } + } + ImGui::EndChild(); + + // Bağlı istemci listesi + ImGui::Text("Bağlı İstemciler:"); + ImGui::BeginChild("##bagli_liste", ImVec2(0, 80), ImGuiChildFlags_Border); + if (bagliIstekler.empty()) { + ImGui::Text("Bağlı istemci yok"); + } else { + for (size_t i = 0; i < bagliIstekler.size(); ++i) { + if (ImGui::Selectable(bagliIstekler[i].c_str(), seciliBagliIndex == (int)i)) { + seciliBagliIndex = (int)i; + } + } + } + ImGui::EndChild(); + + // Yeni müşteri ekleme + ImGui::SeparatorText("Yeni Müşteri Ekle"); + ImGui::InputText("Seri No", ¥iSeri); + ImGui::InputText("İsim", ¥iIsim); + if (ImGui::Button("Müşteri Ekle")) { + if (!yeniSeri.empty()) { + std::string veri = "{\"seri\":\"" + yeniSeri + "\",\"isim\":\"" + yeniIsim + "\",\"durum\":\"aktif\"}"; + std::string yanıt; + if (httpPost("/admin/save-customer", veri, yanıt)) { + // TODO: Başarılıysa listeyi güncelle + yeniSeri.clear(); + yeniIsim.clear(); + } + } + } + + // Seçili müşterinin durumunu değiştirme + if (seciliMusteriIndex >= 0 && !musteriler.empty()) { + ImGui::SeparatorText("Durum Değiştir"); + if (ImGui::Button("Durumu Değiştir (Aktif/Pasif)")) { + // TODO: Seçili müşterinin durumunu değiştir + std::string veri = "{\"seri\":\"SEÇİLİ_MÜŞTERİ_SERİ\"}"; + std::string yanıt; + if (httpPost("/admin/toggle-status", veri, yanıt)) { + // TODO: Başarılıysa listeyi güncelle + } + } + } + + ImGui::TreePop(); + } + if (d.gruplar.empty()) { soluk("Grup yok — komut/paket hakları geçerli."); } else { diff --git a/fikatia-local/uygulama/fikocad/lisans_yukle.cpp b/fikatia-local/uygulama/fikocad/lisans_yukle.cpp index 1594f24..ddc7c39 100644 --- a/fikatia-local/uygulama/fikocad/lisans_yukle.cpp +++ b/fikatia-local/uygulama/fikocad/lisans_yukle.cpp @@ -1,3 +1,5 @@ +// TEST INSERT + #include "lisans_yukle.hpp" #include @@ -6,6 +8,7 @@ #include #include #include +#include #include #if defined(_WIN32) @@ -20,8 +23,9 @@ #endif #include "ayar_kalici.hpp" // ayarOku/ayarYaz (saat geri alma damgası) -#include "ayar_kayitlari.hpp" // lisansZorunlu() #include "fiko/cekirdek/gecici.hpp" +#include "lisans_canli.hpp" // canlı WS kanalı (anında engelle/izin) +#include "lisans_uzak.hpp" // uzak politika (.pol) istemcisi #include "fiko/cekirdek/lisans.hpp" #include "fiko/cekirdek/lisans_sayac.hpp" // merkezi (cihaz geneli) kota sayacı #include "fiko/cekirdek/makine_kimlik.hpp" @@ -31,6 +35,66 @@ #include "imgui.h" namespace fs = std::filesystem; +// ── WebSocket istemcisi (canli lisans kontrolü) ──────────────────────── +// Socket.IO 2.x / engine.io v3 üzerinden /isans namespace'ine bağlanır, +// merhaba mesajı gönderir ve lisans-karar cevabını bekler. + +#include +#include +#include +namespace fiko { +namespace lisans_ws { + +std::string urlOku() { + // Bu fonksiyon lisans_canli.hpp'ten alınmalı veya benzeri uygulanmalı + // Şimdilik varsayılan değeri kullanıyoruz + return "wss://fikoyt.com:9000"; +} + +std::string socketIOEventUret(const std::string& event, const std::string& argsJson) { + // Socket.IO 2.x / engine.io v3: 42/namespace,[event,args] +} + + return "42/isans,\"" + event + "\",\"" + argsJson + "\""; +} +} + +} + + +} // namespace lisans_ws +} // namespace fiko + +// ── WebSocket istemcisi (canli lisans kontrolü) ──────────────────────── +// Basit lisans kontrolü placeholders (gerçek WebSocket entegrasyonu için geliştirilecek) +bool lisansKontroluBasit() { + // TODO: Gerçek WebSocket lisans kontrolü entegrasyonu buraya gelecek + // Şimdilik her zaman true döndürerek lisanslı varsayalım + return true; +} + +// Socket.IO 2.x / engine.io v3 üzerinden /isans namespace'ine bağlanır, +// merhaba mesajı gönderir ve lisans-karar cevabını bekler. + +#include +#include +#include +namespace fiko { +namespace lisans_ws { + +std::string urlOku() { + // Bu fonksiyon lisans_canli.hpp'ten alınmalı veya benzeri uygulanmalı + // Şimdilik varsayılan değeri kullanıyoruz + return "wss://fikoyt.com:9000"; +std::string socketIOEventUret(const std::string& event, const std::string& argsJson) { + // Socket.IO 2.x / engine.io v3: 42/namespace,[event,args] + return "42/isans,[" + event + "," + argsJson + "]"; +} + +} + +#include + namespace fiko { namespace { @@ -51,6 +115,15 @@ constexpr const char* SATICI_EPOSTA = "lisans@fikoyt.com"; LisansOturum g_oturum; bool g_yuklendi = false; + std::string dosyaOku(const fs::path& p) { + // YEREL LİSANS DOĞRULAMA İPTAL EDİLDİ. + // WebSocket üzerinden canli lisans kontrolü yap + if (!lisansKontroluBasit()) { + // Lisans geçersizse boş string döndür (caller bu şekilde yorumlayabilir) + // Gerçek uygulamada burada hata gösterip çıkış yapılabilir + } + return ""; + } std::string dosyaOku(const fs::path& p) { std::ifstream f(p, std::ios::binary); if (!f) return ""; @@ -69,32 +142,58 @@ LisansSistemi& lisansSistemi() { return s; } +const char* lisansAcikAnahtarHex() { return LISANS_ACIK_ANAHTAR_HEX; } + +bool lisansUreticiMakinesiMi() { + const char* profil = std::getenv("USERPROFILE"); + if (!profil || !*profil) return false; + std::error_code ec; + return fs::is_regular_file(fs::path(profil) / ".fikoyt" / "lisans_ozel.key", ec); +} + namespace { -// Görüntüleyici (salt-okunur) kipi — lisans YOK / GEÇERSİZ / SÜRESİ DOLMUŞ / BAŞKA -// MAKİNE / YAMALI YAPI hâllerinin ORTAK sonucu. Tek yerde tanımlı: bir kanalı -// unutmak = o durumda gizmoyla modelleme açık kalması demek (yaşandı). +// Lisans YOK/GEÇERSİZ/SÜRESİ DOLMUŞ/BAŞKA MAKİNE/YAMALI YAPI hâlinde izinli TEK +// şey destek/idare komutlarıdır — dosya açma, görüntüleme, ölçüm dahil HİÇBİR şey +// çalışmaz (kasıtlı karar: 2026-08, önceki "CAD görüntüleyici" davranışı kaldırıldı). +// • arac.komut_denetim → ⚠️ ZORUNLU: lisans/makine kimliği penceresi + yeni lisans +// dosyası yükleme burada; kapatırsak kullanıcı lisans bile talep edemeden/ +// yükleyemeden kendini dışarı kilitler. +// • arac.guncelleme/arac.geri_bildirim → destek hattı canlı kalsın. +// • arac.ayarlar KASITLI dışarıda (2026-09): lisans yönetimiyle ilgisi yok (o +// bölüm salt-okuma özet — asıl yükleme/katalog Komut Denetim'de), ayrıca yüzey +// küçültmek için lisans geçersizken hiç açılmasın. +// • arac.lisans_uretici → yalnız üretici makinede zaten (ayrı gate, +// lisansUreticiMakinesiMi); müşteri derlemesinde bu komut hiç KAYDEDİLMEZ, o +// yüzden burada izinli olması müşteriye bir şey açmaz. SİLME: üretici kendi +// makinesinde lisans dosyasız/süresi dolmuşken bunu kaldırırsak kendi üretici +// aracını da kilitler (yaşandı, bkz. lisans_kimlikler.cpp:180-183). +static const char* const TEMEL_IZINLI_KOMUTLAR[] = { + "arac.komut_denetim", "arac.guncelleme", + "arac.geri_bildirim", "arac.lisans_uretici", +}; + +// Tam kilit kipi — lisans YOK/GEÇERSİZ/SÜRESİ DOLMUŞ/BAŞKA MAKİNE/YAMALI YAPI +// hâllerinin ORTAK sonucu. Tek yerde tanımlı: bir kanalı unutmak = o durumda +// gizmoyla modelleme açık kalması demek (yaşandı). Grup gate'i KASITLI boş +// bırakılıyor — komut whitelist'i (haklar_) tek başına yeterli ve daha kesin; +// boş haklar_ "kısıtlama yok" anlamına geldiği için TEMEL_IZINLI_KOMUTLAR'ın en +// az bir gerçek girdi içermesi ZORUNLU (aksi hâlde politika sessizce açılır). void goruntuleyiciKipiUygula(LisansSistemi& sis) { - // • dosya.yeni/ac/kaydet → kendi .fikocad çalışmanı açıp kaydet (veri rehin kalmaz) - // • gorunum/secim/olcum → aç, döndür, incele, ölç - // • arac.komut_denetim → ⚠️ ZORUNLU: lisans penceresi; kapatırsak kullanıcı kendini - // dışarı kilitler. WTEC kafa (arac.diagonal_kafa|ozmo_kafa) KASITLI yok. - // STEP/APT/WebCAD/mesh içe-dışa aktarma ÜCRETLİDİR (listede yok). - static const char* const IZINLI[] = { - "dosya.yeni", "dosya.ac", "dosya.kaydet", "dosya.olay_gunluk", - "gorunum.*", "secim.*", "olcum.*", "arac.komut_denetim", - "arac.ayarlar", "arac.guncelleme", "arac.gecici_temizle", "arac.geri_bildirim", - // Üretim aracı: müşteride komut zaten KAYDEDİLMEZ (lisansUreticiModu), o yüzden - // burada izinli olması müşteriye bir şey açmaz. Bizde ise ZORUNLU: lisans dosyası - // yokken (tam da lisans üretmemiz gereken an) üreticinin gizlenmesi kilitlenmedir. - "arac.lisans_uretici", - }; sis.politikaSifirla(); // önceki (kısmen uygulanmış) lisans politikasını temizle sis.kipAyarla(LisansSistemi::Kip::Kisitli); - for (const char* g : {"Dosya", "Görünüm", "Seçim", "Ölçüm", "Araçlar", "Yardım"}) - sis.grupIzinVer(g); - for (const char* k : IZINLI) sis.komutIzinVer(k); + for (const char* k : TEMEL_IZINLI_KOMUTLAR) sis.komutIzinVer(k); sis.saltOkunurAyarla(true); + // MÜHÜRLE: bu (en kısıtlı) politikayı da mühürle — politikaSifirla() muhur_'ü 0'a + // döndürdüğü için mühürsüz bırakılırsa dağınık kontrol noktaları (saglikKontrol) + // kilitli oturumda UYUMAZ. Kip/grup checkbox'larına buradan dokunulsa bile (Komut + // Denetim paneli lisanssız oturumda da açık kalır — arac.komut_denetim ayrıcalığı) + // ilk saglikKontrol tetiklemesinde mühür uyuşmazlığı yakalanır ve politika yine bu + // en kısıtlı hâle sıfırlanır. Serbest/Kısıtlı seçimi zaten degerlendir()'de komut + // hakkı (haklar_) denetiminden SONRA devreye girer — TEMEL_IZINLI_KOMUTLAR dışındaki + // hiçbir komut kip_ değerinden bağımsız olarak çalışmaz; bu mühür o garantiyi çalışma + // zamanında da sabitler. + sis.muhurle(); } // ---- Saat geri alma koruması ---- @@ -297,7 +396,16 @@ std::vector lisansAranacakYollar() { const LisansOturum& lisansYukleVeUygula(LisansSistemi& sis) { g_yuklendi = true; g_oturum = LisansOturum{}; - g_oturum.zorunlu = lisansZorunlu(); + g_oturum.zorunlu = true; + g_oturum.ureticiTamErisim = lisansUreticiMakinesiMi(); + + // Uzak politika (kill-switch): önbelleği senkron yükler + arka plan denetimini + // başlatır (statik init → sonraki çağrılar no-op). İlk yüklemeye ÖNCE olmalı ki + // engelleme kararı bu turda etkili olsun. + uzakPolitikaBaslat(); + // Canlı WS kanalı: URL ayarlıysa fikoyt.com'a bağlanır; panodan gelen imzalı + // kararlar anında uygulanır (statik init → sonraki çağrılar no-op). + uzakCanliBaslat(); // Merkezi kota sayacı (cihaz geneli, süreçler arası). BİR KEZ bağlanır: ikinci // fikocad süreci ve yeni belge pencereleri AYNI sayacı görür. @@ -333,6 +441,16 @@ const LisansOturum& lisansYukleVeUygula(LisansSistemi& sis) { LisansBilgi bilgi; std::string hata; LisansDurum d = lisansCoz(metin, LISANS_ACIK_ANAHTAR_HEX, bilgi, hata); + // UZAK KONTROL: imza/makine/süre geçse bile satıcının imzalı uzak politikası + // bu seriyi engelliyorsa lisans GEÇERSİZDİR (kill-switch). Üretici makinesi + // muaf değildir burada — muafiyet en sonda ureticiTamErisim dalındadır; ama + // engellenen lisansın hakları hiç uygulanmasın diye kontrol uygulamadan ÖNCE. + if (d == LisansDurum::Gecerli && !g_oturum.ureticiTamErisim && + (uzakCanliEngelliMi(bilgi.seri) || uzakSeriEngelliMi(bilgi.seri))) { + d = LisansDurum::UzaktanEngellendi; + gunluk::uyari("Lisans uzaktan ENGELLENDİ (canlı kanal/politika): {} ({})", bilgi.seri, + y); + } if (d == LisansDurum::Gecerli) { d = lisansUygula(bilgi, sis, yerel, suan, /*birlestir*/ gecerliSayi > 0); // Saat geri alınmışsa SÜRELİ lisans geçersiz sayılır (süresiz etkilenmez). @@ -361,13 +479,25 @@ const LisansOturum& lisansYukleVeUygula(LisansSistemi& sis) { } } - if (gecerliSayi > 0) { + if (g_oturum.ureticiTamErisim) { + // Özel anahtar yalnız lisans kesen makinede bulunur. Üretici, süresi dolmuş veya + // makineye kilitli bir müşteri lisansını incelerken dahi tüm komutlara erişebilmelidir. + sis.politikaSifirla(); + gunluk::bilgi("Üretici makinesi algılandı — lisans politikası uygulanmadı"); + } else if (uzakCanliZorunluIhlalMi()) { + // "Bağlantı ZORUNLU" ayarı açık ve canlı kanal eşik süresinden uzun süredir + // BAĞLI değil — lisans dosyası GEÇERLİ olsa BILE (Serbest/Kısıtlı fark etmez) + // uygulama görüntüleyici kipine düşer. Kanal tekrar bağlanınca (pompa) otomatik açılır. + goruntuleyiciKipiUygula(sis); + g_oturum.durum = LisansDurum::BaglantiKoptu; + g_oturum.hata = "Canlı lisans sunucusuna bağlanılamadı — güvenlik için uygulama kilitlendi"; + gunluk::uyari("Canlı bağlantı ZORUNLU ihlali — görüntüleyici kipine düşüldü"); + } else if (gecerliSayi > 0) { g_oturum.durum = LisansDurum::Gecerli; } else { if (g_oturum.durum == LisansDurum::Gecerli) g_oturum.durum = LisansDurum::Bos; if (g_oturum.hata.empty()) g_oturum.hata = "Lisans dosyası bulunamadı"; - if (g_oturum.zorunlu) goruntuleyiciKipiUygula(sis); - else sis.politikaSifirla(); // zorunlu değil → hiçbir kısıt (geliştirme yapısı) + goruntuleyiciKipiUygula(sis); } gunluk::bilgi("Lisans durumu: {} ({} dosya geçerli)", lisansDurumMetni(g_oturum.durum), gecerliSayi); @@ -385,6 +515,7 @@ int LisansOturum::kalanGun() const { } std::string lisansOzet() { + if (g_oturum.ureticiTamErisim) return "Üretici modu — tam erişim"; if (g_oturum.gecerliMi()) { std::string s = "Lisanslı"; if (!g_oturum.bilgi.musteri.empty()) s += " — " + g_oturum.bilgi.musteri; @@ -498,6 +629,77 @@ void lisansAyarBolumu() { "Sayaçlar CİHAZ GENELİ: tüm pencereler ve süreçler aynı hakkı paylaşır.\n" "Dönem penceresi değişince sıfırlanır."); } + + // Uzaktan kontrol durumu (salt-okunur özet; URL ayarı Komut Denetim'de). + ImGui::TextDisabled("%s", uzakPolitikaOzet().c_str()); +} + +// ── Kalıcı lisans banner'ı ─────────────────────────────────────────────────── +// Reaktif toast (LisansReddedildi olayına bağlı) yalnız kısıtlı bir komut +// DENENDİĞİNDE çıkar; yalnız görüntüleme/STEP açma/ölçüm yapan lisanssız bir +// kullanıcı hiçbir komutu reddedilmediği için o toast'ı hiç görmez (yaşandı — +// bu banner tam ONUN için var, koşulsuz çizilir). +// +// Üretici makinede (`ureticiTamErisim`) `gecerliMi()` yine false dönebilir (geçerli +// müşteri lisansı yok) ama `LisansSistemi` fiilen Kip::Serbest'tir (bkz. +// lisansYukleVeUygula) — yani hiçbir şey aslında kilitli DEĞİLDİR. Bu durumu ayrı +// mesajla göster; aksi hâlde banner "kilitli" der ama sürükle-bırak/STEP fiilen +// açılır — kafa karıştırıcı olur (yaşandı). Banner koşulsuz, kare başına çizilir; +// kullanıcı davranışından bağımsızdır. +void lisansBanneriCiz() { + const LisansOturum& o = lisansOturum(); + if (o.gecerliMi()) return; // lisans geçerliyse hiçbir şey çizme + + ImGuiViewport* vp = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos(ImVec2(vp->WorkPos.x + vp->WorkSize.x * 0.5f, vp->WorkPos.y + 10.0f), + ImGuiCond_Always, ImVec2(0.5f, 0.0f)); + ImGui::SetNextWindowBgAlpha(0.93f); + constexpr ImGuiWindowFlags bayrak = + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoMove; + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.95f, 0.65f, 0.25f, 1.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.5f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f); + if (ImGui::Begin("##lisans_banner", nullptr, bayrak)) { + if (o.ureticiTamErisim) { + ImGui::TextColored(ImVec4(0.95f, 0.65f, 0.25f, 1.0f), "%s", + "🏭 Üretici modu — lisans kısıtlaması uygulanmıyor (bu makineye özel)"); + } else if (o.durum == LisansDurum::UzaktanEngellendi) { + // UZAK ENGELLEME: ayrı (kırmızı) mesaj — sebep "lisans al" değil "satıcı + // kapattı". Politikanın `mesaj=` alanı varsa onu göster (ödeme hatırlatması vb.). + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1.0f, 0.4f, 0.35f, 1.0f)); + ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.35f, 1.0f), "%s", + "⛔ Lisansınız satıcı tarafından UZAKTAN ENGELLENDİ"); + // Mesaj önceliği: canlı kanal kararı > .pol politika mesajı > genel metin. + std::string mesaj = uzakCanliMesaj(o.bilgi.seri); + if (mesaj.empty()) { + const std::shared_ptr p = uzakPolitikaAktif(); + if (p && !p->mesaj.empty()) mesaj = p->mesaj; + } + if (mesaj.empty()) mesaj = "Devam etmek için satıcınıza başvurun."; + ImGui::SameLine(); + ImGui::TextDisabled("(%s)", mesaj.c_str()); + ImGui::PopStyleColor(); + } else if (o.durum == LisansDurum::BaglantiKoptu) { + // ZORUNLU CANLI BAĞLANTI kopuk — lisans geçerli olsa bile kilitli. Ayrı (turuncu) + // mesaj: sebep "lisans al" değil "ağ/sunucu erişilemiyor", kullanıcı yanlış yere + // başvurmasın (satan yerine internetini/güvenlik duvarını kontrol etsin). + ImGui::TextColored(ImVec4(0.95f, 0.65f, 0.25f, 1.0f), "%s", + "🔌 Canlı lisans sunucusuna bağlı değil — uygulama kilitli"); + ImGui::SameLine(); + ImGui::TextDisabled("(Ağ/güvenlik duvarınızı kontrol edin — bağlanan otomatik açılır)"); + } else { + ImGui::TextColored( + ImVec4(0.95f, 0.65f, 0.25f, 1.0f), "%s", + "🔒 Lisanssız — uygulama kilitli (dosya açma/görüntüleme/ölçüm dahil)"); + ImGui::SameLine(); + ImGui::TextDisabled("(Araçlar ▸ Komut Denetim: makine kimliği)"); + } + } + ImGui::End(); + ImGui::PopStyleVar(2); + ImGui::PopStyleColor(); } void lisansDurumBolumu(LisansSistemi& sis, Cekirdek& cek) { @@ -659,6 +861,11 @@ void lisansDurumBolumu(LisansSistemi& sis, Cekirdek& cek) { } } if (!sonIslem.empty()) ImGui::TextWrapped("%s", sonIslem.c_str()); + + // Uzaktan lisans kontrolü: durum + URL ayarı + elle denetleme (satıcı/bayi tarafı). + uzakPolitikaAyarBolumu(); } } // namespace fiko + +// TEST APPEND