レポジトリ種類: Mercurial

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>

#include <errno.h>
#include <dirent.h>
#include <unistd.h>

#include "common.hh"

Common common;

std::vector<std::string> Common::fullpaths;
std::vector<std::string> Common::dispaths;

Config *Common::getconfig() {
  std::string configpath = getconfigpath();
  if (configpath.empty()) {
    return nullptr;
  }

  common.config = new Config;

  common.config->syncname = "";
  common.config->syncpass = "";
  common.config->syncinstance = "";
  common.config->syncenable = false;
  common.config->showpasswd = false;
  common.config->theme = "dark";
  common.config->language = "ja";

  std::ifstream file(configpath);
  if (!file.is_open()) {
    delete common.config;
    return nullptr;
  }

  std::string line;
  while (std::getline(file, line)) {
    if (line[0] == '#' || line.empty()) continue;

    if (line.find("cloud sync username = ") == 0) {
      common.config->syncname = line.substr(22);
    } else if (line.find("cloud sync password = ") == 0) {
      common.config->syncpass = line.substr(22);
    } else if (line.find("cloud sync instance = ") == 0) {
      common.config->syncinstance = line.substr(22);
    } else if (line.find("cloud sync enabled = true") == 0) {
      common.config->syncenable = true;
    } else if (line.find("simpas show password = true") == 0) {
      common.config->showpasswd = true;
      if (common.config->showpasswd != false) common.showPassFromCnf = true;
    } else if (line.find("simpas theme = ") == 0) {
      common.config->theme = line.substr(15);
      if (common.config->language.compare(0, 4, "dark") != 0)
        common.themeFromCnf = true;
    } else if (line.find("simpas language = ") == 0) {
      common.config->language = line.substr(18);
      if (common.config->language.compare(0, 2, "ja") != 0) common.langFromCnf = true;
    }
  }

  return common.config;
}

std::string Common::getconfigpath() {
#if defined (_WIN32)
  const char *homeEnv = std::getenv("HOME");
  std::string homedir = (homeEnv != nullptr) ? homeEnv : "";

  std::string localdata = "\\AppData\\Local\\076\\sp\\sp.conf";
  std::string roamdata = "\\AppData\\Roaming\\076\\sp\\sp.conf";
  std::string sysdata = "C:\\ProgramData\\sp\\sp.conf";

  if (!homedir.empty()) {
    std::string lpath = homedir + localdata;
    if (access(lpath.c_str(), F_OK) != -1) {
      return lpath;
    }

    std::string rpath = homedir + roamdata;
    if (access(rpath.c_str(), F_OK) != -1) {
      return rpath;
    }
  }

  if (access(sysdata.c_str(), F_OK) != -1) {
    return sysdata;
  }
#elif defined (__HAIKU__)
  std::string cnfpath = "/boot/home/config/settings/sp/sp.conf";
  if (access(cnfpath.c_str(), F_OK) != -1) {
    return cnfpath;
  }
#else
  const char *homeEnv = std::getenv("HOME");
  std::string homedir = (homeEnv != nullptr) ? homeEnv : "";

  std::string userpath = "/.config/sp.conf";
  std::string wrongpath = "/.sp.conf";
  std::string netbsdpath = "/usr/pkg/etc/sp.conf";
  std::string freebsdpath = "/usr/local/etc/sp.conf";
  std::string syspath = "/etc/sp.conf";

  if (!homedir.empty()) {
    std::string correctuser = homedir + userpath;
    if (access(correctuser.c_str(), F_OK) != -1) {
      return correctuser;
    }

    std::string incorrectuser = homedir + wrongpath;
    if (access(incorrectuser.c_str(), F_OK) != -1) {
      return incorrectuser;
    }
  }

  if (access(netbsdpath.c_str(), F_OK) != -1) {
    return netbsdpath;
  }

  if (access(freebsdpath.c_str(), F_OK) != -1) {
    return freebsdpath;
  }

  if (access(syspath.c_str(), F_OK) != -1) {
    return syspath;
  }
#endif
  return "";
}

std::string Common::getbasedir(bool trailing) {
  std::string homedir = std::getenv("HOME") ? std::getenv("HOME") : "";
  if (homedir.empty()) return "";

#if defined(__HAIKU__)
  std::string basedir = "/config/settings/sp";
  std::string slash = "/";
#elif defined(_WIN32)
  std::string basedir = "\\AppData\\Local\\076\\sp";
  std::string slash = "\\";
#else
  std::string basedir = "/.local/share/sp";
  std::string slash = "/";
#endif

#if defined(__HAIKU__)
  return trailing ? (basedir + slash) : basedir;
#else
  return trailing ? (homedir + basedir + slash) : (homedir + basedir);
#endif
}

std::string Common::getlang(Config *cf) {
  if (common.langFromCnf) {
    return cf->language;
  }

  const char *env = std::getenv("SP_LANG");
  return (env ? env : "ja");
}

bool Common::gettheme(Config *cf) {
  if (common.themeFromCnf) {
    return (!cf->theme.empty() && cf->theme == "light" ? true : false);
  }

  const char *env = std::getenv("SP_THEME");
  return (env && strncmp(env, "light", 5) == 0) ? true : false;
}

int Common::mkdir_r(const std::string &path, mode_t mode) {
  char tmp[256];
  size_t len;

  std::snprintf(tmp, sizeof(tmp), "%s", path.c_str());

  len = std::strlen(tmp);
  if (tmp[len - 1] == '/') {
    tmp[len - 1] = 0;
  }

  for (char *p = tmp + 1; *p; p++) {
    if (*p == '/') {
      *p = 0;
      if (mkdir(tmp, mode) != 0 && errno != EEXIST) return -1;
      *p = '/';
    }
  }

  if (mkdir(tmp, mode) != 0 && errno != EEXIST) {
    return -1;
  }

  return 0;
}

void Common::tmpcopy(const std::string &inpath, const std::string &outpath) {
  std::ifstream src(inpath, std::ios::binary);
  std::ofstream dst(outpath, std::ios::binary);
}

std::vector<std::string> Common::explode(const std::string &str, char delimiter) {
  std::vector<std::string> tokens;
  std::string token;
  size_t start = 0, end = 0;

  while ((end = str.find(delimiter, start)) != std::string::npos) {
    tokens.push_back(str.substr(start, end - start));
    start = end + 1;
  }
  tokens.push_back(str.substr(start));

  return tokens;
}

void Common::scandir(const std::string &dpath, const std::string &rpath,
             std::vector<std::string> &fpaths) {
  DIR *dir = opendir(dpath.c_str());
  if (!dir) return;

  struct dirent *entry;
  while ((entry = readdir(dir)) != nullptr) {
    std::string name = entry->d_name;
    if (name == "." || name == ".." || name == ".gpg-id") continue;

    std::string fpath = std::string(dpath) + "/" + name;
    struct stat s;
    if (stat(fpath.c_str(), &s) != 0) {
      closedir(dir);
      return;
    }

    if (S_ISDIR(s.st_mode)) {
      scandir(fpath, rpath, fpaths);
    } else if (name.find(".gpg") != std::string::npos) {
      std::string rel = fpath.substr(rpath.size() + 1);
      fpaths.push_back(rel);
      fullpaths.push_back(fpath);

      std::string disname = rel.substr(0, rel.rfind(".gpg"));
      dispaths.push_back(disname);
    }
  }

  closedir(dir);
}