OSDN Git Service

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