OSDN Git Service

依存関係を更新した
[webchat/WebChat.git] / chatServer.js
index 81cd79f..6b73ea2 100644 (file)
@@ -1,44 +1,53 @@
-/*\r
- * \90Ý\92è\r
+/*\r
+ * 設定\r
  */\r
-$max_room_number = 1;  //\8dÅ\91å\83\8b\81[\83\80\90\94\r
-$log_directory = "log";        //\83\8d\83O\83t\83@\83C\83\8b\82ð\92u\82­\83t\83H\83\8b\83_\81[\r
-$log_file_name = "logfile%d.txt";      //\83\8d\83O\83t\83@\83C\83\8b\96¼(%d\82Í\82»\82Ì\82Ü\82Ü\82É\82µ\82Ä\82¨\82­\82±\82Æ)\r
-$splited_log_file_name = "logfile%d_%s.txt"    //\95ª\8a\84\8cã\82Ì\83t\83@\83C\83\8b\96¼(%d\82Æ%s\82Í\82»\82Ì\82Ü\82Ü\82É\82µ\82Ä\82¨\82­\82±\82Æ)\r
-$spilt_size = 1024 * 512;      //\95ª\8a\84\82·\82é\83T\83C\83Y\r
-$block_message = "failed to send your message.";       //\83u\83\8d\83b\83N\8e\9e\82Ì\83\81\83b\83Z\81[\83W\r
-$failed_authorization = "cooke is not found";  //\94F\8fØ\82É\8e¸\94s\82µ\82½\82Æ\82«\82Ì\83\81\83b\83Z\81[\83W\r
-$invaild_token_message = "token is invailed";  //\83g\81[\83N\83\93\82ª\88ê\92v\82µ\82È\82¢\82Æ\82«\82É\95\\8e¦\82³\82ê\82é\83\81\83b\83Z\81[\83W\r
-$ip_ban_list_file_name = "ipbanlist.txt";      //\83A\83N\83Z\83X\82ð\8bÖ\8e~\82·\82éIP\82ª\8bL\98^\82³\82ê\82Ä\82¢\82é\83t\83@\83C\83\8b\r
-$port = process.env.port || 3000;      //\83|\81[\83g\r
-$username = "admin";   //\8aÇ\97\9d\8eÒ\97p\82Ì\83y\81[\83W\82É\83A\83N\83Z\83X\82Å\82«\82é\83\86\81[\83U\96¼\r
-$password = "admin";   //\8aÇ\97\9d\8eÒ\97p\82Ì\83y\81[\83W\82É\83A\83N\83Z\83X\82·\82é\82Ì\82É\95K\97v\82È\83p\83X\83\8f\81[\83h\r
-$pastlogfile_pattern = "logfile%d(_+.*)?\.txt";        //\89ß\8b\8e\83\8d\83O\82Æ\94»\92è\82·\82é\90³\8bK\95\\8c»\r
-$logfile_pattern = "logfile[0-9]+(_*.*)?\.txt" //\89ß\8b\8e\83\8d\83O\82Æ\94»\92è\82·\82é\90³\8bK\95\\8c»\r
-$token_length = 16;    //\83g\81[\83N\83\93\82Ì\92·\82³\r
-$redisHost = "localhost";      //redis\83T\81[\83o\82Ì\83A\83h\83\8c\83X\r
-$redisPort = 6379;     //redis\83T\81[\83o\82Ì\83|\81[\83g\r
-$redisPassword = "";   //redis\83T\81[\83o\82Ì\83p\83X\83\8f\81[\83h\r
-\r
+$max_room_number = 3;  //最大ルーム数\r
+$spilt_size = 1024 * 512;      //分割するサイズ\r
+$reset_password_diff = 1000 * 60 * 60; //ルームパスワードをリセットする間隔\r
+$gc_time_interval = 1000 * 60 * 60;    //ゴミ掃除を行う間隔\r
+$invaild_token_message = "トークンが一致しませんでした";\r
+$block_message = "メッセージの送信に失敗しました";      //ブロック時のメッセージ\r
+$not_match_password = "パスワードが一致しませんでした"; //パスワードが一致しない場合に表示されるメッセージ\r
+$password_setted_message = "パスワードを設定しました";     //パスワードが設定されたときに表示されるメッセージ\r
+$password_resetted_message = "パスワードをリセットしました";     //パスワードが再設定されたときに表示されるメッセージ\r
+$failed_set_password_message = "パスワードの設定に失敗しました";        //パスワードが再設定されたときに表示されるメッセージ\r
+$ip_ban_list_file_name = "ipbanlist.txt";      //アクセスを禁止するIPが記録されているファイル\r
+$room_configure_file_name = "roomlist.txt";    //ルームの設定が記録されているファイル\r
+$port = process.env.port || 3000;      //ポート\r
+$username = "admin";   //管理者用のページにアクセスできるユーザ名\r
+$password = "admin";   //管理者用のページにアクセスするのに必要なパスワード\r
+$token_length = 32;    //トークンの長さ\r
+$redisHost = "localhost";      //redisサーバのアドレス\r
+$redisPort = 6379;     //redisサーバのポート\r
+$redisPassword = "";   //redisサーバのパスワード\r
+$system_name = "system";       //システム発言を表す名前\r
+$log_directory = "log";        //ログファイルを置くフォルダー\r
+$log_file_name = "logfile%d.txt";      //ログファイル名(%dはそのままにしておくこと)\r
+$splited_log_file_name = "logfile%d_%s.txt"    //分割後のファイル名(%dと%sはそのままにしておくこと)\r
+$pastlogfile_pattern = "logfile%d(_+.*)?\.txt";        //過去ログと判定する正規表現\r
+$secret = "5514EA2B-C9B2-4D65-8D81-1F33A180A0C2";      //cookie用秘密鍵\r
 /**\r
  * Module dependencies.\r
  */\r
 \r
 // Server\r
-var express = require('express');\r
+var express = require("express");\r
 \r
-var app = module.exports = express.createServer();\r
+var app = express();\r
+\r
+var http = require("http");\r
 \r
 var util = require("util");\r
 \r
-var lazy = require("lazy");\r
+var lazy = require("./lazy.js");\r
 \r
 var fs = require("fs");\r
 \r
-var parseCookie = require("connect").utils.parseCookie;\r
+var cookie = require("express/node_modules/cookie");\r
+\r
+var connectUtils = require("express/node_modules/connect/lib/utils");\r
 \r
 var RedisStore = require("connect-redis")(express);\r
-//var   sessionStore = new (require('connect').session.MemoryStore)();\r
 var sessionStore = new RedisStore({host:$redisHost,port:$redisPort,pass:$redisPassword});\r
 \r
 var async = require("async");\r
@@ -54,10 +63,9 @@ app.configure(function(){
        app.set("view engine", "ejs");\r
        app.use(express.bodyParser());\r
        app.use(express.methodOverride());\r
-       app.use(express.cookieParser());\r
+       app.use(express.cookieParser($secret));\r
        app.use(express.session({\r
                store:sessionStore,\r
-               secret: "5514EA2B-C9B2-4D65-8D81-1F33A180A0C2",\r
                cookie: { httpOnly: false }\r
        }));\r
        app.use(app.router);\r
@@ -72,10 +80,16 @@ app.configure('production', function(){
   app.use(express.errorHandler()); \r
 });\r
 \r
+function SessionInfomation(token,admin)\r
+{\r
+       this.token = token;\r
+       this.admin = admin;\r
+}\r
+\r
 // Routes\r
 app.get("/chat", function(req, res){\r
        var auth_string = getRandomString($token_length);\r
-       req.session.items = {token:auth_string};\r
+       req.session.items = new SessionInfomation(auth_string,false);\r
 \r
        var room_number = 0;\r
        if(typeof(req.query.rno) != "undefined")\r
@@ -83,14 +97,28 @@ app.get("/chat", function(req, res){
        res.render("chat",{rno:room_number,token:auth_string});\r
 });\r
 \r
-app.all("/log/" + $logfile_pattern,express.basicAuth(function (user, pass) {\r
+app.all("/log/*",express.basicAuth(function (user, pass) {\r
        return user === $username && pass === $password;\r
 }));\r
 \r
-app.get("/log/" + $logfile_pattern, function(req, res){\r
+app.get("/log/*",function (req, res) {\r
        res.sendfile(__dirname + req.url);\r
 });\r
 \r
+app.all("/admin_chat",express.basicAuth(function (user, pass) {\r
+       return user === $username && pass === $password;\r
+}));\r
+\r
+app.get("/admin_chat", function(req, res){\r
+       var auth_string = getRandomString($token_length);\r
+       req.session.items = new SessionInfomation(auth_string,true);\r
+\r
+       var room_number = 0;\r
+       if(typeof(req.query.rno) != "undefined")\r
+               room_number = req.query.rno;\r
+       res.render("chat",{rno:room_number,token:auth_string});\r
+});\r
+\r
 app.all("/admin",express.basicAuth(function (user, pass) {\r
        return user === $username && pass === $password;\r
 }));\r
@@ -113,7 +141,13 @@ app.post("/admin",function(req,res){
        }\r
        if(typeof(req.body.registor) != "undefined")\r
        {\r
-               updateIpBanList(req.body.newbanlist,function(){\r
+               ipbanlist.Update(req.body.newbanlist,function(){\r
+                       renderAdmin(req,res);\r
+               });\r
+       }\r
+       if(typeof(req.body.updateroom) != "undefined")\r
+       {\r
+               $rooms.Update(req.body.newroomlist,function(){\r
                        renderAdmin(req,res);\r
                });\r
        }\r
@@ -123,13 +157,15 @@ function renderAdmin(req,res)
 {\r
        var auth_string = getRandomString($token_length);\r
        req.session.items = {token:auth_string};\r
+       var iplist = ipbanlist.GetText();\r
 \r
        fs.readdir($log_directory,function(err,list){\r
                res.render("admin", {\r
                        files: list,\r
                        log_directory:$log_directory,\r
-                       ipbanlist:getTextFromIpBanlist(ipbanlist),\r
-                       token:auth_string\r
+                       ipbanlist:iplist,\r
+                       token:auth_string,\r
+                       roomlist:$rooms.GetString()\r
                });\r
        });\r
 }\r
@@ -137,7 +173,7 @@ function renderAdmin(req,res)
 function getRandomString(length)\r
 {\r
        var RandomString = "";\r
-       var BaseString ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()=~|`{}/+*@[];:,.";\r
+       var BaseString ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&'()=~|-^\@[;:],./\`{+*}<>?_";\r
        for(var i=0; i<length; i++) {\r
                RandomString += BaseString.charAt( Math.floor( Math.random() * BaseString.length));\r
        }\r
@@ -146,6 +182,13 @@ function getRandomString(length)
 \r
 function removeLog(files,callback)\r
 {\r
+       if(typeof(files) == "undefined")\r
+       {\r
+               if(typeof(callback) == "function")\r
+                       callback();\r
+               return;\r
+       }\r
+\r
        async.map(files,\r
        function(item,callback){\r
                fs.unlink($log_directory + "/" + item,callback);\r
@@ -156,81 +199,73 @@ function removeLog(files,callback)
        });\r
 }\r
 \r
-function getTextFromIpBanlist(list)\r
-{\r
-       var text = "";\r
-       for(var key in ipbanlist)\r
-       {\r
-               if(ipbanlist[key] == "")\r
-                       text += key + "\r\n";\r
-               else\r
-                       text += key + ":" + ipbanlist[key] + "\r\n";\r
-       }\r
-       return text;\r
-}\r
-\r
-function updateIpBanList(text,callfunc)\r
-{\r
-       async.waterfall([\r
-               function(callback){\r
-                       fs.open($ip_ban_list_file_name,"w",callback);\r
-               },\r
-               function(fd,callback){\r
-                       var buf = new Buffer(text);\r
-                       fs.write(fd,buf,0,Buffer.byteLength(text),null,function(){\r
-                               callback(null,fd);\r
-                       });\r
-               },\r
-               function(fd,callback){\r
-                       fs.close(fd,function(){\r
-                               getIpBanList(callfunc);\r
-                       });\r
-               }\r
-       ]);\r
-}\r
-\r
-app.listen($port);\r
-console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);\r
+var server = http.createServer(app).listen($port);\r
+console.log("Express server listening on port %d in %s mode", $port, app.settings.env);\r
 \r
 /*\r
- * \83T\81[\83o\81[\95\94\95ª\r
+ * サーバー部分\r
  */\r
 \r
-var io = require("socket.io").listen(app);\r
+var io = require("socket.io").listen(server);\r
 io.configure('production', function(){\r
-  io.enable('browser client minification');  // minified \82³\82ê\82½\83N\83\89\83C\83A\83\93\83g\83t\83@\83C\83\8b\82ð\91\97\90M\82·\82é\r
-  io.enable('browser client etag');          // \83o\81[\83W\83\87\83\93\82É\82æ\82Á\82Ä etag \82É\82æ\82é\83L\83\83\83b\83V\83\93\83O\82ð\97L\8cø\82É\82·\82é\r
-  io.set('log level', 1);                    // \83\8d\83O\83\8c\83x\83\8b\82ð\90Ý\92è(\83f\83t\83H\83\8b\83g\82æ\82è\89º\82°\82Ä\82¢\82é)\r
-  io.set('transports', [                     // \91S\82Ä\82Ìtransport\82ð\97L\8cø\82É\82·\82é\r
-      'websocket'\r
-    , 'flashsocket'\r
-    , 'htmlfile'\r
-    , 'xhr-polling'\r
-    , 'jsonp-polling'\r
-  ]);\r
+  io.enable('browser client minification');  // minified されたクライアントファイルを送信する\r
+  io.enable('browser client etag');          // バージョンによって etag によるキャッシングを有効にする\r
+  io.set('log level', 1);                    // ログレベルを設定(デフォルトより下げている)\r
 });\r
 var clients = new Array();\r
 \r
-var ipbanlist = {};\r
+var ipbanlist = new IpBanCollecion();\r
+var $rooms = new RoomInfomationCollection();\r
 \r
 createLogDirectory();\r
 \r
-getIpBanList();\r
-\r
 for(var i = 0; i < $max_room_number; i++)\r
 {\r
        clients[i] =io\r
        .of(GetNameFromRoomNumber(i))\r
        .authorization(ParseAuthorization)\r
        .on("connection", function (socket) {\r
-               socket.sessionID = socket.handshake.sessionID;  //\90Ø\92f\8e\9e\82Ì\82½\82ß\82É\82Æ\82Á\82Ä\82¨\82­\r
-               console.log("connected from %s",socket.handshake.address.address);\r
+               var ip = GetClientIPAdress(socket);\r
+\r
+               console.log("connected from %s",ip);\r
+\r
+               var rno = GetRoomNumberFromName(socket.namespace.name);\r
+               var roomconfig = {};\r
+               $rooms.Get(rno).AddRom(ip);\r
+               if($rooms.Get(rno).IsVolatile() == false)\r
+               {\r
+                       if($rooms.Get(rno).IsFixedPassword())\r
+                               roomconfig.type = 2;\r
+                       else if($rooms.Get(rno).IsHiddenLogFromRom())\r
+                               roomconfig.type = 3;\r
+                       else\r
+                               roomconfig.type = 1;\r
+                       roomconfig.IsOwned = !$rooms.Get(rno).IsFirstAuth();\r
+               }else{\r
+                       roomconfig.type = 0;\r
+               }\r
+               roomconfig.admin = socket.handshake.admin;\r
+               socket.json.emit("send roominfo",roomconfig);\r
+\r
+               var romcount = $rooms.Get(rno).GetRomCount();\r
+               socket.json.emit("send romcount",romcount);\r
+               socket.json.broadcast.emit("send romcount",romcount);\r
+\r
                socket.on("get pastLogList", function (msg) {\r
                        ParseGetPastLogList(socket,msg);\r
                });\r
                socket.on("get pastLog", function (msg) {\r
                        ParseGetPastLog(socket,msg);\r
                });\r
+               socket.on("join",function(msg){\r
+                       ParseJoin(socket,msg);\r
+               });\r
+               socket.on("quit",function(msg){\r
+                       ParseQuit(socket,msg);\r
+               });\r
+               socket.on("set password",function(msg){\r
+                       ParseSetPassword(socket,msg);\r
+               });\r
                socket.on("send msg", function (msg) {\r
                        ParseSendMsg(socket,msg);\r
                });\r
@@ -242,78 +277,156 @@ for(var i = 0; i < $max_room_number; i++)
 \r
 function createLogDirectory()\r
 {\r
-       path.exists($log_directory,function(exists){\r
+       fs.exists($log_directory,function(exists){\r
                if(exists == false)\r
                        fs.mkdirSync($log_directory);\r
        });\r
 }\r
 \r
-function getIpBanList(callback)\r
-{\r
-       ipbanlist = {};\r
-       path.exists($ip_ban_list_file_name,function(exists){\r
-               if(exists == false)\r
-               {\r
-                       if(typeof(callback) == "function")\r
-                               callback();\r
-                       return;\r
-               }\r
-               var stream = fs.createReadStream($ip_ban_list_file_name);\r
-               new lazy(stream)\r
-                       .lines\r
-                       .forEach(function(line){\r
-                               var token = line.toString().split(":");\r
-                               var ip = token[0].replace(/(\r|\n|\r\n)/gm, "");\r
-                               if(token.length == 1)\r
-                                       ipbanlist[ip] = "";\r
-                               else\r
-                                       ipbanlist[ip] = token[1];\r
-                       })\r
-                       .join(function(){\r
-                               if(typeof(callback) == "function")\r
-                                       callback();\r
-                       });\r
-       });\r
-}\r
-\r
 function ParseAuthorization(handshakeData, callback)\r
 {\r
        if(handshakeData.headers.cookie) {\r
-               var cookie = handshakeData.headers.cookie;\r
-               var sessionID = parseCookie(cookie)["connect.sid"];\r
-               handshakeData.sessionID = sessionID;\r
+               var signedCookie = cookie.parse(handshakeData.headers.cookie);\r
+               var sessionID = connectUtils.parseSignedCookies(signedCookie, $secret)["connect.sid"];\r
                sessionStore.get(sessionID, function (err, session) {\r
-                       if (err || ipbanlist[handshakeData.address.address] == "r") {\r
-                               console.log("faild authorization");\r
-                               callback($failed_authorization, false);\r
-                       } else {\r
-                               handshakeData.session =  session;\r
-                               callback(null, true);\r
+                       var result = null;\r
+                       if (ipbanlist.IsBaned(handshakeData.address.address))\r
+                               result = "failed get from session store";\r
+                       else if(err)\r
+                               result = err;\r
+                       else if(handshakeData.query.token != session.items.token)\r
+                               result = "invaild token";\r
+                       if(typeof(session) != "undefined" && result == null)\r
+                       {\r
+                               handshakeData.admin = session.items.admin;\r
+                               handshakeData.sessionID = sessionID;\r
                        }\r
+                       callback(result,result == null && !err);\r
                });\r
        } else {\r
-               console.log("faild authorization");\r
-               return callback($failed_authorization, false);\r
+               return callback("failed get cookie", false);\r
        }\r
 }\r
 \r
 function ParseDisconnect(socket,msg)\r
 {\r
-       sessionStore.destroy(socket.sessionID);\r
+       var ip = GetClientIPAdress(socket);\r
+       var rno = GetRoomNumberFromName(socket.namespace.name);\r
+       $rooms.Get(rno).RemoveRom(ip);\r
+\r
+       var romcount = $rooms.Get(rno).GetRomCount();\r
+       socket.json.emit("send romcount",romcount);\r
+       socket.json.broadcast.emit("send romcount",romcount);\r
+\r
+       //sessionStore.destroy(socket.handshake.sessionID);\r
+\r
        console.log("disconnected");\r
 }\r
 \r
-//socket \90Ú\91±\92\86\82Ì\83\\83P\83b\83g\r
-//msg msg\83N\83\89\83X\r
-function ParseSendMsg(socket,msg)\r
+function ParseSetPassword(socket,msg)\r
+{\r
+       var rno = GetRoomNumberFromName(socket.namespace.name);\r
+       var newMeg = {\r
+               name:$system_name,\r
+               message:null,\r
+       };\r
+       if($rooms.Get(rno).IsVolatile() == false && $rooms.Get(rno).SetPassword(msg.owner,msg.password))\r
+               newMeg.message = $password_setted_message;\r
+       else\r
+               newMeg.message = $failed_set_password_message;\r
+       ParseSendMsg(socket,newMeg);\r
+}\r
+\r
+function ParseJoin(socket,msg)\r
+{\r
+       var ip = GetClientIPAdress(socket);\r
+\r
+       if(ipbanlist.IsBlockedToWrite(ip))\r
+       {\r
+               socket.emit("error",$block_message);\r
+               return;\r
+       }\r
+\r
+       var rno = GetRoomNumberFromName(socket.namespace.name);\r
+\r
+       $rooms.Get(rno).RemoveRom(ip);\r
+       \r
+       var romcount = $rooms.Get(rno).GetRomCount();\r
+       socket.json.emit("send romcount",romcount);\r
+       socket.json.broadcast.emit("send romcount",romcount);\r
+\r
+       if($rooms.Get(rno).IsVolatile() == false)\r
+       {\r
+               if($rooms.Get(rno).IsTimeout() ||\r
+                       $rooms.Get(rno).IsFirstAuth())\r
+               {\r
+                       $rooms.Get(rno).Reset(msg.name);\r
+                       ParseGetPastLog(socket,util.format($log_file_name,rno));\r
+               }\r
+               else if($rooms.Get(rno).Auth(msg.name,msg.password))\r
+               {\r
+                       ParseGetPastLog(socket,util.format($log_file_name,rno));\r
+               }\r
+               else\r
+               {\r
+                       socket.emit("error",$not_match_password);\r
+                       return;\r
+               }\r
+       }\r
+\r
+       var newMeg = {\r
+               name:$system_name,\r
+               message:util.format("/enteredby %s %s %s",msg.name,msg.color,msg.mailto),\r
+       };\r
+       ParseSendMsg(socket,newMeg);\r
+}\r
+\r
+function ParseQuit(socket,msg)\r
 {\r
-       if(typeof(socket.handshake.session)=="undefined" || socket.handshake.session.items.token != msg.token)\r
+       var ip = GetClientIPAdress(socket);\r
+\r
+       if(ipbanlist.IsBlockedToWrite(ip))\r
        {\r
-               socket.emit("error",$invaild_token_message);\r
+               socket.emit("error",$block_message);\r
                return;\r
        }\r
 \r
-       var ip = socket.handshake.address.address;\r
+       var rno = GetRoomNumberFromName(socket.namespace.name);\r
+\r
+       var newMeg = {\r
+               name:$system_name,\r
+               message:$password_resetted_message,\r
+       };\r
+\r
+       $rooms.Get(rno).AddRom(ip);\r
+\r
+       var romcount = $rooms.Get(rno).GetRomCount();\r
+       socket.json.emit("send romcount",romcount);\r
+       socket.json.broadcast.emit("send romcount",romcount);\r
+\r
+       if($rooms.Get(rno).IsVolatile() == false)\r
+       {\r
+               if($rooms.Get(rno).IsOwner(msg.name))\r
+               {\r
+                       $rooms.Get(rno).Reset(null);\r
+                       ParseSendMsg(socket,newMeg);\r
+               }\r
+               if(!$rooms.Get(rno).IsFirstAuth() &&\r
+                       !$rooms.Get(rno).IsAuthed(msg.name))\r
+                       return;\r
+               else\r
+                       $rooms.Get(rno).RemoveAuth(msg.name);\r
+       }\r
+\r
+       newMeg.message = util.format("/quitedby %s",msg.name);\r
+       ParseSendMsg(socket,newMeg);\r
+}\r
+\r
+//socket 接続中のソケット\r
+//msg msgクラス\r
+function ParseSendMsg(socket,msg)\r
+{\r
+       var ip = GetClientIPAdress(socket);\r
 \r
        if(ip in ipbanlist)\r
        {\r
@@ -321,19 +434,30 @@ function ParseSendMsg(socket,msg)
                return;\r
        }\r
 \r
+       var rno = GetRoomNumberFromName(socket.namespace.name);\r
+\r
+       if(msg.name != $system_name && \r
+               $rooms.Get(rno).IsVolatile() == false &&\r
+               !$rooms.Get(rno).IsAuthed(msg.name) &&\r
+               !$rooms.Get(rno).IsOwner(rno,msg.name))\r
+       {\r
+               return;\r
+       }\r
+\r
        var date = new Date();\r
-       //var dateString = date.toFormat("YYYY/MM/DD HH24:MI:SS");\r
 \r
-       var repacked_msg = CreateMessage(msg,date);\r
+       var repacked_msg = CreateMessage(msg.name,date,msg.message);\r
+\r
+       if(socket.handshake.admin)\r
+               repacked_msg.ip = ip;\r
 \r
        socket.json.emit("req msg", repacked_msg);\r
 \r
        socket.json.broadcast.emit("req msg", repacked_msg);\r
 \r
-       var rno = GetRoomNumberFromName(socket.namespace.name);\r
        var path = $log_directory + "/" + util.format($log_file_name,rno);\r
        var log = new ChatLog(path);\r
-       log.Save(repacked_msg,ip);\r
+       log.Save(repacked_msg,ip,rno);\r
 }\r
 \r
 function GetNameFromRoomNumber(number)\r
@@ -370,29 +494,38 @@ function ParseGetPastLog(socket,file)
                return;\r
        var path = $log_directory + "/" + file;\r
        var log = new ChatLog(path);\r
-       log.ForEach(function(line){\r
-               socket.json.emit("req pastlog",CreateMessageFromText(line.toString()));\r
+       log.ToArray(socket.handshake.admin,function(array){\r
+               socket.json.emit("req pastlog",array);\r
        });\r
 }\r
 \r
 function ChatLog(path)\r
 {\r
-       this.ForEach = function(callback)\r
+       this.ToArray = function(hasIp,callback)\r
        {\r
                var state = fs.stat(path,function(err,state){\r
                        if(err)\r
                                return;\r
+                       var array = new Array();\r
                        var stream = fs.createReadStream(path);\r
                        new lazy(stream)\r
-                               .lines\r
-                               .forEach(callback);\r
+                               .spilt(";")\r
+                               .forEach(function(line){\r
+                                       var msg = CreateMessageFromText(line.toString());\r
+                                       if(hasIp == false)\r
+                                               msg.ip = "";\r
+                                       array.push(msg);\r
+                               })\r
+                               .join(function(){\r
+                                       callback(array);\r
+                               });\r
                });\r
        }\r
 \r
-       this.Save = function(msg,ip){\r
+       this.Save = function(msg,ip,rno){\r
                var text = GetTextFromMessage(msg,ip);\r
 \r
-               SplitLog(path,function(){\r
+               SplitLog(rno,function(){\r
                        WritePastLog(path,text);\r
                });\r
        };\r
@@ -403,11 +536,11 @@ function ChatLog(path)
                                msg.date + "<>" +\r
                                ip + "<>" +\r
                                msg.message +\r
-                               "\n";\r
+                               ";";\r
                return text;\r
        }\r
 \r
-       function SplitLog(path,callback)\r
+       function SplitLog(rno,callback)\r
        {\r
                var state = fs.stat(path,function(err,state){\r
                        if(err && typeof(callback) == "function")\r
@@ -418,9 +551,10 @@ function ChatLog(path)
                        if(state.size > $spilt_size)\r
                        {\r
                                var date = new Date();\r
+                               var dateString = ""+date.getFullYear()+date.getMonth()+date.getDate()+date.getHours()+date.getMinutes()+date.getSeconds();\r
 \r
                                var newpath = $log_directory + "/" +\r
-                                       util.format($splited_log_file_name,rno,date.toFormat("YYYYMMDDHH24MISS"));\r
+                                       util.format($splited_log_file_name,rno,dateString);\r
                                fs.rename(path,newpath,callback);\r
                        }else{\r
                                if(typeof(callback) == "function")\r
@@ -448,19 +582,301 @@ function ChatLog(path)
        }\r
 }\r
 \r
-// Message \83N\83\89\83X\r
-function CreateMessage(msg,date)\r
+function GetClientIPAdress(socket)\r
+{\r
+       return socket.handshake.headers["x-forwarded-for"] || socket.handshake.address.address;\r
+}\r
+\r
+// Message クラス\r
+function CreateMessage(name,date,message)\r
 {\r
-       var result = {name:msg.name,\r
+       var result = {name:name,\r
                date:date,\r
-               message:msg.message};\r
+               ip:"",\r
+               message:message};\r
        return result;\r
 }\r
 function CreateMessageFromText(text)\r
 {\r
        var data = text.split("<>");\r
        var msg = {name:data[0],\r
+               ip:data[2],\r
                date:data[1],\r
                message:data[3]};\r
        return msg;\r
 }\r
+\r
+//RoomInfomationCollecionクラス\r
+function RoomInfomationCollection()\r
+{\r
+       var collection = {};\r
+       this.Get = function(rno){\r
+               return collection[rno];\r
+       }\r
+       this.IsContains = function(rno){\r
+               return rno in collection;\r
+       };\r
+       this.GetString = function(){\r
+               var retval = "";\r
+               for(var rno in collection)\r
+               {\r
+                       if($rooms.Get(rno).IsVolatile())\r
+                               continue;\r
+                       var pass = collection[rno].password;\r
+                       if(pass == null)\r
+                               pass = "";\r
+                       var hiddenlog = collection[rno].hiddenlog;\r
+                       retval += rno + ":" + pass + ":" + hiddenlog + "\r\n";\r
+               }\r
+               return retval;\r
+       };\r
+       this.GetKeys = function(){\r
+               var retval = {};\r
+               for(var rno in collection)\r
+               {\r
+                       retval[rno] = {};\r
+               }\r
+               return retval;\r
+       }\r
+       this.Update = function(text,callfunc){\r
+               async.waterfall([\r
+                       function(callback){\r
+                               fs.open($room_configure_file_name,"w",callback);\r
+                       },\r
+                       function(fd,callback){\r
+                               var buf = new Buffer(text);\r
+                               fs.write(fd,buf,0,Buffer.byteLength(text),null,function(){\r
+                                       callback(null,fd);\r
+                               });\r
+                       },\r
+                       function(fd,callback){\r
+                               fs.close(fd,function(){\r
+                                       GetRoomList(callfunc);\r
+                               });\r
+                       }\r
+               ]);\r
+       }\r
+       function GetRoomList(callback){\r
+               Clear();\r
+               fs.exists($room_configure_file_name,function(exists){\r
+                       if(exists == false)\r
+                       {\r
+                               if(typeof(callback) == "function")\r
+                                       callback();\r
+                               return;\r
+                       }\r
+                       var stream = fs.createReadStream($room_configure_file_name);\r
+                       new lazy(stream)\r
+                               .lines\r
+                               .forEach(function(line){\r
+                                       var token = line.toString().replace(/(\r|\n|\r\n)/gm, "").split(":");\r
+                                       if(token.length == 1)\r
+                                       {\r
+                                               Add(token[0],null,false);\r
+                                       }\r
+                                       else if(token.length == 2)\r
+                                       {\r
+                                               var rno = token[0];\r
+                                               var pass = token[1];\r
+                                               if(pass == "")\r
+                                                       pass = null;\r
+                                               Add(rno, pass,false);\r
+                                       }\r
+                                       else if(token.length == 3)\r
+                                       {\r
+                                               var rno = token[0];\r
+                                               var pass = token[1];\r
+                                               if(pass == "")\r
+                                                       pass = null;\r
+                                               var hiddenlog = false;\r
+                                               if(token[2] == "true")\r
+                                                       hiddenlog = true;\r
+                                               Add(rno, pass,hiddenlog);\r
+                                       }\r
+                               })\r
+                               .join(function(){\r
+                                       if(typeof(callback) == "function")\r
+                                               callback();\r
+                               });\r
+               });\r
+       }\r
+       function Clear(){\r
+               collection = {};\r
+               for(var i = 0; i < $max_room_number; i++)\r
+                       Add(i,null,null);\r
+       };\r
+       function Add(rno,pass,hiddenlogflag){\r
+               collection[rno] = new RoomInfomation(pass,hiddenlogflag);\r
+               if(pass != null)\r
+                       collection[rno].owner = $system_name;\r
+       };\r
+       var $gc_interval_id = setInterval(function(){\r
+               for(var rno in this.rom_list)\r
+                       collection[rno].GCRomList();\r
+       },$gc_time_interval);\r
+       GetRoomList();\r
+}\r
+\r
+//RoomInfomationクラス\r
+function RoomInfomation(pass,hiddenlogflag)\r
+{\r
+       this.password = pass;\r
+       this.rom_list = {};\r
+       this.authed_list = {};\r
+       this.owner = null;\r
+       this.time = null;\r
+       this.hiddenlog = hiddenlogflag;\r
+       this.IsVolatile = function(){\r
+               return this.owner == null &&\r
+                       this.password == null &&\r
+                       this.time == null &&\r
+                       this.hiddenlog == null;\r
+       }\r
+       this.GetRomCount = function(){\r
+               var count = 0;\r
+               for(var key in this.rom_list)\r
+                       count++;\r
+               return count;\r
+       };\r
+       this.AddRom = function(ip){\r
+               var date = new Date();\r
+               this.rom_list[ip] = {time:date.getTime()};\r
+       };\r
+       this.RemoveRom = function(ip){\r
+               delete this.rom_list[ip];\r
+       };\r
+       this.Reset = function(owner){\r
+               var date = new Date();\r
+               var time = date.getTime();\r
+               this.password = null;\r
+               this.authed_list = {};\r
+               this.owner = owner;\r
+               this.time = time;\r
+       };\r
+       this.IsFirstAuth = function(){\r
+               return this.owner == null;\r
+       };\r
+       this.IsAuthed = function(name){\r
+               return name == this.owner ||\r
+                       name in this.authed_list;\r
+       };\r
+       this.IsHiddenLogFromRom = function(){\r
+               return this.hiddenlog;\r
+       };\r
+       this.IsFixedPassword = function(){\r
+               return this.owner == $system_name;\r
+       };\r
+       this.IsOwner = function(name){\r
+               return this.owner == name;\r
+       };\r
+       this.IsTimeout = function(){\r
+               var date = new Date();\r
+               var current_time = date.getTime();\r
+               return !this.IsFixedPassword() &&\r
+                       current_time - this.time >= $reset_password_diff;\r
+       };\r
+       this.RemoveAuth = function(name)\r
+       {\r
+               delete this.authed_list[name];\r
+       };\r
+       this.Auth = function(name,password){\r
+               if(this.password != password)\r
+                       return false;\r
+               var date = new Date();\r
+               var time = date.getTime();\r
+               this.time = time;\r
+               this.authed_list[name] = "";\r
+               return true;\r
+       };\r
+       this.SetPassword = function(owner,password){\r
+               if(owner == this.owner &&\r
+                       !this.IsFixedPassword() &&\r
+                       !this.IsHiddenLogFromRom())\r
+               {\r
+                       var date = new Date();\r
+                       this.time = date.getTime();\r
+                       this.password = password;\r
+                       return true;\r
+               }\r
+               return false;\r
+       };\r
+       this.GCRomList = function(){\r
+               var date = new Date();\r
+               var current_time = date.getTime();\r
+               for(var ip in this.rom_list)\r
+               {\r
+                       if(current_time - this.rom_list[ip].time >= $gc_time_interval)\r
+                               delete this.rom_list[ip];\r
+               }\r
+       };\r
+}\r
+\r
+//IPBANクラス\r
+function IpBanCollecion()\r
+{\r
+       var collection = {};\r
+       this.IsBaned = function(ip){\r
+               return collection[ip] == "r";\r
+       }\r
+       this.IsBlockedToWrite = function(ip){\r
+               return ip in collection;\r
+       }\r
+       this.GetText = function(){\r
+               var text = "";\r
+               for(var key in collection)\r
+               {\r
+                       if(collection[key] == "")\r
+                               text += key + "\r\n";\r
+                       else\r
+                               text += key + ":" + collection[key] + "\r\n";\r
+               }\r
+               return text;\r
+       }\r
+       this.Update = function(text,callfunc){\r
+               async.waterfall([\r
+                       function(callback){\r
+                               fs.open($ip_ban_list_file_name,"w",callback);\r
+                       },\r
+                       function(fd,callback){\r
+                               var buf = new Buffer(text);\r
+                               fs.write(fd,buf,0,Buffer.byteLength(text),null,function(){\r
+                                       callback(null,fd);\r
+                               });\r
+                       },\r
+                       function(fd,callback){\r
+                               fs.close(fd,function(){\r
+                                       GetIpBanList(callfunc);\r
+                               });\r
+                       }\r
+               ]);\r
+       }\r
+       function GetIpBanList(callback)\r
+       {\r
+               collection = {};\r
+               fs.exists($ip_ban_list_file_name,function(exists){\r
+                       if(exists == false)\r
+                       {\r
+                               if(typeof(callback) == "function")\r
+                                       callback();\r
+                               return;\r
+                       }\r
+                       var stream = fs.createReadStream($ip_ban_list_file_name);\r
+                       new lazy(stream)\r
+                               .lines\r
+                               .forEach(function(line){\r
+                                       var token = line.toString().replace(/(\r|\n|\r\n)/gm, "").split(":");\r
+                                       var ip = token[0];\r
+                                       if(token.length == 1)\r
+                                               collection[ip] = "";\r
+                                       else\r
+                                               collection[ip] = token[1];\r
+                               })\r
+                               .join(function(){\r
+                                       if(typeof(callback) == "function")\r
+                                               callback();\r
+                               });\r
+               });\r
+       }\r
+       GetIpBanList();\r
+}\r
+\r