OSDN Git Service

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