apply.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /**
  2. * @author oldj
  3. * @blog https://oldj.net
  4. *
  5. * try to apply hosts
  6. */
  7. 'use strict'
  8. const fs = require('fs')
  9. const path = require('path')
  10. const exec = require('child_process').exec
  11. const getPref = require('./actions/getPref')
  12. const getLang = require('./actions/getLang')
  13. const io = require('./io')
  14. const {sys_hosts_path, work_path} = require('./paths')
  15. const crypto = require('crypto')
  16. const md5File = require('md5-file')
  17. const applyAfter_Unix = require('./applyAfter_Unix')
  18. const platform = process.platform
  19. const svr = require('./svr')
  20. let sudo_pswd = ''
  21. let lang = null
  22. function needPswd (str) {
  23. str = str.toLowerCase()
  24. console.log('---')
  25. console.log(str)
  26. let keys = [
  27. 'Permission denied'
  28. , 'incorrect password'
  29. , 'Password:Sorry, try again.'
  30. ]
  31. return !!keys.find(k => str.includes(k.toLowerCase()))
  32. }
  33. function apply_Unix (content, callback) {
  34. let tmp_fn = path.join(work_path, 'tmp.txt')
  35. if (typeof content !== 'string') {
  36. callback('bad content')
  37. return
  38. }
  39. io.pWriteFile(tmp_fn, content)
  40. .then(() => {
  41. let cmd
  42. if (!sudo_pswd) {
  43. cmd = [
  44. `cat "${tmp_fn}" > ${sys_hosts_path}`
  45. , `rm -rf ${tmp_fn}`
  46. ].join(' && ')
  47. } else {
  48. sudo_pswd = sudo_pswd.replace(/'/g, '\\x27')
  49. cmd = [
  50. `echo '${sudo_pswd}' | sudo -S chmod 777 ${sys_hosts_path}`
  51. , `cat "${tmp_fn}" > ${sys_hosts_path}`
  52. , `echo '${sudo_pswd}' | sudo -S chmod 644 ${sys_hosts_path}`
  53. // , 'rm -rf ' + tmp_fn
  54. ].join(' && ')
  55. }
  56. return cmd
  57. })
  58. .then(cmd => {
  59. exec(cmd, function (error, stdout, stderr) {
  60. // command output is in stdout
  61. if (!error) {
  62. callback()
  63. return
  64. }
  65. callback(!sudo_pswd || needPswd(stdout + stderr) ? 'need_sudo' : error)
  66. })
  67. })
  68. }
  69. function apply_Win32 (content, callback) {
  70. // todo 判断写入权限
  71. try {
  72. fs.writeFileSync(sys_hosts_path, content, 'utf-8')
  73. } catch (e) {
  74. console.log(e)
  75. let msg = e.message
  76. msg = `${msg}\n\n${lang.please_run_as_admin}`
  77. console.log(msg)
  78. svr.broadcast('alert', msg)
  79. return
  80. }
  81. // todo 刷新 DNS 缓存
  82. callback()
  83. }
  84. function tryToApply (content, callback) {
  85. if (platform !== 'win32') {
  86. // unix
  87. apply_Unix(content, (e) => {
  88. if (e) {
  89. callback(e)
  90. } else {
  91. applyAfter_Unix(sudo_pswd, callback)
  92. }
  93. })
  94. } else {
  95. // win32
  96. apply_Win32(content, callback)
  97. }
  98. }
  99. module.exports = (cnt, pswd) => {
  100. if (pswd) {
  101. sudo_pswd = pswd
  102. }
  103. let pref
  104. return Promise.resolve()
  105. .then(() => {
  106. return getPref()
  107. .then(p => {
  108. pref = p
  109. return p.user_language || 'en'
  110. })
  111. .then(l => {
  112. return getLang(svr, l)
  113. })
  114. .then(v => lang = v || {})
  115. })
  116. .then(() => {
  117. return new Promise((resolve, reject) => {
  118. let file_md5 = md5File.sync(sys_hosts_path)
  119. let cnt_md5 = crypto.createHash('md5').update(cnt).digest('hex')
  120. if (file_md5 === cnt_md5) {
  121. // 文件相同
  122. resolve()
  123. return
  124. }
  125. tryToApply(cnt, e => e ? reject(e) : resolve())
  126. //reject('need_sudo')
  127. })
  128. })
  129. .then(() => {
  130. return new Promise((resolve, reject) => {
  131. let after_cmd = pref.after_cmd
  132. if (after_cmd) {
  133. exec(after_cmd, (error, stdout, stderr) => {
  134. // command output is in stdout
  135. if (error) {
  136. reject(`AfterCmdError:\n\n${stderr}`)
  137. } else {
  138. resolve()
  139. }
  140. })
  141. } else {
  142. resolve()
  143. }
  144. })
  145. })
  146. }