OSDN Git Service

ルームごとにROMできるかどうかを設定できるようにした
[webchat/WebChat.git] / chatServer.js
1 /*\r
2  * 設定\r
3  */\r
4 $max_room_number = 3;   //最大ルーム数\r
5 $spilt_size = 1024 * 512;       //分割するサイズ\r
6 $reset_password_diff = 1000 * 60 * 60;\r
7 $block_message = "メッセージの送信に失敗しました";       //ブロック時のメッセージ\r
8 $not_match_password = "パスワードが一致しませんでした";  //パスワードが一致しない場合に表示されるメッセージ\r
9 $password_setted_message = "パスワードを設定しました";      //パスワードが設定されたときに表示されるメッセージ\r
10 $password_resetted_message = "パスワードをリセットしました";      //パスワードが再設定されたときに表示されるメッセージ\r
11 $failed_set_password_message = "パスワードの設定に失敗しました"; //パスワードが再設定されたときに表示されるメッセージ\r
12 $ip_ban_list_file_name = "ipbanlist.txt";       //アクセスを禁止するIPが記録されているファイル\r
13 $room_configure_file_name = "roomlist.txt";     //ルームの設定が記録されているファイル\r
14 $port = process.env.port || 3000;       //ポート\r
15 $username = "admin";    //管理者用のページにアクセスできるユーザ名\r
16 $password = "admin";    //管理者用のページにアクセスするのに必要なパスワード\r
17 $token_length = 32;     //トークンの長さ\r
18 $redisHost = "localhost";       //redisサーバのアドレス\r
19 $redisPort = 6379;      //redisサーバのポート\r
20 $redisPassword = "";    //redisサーバのパスワード\r
21 $system_name = "system";        //システム発言を表す名前\r
22 $log_directory = "log"; //ログファイルを置くフォルダー\r
23 $log_file_name = "logfile%d.txt";       //ログファイル名(%dはそのままにしておくこと)\r
24 $splited_log_file_name = "logfile%d_%s.txt"     //分割後のファイル名(%dと%sはそのままにしておくこと)\r
25 $pastlogfile_pattern = "logfile%d(_+.*)?\.txt"; //過去ログと判定する正規表現\r
26 $logfile_pattern = "logfile[0-9]+(_*.*)?\.txt"  //過去ログと判定する正規表現\r
27 \r
28 /**\r
29  * Module dependencies.\r
30  */\r
31 \r
32 // Server\r
33 var express = require('express');\r
34 \r
35 var app = module.exports = express.createServer();\r
36 \r
37 var util = require("util");\r
38 \r
39 var lazy = require("lazy");\r
40 \r
41 var fs = require("fs");\r
42 \r
43 var parseCookie = require("connect").utils.parseCookie;\r
44 \r
45 var RedisStore = require("connect-redis")(express);\r
46 var sessionStore = new RedisStore({host:$redisHost,port:$redisPort,pass:$redisPassword});\r
47 \r
48 var async = require("async");\r
49 \r
50 var path = require("path");\r
51 \r
52 // Configuration\r
53 \r
54 app.configure(function(){\r
55         app.disabled("view cache");\r
56         app.set("view options", { layout: false })\r
57         app.set("views", __dirname + "/public");\r
58         app.set("view engine", "ejs");\r
59         app.use(express.bodyParser());\r
60         app.use(express.methodOverride());\r
61         app.use(express.cookieParser());\r
62         app.use(express.session({\r
63                 store:sessionStore,\r
64                 secret: "5514EA2B-C9B2-4D65-8D81-1F33A180A0C2",\r
65                 cookie: { httpOnly: false }\r
66         }));\r
67         app.use(app.router);\r
68         app.use(express.static(__dirname + "/public"));\r
69 });\r
70 \r
71 app.configure('development', function(){\r
72   app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); \r
73 });\r
74 \r
75 app.configure('production', function(){\r
76   app.use(express.errorHandler()); \r
77 });\r
78 \r
79 // Routes\r
80 app.get("/chat", function(req, res){\r
81         var auth_string = getRandomString($token_length);\r
82         req.session.items = {token:auth_string};\r
83 \r
84         var room_number = 0;\r
85         if(typeof(req.query.rno) != "undefined")\r
86                 room_number = req.query.rno;\r
87         res.render("chat",{rno:room_number,token:auth_string});\r
88 });\r
89 \r
90 app.all("/log/" + $logfile_pattern,express.basicAuth(function (user, pass) {\r
91         return user === $username && pass === $password;\r
92 }));\r
93 \r
94 app.get("/log/" + $logfile_pattern, function(req, res){\r
95         res.sendfile(__dirname + req.url);\r
96 });\r
97 \r
98 app.all("/admin",express.basicAuth(function (user, pass) {\r
99         return user === $username && pass === $password;\r
100 }));\r
101 \r
102 app.get("/admin", function(req, res){\r
103         renderAdmin(req,res);\r
104 });\r
105 \r
106 app.post("/admin",function(req,res){\r
107         if(req.session.items.token != req.body.token)\r
108         {\r
109                 res.send($invaild_token_message);\r
110                 return;\r
111         }\r
112         if(typeof(req.body.erase) != "undefined")\r
113         {\r
114                 removeLog(req.body.file,function(){\r
115                         renderAdmin(req,res);\r
116                 });\r
117         }\r
118         if(typeof(req.body.registor) != "undefined")\r
119         {\r
120                 ipbanlist.Update(req.body.newbanlist,function(){\r
121                         renderAdmin(req,res);\r
122                 });\r
123         }\r
124         if(typeof(req.body.updateroom) != "undefined")\r
125         {\r
126                 $rooms.Update(req.body.newroomlist,function(){\r
127                         renderAdmin(req,res);\r
128                 });\r
129         }\r
130 });\r
131 \r
132 function renderAdmin(req,res)\r
133 {\r
134         var auth_string = getRandomString($token_length);\r
135         req.session.items = {token:auth_string};\r
136         var iplist = ipbanlist.GetText();\r
137 \r
138         fs.readdir($log_directory,function(err,list){\r
139                 res.render("admin", {\r
140                         files: list,\r
141                         log_directory:$log_directory,\r
142                         ipbanlist:iplist,\r
143                         token:auth_string,\r
144                         roomlist:$rooms.GetString()\r
145                 });\r
146         });\r
147 }\r
148 \r
149 function getRandomString(length)\r
150 {\r
151         var RandomString = "";\r
152         var BaseString ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&'()=~|-^\@[;:],./\`{+*}<>?_";\r
153         for(var i=0; i<length; i++) {\r
154                 RandomString += BaseString.charAt( Math.floor( Math.random() * BaseString.length));\r
155         }\r
156         return RandomString\r
157 }\r
158 \r
159 function removeLog(files,callback)\r
160 {\r
161         async.map(files,\r
162         function(item,callback){\r
163                 fs.unlink($log_directory + "/" + item,callback);\r
164         },\r
165         function(err,results){\r
166                 if(typeof(callback) == "function")\r
167                         callback();\r
168         });\r
169 }\r
170 \r
171 app.listen($port);\r
172 console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);\r
173 \r
174 /*\r
175  * サーバー部分\r
176  */\r
177 \r
178 var io = require("socket.io").listen(app);\r
179 io.configure('production', function(){\r
180   io.enable('browser client minification');  // minified されたクライアントファイルを送信する\r
181   io.enable('browser client etag');          // バージョンによって etag によるキャッシングを有効にする\r
182   io.set('log level', 1);                    // ログレベルを設定(デフォルトより下げている)\r
183 });\r
184 var clients = new Array();\r
185 \r
186 var ipbanlist = new IpBanCollecion();\r
187 var $rooms = new RoomInfomationCollection();\r
188 \r
189 createLogDirectory();\r
190 \r
191 for(var i = 0; i < $max_room_number; i++)\r
192 {\r
193         clients[i] =io\r
194         .of(GetNameFromRoomNumber(i))\r
195         .authorization(ParseAuthorization)\r
196         .on("connection", function (socket) {\r
197                 console.log("connected from %s",GetClientIPAdress(socket));\r
198 \r
199                 var rno = GetRoomNumberFromName(socket.namespace.name);\r
200                 var roomconfig = {};\r
201                 if($rooms.IsFixedPassword(rno))\r
202                         roomconfig.type = 2;\r
203                 else if($rooms.IsHiddenLogFromRom(rno))\r
204                         roomconfig.type = 3;\r
205                 else if($rooms.IsContains(rno))\r
206                         roomconfig.type = 1;\r
207                 else\r
208                         roomconfig.type = 0;\r
209                 roomconfig.IsOwned = !$rooms.IsFirstAuth(rno);\r
210                 socket.json.emit("send roominfo",roomconfig);\r
211 \r
212                 socket.on("get pastLogList", function (msg) {\r
213                         ParseGetPastLogList(socket,msg);\r
214                 });\r
215                 socket.on("get pastLog", function (msg) {\r
216                         ParseGetPastLog(socket,msg);\r
217                 });\r
218                 socket.on("join",function(msg){\r
219                         ParseJoin(socket,msg);\r
220                 });\r
221                 socket.on("quit",function(msg){\r
222                         ParseQuit(socket,msg);\r
223                 });\r
224                 socket.on("set password",function(msg){\r
225                         ParseSetPassword(socket,msg);\r
226                 });\r
227                 socket.on("send msg", function (msg) {\r
228                         ParseSendMsg(socket,msg);\r
229                 });\r
230                 socket.on("disconnect", function (msg) {\r
231                         ParseDisconnect(socket,msg);\r
232                 });\r
233         });\r
234 }\r
235 \r
236 function createLogDirectory()\r
237 {\r
238         path.exists($log_directory,function(exists){\r
239                 if(exists == false)\r
240                         fs.mkdirSync($log_directory);\r
241         });\r
242 }\r
243 \r
244 function ParseAuthorization(handshakeData, callback)\r
245 {\r
246         if(handshakeData.headers.cookie) {\r
247                 var cookie = handshakeData.headers.cookie;\r
248                 var sessionID = parseCookie(cookie)["connect.sid"];\r
249                 sessionStore.get(sessionID, function (err, session) {\r
250                         var result = null;\r
251                         if (err || ipbanlist.IsBaned(handshakeData.address.address))\r
252                                 result = "failed get from session store";\r
253                         else if(handshakeData.query.token != session.items.token)\r
254                                 result = "invaild token";\r
255                         sessionStore.destroy(sessionID);\r
256                         callback(result,result == null && !err);\r
257                 });\r
258         } else {\r
259                 return callback("failed get cookie", false);\r
260         }\r
261 }\r
262 \r
263 function ParseDisconnect(socket,msg)\r
264 {\r
265         console.log("disconnected");\r
266 }\r
267 \r
268 function ParseSetPassword(socket,msg)\r
269 {\r
270         var rno = GetRoomNumberFromName(socket.namespace.name);\r
271         var newMeg = {\r
272                 name:$system_name,\r
273                 message:null,\r
274         };\r
275         if($rooms.SetPassword(rno,msg.owner,msg.password))\r
276                 newMeg.message = $password_setted_message;\r
277         else\r
278                 newMeg.message = $failed_set_password_message;\r
279         ParseSendMsg(socket,newMeg);\r
280 }\r
281 \r
282 function ParseJoin(socket,msg)\r
283 {\r
284         var ip = GetClientIPAdress(socket);\r
285 \r
286         if(ipbanlist.IsBlockedToWrite(ip))\r
287         {\r
288                 socket.emit("error",$block_message);\r
289                 return;\r
290         }\r
291 \r
292         var rno = GetRoomNumberFromName(socket.namespace.name);\r
293         if($rooms.IsContains(rno))\r
294         {\r
295                 if($rooms.IsTimeout(rno) ||\r
296                         $rooms.IsFirstAuth(rno))\r
297                 {\r
298                         $rooms.Reset(rno,msg.name);\r
299                         ParseGetPastLog(socket,util.format($log_file_name,rno));\r
300                 }\r
301                 else if($rooms.Auth(rno,msg.name,msg.password))\r
302                 {\r
303                         ParseGetPastLog(socket,util.format($log_file_name,rno));\r
304                 }\r
305                 else\r
306                 {\r
307                         socket.emit("error",$not_match_password);\r
308                         return;\r
309                 }\r
310         }\r
311 \r
312         var newMeg = {\r
313                 name:$system_name,\r
314                 message:util.format("/enteredby %s %s %s",msg.name,msg.color,msg.mailto),\r
315         };\r
316         ParseSendMsg(socket,newMeg);\r
317 }\r
318 \r
319 function ParseQuit(socket,msg)\r
320 {\r
321         var ip = GetClientIPAdress(socket);\r
322 \r
323         if(ipbanlist.IsBlockedToWrite(ip))\r
324         {\r
325                 socket.emit("error",$block_message);\r
326                 return;\r
327         }\r
328 \r
329         var rno = GetRoomNumberFromName(socket.namespace.name);\r
330 \r
331         var newMeg = {\r
332                 name:$system_name,\r
333                 message:$password_resetted_message,\r
334         };\r
335         if($rooms.IsContains(rno))\r
336         {\r
337                 if($rooms.IsOwner(rno,msg.name))\r
338                 {\r
339                         $rooms.Reset(rno,null);\r
340                         ParseSendMsg(socket,newMeg);\r
341                 }\r
342                 if(!$rooms.IsFirstAuth(rno) &&\r
343                         !$rooms.IsAuthed(rno,msg.name))\r
344                         return;\r
345                 else\r
346                         $rooms.RemoveAuth(rno,msg.name);\r
347         }\r
348 \r
349         newMeg.message = util.format("/quitedby %s",msg.name);\r
350         ParseSendMsg(socket,newMeg);\r
351 }\r
352 \r
353 //socket 接続中のソケット\r
354 //msg msgクラス\r
355 function ParseSendMsg(socket,msg)\r
356 {\r
357         var ip = GetClientIPAdress(socket);\r
358 \r
359         if(ip in ipbanlist)\r
360         {\r
361                 socket.emit("error",$block_message);\r
362                 return;\r
363         }\r
364 \r
365         var rno = GetRoomNumberFromName(socket.namespace.name);\r
366 \r
367         if(msg.name != $system_name && \r
368                 $rooms.IsContains(rno) &&\r
369                 !$rooms.IsAuthed(rno,msg.name) &&\r
370                 !$rooms.IsOwner(rno,msg.name))\r
371         {\r
372                 return;\r
373         }\r
374 \r
375         var date = new Date();\r
376 \r
377         var repacked_msg = CreateMessage(msg.name,date,msg.message);\r
378 \r
379         socket.json.emit("req msg", repacked_msg);\r
380 \r
381         socket.json.broadcast.emit("req msg", repacked_msg);\r
382 \r
383         var path = $log_directory + "/" + util.format($log_file_name,rno);\r
384         var log = new ChatLog(path);\r
385         log.Save(repacked_msg,ip,rno);\r
386 }\r
387 \r
388 function GetNameFromRoomNumber(number)\r
389 {\r
390         return "/" + number;\r
391 }\r
392 \r
393 function GetRoomNumberFromName(name)\r
394 {\r
395         if(name.charAt(0) == "/")\r
396                 return parseInt(name.substr(1));\r
397         throw "GetRoomNumberFromName error";\r
398 }\r
399 \r
400 function ParseGetPastLogList(socket,msg)\r
401 {\r
402         var list = fs.readdir($log_directory,function(err,files){\r
403                 var text = "";\r
404                 var rno = GetRoomNumberFromName(socket.namespace.name);\r
405                 var pattern = $pastlogfile_pattern.replace("%d",rno);\r
406                 for(var i = 0; i < files.length; i++)\r
407                 {\r
408                         var logname = files[i];\r
409                         if(logname.match(pattern))\r
410                                 text += files[i] + "\n";\r
411                 }\r
412                 socket.emit("req pastloglist",text);\r
413         });\r
414 }\r
415 \r
416 function ParseGetPastLog(socket,file)\r
417 {\r
418         if(file == "")\r
419                 return;\r
420         var path = $log_directory + "/" + file;\r
421         var log = new ChatLog(path);\r
422         log.ToArray(function(array){\r
423                 socket.json.emit("req pastlog",array);\r
424         });\r
425 }\r
426 \r
427 function ChatLog(path)\r
428 {\r
429         this.ToArray = function(callback)\r
430         {\r
431                 var state = fs.stat(path,function(err,state){\r
432                         if(err)\r
433                                 return;\r
434                         var array = new Array();\r
435                         var stream = fs.createReadStream(path);\r
436                         new lazy(stream)\r
437                                 .lines\r
438                                 .forEach(function(line){\r
439                                         array.push(CreateMessageFromText(line.toString()));\r
440                                 })\r
441                                 .join(function(){\r
442                                         callback(array);\r
443                                 });\r
444                 });\r
445         }\r
446 \r
447         this.Save = function(msg,ip,rno){\r
448                 var text = GetTextFromMessage(msg,ip);\r
449 \r
450                 SplitLog(rno,function(){\r
451                         WritePastLog(path,text);\r
452                 });\r
453         };\r
454 \r
455         function GetTextFromMessage(msg,ip)\r
456         {\r
457                 var text = msg.name + "<>" +\r
458                                 msg.date + "<>" +\r
459                                 ip + "<>" +\r
460                                 msg.message +\r
461                                 "\n";\r
462                 return text;\r
463         }\r
464 \r
465         function SplitLog(rno,callback)\r
466         {\r
467                 var state = fs.stat(path,function(err,state){\r
468                         if(err && typeof(callback) == "function")\r
469                         {\r
470                                 callback();\r
471                                 return;\r
472                         }\r
473                         if(state.size > $spilt_size)\r
474                         {\r
475                                 var date = new Date();\r
476                                 var dateString = ""+date.getFullYear()+date.getMonth()+date.getDate()+date.getHours()+date.getMinutes()+date.getSeconds();\r
477 \r
478                                 var newpath = $log_directory + "/" +\r
479                                         util.format($splited_log_file_name,rno,dateString);\r
480                                 fs.rename(path,newpath,callback);\r
481                         }else{\r
482                                 if(typeof(callback) == "function")\r
483                                         callback();\r
484                         }\r
485                 });\r
486         }\r
487 \r
488         function WritePastLog(path,text)\r
489         {\r
490                 async.waterfall([\r
491                         function(callback){\r
492                                 fs.open(path,"a",callback);\r
493                         },\r
494                         function(fd,callback){\r
495                                 var buf = new Buffer(text);\r
496                                 fs.write(fd,buf,0,Buffer.byteLength(text),null,function(){\r
497                                         callback(null,fd);\r
498                                 });\r
499                         },\r
500                         function(fd){\r
501                                 fs.close(fd);\r
502                         }\r
503                 ]);\r
504         }\r
505 }\r
506 \r
507 function GetClientIPAdress(socket)\r
508 {\r
509         return socket.handshake.headers["x-forwarded-for"] || socket.handshake.address.address;\r
510 }\r
511 \r
512 // Message クラス\r
513 function CreateMessage(name,date,message)\r
514 {\r
515         var result = {name:name,\r
516                 date:date,\r
517                 message:message};\r
518         return result;\r
519 }\r
520 function CreateMessageFromText(text)\r
521 {\r
522         var data = text.split("<>");\r
523         var msg = {name:data[0],\r
524                 date:data[1],\r
525                 message:data[3]};\r
526         return msg;\r
527 }\r
528 \r
529 //RoomInfomationCollecionクラス\r
530 function RoomInfomationCollection()\r
531 {\r
532         var collection = {};\r
533         this.Reset = function(rno,owner){\r
534                 var date = new Date();\r
535                 var time = date.getTime();\r
536                 collection[rno].password = null;\r
537                 collection[rno].authed_list = {};\r
538                 collection[rno].owner = owner;\r
539                 collection[rno].time = time;\r
540                 console.log(util.format("password is reseted in %s",rno));\r
541         };\r
542         this.IsContains = function(rno){\r
543                 return rno in collection;\r
544         };\r
545         this.IsFirstAuth = function(rno){\r
546                 if(!this.IsContains(rno) || typeof(collection[rno].owner) == "undefined")\r
547                         return false;\r
548                 return collection[rno].owner == null;\r
549         }\r
550         this.IsAuthed = function(rno,name){\r
551                 if(!this.IsContains(rno))\r
552                         return false;\r
553                 return name == collection[rno].owner ||\r
554                         name in collection[rno].authed_list;\r
555         };\r
556         this.IsHiddenLogFromRom = function(rno){\r
557                 if(!this.IsContains(rno))\r
558                         return false;\r
559                 return collection[rno].hiddenlog;\r
560         };\r
561         this.IsFixedPassword = function(rno){\r
562                 if(!this.IsContains(rno))\r
563                         return false;\r
564                 return collection[rno].owner == $system_name;\r
565         };\r
566         this.IsOwner = function(rno,name){\r
567                 return this.IsContains(rno) &&\r
568                         typeof(collection[rno].owner) != "undefined" &&\r
569                         collection[rno].owner == name;\r
570         }\r
571         this.IsTimeout = function(rno){\r
572                 var date = new Date();\r
573                 var time = date.getTime();\r
574                 return this.IsContains(rno) &&\r
575                         !this.IsFixedPassword(rno) &&\r
576                         (typeof(collection[rno].time) != "undefined" &&\r
577                         time - collection[rno].time >= $reset_password_diff);\r
578         };\r
579         this.RemoveAuth = function(rno,name)\r
580         {\r
581                 delete collection[rno].authed_list[name];\r
582         }\r
583         this.Auth = function(rno,name,password){\r
584                 if(typeof(collection[rno].password) != "undefined" &&\r
585                         collection[rno].password != password)\r
586                         return false;\r
587                 var date = new Date();\r
588                 var time = date.getTime();\r
589                 collection[rno].time = time;\r
590                 collection[rno].authed_list[name] = "";\r
591                 return true;\r
592         }\r
593         this.SetPassword = function(rno,owner,password){\r
594                 if(this.IsContains(rno) && \r
595                         owner == collection[rno].owner &&\r
596                         !this.IsFixedPassword(rno) &&\r
597                         !this.IsHiddenLogFromRom(rno))\r
598                 {\r
599                         var date = new Date();\r
600                         collection[rno].time = date.getTime();\r
601                         collection[rno].password = password;\r
602                         \r
603                         console.log(util.format("password is seted to %s in %s",password,rno));\r
604                         return true;\r
605                 }\r
606                 return false;\r
607         };\r
608         this.GetString = function(){\r
609                 var retval = "";\r
610                 for(var rno in collection)\r
611                 {\r
612                         var pass = collection[rno].password;\r
613                         if(pass == null)\r
614                                 pass = "";\r
615                         var hiddenlog = collection[rno].hiddenlog;\r
616                         retval += rno + ":" + pass + ":" + hiddenlog + "\r\n";\r
617                 }\r
618                 return retval;\r
619         };\r
620         this.GetKeys = function(){\r
621                 var retval = {};\r
622                 for(var rno in collection)\r
623                 {\r
624                         retval[rno] = {};\r
625                 }\r
626                 return retval;\r
627         }\r
628         this.Update = function(text,callfunc){\r
629                 async.waterfall([\r
630                         function(callback){\r
631                                 fs.open($room_configure_file_name,"w",callback);\r
632                         },\r
633                         function(fd,callback){\r
634                                 var buf = new Buffer(text);\r
635                                 fs.write(fd,buf,0,Buffer.byteLength(text),null,function(){\r
636                                         callback(null,fd);\r
637                                 });\r
638                         },\r
639                         function(fd,callback){\r
640                                 fs.close(fd,function(){\r
641                                         GetRoomList(callfunc);\r
642                                 });\r
643                         }\r
644                 ]);\r
645         }\r
646         function GetRoomList(callback){\r
647                 Clear();\r
648                 path.exists($room_configure_file_name,function(exists){\r
649                         if(exists == false)\r
650                         {\r
651                                 if(typeof(callback) == "function")\r
652                                         callback();\r
653                                 return;\r
654                         }\r
655                         var stream = fs.createReadStream($room_configure_file_name);\r
656                         new lazy(stream)\r
657                                 .lines\r
658                                 .forEach(function(line){\r
659                                         var token = line.toString().replace(/(\r|\n|\r\n)/gm, "").split(":");\r
660                                         if(token.length == 1)\r
661                                         {\r
662                                                 Add(token[0],null,false);\r
663                                         }\r
664                                         else if(token.length == 2)\r
665                                         {\r
666                                                 var rno = token[0];\r
667                                                 var pass = token[1];\r
668                                                 if(pass == "")\r
669                                                         pass = null;\r
670                                                 Add(rno, pass,false);\r
671                                         }\r
672                                         else if(token.length == 3)\r
673                                         {\r
674                                                 var rno = token[0];\r
675                                                 var pass = token[1];\r
676                                                 if(pass == "")\r
677                                                         pass = null;\r
678                                                 var hiddenlog = false;\r
679                                                 if(token[2] == "true")\r
680                                                         hiddenlog = true;\r
681                                                 Add(rno, pass,hiddenlog);\r
682                                         }\r
683                                 })\r
684                                 .join(function(){\r
685                                         if(typeof(callback) == "function")\r
686                                                 callback();\r
687                                 });\r
688                 });\r
689         }\r
690         function Clear(){\r
691                 collection = {};\r
692         };\r
693         function Add(rno,pass,hiddenlogflag){\r
694                 collection[rno] = {time : null,\r
695                         password : pass,\r
696                         owner : null,\r
697                         hiddenlog : hiddenlogflag,\r
698                         authed_list : {}};\r
699                 if(pass != null)\r
700                         collection[rno].owner = $system_name;\r
701         };\r
702 \r
703         GetRoomList();\r
704 }\r
705 \r
706 //IPBANクラス\r
707 function IpBanCollecion()\r
708 {\r
709         var collection = {};\r
710         this.IsBaned = function(ip){\r
711                 return collection[ip] == "r";\r
712         }\r
713         this.IsBlockedToWrite = function(ip){\r
714                 return ip in collection;\r
715         }\r
716         this.GetText = function(){\r
717                 var text = "";\r
718                 for(var key in collection)\r
719                 {\r
720                         if(collection[key] == "")\r
721                                 text += key + "\r\n";\r
722                         else\r
723                                 text += key + ":" + collection[key] + "\r\n";\r
724                 }\r
725                 return text;\r
726         }\r
727         this.Update = function(text,callfunc){\r
728                 async.waterfall([\r
729                         function(callback){\r
730                                 fs.open($ip_ban_list_file_name,"w",callback);\r
731                         },\r
732                         function(fd,callback){\r
733                                 var buf = new Buffer(text);\r
734                                 fs.write(fd,buf,0,Buffer.byteLength(text),null,function(){\r
735                                         callback(null,fd);\r
736                                 });\r
737                         },\r
738                         function(fd,callback){\r
739                                 fs.close(fd,function(){\r
740                                         GetIpBanList(callfunc);\r
741                                 });\r
742                         }\r
743                 ]);\r
744         }\r
745         function GetIpBanList(callback)\r
746         {\r
747                 collection = {};\r
748                 path.exists($ip_ban_list_file_name,function(exists){\r
749                         if(exists == false)\r
750                         {\r
751                                 if(typeof(callback) == "function")\r
752                                         callback();\r
753                                 return;\r
754                         }\r
755                         var stream = fs.createReadStream($ip_ban_list_file_name);\r
756                         new lazy(stream)\r
757                                 .lines\r
758                                 .forEach(function(line){\r
759                                         var token = line.toString().replace(/(\r|\n|\r\n)/gm, "").split(":");\r
760                                         var ip = token[0];\r
761                                         if(token.length == 1)\r
762                                                 collection[ip] = "";\r
763                                         else\r
764                                                 collection[ip] = token[1];\r
765                                 })\r
766                                 .join(function(){\r
767                                         if(typeof(callback) == "function")\r
768                                                 callback();\r
769                                 });\r
770                 });\r
771         }\r
772         GetIpBanList();\r
773 }\r
774 \r