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