// -- Lisans Yonetim Paneli - UI --------------------------------------------------- // Uretici makinesinde: bagli fikocad'lari listele, aninda yetki/lisans ver, // uzaktan komut gonder, kilitle. Tum cihazlar TEK ekrandan yonetilir. // // Ag isleri lisans_yonetim_http.cpp'de; bu dosya yalniz CAZER. #include #include #include #include #include #include #include #include "lisans_yonetim.hpp" #include "fiko/core/gunluk.hpp" #include "fiko/ui/bilesen.hpp" #include "fiko/ui/bilesen_ek.hpp" #include "fiko/ui/tema.hpp" #include "imgui.h" #include "fiko/cekirdek/makine_kimlik.hpp" // cihazKimlikUret (bu makine mi?) #include "ayar_kalici.hpp" // ayarOku/ayarYaz (cihaz takma adlari) #include "lisans_kimlikler.hpp" #include "lisans_yukle.hpp" // lisansUreticiMakinesiMi #include "lisans_uzaktan.hpp" // uzak kanal durumu + komut kayitlari namespace fiko { namespace { // -- Panel durumu (UI'a ozel; is mantigi degil) -------------------------------- struct UiDurum { char sunucu[128] = "https://fikoyt.com:9000"; char kullanici[64] = "admin"; char parola[64] = ""; char filtre[64] = ""; bool bilinmeyenGizle = false; // fikocad kaydı (bilgisayar adı) olmayan cihazları gizle int saat = 23, dakika = 59; // süreli lisans bitiş saati (varsayılan gece yarısı öncesi) int takvimAy = 0, takvimYil = 0; // takvim popup'ının gösterdiği ay/yıl (0 = seçili tarihten al) char komutMesaj[256] = ""; char ozelAnahtar[260] = ""; char yeniSeri[64] = ""; char adminToken[128] = ""; // yonetici token (yalniz bellekte, diske yazilmaz) char yeniMusteri[128] = ""; char komutFiltre[64] = ""; char cihazAd[64] = ""; // secili cihazin takma adi (duzenleme tamponu) std::string cihazAdKimlik; // tamponun hangi cihaza ait oldugu (secim degisince yenile) std::string adSunucuHata; // sunucudan ad okuma/yazma hatasi (bos = sorun yok) int seciliCihaz = -1; int seciliKomut = 0; int yil = 0, ay = 0, gun = 0; bool suresiz = true; std::vector seciliKomutlar; // bilet icin secilen haklar bool ilkAcilis = true; i64 sonCevap = 0; float silOnayZaman = -99.0f; // ImGui zamani; iki adimli sil onayi penceresi int silOnayKip = 0; // 0=yok 1=tekil cihaz 2=gorunen toplu }; UiDurum g_ui; std::vector g_cihazlar; // -- Yardimcilar --------------------------------------------------------------- std::string kucukHarf(const std::string& s) { std::string o = s; for (char& c : o) c = (char)std::tolower((unsigned char)c); return o; } // "2026-09-28T14:22:31..." -> "28.09 14:22" std::string kisaZaman(const std::string& iso) { if (iso.size() < 16) return iso; return iso.substr(8, 2) + "." + iso.substr(5, 2) + " " + iso.substr(11, 5); } // Bu konsolun calistigi uretici makinesinin KENDI fikocad kaydi: lisans dosyasi yoktur // ve OLMAMALIDIR (uretici politika disinda). "LISANS YOK" yaniltici oldugu icin ayri etiket. bool ureticiKendiCihazi(const CihazOzet& c) { static const std::string benim = cihazKimlikUret(); static const bool uretici = lisansUreticiMakinesiMi(); return uretici && !benim.empty() && c.cihazKimlik == benim; } // Uretici makinesi mi? Bu konsolun kendi kaydi VEYA cihazin kayit paketinde // "uretici" bayragi tasiyan baska bir uretici makinesi. Ikisinde de lisans // dosyasi olmamasi NORMALDIR; "LISANS YOK" tek basina yaniltici olur. bool ureticiCihazi(const CihazOzet& c) { return ureticiKendiCihazi(c) || c.uretici == "1"; } // -- Cihaz takma adi (satici kendi verdigi isim) ------------------------------- // fikocad.ayar icinde "cihaz_ad.=" olarak tutulur; yalniz bu // (uretici) makinede gecerli, sunucuya gonderilmez. Bos deger = takma ad yok. std::string cihazTakmaAdi(const std::string& kimlik) { if (kimlik.empty()) return {}; return ayarOku(("cihaz_ad." + kimlik).c_str(), ""); } void cihazTakmaAdiYaz(const std::string& kimlik, std::string ad) { if (kimlik.empty()) return; for (char& ch : ad) // satir sonu ayar dosyasini bozar if (ch == '\r' || ch == '\n') ch = ' '; ayarYaz(("cihaz_ad." + kimlik).c_str(), ad); } // Listede/basliktada gorunen ad: takma ad varsa o, yoksa bilgisayar adi. std::string gorunenAd(const CihazOzet& c) { std::string a = cihazTakmaAdi(c.cihazKimlik); return a.empty() ? c.bilgisayar : a; } ImVec4 durumRengi(const CihazOzet& c) { const ui::Tema& t = ui::tema(); if (c.kilitli || c.engelli) return t.hata; if (ureticiCihazi(c) && c.cevrimici) return t.basari; if (!c.cevrimici) return t.metinSoluk; if (c.seri.empty()) return t.uyari; return t.basari; } const char* durumEtiketi(const CihazOzet& c) { if (c.engelli) return "ENGELLI"; if (c.kilitli) return "KILITLI"; if (!c.cevrimici) return "cevrimdisi"; if (ureticiCihazi(c)) return c.seri.empty() ? "URETICI (lisans yok)" : "URETICI"; if (c.seri.empty()) return "LISANS YOK"; return "AKTIF"; } // Fikocad kaydi olmayan cihaz: bilgisayar adi bos ya da '(bilinmiyor)' (http katmani doldurur). bool bilinmeyenMi(const CihazOzet& c) { return c.bilgisayar.empty() || c.bilgisayar == "(bilinmiyor)"; } int durumLedKodu(const CihazOzet& c) { if (c.kilitli || c.engelli) return 3; if (!c.cevrimici) return 0; if (ureticiCihazi(c)) return 1; if (c.seri.empty()) return 2; return 1; } // -- Tarih/saat seçici (açılır takvim + saat/dakika kaydırıcısı) --------------- int aylikGunSayisi(int yil, int ay) { // ay 1..12 static const int gunler[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const bool artik = (yil % 4 == 0 && yil % 100 != 0) || yil % 400 == 0; return (ay == 2 && artik) ? 29 : gunler[ay - 1]; } int ayinIlkGunuHaftaIci(int yil, int ay) { // 0 = Pazar std::tm t{}; t.tm_year = yil - 1900; t.tm_mon = ay - 1; t.tm_mday = 1; t.tm_hour = 12; t.tm_isdst = -1; std::mktime(&t); return t.tm_wday; } void tarihSaatSecici(UiDurum& u) { static const char* aylar[] = {"Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"}; char etiket[64]; std::snprintf(etiket, sizeof etiket, "%02d.%02d.%04d %02d:%02d v", u.gun, u.ay, u.yil, u.saat, u.dakika); if (ImGui::Button(etiket, ImVec2(230, 0))) { u.takvimAy = u.ay; u.takvimYil = u.yil; ImGui::OpenPopup("##takvim"); } if (ImGui::BeginPopup("##takvim")) { if (u.takvimAy < 1 || u.takvimAy > 12) { u.takvimAy = u.ay; u.takvimYil = u.yil; } // Ay başlığı ve gezinme if (ImGui::Button("<", ImVec2(30, 0))) { if (--u.takvimAy < 1) { u.takvimAy = 12; --u.takvimYil; } } ImGui::SameLine(); char baslik[48]; std::snprintf(baslik, sizeof baslik, "%s %d", aylar[u.takvimAy - 1], u.takvimYil); const float genislik = 7 * 40.0f; const float yazi = ImGui::CalcTextSize(baslik).x; ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (genislik - yazi) * 0.5f - 40.0f); ImGui::TextUnformatted(baslik); ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 0.0f); if (ImGui::Button(">", ImVec2(30, 0))) { if (++u.takvimAy > 12) { u.takvimAy = 1; ++u.takvimYil; } } ImGui::Separator(); // Gün başlıkları ve takvim ızgarası (7 sütun, Pazartesi değil Pazar başlangıçlı) static const char* gunAd[] = {"Pz", "Pt", "Sa", "Ça", "Pe", "Cu", "Ct"}; ImGui::Columns(7, "takvim", false); for (int i = 0; i < 7; ++i) { ImGui::SetColumnWidth(i, 40.0f); ImGui::TextDisabled("%s", gunAd[i]); ImGui::NextColumn(); } const int bos = ayinIlkGunuHaftaIci(u.takvimYil, u.takvimAy); const int gunSayisi = aylikGunSayisi(u.takvimYil, u.takvimAy); for (int i = 0; i < bos; ++i) ImGui::NextColumn(); for (int d = 1; d <= gunSayisi; ++d) { char lb[8]; std::snprintf(lb, sizeof lb, "%d", d); const bool secili = (d == u.gun && u.takvimAy == u.ay && u.takvimYil == u.yil); if (secili) ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.20f, 0.50f, 0.90f, 1.0f)); if (ImGui::Button(lb, ImVec2(34, 0))) { u.gun = d; u.ay = u.takvimAy; u.yil = u.takvimYil; } if (secili) ImGui::PopStyleColor(); ImGui::NextColumn(); } ImGui::Columns(1); ImGui::Separator(); // Saat ve dakika kaydırıcıları ImGui::SetNextItemWidth(280.0f); ImGui::SliderInt("Saat", &u.saat, 0, 23); ImGui::SetNextItemWidth(280.0f); ImGui::SliderInt("Dakika", &u.dakika, 0, 59); // Hızlı seçimler if (ImGui::Button("Bugün")) { const std::time_t simdi = std::time(nullptr); std::tm bugun{}; localtime_s(&bugun, &simdi); u.gun = bugun.tm_mday; u.ay = bugun.tm_mon + 1; u.yil = bugun.tm_year + 1900; u.takvimAy = u.ay; u.takvimYil = u.yil; } ImGui::SameLine(); if (ImGui::Button("23:59")) { u.saat = 23; u.dakika = 59; } ImGui::SameLine(); if (ImGui::Button("Kapat")) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); } } bool kucukHarfIcerir(const std::string& hay, const std::string& ara) { if (ara.empty()) return true; return kucukHarf(hay).find(kucukHarf(ara)) != std::string::npos; } } // namespace // ============================================================================== void lisansYonetimCiz(UygulamaBaglam& b, bool& acik) { if (!acik) return; const ui::Tema& t = ui::tema(); YonetimDurumu& durum = yonetimDurumu(); (void)b; ImGui::SetNextWindowSize(ImVec2(1220, 740), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(100, 70), ImGuiCond_FirstUseEver); bool gorunur = true; if (!ImGui::Begin("[SATICI] Lisans Yonetimi - Satici Konsolu", &gorunur, ImGuiWindowFlags_NoCollapse)) { ImGui::End(); if (!gorunur) acik = false; return; } if (!gorunur) { acik = false; ImGui::End(); return; } // ═══ UST SERIT: sunucu + oturum ═══════════════════════════════════════════ { ImGui::AlignTextToFramePadding(); ui::durumLed(durum.sunucuyaBagli ? 1 : 0, 6.0f); ImGui::SameLine(); ImGui::TextUnformatted("Sunucu"); ImGui::SameLine(); ImGui::SetNextItemWidth(230.0f); ImGui::InputText("##sunucu", g_ui.sunucu, sizeof g_ui.sunucu); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Lisans sunucusu adresi"); ImGui::SameLine(); ImGui::SetNextItemWidth(120.0f); ImGui::InputText("##kullanici", g_ui.kullanici, sizeof g_ui.kullanici); ImGui::SameLine(); ImGui::SetNextItemWidth(150.0f); ImGui::InputTextWithHint("##parola", "sifre", g_ui.parola, sizeof g_ui.parola, ImGuiInputTextFlags_Password); ImGui::SameLine(); if (durum.oturumAcik) { ui::rozet(durum.kullaniciAdi.c_str(), t.basari); ImGui::SameLine(); if (ui::buton("Cikis Yap", ImVec2(74, 0), ui::ButonTip::Ikincil)) { durum.oturumAcik = false; durum.kullaniciAdi.clear(); durum.sunucuyaBagli = false; g_cihazlar.clear(); ui::toastGoster("Oturum kapatildi", ui::ToastTip::Bilgi); } } else if (ui::buton("Baglan", ImVec2(96, 0), ui::ButonTip::Birincil)) { std::string hata; durum.yukleniyor = true; if (yonetimOturumAc(g_ui.sunucu, g_ui.kullanici, g_ui.parola, hata)) { ui::toastGoster("Sunucuya baglanildi", ui::ToastTip::Basari); } else { durum.cevapHatasi = hata; ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } durum.yukleniyor = false; std::memset(g_ui.parola, 0, sizeof g_ui.parola); } } if (!durum.cevapHatasi.empty()) { ImGui::Spacing(); ImGui::TextColored(t.hata, "[UYARI] %s", durum.cevapHatasi.c_str()); } // Bağlantı özeti: hangi sunucuya bağlı, kaç cihaz görülüyor (belirsizlik // bırakmaz — "0 cihaz" ile "yanlış sunucuya bağlı" karışmasın). { ImGui::Spacing(); const bool bagli = durum.oturumAcik && durum.sunucuyaBagli; ImGui::TextColored(bagli ? t.basari : t.metinSoluk, "%s Sunucu: %s", bagli ? "[BAGLI]" : "[KOPUK]", g_ui.sunucu); ImGui::SameLine(); ImGui::TextDisabled(" · %d cihaz listeleniyor · komut gonderilen: %d", (int)g_cihazlar.size(), durum.komutSayaci); } ImGui::Separator(); // ═══ ANA ICERIK: sol liste | sag detay ═════════════════════════════════════ const float solGenislik = 600.0f; ImGui::BeginChild("solpanel", ImVec2(solGenislik, 0), 0); ImGui::SetNextItemWidth(300.0f); ImGui::InputTextWithHint("##filtre", "[ARA] filtre (bilgisayar / seri / musteri)", g_ui.filtre, sizeof g_ui.filtre); ImGui::SameLine(); if (ui::buton("Yenile", ImVec2(100, 0), ui::ButonTip::Ikincil)) g_ui.ilkAcilis = true; ImGui::SameLine(); if (ui::buton("Temizle", ImVec2(74, 0), ui::ButonTip::Hayalet)) { std::memset(g_ui.filtre, 0, sizeof g_ui.filtre); } ImGui::SameLine(); ImGui::Checkbox("Bilinmeyenleri gizle", &g_ui.bilinmeyenGizle); if (ImGui::IsItemHovered()) ImGui::SetTooltip("fikocad kaydi (bilgisayar adi) olmayan, hic baglanmamis cihazlari listede gizler.\nSilme ve komut islemleri de yalniz gorunen cihazlara uygulanir."); // Otomatik yenileme (3 sn) + ilk acilista hemen const float simdi = (float)ImGui::GetTime(); static float sonCekim = -99.0f; // Iki adimli sil onayinin suresi doldu mu? (8 sn sonra buton normale doner) if (g_ui.silOnayKip != 0 && simdi - g_ui.silOnayZaman > 8.0f) g_ui.silOnayKip = 0; if (durum.oturumAcik && (g_ui.ilkAcilis || simdi - sonCekim > 3.0f)) { g_ui.ilkAcilis = false; sonCekim = simdi; // Secimi KIMLIKLE koru: liste tazelendiginde indeksler kayar (tarihe gore // siralama + silme sonrasi) — ayni cihaz secili kalmaya devam etsin. std::string seciliKimlik; if (g_ui.seciliCihaz >= 0 && g_ui.seciliCihaz < (int)g_cihazlar.size()) seciliKimlik = g_cihazlar[(size_t)g_ui.seciliCihaz].cihazKimlik; std::string hata; if (yonetimCihazlariYenile(g_cihazlar, hata)) { // PC bazli engel kararlari lisans sunucusundan okunup listeye islenir. std::vector engelliler; std::string engelHata; if (yonetimEngelliKimlikleri(g_ui.adminToken, engelliler, engelHata)) { for (CihazOzet& cc : g_cihazlar) cc.engelli = std::find(engelliler.begin(), engelliler.end(), cc.cihazKimlik) != engelliler.end(); } durum.sunucuyaBagli = true; durum.cevapHatasi.clear(); // Cihaz adlari (takma adlar): sunucudan girişte ve sonra 30 sn'de bir cek; sunucudaki // deger yerel kaydi gunceller (sunucu kaynak, yerel onbellek). Hata liste akisini bozmaz. static float sonAdCekim = -99.0f; if (simdi - sonAdCekim > 30.0f) { sonAdCekim = simdi; std::map adlar; std::string adHata; if (yonetimCihazAdlariOku(adlar, adHata)) { g_ui.adSunucuHata.clear(); for (const auto& [kimlik, ad] : adlar) if (cihazTakmaAdi(kimlik) != ad) cihazTakmaAdiYaz(kimlik, ad); } else { g_ui.adSunucuHata = adHata; } } if (!seciliKimlik.empty()) { g_ui.seciliCihaz = -1; for (int i = 0; i < (int)g_cihazlar.size(); ++i) if (g_cihazlar[(size_t)i].cihazKimlik == seciliKimlik) { g_ui.seciliCihaz = i; break; } } } else { durum.cevapHatasi = hata; } } // Cihaz sayisi / komut sayaci yukaridaki baglanti ozetinde zaten var (tekrar yok). // -- Toplu silme: filtredekileri (filtre bosken gorunen tumunu) iki adimda sil. // "bilinmiyor" gibi eski kayitlari tek tek temizlememek icin. { int gorunur = 0; for (const CihazOzet& cc : g_cihazlar) if (!(g_ui.bilinmeyenGizle && bilinmeyenMi(cc)) && kucukHarfIcerir(cc.bilgisayar + " " + cc.seri + " " + cc.musteri + " " + cc.ip, g_ui.filtre)) ++gorunur; if (durum.oturumAcik && gorunur > 0) { if (g_ui.silOnayKip == 2) { char etiket[64]; std::snprintf(etiket, sizeof etiket, "EMIN MISIN? %d cihaz silinsin", gorunur); if (ui::buton(etiket, ImVec2(280, 0), ui::ButonTip::Tehlike)) { g_ui.silOnayKip = 0; std::vector kimlikler; kimlikler.reserve((size_t)gorunur); for (const CihazOzet& cc : g_cihazlar) if (!(g_ui.bilinmeyenGizle && bilinmeyenMi(cc)) && kucukHarfIcerir(cc.bilgisayar + " " + cc.seri + " " + cc.musteri + " " + cc.ip, g_ui.filtre)) kimlikler.push_back(cc.cihazKimlik); std::string hata; int silinen = -1; if (yonetimCihazlariSil(kimlikler, silinen, hata)) { std::string m = silinen >= 0 ? std::to_string(silinen) + " cihaz kaydi silindi" : "Silme istegi gonderildi"; ui::toastGoster(m.c_str(), ui::ToastTip::Basari, 5.0f); g_ui.ilkAcilis = true; // liste hemen tazelenir } else { ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } } ImGui::SameLine(); if (ui::buton("Vazgec", ImVec2(74, 0), ui::ButonTip::Hayalet)) g_ui.silOnayKip = 0; } else { char etiket[48]; std::snprintf(etiket, sizeof etiket, "Gorunenleri sil (%d)", gorunur); if (ui::buton(etiket, ImVec2(180, 0), ui::ButonTip::Tehlike)) { g_ui.silOnayKip = 2; g_ui.silOnayZaman = simdi; } if (ImGui::IsItemHovered()) ImGui::SetTooltip( "Filtreye uyan cihazlarin goCihazlar kaydini sunucudan siler\n" "(filtre bosken gorunen tumu). Cihazlar bir sonraki baglantisinda\n" "kendiliginden yeniden kayit olur."); } } } if (g_cihazlar.empty()) { ImGui::Spacing(); ImGui::Separator(); if (durum.oturumAcik) { ImGui::TextDisabled("Henuz cihaz gorunmuyor."); ImGui::TextDisabled("Fikocad acildiginda burada belirir."); } else { ImGui::TextDisabled("Once sunucuya baglanin (ust satir)."); } } if (ImGui::BeginTable("cihaztablo", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, ImGui::GetContentRegionAvail().y - 10.0f))) { ImGui::TableSetupColumn("Bilgisayar", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Seri", ImGuiTableColumnFlags_WidthFixed, 105.0f); ImGui::TableSetupColumn("IP", ImGuiTableColumnFlags_WidthFixed, 92.0f); ImGui::TableSetupColumn("Son", ImGuiTableColumnFlags_WidthFixed, 78.0f); ImGui::TableSetupColumn("Durum", ImGuiTableColumnFlags_WidthFixed, 96.0f); ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableHeadersRow(); for (int i = 0; i < (int)g_cihazlar.size(); ++i) { const CihazOzet& c = g_cihazlar[(size_t)i]; if ((g_ui.bilinmeyenGizle && bilinmeyenMi(c)) || !kucukHarfIcerir(gorunenAd(c) + " " + c.bilgisayar + " " + c.seri + " " + c.musteri + " " + c.ip, g_ui.filtre)) continue; ImGui::PushID(i); ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ui::durumLed(durumLedKodu(c), 4.0f); ImGui::SameLine(); if (ImGui::Selectable(gorunenAd(c).c_str(), g_ui.seciliCihaz == i, 0, ImVec2(ImGui::GetContentRegionAvail().x, 0))) g_ui.seciliCihaz = i; if (ImGui::IsItemHovered() && ImGui::BeginTooltip()) { if (gorunenAd(c) != c.bilgisayar) ImGui::Text("Bilgisayar: %s", c.bilgisayar.c_str()); ImGui::Text("Cihaz: %s", c.cihazKimlik.c_str()); ImGui::Text("Musteri: %s", c.musteri.empty() ? "-" : c.musteri.c_str()); ImGui::Text("Surum: %s", c.surum.empty() ? "-" : c.surum.c_str()); if (ureticiCihazi(c)) ImGui::TextColored(ui::tema().basari, "Uretici makinesi - lisans dosyasi gerekmez"); ImGui::TextDisabled("Sol tikla: yonet"); ImGui::EndTooltip(); } ImGui::TableSetColumnIndex(1); ImGui::TextUnformatted(c.seri.empty() ? "-" : c.seri.c_str()); ImGui::TableSetColumnIndex(2); ImGui::TextUnformatted(c.ip.empty() ? "-" : c.ip.c_str()); ImGui::TableSetColumnIndex(3); ImGui::TextDisabled("%s", kisaZaman(c.sonBaglanma).c_str()); ImGui::TableSetColumnIndex(4); ImGui::TextColored(durumRengi(c), "%s", durumEtiketi(c)); ImGui::PopID(); } ImGui::EndTable(); } ImGui::EndChild(); // ═══ SAG PANEL ══════════════════════════════════════════════════════════════ ImGui::SameLine(); ImGui::BeginChild("sagpanel", ImVec2(0, 0), 0); if (g_ui.seciliCihaz < 0 || g_ui.seciliCihaz >= (int)g_cihazlar.size()) { ImGui::TextDisabled("Soldaki listeden bir cihaz secin."); ImGui::EndChild(); ImGui::End(); return; } CihazOzet& c = g_cihazlar[(size_t)g_ui.seciliCihaz]; ui::baslikSeridi("[CIHAZ]", gorunenAd(c).c_str()); ImGui::SameLine(); ui::rozet(durumEtiketi(c), durumRengi(c)); ui::neonAyrac(); // -- Cihaz bilgisi ---------------------------------------------------------- // Sag panel sekmeli: Cihaz | Komut | Lisans | Kanal. Eskiden 6 acilir baslik ust uste // diziliyor, ekran uzayip karisiyordu; artik tek seferde tek is gorunur. if (ImGui::BeginTabBar("yonetimsekmeler")) { // -- Sekme 1: Cihaz ----------------------------------------------------------- if (ImGui::BeginTabItem("Cihaz")) { // -- Cihaz adi (takma ad): satici kendi verdigi isim, listede bilgisayar adi yerine // gorunur. Secim degisince tampon o cihazin kayitli adiyla yenilenir. if (g_ui.cihazAdKimlik != c.cihazKimlik) { g_ui.cihazAdKimlik = c.cihazKimlik; const std::string kayitli = cihazTakmaAdi(c.cihazKimlik); std::snprintf(g_ui.cihazAd, sizeof g_ui.cihazAd, "%s", kayitli.c_str()); } ImGui::AlignTextToFramePadding(); ImGui::TextDisabled("Cihaz adi"); ImGui::SameLine(110.0f); ImGui::SetNextItemWidth(220.0f); const bool enter = ImGui::InputTextWithHint("##cihazad", c.bilgisayar.c_str(), g_ui.cihazAd, sizeof g_ui.cihazAd, ImGuiInputTextFlags_EnterReturnsTrue); ImGui::SameLine(); const bool kaydet = ImGui::Button("Kaydet"); ImGui::SameLine(); const bool sifirla = ImGui::Button("Sifirla"); if (sifirla) g_ui.cihazAd[0] = '\0'; if (enter || kaydet || sifirla) { cihazTakmaAdiYaz(c.cihazKimlik, g_ui.cihazAd); // yerel onbellek her durumda std::string adHata; if (yonetimCihazAdiYaz(c.cihazKimlik, g_ui.cihazAd, adHata)) { g_ui.adSunucuHata.clear(); ui::toastGoster(g_ui.cihazAd[0] ? "Cihaz adi sunucuya kaydedildi" : "Cihaz adi sifirlandi (sunucudan silindi)", ui::ToastTip::Basari, 3.0f); } else { g_ui.adSunucuHata = adHata; const std::string msj = "Ad yalniz bu makinede kaydedildi, sunucu reddetti: " + adHata; ui::toastGoster(msj.c_str(), ui::ToastTip::Hata, 8.0f); } } if (!g_ui.adSunucuHata.empty()) ImGui::TextColored(ui::tema().uyari, "Sunucu (cihaz adlari): %s", g_ui.adSunucuHata.c_str()); ImGui::TextDisabled("Bos birakirsan bilgisayar adi (%s) gorunur. Ad sunucuda " "saklanir (tum konsollarda ayni).", bilinmeyenMi(c) ? "-" : c.bilgisayar.c_str()); ImGui::Spacing(); if (ImGui::BeginTable("cihazbilgi", 2, ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) { ImGui::TableSetupColumn("a", ImGuiTableColumnFlags_WidthFixed, 110.0f); ImGui::TableSetupColumn("b", ImGuiTableColumnFlags_WidthStretch); auto satir = [](const char* ad, const std::string& deger, const char* bos) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::TextDisabled("%s", ad); ImGui::TableSetColumnIndex(1); ImGui::TextUnformatted(deger.empty() ? bos : deger.c_str()); }; satir("Seri", c.seri, "(lisanssiz)"); satir("Musteri", c.musteri, "-"); satir("IP", c.ip, "-"); satir("Surum", c.surum, "-"); satir("Son baglanma", kisaZaman(c.sonBaglanma), "-"); satir("Cihaz kimligi", c.cihazKimlik, "-"); ImGui::EndTable(); } ImGui::Spacing(); ImGui::TextDisabled("Sil: goCihazlar kaydi kaldirilir; cihaz bir sonraki " "baglantisinda kendiliginden yeniden kayit olur."); if (g_ui.silOnayKip == 1) { if (ui::buton("EMIN MISIN? KAYDI SIL (2. tik)", ImVec2(260, 0), ui::ButonTip::Tehlike)) { g_ui.silOnayKip = 0; std::string hata; int silinen = -1; if (yonetimCihazlariSil({c.cihazKimlik}, silinen, hata)) { ui::toastGoster("Cihaz kaydi silindi", ui::ToastTip::Basari, 5.0f); g_ui.ilkAcilis = true; // liste hemen tazelenir } else { ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } } ImGui::SameLine(); if (ui::buton("Vazgec", ImVec2(74, 0), ui::ButonTip::Hayalet)) g_ui.silOnayKip = 0; } else if (ui::buton("KAYDI SIL", ImVec2(140, 0), ui::ButonTip::Tehlike)) { g_ui.silOnayKip = 1; g_ui.silOnayZaman = simdi; } ImGui::EndTabItem(); } // -- Sekme 2: Komut (uzaktan komut + kilit) ------------------------------------ if (ImGui::BeginTabItem("Komut")) { ImGui::TextDisabled("Secili cihaza beyaz listedeki bir komutu imzalayip gonderir."); ImGui::Spacing(); const std::vector& bl = yonetimBeyazListe(); if (g_ui.seciliKomut >= (int)bl.size()) g_ui.seciliKomut = 0; ImGui::SetNextItemWidth(300.0f); if (ImGui::BeginCombo("##komutsec", bl[(size_t)g_ui.seciliKomut].c_str())) { for (int i = 0; i < (int)bl.size(); ++i) if (ImGui::Selectable(bl[(size_t)i].c_str(), g_ui.seciliKomut == i)) g_ui.seciliKomut = i; ImGui::EndCombo(); } if (ImGui::IsItemHovered()) ImGui::SetTooltip("Beyaz listedeki komutlar. Fikocad ayrica imza + gate dener."); ImGui::SetNextItemWidth(240.0f); ImGui::InputTextWithHint("##komutmesaj", "mesaj (opsiyonel)", g_ui.komutMesaj, sizeof g_ui.komutMesaj); ImGui::SameLine(); if (ui::buton("Gonder", ImVec2(110, 0), ui::ButonTip::Birincil)) { std::string hata; if (yonetimKomutGonder(c, bl[(size_t)g_ui.seciliKomut], g_ui.komutMesaj, hata)) { ui::toastGoster(("Gonderildi: " + bl[(size_t)g_ui.seciliKomut]).c_str(), ui::ToastTip::Basari); std::memset(g_ui.komutMesaj, 0, sizeof g_ui.komutMesaj); } else { ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } } ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); ImGui::TextDisabled("Kilitle: tum komutlar kapanir (gorsuntuleyici kipi)."); if (ui::buton(c.kilitli ? "KILIT ACI" : "KILITLE", ImVec2(150, 0), c.kilitli ? ui::ButonTip::Birincil : ui::ButonTip::Tehlike)) { std::string hata; if (yonetimKilitle(c, !c.kilitli, "", hata)) ui::toastGoster(c.kilitli ? "Kilit acma gonderildi" : "Kilitleme gonderildi", ui::ToastTip::Basari); else ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } ImGui::Spacing(); // Yonetici tokeni: %USERPROFILE%\.fikoyt\yonetici_token dosyasindan bir kez okunur // (exe icine gomulmez; lisans_ozel.key ile ayni klasor). Dosya yoksa alan bos kalir. static bool tokenDenendi = false; if (!tokenDenendi) { tokenDenendi = true; if (!g_ui.adminToken[0]) { if (const char* up2 = std::getenv("USERPROFILE")) { std::ifstream tf(std::string(up2) + "\\.fikoyt\\yonetici_token"); std::string satir; if (tf && std::getline(tf, satir)) { while (!satir.empty() && (satir.back() == 13 || satir.back() == 32 || satir.back() == 10)) satir.pop_back(); std::snprintf(g_ui.adminToken, sizeof g_ui.adminToken, "%s", satir.c_str()); } } } } ImGui::TextDisabled("Secili bilgisayar (yonetici tokeni gerekir):"); ImGui::SetNextItemWidth(240.0f); ImGui::InputText("##admintoken", g_ui.adminToken, sizeof g_ui.adminToken, ImGuiInputTextFlags_Password); ImGui::SameLine(); if (ui::buton("Engelle", ImVec2(120, 0), ui::ButonTip::Tehlike)) { std::string hata; if (yonetimEngelDegistir(c, true, g_ui.adminToken, hata)) ui::toastGoster("Engel karari gonderildi", ui::ToastTip::Basari); else ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } ImGui::SameLine(); if (ui::buton("Izin ver", ImVec2(120, 0), ui::ButonTip::Birincil)) { std::string hata; if (yonetimEngelDegistir(c, false, g_ui.adminToken, hata)) ui::toastGoster("Izin karari gonderildi", ui::ToastTip::Basari); else ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } ImGui::EndTabItem(); } // -- Sekme 3: Lisans ver / komut yetkilendir ----------------------------------- if (ImGui::BeginTabItem("Lisans")) { ImGui::TextDisabled("Satilan komutlari sec -> bilet imzalanir -> cihaza aninda gider."); ImGui::SetNextItemWidth(220.0f); ImGui::InputTextWithHint("##yseri", "seri no (FKC-2026-0001)", g_ui.yeniSeri, sizeof g_ui.yeniSeri); ImGui::SameLine(); ImGui::SetNextItemWidth(260.0f); ImGui::InputTextWithHint("##ymusteri", "musteri adi", g_ui.yeniMusteri, sizeof g_ui.yeniMusteri); // Komut katalogu ImGui::Spacing(); ImGui::SetNextItemWidth(220.0f); ImGui::InputTextWithHint("##komutfiltre", "[ARA] komut filtresi", g_ui.komutFiltre, sizeof g_ui.komutFiltre); // Gorunur (filtre uygun) / toplam sayim: "Tumunu sec" ne kapsiyor gorelsin. const int toplamKomut = lisansKimlikSayisi(); int gorunurKomut = 0; for (int i = 0; i < toplamKomut; ++i) { const char *g0 = nullptr, *a0 = nullptr, *k0 = nullptr; if (!lisansKimlikKaydi(i, g0, a0, k0)) continue; if (kucukHarfIcerir(std::string(g0) + " " + a0 + " " + k0, g_ui.komutFiltre)) ++gorunurKomut; } ImGui::SameLine(); ImGui::TextDisabled("%d / %d kayit", gorunurKomut, toplamKomut); ImGui::SameLine(); if (ui::buton("Tumunu sec", ImVec2(110, 0), ui::ButonTip::Ikincil)) { // Filtreye uyanlari (filtre bosken tumunu) tek tikla sec; zaten secili // olanlar tekrar eklenmez. for (int i = 0; i < toplamKomut; ++i) { const char *g0 = nullptr, *a0 = nullptr, *k0 = nullptr; if (!lisansKimlikKaydi(i, g0, a0, k0)) continue; if (!kucukHarfIcerir(std::string(g0) + " " + a0 + " " + k0, g_ui.komutFiltre)) continue; const std::string k(k0); if (std::find(g_ui.seciliKomutlar.begin(), g_ui.seciliKomutlar.end(), k) == g_ui.seciliKomutlar.end()) g_ui.seciliKomutlar.push_back(k); } } if (ImGui::IsItemHovered()) ImGui::SetTooltip("Filtreye uyan tum komutlari secer.\nFiltre bosken katalogdaki tumu."); if (!g_ui.seciliKomutlar.empty()) { ImGui::SameLine(); if (ui::buton("Secimi temizle", ImVec2(120, 0), ui::ButonTip::Hayalet)) g_ui.seciliKomutlar.clear(); } if (ImGui::BeginChild("katalog", ImVec2(0, 190.0f), ImGuiChildFlags_Borders)) { const int toplam = lisansKimlikSayisi(); for (int i = 0; i < toplam; ++i) { const char* g = nullptr; const char* ad = nullptr; const char* kim = nullptr; if (!lisansKimlikKaydi(i, g, ad, kim)) continue; if (!kucukHarfIcerir(std::string(g) + " " + ad + " " + kim, g_ui.komutFiltre)) continue; const std::string k(kim); bool sec = std::find(g_ui.seciliKomutlar.begin(), g_ui.seciliKomutlar.end(), k) != g_ui.seciliKomutlar.end(); ImGui::PushID(i); const std::string etiket = std::string(g) + " > " + ad; if (ImGui::Checkbox(etiket.c_str(), &sec)) { if (sec) g_ui.seciliKomutlar.push_back(k); else g_ui.seciliKomutlar.erase( std::remove(g_ui.seciliKomutlar.begin(), g_ui.seciliKomutlar.end(), k), g_ui.seciliKomutlar.end()); } if (ImGui::IsItemHovered()) ImGui::SetTooltip("Kimlik: %s", kim); ImGui::SameLine(); ImGui::TextDisabled("(%s)", kim); ImGui::PopID(); } ImGui::EndChild(); } // Anahtar ImGui::Spacing(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 110.0f); ImGui::InputTextWithHint("##anahtaryolu", "ozel anahtar dosyasi (.key)", g_ui.ozelAnahtar, sizeof g_ui.ozelAnahtar); // Komut gonderme de (uzak kilit/lisans.yenile) ayni anahtarla imzaliyor: // degisince http katmanini da guncelle. yonetimOzelAnahtarYolAyarla(g_ui.ozelAnahtar); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Uretici makinesindeki ozel imza anahtari.\n" "Bileti o imzalar; musteride bu dosya ASLA bulunmaz."); ImGui::SameLine(); if (ui::buton("Sec", ImVec2(74, 0), ui::ButonTip::Ikincil)) { // varsayilan yol onerisi const char* up = std::getenv("USERPROFILE"); if (up) std::snprintf(g_ui.ozelAnahtar, sizeof g_ui.ozelAnahtar, "%s\\.fikoyt\\lisans_ozel.key", up); yonetimOzelAnahtarYolAyarla(g_ui.ozelAnahtar); } // Bitis ImGui::Spacing(); if (ui::anahtar("Suresiz", &g_ui.suresiz)) { /* aninda yansitir */ } if (!g_ui.suresiz) { ImGui::SameLine(); tarihSaatSecici(g_ui); } // Cihazin kayitli seri/musteri bilgisini bos alanlara otomatik doldur. if (!g_ui.yeniSeri[0] && !c.seri.empty()) std::snprintf(g_ui.yeniSeri, sizeof g_ui.yeniSeri, "%s", c.seri.c_str()); if (!g_ui.yeniMusteri[0] && !c.musteri.empty()) std::snprintf(g_ui.yeniMusteri, sizeof g_ui.yeniMusteri, "%s", c.musteri.c_str()); // Seri bos kalirsa uretici kendisi uretir (cihaz kaydinda seri yoksa). if (!g_ui.yeniSeri[0]) { const long zaman = (long)(std::time(nullptr) % 100000000LL); std::snprintf(g_ui.yeniSeri, sizeof g_ui.yeniSeri, "FKC-%ld-%04d", zaman, std::rand() % 10000); } // Ozet + gonder ImGui::Spacing(); const bool hazir = !g_ui.seciliKomutlar.empty() && g_ui.ozelAnahtar[0] && g_ui.yeniSeri[0] && (g_ui.suresiz || (g_ui.yil > 2000 && g_ui.ay > 0 && g_ui.gun > 0)); ImGui::Text("%d komut secildi", (int)g_ui.seciliKomutlar.size()); if (!g_ui.suresiz && g_ui.yil > 2000 && g_ui.ay > 0 && g_ui.gun > 0) { ImGui::SameLine(); ImGui::TextDisabled("| bitis: %02d.%02d.%04d %02d:%02d", g_ui.gun, g_ui.ay, g_ui.yil, g_ui.saat, g_ui.dakika); } ImGui::BeginDisabled(!hazir); if (ui::buton("LISANSI YAZ ve aninda gonder", ImVec2(-1, 34.0f), ui::ButonTip::Birincil)) { // Bitis hesapla (gece yarisi -> 23:59:59) i64 bitis = 0; if (!g_ui.suresiz) { std::tm tm{}; tm.tm_mday = g_ui.gun; tm.tm_mon = g_ui.ay - 1; tm.tm_year = g_ui.yil - 1900; tm.tm_hour = g_ui.saat; tm.tm_min = g_ui.dakika; tm.tm_sec = 0; tm.tm_isdst = -1; const time_t tt = mktime(&tm); bitis = (i64)tt; } std::string hata; if (yonetimLisansYaz(g_ui.ozelAnahtar, c, g_ui.yeniMusteri, g_ui.yeniSeri, g_ui.seciliKomutlar, bitis, hata)) { ui::toastGoster("Lisans yazildi ve cihaza gonderildi", ui::ToastTip::Basari, 5.0f); } else { ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 8.0f); } } ImGui::EndDisabled(); if (!hazir) { if (g_ui.seciliKomutlar.empty()) ImGui::TextDisabled("Eksik: komut sec"); if (!g_ui.ozelAnahtar[0]) ImGui::TextDisabled("Eksik: anahtar yolu"); if (!g_ui.yeniSeri[0]) ImGui::TextDisabled("Eksik: seri no"); if (!(g_ui.suresiz || (g_ui.yil > 2000 && g_ui.ay > 0 && g_ui.gun > 0))) ImGui::TextDisabled("Eksik: gecerli bitis tarihi"); } ImGui::EndTabItem(); } // -- Sekme 4: Kanal durumu + komut gecmisi --------------------------------------- if (ImGui::BeginTabItem("Kanal")) { const UzakKanalDurum kd = uzakKanalDurumu(); ImGui::Text("Kanal: %s", uzakKanalDurumAdi(kd)); ImGui::SameLine(); ImGui::TextDisabled("| %s", uzakKanalOzet().c_str()); ImGui::TextDisabled("Bu kanal URETICI tarafindan gelen komutlari karsilar " "(Engelle / Lisans yenile / Komut yetkilendir)."); ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); ImGui::AlignTextToFramePadding(); ImGui::TextUnformatted("Son komutlar (bu makine)"); if (!uzakKomutKayitlari().empty()) { ImGui::SameLine(); if (ui::buton("Gecmisi temizle", ImVec2(120, 0), ui::ButonTip::Hayalet)) uzakKomutKayitTemizle(); } if (uzakKomutKayitlari().empty()) { ImGui::TextDisabled("Henuz uzaktan komut calismadi."); } else if (ImGui::BeginTable("gecmis", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, ImGui::GetContentRegionAvail().y - 6.0f))) { ImGui::TableSetupColumn("Saat", ImGuiTableColumnFlags_WidthFixed, 60.0f); ImGui::TableSetupColumn("Komut", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Sonuc", ImGuiTableColumnFlags_WidthFixed, 50.0f); ImGui::TableSetupColumn("Detay", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableHeadersRow(); for (const UzaktanKomutKaydi& k : uzakKomutKayitlari()) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::TextDisabled("%s", k.zaman.c_str()); ImGui::TableSetColumnIndex(1); ImGui::TextUnformatted(k.komutKodu.c_str()); ImGui::TableSetColumnIndex(2); ImGui::TextColored(k.basarili ? t.basari : t.hata, "%s", k.basarili ? "OK" : "RED"); ImGui::TableSetColumnIndex(3); ImGui::TextDisabled("%s", k.sonucMesaji.c_str()); } ImGui::EndTable(); } ImGui::EndTabItem(); } ImGui::EndTabBar(); } // BeginTabBar ImGui::EndChild(); ImGui::End(); } } // namespace fiko