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