1 | var fsLib = require("fs");
|
2 | var dns = require("dns");
|
3 | var util = require("util");
|
4 | var exec = require("child_process").exec;
|
5 | var async = require("async");
|
6 | var sys = require("./lib/system");
|
7 |
|
8 | var DNSLookup = function(domain, timeout, callback) {
|
9 | var callbackCalled = false;
|
10 | var doCallback = function(err, domains) {
|
11 | if (!callbackCalled) {
|
12 | callbackCalled = true;
|
13 | callback(err, domains);
|
14 | }
|
15 | else {
|
16 | clearTimeout(t);
|
17 | t = null;
|
18 | }
|
19 | };
|
20 |
|
21 | var t = setTimeout(function() {
|
22 | doCallback(new Error("Timeout exceeded"), null);
|
23 | }, timeout);
|
24 |
|
25 | dns.resolve(domain, doCallback);
|
26 | };
|
27 |
|
28 | var str2regx = function(str) {
|
29 | return str.replace(/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g, "\\$&");
|
30 | };
|
31 |
|
32 | function FlexHosts(param, confFile, cb) {
|
33 | this.cb = cb;
|
34 | this.host2ip = {};
|
35 | this.hostsFuncArr = [];
|
36 | this.hostsTextArr = [];
|
37 | this.content = '';
|
38 |
|
39 | this.beginTag = "##### " + process.cwd() + " Begin #####";
|
40 | this.endTag = "##### " + process.cwd() + " End #####";
|
41 |
|
42 | if (confFile) {
|
43 | if (!fsLib.existsSync(confFile)) {
|
44 | fsLib.writeFileSync(confFile, JSON.stringify(require("./lib/param"), null, 2), {encoding: "utf-8"});
|
45 | fsLib.chmod(confFile, 0777);
|
46 | }
|
47 |
|
48 | try {
|
49 | this.param = JSON.parse(fsLib.readFileSync(confFile));
|
50 |
|
51 | for (var ip in param) {
|
52 | if (this.param[ip]) {
|
53 | this.param[ip] = this.param[ip].concat(param[ip]);
|
54 | }
|
55 | else {
|
56 | this.param[ip] = param[ip];
|
57 | }
|
58 | }
|
59 | }
|
60 | catch (e) {
|
61 | console.log("Params Error!");
|
62 | this.param = {};
|
63 | }
|
64 | }
|
65 | else {
|
66 | this.param = param;
|
67 | }
|
68 |
|
69 | var hostList;
|
70 | for (var host in this.param) {
|
71 | hostList = [];
|
72 | if (typeof this.param[host] == "string") {
|
73 | hostList = this.param[host].split(/\s{1,}/g);
|
74 | }
|
75 | else if (util.isArray(this.param[host]) && this.param[host].length) {
|
76 | hostList = this.param[host];
|
77 | hostList = hostList.filter(function (elem, pos) {
|
78 | return hostList.indexOf(elem) == pos;
|
79 | });
|
80 | }
|
81 |
|
82 | if (hostList && hostList.length) {
|
83 | this.hostsTextArr.push(host + " " + hostList.join(' '));
|
84 | this.hostfunc(hostList);
|
85 | }
|
86 | }
|
87 |
|
88 | DNSLookup("ju.taobao.com", 5000, function (err) {
|
89 | if (err) {
|
90 | this.start(err);
|
91 | }
|
92 | else {
|
93 | async.parallel(this.hostsFuncArr, (function (e, result) {
|
94 | var host, ip;
|
95 | for (var i = 0, len = result.length; i < len; i++) {
|
96 | if (result[i]) {
|
97 | host = result[i][0];
|
98 | ip = result[i][1];
|
99 | if (host && ip && ip != "127.0.0.1") {
|
100 | this.host2ip[host] = ip;
|
101 | }
|
102 | }
|
103 | }
|
104 | console.log("\n-------------------");
|
105 | console.log(" MAP of host to IP");
|
106 | console.log("-------------------");
|
107 | console.log("\x1b[37m%s\x1b[0m\n", JSON.stringify(this.host2ip, null, 2));
|
108 |
|
109 | this.start(null);
|
110 | }).bind(this));
|
111 | }
|
112 | }.bind(this));
|
113 |
|
114 | return this;
|
115 | }
|
116 |
|
117 | FlexHosts.prototype = {
|
118 | constructor: FlexHosts,
|
119 | read: function () {
|
120 | this.content = fsLib.readFileSync(sys.path, "utf-8");
|
121 | },
|
122 | hostfunc: function (hosts) {
|
123 | for (var i = 0, len = hosts.length; i < len; i++) {
|
124 | this.hostsFuncArr.push((function (host) {
|
125 | return function (callback) {
|
126 | DNSLookup(host, 5000, function(e, address) {
|
127 | if (e) {
|
128 | console.log("Warning: \x1b[33m%s\x1b[0m can't be resolved!", e.hostname || host);
|
129 | callback(null, host, null);
|
130 | }
|
131 | else {
|
132 | callback(null, host, address[0]);
|
133 | }
|
134 | });
|
135 | }
|
136 | })(hosts[i]));
|
137 | }
|
138 | },
|
139 | finish: function (isStart) {
|
140 | this.read();
|
141 |
|
142 | if (this.content) {
|
143 | console.log("\n---------------");
|
144 | console.log(" Current HOSTS");
|
145 | console.log("---------------");
|
146 | console.log("\x1b[37m%s\x1b[0m\n", this.content);
|
147 | }
|
148 |
|
149 | if (isStart) {
|
150 | this.cb(null, this.host2ip);
|
151 | }
|
152 | else {
|
153 | console.log("\x1b[32m%s\x1b[0m\n", "Bye-bye!");
|
154 | process.exit();
|
155 | }
|
156 | },
|
157 | write: function (isStart) {
|
158 | var self = this;
|
159 | fsLib.writeFile(sys.path, this.content, function () {
|
160 | if (typeof sys.cmd == "string") {
|
161 | exec(sys.cmd, function () {
|
162 | self.finish(isStart);
|
163 | });
|
164 | }
|
165 | else if (util.isArray(sys.cmd) && sys.cmd.length == 2) {
|
166 | exec(sys.cmd[0], function () {
|
167 | exec(sys.cmd[1], function () {
|
168 | self.finish(isStart);
|
169 | });
|
170 | });
|
171 | }
|
172 | else {
|
173 | console.log("Unknown Command!");
|
174 | }
|
175 | });
|
176 | },
|
177 | add: function () {
|
178 | if (this.hostsTextArr.length) {
|
179 | this.content = this.beginTag + "\n" + this.hostsTextArr.join("\n") + "\n" + this.endTag + "\n\n" + this.content;
|
180 | }
|
181 | },
|
182 | clear: function () {
|
183 | if (fsLib.existsSync(sys.path)) {
|
184 | this.read();
|
185 |
|
186 | try {
|
187 | fsLib.writeFileSync(sys.path + ".backup", this.content);
|
188 | }
|
189 | catch (e) {
|
190 | }
|
191 |
|
192 | this.content = this.content.replace(
|
193 | new RegExp("\\s{0,}" + str2regx(this.beginTag) + "[\\s\\S]*?" + str2regx(this.endTag) + "\\s{0,}", 'g'),
|
194 | ''
|
195 | );
|
196 |
|
197 | return true;
|
198 | }
|
199 | else {
|
200 | console.log("hosts file NOT FOUND!");
|
201 | return false;
|
202 | }
|
203 | },
|
204 | start: function (err) {
|
205 | if (err) {
|
206 | this.cb(err, this.host2ip);
|
207 | }
|
208 | else if (this.clear()) {
|
209 | this.add();
|
210 | this.write(true);
|
211 | }
|
212 | },
|
213 | restore: function () {
|
214 | if (this.clear()) {
|
215 | this.write(false);
|
216 | }
|
217 | }
|
218 | };
|
219 |
|
220 | module.exports = FlexHosts;
|