レポジトリ種類: Mercurial

#undef Status
#undef None
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Select_Browser.H>
#include <FL/Fl_Text_Display.H>
#include <FL/Fl_Text_Buffer.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Secret_Input.H>
#include <FL/Fl_Hold_Browser.H>
#include <FL/Fl_Copy_Surface.H>
#include <FL/Fl_PNG_Image.H>

#include <dirent.h>
#include <sys/stat.h>

#include <iostream>
#include <string>
#include <vector>

#include "src/addpass.hh"
#include "src/browser.hh"
#include "src/chkpass.hh"
#include "src/delpass.hh"
#include "src/editpass.hh"
#include "src/genpass.hh"
#include "src/hidepass.hh"
#include "src/initpass.hh"
#include "src/showpass.hh"
#include "src/theme.hh"
#include "src/vulnpass.hh"
#include "main.hh"

Fl_Text_Display *textview = nullptr;
Fl_Text_Buffer *textbuf = nullptr;
Fl_Input *searchfield = nullptr;
Fl_Button *showbtn = nullptr;

Addpass a;
Chkpass c;
Delpass d;
Editpass e;
Genpass g;
Hidepass h;
Initpass i;
Showpass s;
Vulnpass v;

Theme theme;

const char *sofname = "simpas";
const char *intname = "SimPas";
const char *version = "1.2.0";
const char *basedof = "sp-1.6.0";

int browseId;
std::string realpass = "";
Config *cnf;
std::string lang = "ja";

void browse(std::string &path, bool isNew) {
  std::string cont = s.exec(path.c_str(), false);
  realpass = cont;

  if (isNew) browseId = Browser::browser->size();
  Browser::browser->value(browseId);

  if (!cont.empty()) {
    if (Hidepass::isPassHidden) {
      if (lang.compare(0, 2, "en") == 0) {
        textbuf->text("(Hidden, please click the \"show\" button to reveal)");
      } else {
        textbuf->text("(非表示、「表示」ボタンをクリックして確認して下さい)");
      }
      s.btn->activate();
      s.btn->label((lang.compare(0, 2, "en") == 0) ?
          "Show password" : "パスワードの表示");
    } else {
      textbuf->text(cont.c_str());
      s.btn->label((lang.compare(0, 2, "en") == 0) ?
          "Hide password" : "パスワードを隠す");
      s.btn->activate();}
    Editpass::setFile(path);
    Delpass::setFile(path);
    d.btn->activate();
    e.btn->activate();
  }
}

void clearpaths(bool isReset) {
  Common::fullpaths.clear();
  Common::dispaths.clear();
  if (isReset) {
    std::string mockpath = "";
    Editpass::setFile(mockpath);
    Delpass::setFile(mockpath);
    d.btn->deactivate();
    e.btn->deactivate();
  }
}

void search_cb(Fl_Widget *, void *) {
  std::string mockpath = "";
  Editpass::setFile(mockpath);
  Delpass::setFile(mockpath);
  d.btn->deactivate();
  e.btn->deactivate();
  Browser::updatelist();
}

void copy_cb(Fl_Widget *, void *) {
  if (!realpass.empty()) {
    Fl::copy(realpass.c_str(), realpass.length(), 1, Fl::clipboard_plain_text);
  } else {
    Fl::copy("", 0, 1, Fl::clipboard_plain_text);
  }
}

void browser_cb(Fl_Widget *w, void *) {
  (void)w;
  int idx = Browser::browser->value();
  if (idx == 0) return;
  browseId = idx;

  std::string path = Browser::filterpaths[idx - 1];
  browse(path, false);
}

void show_cb(Fl_Widget *, void *) {
  int idx = Browser::browser->value();
  if (idx == 0) return;
  std::string path = Browser::filterpaths[idx - 1];

  if (Hidepass::isPassHidden) {
    std::string cont = s.exec(path.c_str(), false);
    realpass = cont;
    textbuf->text(cont.c_str());

    if (lang.compare(0, 2, "en") == 0) {
      s.btn->label("Hide password");
    } else {
      s.btn->label("パスワードを隠す");
    }
    Hidepass::isPassHidden = false;
  } else {
    if (lang.compare(0, 2, "en") == 0) {
      textbuf->text("(Hidden, please click the \"show\" button to reveal)");
      s.btn->label("Show password");
    } else {
      textbuf->text("(非表示、「表示」ボタンをクリックして確認して下さい)");
      s.btn->label("パスワードの表示");
    }
    Hidepass::isPassHidden = true;
  }
}

void init_cb(Fl_Widget *w, void *data) {
  i.exec(i.gpgid->value());
  i.btn->deactivate();
  ((Initpass *)data)->cancel_cb(w, data);
}

void init_dialog_cb(Fl_Widget *w, void *) {
  (void)w;
  Fl_Window *dialog = new Fl_Window(450, 120,
      (lang.compare(0, 2, "en") == 0 ?
       "Initialize password" : "パスワードの初期設定"));

  i.gpgid = new Fl_Input(90, 20, 300, 30,
      (lang.compare(0, 2, "en") == 0 ? "GPG secret key:" : "gpg秘密鍵:"));
  dialog->add(i.gpgid);

  Fl_Button *startbtn = new Fl_Button(185, 70, 80, 30,
      (lang.compare(0, 2, "en") == 0 ? "Start" : "開始"));

  startbtn->callback(init_cb, dialog);

  dialog->add(startbtn);

  dialog->end();
  dialog->set_modal();
  dialog->show();
}

int main(int argc, char **argv) {
  cnf = Common::getconfig();
  if (cnf == nullptr) {
#if defined (_WIN32)
    std::string cnfpath = "type nul > \\AppData\\Local\\076\\sp\\sp.conf";
#elif defined (__HAIKU__)
    std::string cnfpath = "touch /boot/home/config/settings/sp/sp.conf";
#else
    std::string cnfpath = "touch ~/config/sp.conf";
#endif
    std::cout << "コンフィグファイルを見つけられません。"
      "「" << cnfpath << "」を実効して下さい。" << std::endl;
    return -1;
  }

  Theme::isLight = Common::gettheme(cnf);
  lang = Common::getlang(cnf);
  if (cnf->showpasswd) Hidepass::isPassHidden = false;
  std::string windowtit = std::string(intname) + " " + version;
  Fl_Window *window = new Fl_Window(790, 740, windowtit.c_str());

  if (!Theme::isLight) {
    Theme::set_dark_theme();
    theme.lbl = (lang.compare(0, 2, "en") == 0 ?
        "To light mode" : "ライトモードへ");
  } else {
    Theme::set_light_theme();
    theme.lbl = (lang.compare(0, 2, "en") == 0 ?
        "To dark mode" : "ダークモードへ");
  }

#if defined(__linux)
  const char *iconPath = "/usr/share/icons/076/512x512/simpas.png";
#else
  const char *iconPath = "/usr/local/share/icons/076/512x512/simpas.png";
#endif

  Fl_PNG_Image *icon = new Fl_PNG_Image(iconPath);

  window->icon(icon);

  searchfield = new Fl_Input(
      (lang.compare(0, 2, "en") == 0 ? 70 : 50), 10,
      (lang.compare(0, 2, "en") == 0 ? 710 : 730), 30,
      (lang.compare(0, 2, "en") == 0 ? "Search:" : "検索:"));
  searchfield->callback(search_cb);

  Browser::browser = new Fl_Select_Browser(10, 50, 380, 500);
  textview = new Fl_Text_Display(400, 50, 380, 500);
  textbuf = new Fl_Text_Buffer();
  textview->buffer(textbuf);

  Browser::browser->callback(browser_cb);

  Fl_Button *copybtn = new Fl_Button(400, 600, 150, 30,
      (lang.compare(0, 2, "en") == 0 ? "Copy password" : "パスワードのコピー"));
  copybtn->callback(copy_cb);

  a.btn = new Fl_Button(10, 560, 150, 30,
      (lang.compare(0, 2, "en") == 0 ? "Add password" : "パスワードの追加"));
  a.btn->callback(a.dialog_cb);

  d.btn = new Fl_Button(10, 600, 150, 30,
      (lang.compare(0, 2, "en") == 0 ? "Delete password" : "パスワードの削除"));
  d.btn->deactivate();
  d.btn->callback(d.dialog_cb);

  e.btn = new Fl_Button(400, 560, 150, 30,
    (lang.compare(0, 2, "en") == 0 ? "Edit password" : "パスワードの編集"));
  e.btn->deactivate();
  e.btn->callback(e.dialog_cb);

  s.btn = new Fl_Button(560, 600, 150, 30,
    (lang.compare(0, 2, "en") == 0 ? "Show password" : "パスワードの表示"));
  s.btn->deactivate();
  s.btn->callback(show_cb);

  Hidepass::setShowButton(s.btn);

  h.chk = new Fl_Check_Button(560, 560, 150, 30,
    (lang.compare(0, 2, "en") == 0 ? "Hide password" : "パスワードを隠す"));
  if (!cnf->showpasswd) h.chk->set();
  h.chk->callback(h.dialog_cb);

  Theme::setLang(&lang);
  theme.btn = new Fl_Button(630, 670, 150, 30, Theme::lbl.c_str());
  theme.btn->callback(theme.cb);

  g.btn = new Fl_Button(10, 640, 150, 30,
      (lang.compare(0, 2, "en") == 0 ? "Generate password" : "パスワードの作成"));
  g.btn->callback(g.dialog_cb);

  i.btn = new Fl_Button(10, 680, 150, 30,
      (lang.compare(0, 2, "en") == 0 ?
       "Initialize password" :
       "パスワードの初期設定"));

  v.btn = new Fl_Button(170, 560, 200, 30,
      (lang.compare(0, 2, "en") == 0 ? "Check for breach" : "漏洩されたかの確認"));
  v.btn->callback(v.dialog_cb);

  c.btn = new Fl_Button(170, 600, 200, 30,
      (lang.compare(0, 2, "en") == 0 ?
       "Check for unsafe passwords" : "不安定的なパスワードの確認"));
  c.btn->callback(c.dialog_cb);

  std::string gpgidpath = Common::getbasedir(true) + ".gpg-id";

  struct stat buf;
  if (stat(gpgidpath.c_str(), &buf) == 0) {
    i.btn->deactivate();
  }
  i.btn->callback(init_dialog_cb);

  std::string osname = "Unknown OS";
#if defined(__OpenBSD__)
  osname = "OpenBSD";
#elif defined(__FreeBSD__)
  osname = "FreeBSD";
#elif defined(__NetBSD__)
  osname = "NetBSD";
#elif defined(__linux)
  osname = "Linux";
#elif defined(__HAIKU__)
  osname = "Haiku";
#elif defined(_WIN32) | defined(_WIN64)
  osname = "Windows";
#endif

  std::string archname = "Unknown ARCH";
#if defined(__x86_64__) || defined(_M_X64)
  archname = "Intel/AMD 64";
#elif defined(__i386) || defined(_M_IX86)
  archname = "Intel";
#elif defined(__mips) || defined(__mips__)
  archname = "MIPS";
#elif defined(__powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
  archname = "PowerPC";
#elif defined(__powerpc64) || defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || defined(_ARCH_PPC64)
  archname = "PowerPC 64";
#elif defined(__sparc__) || defined(__sparc)
  archname = "SPARC";
#elif defined(__m68k__)
  archname = "m68k";
#elif defined(__aarch64__) || defined(_M_ARM64)
  archname = "ARM 64";
#elif defined(__riscv)
  archname = "RISC-V";
#endif

  std::string bothver = windowtit + " (" + std::string(basedof) + ")";
  Fl_Box *versionlabel = new Fl_Box(FL_NO_BOX, 620, 700, 160, 30, bothver.c_str());
  versionlabel->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE);

  std::string osarch = osname + std::string(" @@ ") + std::string(archname);
  Fl_Box *osarchlabel = new Fl_Box(FL_NO_BOX, 10, 700, 320, 30, osarch.c_str());
  osarchlabel->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);

  std::vector<std::string> fpaths;
  std::string rdir = Common::getbasedir(false);
  Common::scandir(rdir, rdir, fpaths);
  Browser::updatelist();

  window->end();
  window->show(argc, argv);

  return Fl::run();
}