| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- /**
- * @author oldj
- * @blog http://oldj.net
- *
- * 和系统、平台相关的方法
- */
- 'use strict';
- const fs = require('fs');
- const path = require('path');
- const request = require('request');
- const moment = require('moment');
- const io = require('./libs/io');
- const platform = process.platform;
- const paths = require('./libs/paths');
- const pref = require('./libs/pref');
- const sys_host_path = paths.sys_host_path;
- const work_path = paths.work_path;
- const data_path = paths.data_path;
- const preference_path = paths.preference_path;
- const exec = require('child_process').exec;
- const stat = require('./modules/stat');
- stat.init();
- const crypto = require('crypto');
- function md5(text) {
- return crypto.createHash('md5').update(text).digest('hex');
- }
- const m_lang = require('./lang');
- let sudo_pswd = '';
- function getUserLang() {
- let user_lang;
- let p_lang = location.search.match(/\blang=(\w+)/);
- user_lang = (p_lang && p_lang[1]) || pref.get('user_language') || navigator.language || navigator.userLanguage || '';
- user_lang = user_lang.toString().toLowerCase();
- if (user_lang == 'cn' || user_lang == 'zh_cn') {
- user_lang = 'cn';
- } else {
- user_lang = 'en';
- }
- return user_lang;
- }
- let lang_key = getUserLang();
- const lang = m_lang.getLang(lang_key);
- function getSysHosts() {
- let cnt = '';
- try {
- cnt = fs.readFileSync(sys_host_path, 'utf-8');
- } catch (e) {
- console.log(e.message);
- }
- return cnt;
- }
- function tryToCreateWorkDir() {
- if (io.isDirectory((work_path))) {
- console.log('work dir exists.');
- return;
- }
- console.log(`try to create work directory: ${work_path}`);
- try {
- fs.mkdirSync(work_path);
- console.log('work directory created.');
- } catch (e) {
- alert('Fail to create work directory!');
- }
- }
- function saveData(content) {
- let txt = JSON.stringify({
- list: content
- });
- fs.writeFile(data_path, txt, 'utf-8', (error) => {
- if (error) {
- alert(error.message);
- }
- });
- }
- function apply_UNIX(content, success) {
- let tmp_fn = path.join(work_path, 'tmp.txt');
- if (content) {
- fs.writeFileSync(tmp_fn, content, 'utf-8');
- }
- let cmd;
- if (!sudo_pswd) {
- cmd = [
- `cat "${tmp_fn}" > ${sys_host_path}`
- , `rm -rf ${tmp_fn}`
- ].join(' && ');
- } else {
- sudo_pswd = sudo_pswd.replace(/'/g, '\\x27');
- cmd = [
- `echo '${sudo_pswd}' | sudo -S chmod 777 ${sys_host_path}`
- , `cat "${tmp_fn}" > ${sys_host_path}`
- , `echo '${sudo_pswd}' | sudo -S chmod 644 ${sys_host_path}`
- // , 'rm -rf ' + tmp_fn
- ].join(' && ');
- }
- exec(cmd, function (error, stdout, stderr) {
- // command output is in stdout
- if (error) {
- if (!sudo_pswd) {
- // 尝试让用户输入管理密码
- SH_event.emit('show_app');
- SH_event.emit('sudo_prompt', (pswd) => {
- sudo_pswd = pswd;
- tryToApply(null, success);
- });
- } else {
- alert(stderr);
- }
- return;
- }
- if (!error) {
- after_apply(success);
- }
- });
- }
- function _after_apply_unix(callback) {
- let cmd_fn = path.join(work_path, '_restart_mDNSResponder.sh');
- let cmd = `
- p1=/System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
- if [ -f $p1 ]; then
- sudo launchctl unload -w $p1
- sudo launchctl load -w $p1
- fi
- p2=/System/Library/LaunchDaemons/com.apple.discoveryd.plist
- if [ -f p2 ]; then
- sudo launchctl unload -w $p2
- sudo launchctl load -w $p2
- fi
- sudo killall -HUP mDNSResponder
- `;
- fs.writeFileSync(cmd_fn, cmd, 'utf-8');
- exec(`/bin/sh ${cmd_fn}`, function (error, stdout, stderr) {
- // command output is in stdout
- if (error) {
- console.log(error);
- }
- console.log(stdout, stderr);
- callback();
- });
- }
- function after_apply(callback) {
- SH_event.emit('after_apply');
- if (!sudo_pswd) {
- callback();
- return;
- }
- if (platform === 'darwin') {
- _after_apply_unix(callback);
- return;
- }
- callback();
- }
- function apply_Win32(content, success) {
- // todo 判断写入权限
- try {
- fs.writeFileSync(sys_host_path, content, 'utf-8');
- } catch (e) {
- console.log(e);
- let msg = e.message;
- if (platform === 'win32') {
- msg = `${msg}\n\n${lang.please_run_as_admin}`;
- }
- alert(msg);
- return;
- }
- success && success();
- // todo 更新 DNS 缓存
- }
- function tryToApply(content, success) {
- if (platform !== 'win32') {
- apply_UNIX(content, success);
- } else {
- apply_Win32(content, success);
- }
- }
- // init
- tryToCreateWorkDir();
- SH_event.on('test', () => {
- console.log('ttt');
- });
- SH_event.on('apply', (content, success) => {
- tryToApply(content, () => {
- let cmd = pref.get('after_cmd');
- if (cmd) {
- exec(cmd, function (error, stdout, stderr) {
- // command output is in stdout
- if (error) {
- alert(`AfterCmdError:\n\n${stderr}`);
- }
- });
- }
- success && success();
- });
- });
- SH_event.on('sudo_pswd', (pswd) => {
- sudo_pswd = pswd;
- });
- SH_event.on('show_app', (pswd) => {
- ipcRenderer.send('show_app');
- });
- SH_event.on('save_data', (content) => {
- saveData(content);
- ipcRenderer.send('send_host_list', content);
- });
- SH_event.on('check_host_refresh', (host, force = false) => {
- if (host.where !== 'remote' || !host.url || (!force && !host.refresh_interval)) {
- return;
- }
- let last_refresh = host.last_refresh;
- let refresh_interval = parseInt(host.refresh_interval) || 0;
- if (last_refresh && !force) {
- last_refresh = new Date(last_refresh);
- let delta = ((new Date()).getTime() - (last_refresh.getTime() || 0)) / (1000 * 3600);
- if (delta < refresh_interval) {
- return;
- }
- }
- // refresh
- // console.log(`getting '${host.url}' ..`);
- SH_event.emit('loading', host);
- host.is_loading = true;
- request(host.url, (err, res, body) => {
- console.log('got', res && res.statusCode);
- let out = {};
- // console.log(err, res && res.statusCode);
- host.is_loading = false;
- if (!err && res.statusCode === 200) {
- // console.log(body);
- host.content = body;
- delete host.error;
- host.last_refresh = moment().format('YYYY-MM-DD HH:mm:ss');
- SH_event.emit('change');
- } else {
- console.log(err, res && res.statusCode);
- // out.content = 'Error: ' + err.message;
- out.error = 'Error: ' + err.message;
- }
- SH_event.emit('loading_done', host, Object.assign({}, host, out));
- });
- });
- /**
- * 如果本地没有 data 文件,认为是第一次运行
- */
- function initGet() {
- let dd = require('./libs/default_data');
- let data = dd.make();
- data.sys.content = getSysHosts();
- data.list.push({
- title: 'backup',
- content: data.sys.content
- });
- return data;
- }
- module.exports = {
- md5: md5,
- getHosts: function () {
- let data = null;
- if (!io.isFile(data_path)) {
- return initGet();
- }
- try {
- let cnt = fs.readFileSync(data_path, 'utf-8');
- data = JSON.parse(cnt);
- } catch (e) {
- console.log(e);
- alert('bad data file.. :(');
- return initGet();
- }
- return {
- sys: {
- is_sys: true
- , content: getSysHosts()
- },
- list: data.list.map((i) => {
- return {
- title: i.title || ''
- , content: i.content || ''
- , on: !!i.on
- , where: i.where || 'local'
- , url: i.url || ''
- , last_refresh: i.last_refresh || null
- , refresh_interval: i.refresh_interval || 0
- }
- })
- };
- },
- getSysHosts: function () {
- return {
- is_sys: true
- , content: getSysHosts()
- }
- },
- readFile: function (fn, callback) {
- fs.readFile(fn, 'utf-8', callback);
- },
- notify: (options) => {
- notifier.notify(Object.assign({
- title: 'SwitchHosts!',
- message: '',
- icon: path.join(__dirname, 'assets', 'logo_512.png')
- }, options));
- },
- lang: lang,
- lang_key: lang_key,
- pref: pref,
- relaunch() {
- ipcRenderer.send('relaunch');
- }
- };
|