OSDN Git Service

プロフィール機能を追加した
authorkonekoneko <jbh03215@hotmail.co.jp>
Tue, 13 Nov 2012 09:35:52 +0000 (18:35 +0900)
committerkonekoneko <jbh03215@hotmail.co.jp>
Tue, 13 Nov 2012 09:35:52 +0000 (18:35 +0900)
13 files changed:
chat.js [moved from chatServer.js with 75% similarity]
init.sql [new file with mode: 0644]
main.js [new file with mode: 0644]
package.json
profile.js [new file with mode: 0644]
public/profile/detail.ejs [new file with mode: 0644]
public/profile/edit.ejs [new file with mode: 0644]
public/profile/list.ejs [new file with mode: 0644]
public/profile/message.ejs [new file with mode: 0644]
public/profile/registor.ejs [new file with mode: 0644]
readme.html [new file with mode: 0644]
readme.txt [deleted file]
security.js [new file with mode: 0644]

similarity index 75%
rename from chatServer.js
rename to chat.js
index 3a34f8e..a2fd994 100644 (file)
+++ b/chat.js
@@ -1,7 +1,4 @@
-/*\r
- * 設定\r
- */\r
-$max_room_number = 3;  //最大ルーム数\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
@@ -13,121 +10,83 @@ $password_resetted_message = "パスワードをリセットしました"; //パ
 $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
-\r
-var app = express();\r
-\r
-var http = require("http");\r
-\r
-var util = require("util");\r
 \r
 var lazy = require("./lazy.js");\r
-\r
+var security = require("./security.js");\r
 var fs = require("fs");\r
-\r
+var async = require("async");\r
+var path = require("path");\r
+var util = require("util");\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 RedisStore({host:$redisHost,port:$redisPort,pass:$redisPassword});\r
-\r
-var async = require("async");\r
+var clients = new Array();\r
 \r
-var path = require("path");\r
+var sessionStore;\r
+\r
+module.exports = function(app,server,express,session){\r
+       sessionStore = session;\r
+       app.get("/chat", chat_proc);\r
+       app.all("/log/*",express.basicAuth(auth_proc));\r
+       app.get("/log/*",log_proc);\r
+       app.all("/admin_chat",express.basicAuth(auth_proc));\r
+       app.get("/admin_chat", adminchat_proc);\r
+       app.all("/admin",express.basicAuth(auth_proc));\r
+       app.get("/admin", admin_proc);\r
+       app.post("/admin",admin_postproc);\r
+\r
+       var io = require("socket.io").listen(server);\r
+       io.configure("production", function(){\r
+               io.enable("browser client minification");  // minified されたクライアントファイルを送信する\r
+       io.enable("browser client etag");          // バージョンによって etag によるキャッシングを有効にする\r
+       io.set("log level", 1);                    // ログレベルを設定(デフォルトより下げている)\r
+       });\r
 \r
-// Configuration\r
-\r
-app.configure(function(){\r
-       app.disabled("view cache");\r
-       app.set("view options", { layout: false })\r
-       app.set("views", __dirname + "/public");\r
-       app.set("view engine", "ejs");\r
-       app.use(express.bodyParser());\r
-       app.use(express.methodOverride());\r
-       app.use(express.cookieParser($secret));\r
-       app.use(express.session({\r
-               store:sessionStore,\r
-               cookie: { httpOnly: false }\r
-       }));\r
-       app.use(app.router);\r
-       app.use(express.static(__dirname + "/public"));\r
-});\r
-\r
-app.configure('development', function(){\r
-  app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); \r
-});\r
-\r
-app.configure('production', function(){\r
-  app.use(express.errorHandler()); \r
-});\r
-\r
-function SessionInfomation(token,admin)\r
-{\r
-       this.token = token;\r
-       this.admin = admin;\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",ParseConnect);\r
+       }\r
+};\r
 \r
-// Routes\r
-app.get("/chat", function(req, res){\r
-       var auth_string = getRandomString($token_length);\r
-       req.session.items = new SessionInfomation(auth_string,false);\r
+function chat_proc(req, res){\r
+       var info = new security.SessionInfomation(false);\r
+       req.session.items = info;\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
+       res.render("chat",{rno:room_number,token:info.token});\r
+}\r
 \r
-app.all("/log/*",express.basicAuth(function (user, pass) {\r
+function auth_proc(user, pass) {\r
        return user === $username && pass === $password;\r
-}));\r
+}\r
 \r
-app.get("/log/*",function (req, res) {\r
+function log_proc(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
 \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
+function adminchat_proc(req, res){\r
+       var info = new security.SessionInfomation(true);\r
+       req.session.items = info;\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
-\r
-app.get("/admin", function(req, res){\r
-       renderAdmin(req,res);\r
-});\r
+       res.render("chat",{rno:room_number,token:info.token});\r
+}\r
 \r
-app.post("/admin",function(req,res){\r
+function admin_postproc(req,res){\r
        if(req.session.items.token != req.body.token)\r
        {\r
                res.send($invaild_token_message);\r
@@ -136,27 +95,27 @@ app.post("/admin",function(req,res){
        if(typeof(req.body.erase) != "undefined")\r
        {\r
                removeLog(req.body.file,function(){\r
-                       renderAdmin(req,res);\r
+                       res.redirect("/admin");\r
                });\r
        }\r
        if(typeof(req.body.registor) != "undefined")\r
        {\r
                ipbanlist.Update(req.body.newbanlist,function(){\r
-                       renderAdmin(req,res);\r
+                       res.redirect("/admin");\r
                });\r
        }\r
        if(typeof(req.body.updateroom) != "undefined")\r
        {\r
                $rooms.Update(req.body.newroomlist,function(){\r
-                       renderAdmin(req,res);\r
+                       res.redirect("/admin");\r
                });\r
        }\r
-});\r
+}\r
 \r
-function renderAdmin(req,res)\r
+function admin_proc(req,res)\r
 {\r
-       var auth_string = getRandomString($token_length);\r
-       req.session.items = {token:auth_string};\r
+       var info = new security.SessionInfomation(true);\r
+       req.session.items = info;\r
        var iplist = ipbanlist.GetText();\r
 \r
        fs.readdir($log_directory,function(err,list){\r
@@ -164,22 +123,12 @@ function renderAdmin(req,res)
                        files: list,\r
                        log_directory:$log_directory,\r
                        ipbanlist:iplist,\r
-                       token:auth_string,\r
+                       token:info.token,\r
                        roomlist:$rooms.GetString()\r
                });\r
        });\r
 }\r
 \r
-function getRandomString(length)\r
-{\r
-       var RandomString = "";\r
-       var BaseString ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&'()=~|-^\@[;:],./\`{+*}<>?_";\r
-       for(var i=0; i<length; i++) {\r
-               RandomString += BaseString.charAt( Math.floor( Math.random() * BaseString.length));\r
-       }\r
-       return RandomString\r
-}\r
-\r
 function removeLog(files,callback)\r
 {\r
        if(typeof(files) == "undefined")\r
@@ -199,512 +148,115 @@ function removeLog(files,callback)
        });\r
 }\r
 \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
- * サーバー部分\r
- */\r
-\r
-var io = require("socket.io").listen(server);\r
-io.configure('production', function(){\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 = new IpBanCollecion();\r
-var $rooms = new RoomInfomationCollection();\r
-\r
-createLogDirectory();\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
-               var ip = GetClientIPAdress(socket);\r
-\r
-               console.log("connected from %s",ip);\r
-\r
-               var rno = GetRoomNumberFromName(socket.namespace.name);\r
-               var room = $rooms.Get(rno);\r
-               room.AddRom(ip);\r
-\r
-               var roomconfig = room.GetConfig();\r
-               roomconfig.admin = socket.handshake.admin;\r
-               socket.json.emit("send roominfo",roomconfig);\r
-\r
-               var romcount = room.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
-               socket.on("disconnect", function (msg) {\r
-                       ParseDisconnect(socket,msg);\r
-               });\r
-       });\r
-}\r
-\r
-function createLogDirectory()\r
-{\r
-       fs.exists($log_directory,function(exists){\r
-               if(exists == false)\r
-                       fs.mkdirSync($log_directory);\r
-       });\r
-}\r
-\r
-function ParseAuthorization(handshakeData, callback)\r
+//RoomInfomationCollecionクラス\r
+function RoomInfomationCollection()\r
 {\r
-       if(handshakeData.headers.cookie) {\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
-                       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
-               return callback("failed get cookie", false);\r
+       var collection = {};\r
+       this.Get = function(rno){\r
+               return collection[rno];\r
        }\r
-}\r
-\r
-function ParseDisconnect(socket,msg)\r
-{\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
-function ParseSetPassword(socket,msg)\r
-{\r
-       var rno = GetRoomNumberFromName(socket.namespace.name);\r
-       var newMeg = {\r
-               name:$system_name,\r
-               message:null,\r
+       this.IsContains = function(rno){\r
+               return rno in collection;\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
+       this.GetString = function(){\r
+               var retval = "";\r
+               for(var rno in collection)\r
                {\r
-                       ParseGetPastLog(socket,util.format($log_file_name,rno));\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
-               else\r
+               return retval;\r
+       };\r
+       this.GetKeys = function(){\r
+               var retval = {};\r
+               for(var rno in collection)\r
                {\r
-                       socket.emit("error",$not_match_password);\r
-                       return;\r
+                       retval[rno] = {};\r
                }\r
+               return retval;\r
        }\r
-\r
-       var newMeg = {\r
-               name:$system_name,\r
-               message:util.format("/enteredby %s %s %s",msg.name,msg.color,msg.mailto),\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
-       ParseSendMsg(socket,newMeg);\r
-}\r
-\r
-function ParseQuit(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
-       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
-               socket.emit("error",$block_message);\r
-               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
-\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 path = $log_directory + "/" + util.format($log_file_name,rno);\r
-       var log = new ChatLog(path);\r
-       log.Save(repacked_msg,ip,rno);\r
-}\r
-\r
-function GetNameFromRoomNumber(number)\r
-{\r
-       return "/" + number;\r
-}\r
-\r
-function GetRoomNumberFromName(name)\r
-{\r
-       if(name.charAt(0) == "/")\r
-               return parseInt(name.substr(1));\r
-       throw "GetRoomNumberFromName error";\r
-}\r
-\r
-function ParseGetPastLogList(socket,msg)\r
-{\r
-       var list = fs.readdir($log_directory,function(err,files){\r
-               var text = "";\r
-               var rno = GetRoomNumberFromName(socket.namespace.name);\r
-               var pattern = $pastlogfile_pattern.replace("%d",rno);\r
-               for(var i = 0; i < files.length; i++)\r
-               {\r
-                       var logname = files[i];\r
-                       if(logname.match(pattern))\r
-                               text += files[i] + "\n";\r
-               }\r
-               socket.emit("req pastloglist",text);\r
-       });\r
-}\r
-\r
-function ParseGetPastLog(socket,file)\r
-{\r
-       if(file == "")\r
-               return;\r
-       var path = $log_directory + "/" + file;\r
-       var log = new ChatLog(path);\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.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
-                               .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,rno){\r
-               var text = GetTextFromMessage(msg,ip);\r
-\r
-               SplitLog(rno,function(){\r
-                       WritePastLog(path,text);\r
-               });\r
-       };\r
-\r
-       function GetTextFromMessage(msg,ip)\r
-       {\r
-               var text = msg.name + "<>" +\r
-                               msg.date + "<>" +\r
-                               ip + "<>" +\r
-                               msg.message +\r
-                               ";";\r
-               return text;\r
-       }\r
-\r
-       function SplitLog(rno,callback)\r
-       {\r
-               var state = fs.stat(path,function(err,state){\r
-                       if(err && typeof(callback) == "function")\r
-                       {\r
-                               callback();\r
-                               return;\r
-                       }\r
-                       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,dateString);\r
-                               fs.rename(path,newpath,callback);\r
-                       }else{\r
-                               if(typeof(callback) == "function")\r
-                                       callback();\r
-                       }\r
-               });\r
-       }\r
-\r
-       function WritePastLog(path,text)\r
-       {\r
-               async.waterfall([\r
-                       function(callback){\r
-                               fs.open(path,"a",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){\r
-                               fs.close(fd);\r
-                       }\r
-               ]);\r
-       }\r
-}\r
-\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:name,\r
-               date:date,\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
+       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
@@ -806,42 +358,424 @@ function RoomInfomation(pass,hiddenlogflag)
                }\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
+       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
+var ipbanlist = new IpBanCollecion();\r
+var $rooms = new RoomInfomationCollection();\r
+\r
+createLogDirectory();\r
+\r
+function createLogDirectory()\r
+{\r
+       fs.exists($log_directory,function(exists){\r
+               if(exists == false)\r
+                       fs.mkdirSync($log_directory);\r
+       });\r
+}\r
+\r
+function ParseConnect(socket)\r
+{\r
+       var ip = GetClientIPAdress(socket);\r
+       console.log("connected from %s",ip);\r
+\r
+       var rno = GetRoomNumberFromName(socket.namespace.name);\r
+\r
+       var room = $rooms.Get(rno);\r
+\r
+       room.AddRom(ip);\r
+\r
+       var roomconfig = room.GetConfig();\r
+       roomconfig.admin = socket.handshake.admin;\r
+       socket.json.emit("send roominfo",roomconfig);\r
+\r
+       var romcount = room.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
+       socket.on("disconnect", function (msg) {\r
+               ParseDisconnect(socket,msg);\r
+       });\r
+}\r
+\r
+function ParseAuthorization(handshakeData, callback)\r
+{\r
+       if(handshakeData.headers.cookie) {\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
+                       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
+               return callback("failed get cookie", false);\r
+       }\r
+}\r
+\r
+function ParseDisconnect(socket,msg)\r
+{\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
+       console.log("disconnected");\r
+}\r
+\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
+       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
+       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
-                       if(current_time - this.rom_list[ip].time >= $gc_time_interval)\r
-                               delete this.rom_list[ip];\r
+                       $rooms.Get(rno).Reset(null);\r
+                       ParseSendMsg(socket,newMeg);\r
                }\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
-//IPBANクラス\r
-function IpBanCollecion()\r
+//socket 接続中のソケット\r
+//msg msgクラス\r
+function ParseSendMsg(socket,msg)\r
 {\r
-       var collection = {};\r
-       this.IsBaned = function(ip){\r
-               return collection[ip] == "r";\r
+       var ip = GetClientIPAdress(socket);\r
+\r
+       if(ip in ipbanlist)\r
+       {\r
+               socket.emit("error",$block_message);\r
+               return;\r
        }\r
-       this.IsBlockedToWrite = function(ip){\r
-               return ip in collection;\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
-       this.GetText = function(){\r
+\r
+       var date = new Date();\r
+\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 path = $log_directory + "/" + util.format($log_file_name,rno);\r
+       var log = new ChatLog(path);\r
+       log.Save(repacked_msg,ip,rno);\r
+}\r
+\r
+function GetNameFromRoomNumber(number)\r
+{\r
+       return "/" + number;\r
+}\r
+\r
+function GetRoomNumberFromName(name)\r
+{\r
+       if(name.charAt(0) == "/")\r
+               return parseInt(name.substr(1));\r
+       throw "GetRoomNumberFromName error";\r
+}\r
+\r
+function ParseGetPastLogList(socket,msg)\r
+{\r
+       var list = fs.readdir($log_directory,function(err,files){\r
                var text = "";\r
-               for(var key in collection)\r
+               var rno = GetRoomNumberFromName(socket.namespace.name);\r
+               var pattern = $pastlogfile_pattern.replace("%d",rno);\r
+               for(var i = 0; i < files.length; i++)\r
                {\r
-                       if(collection[key] == "")\r
-                               text += key + "\r\n";\r
-                       else\r
-                               text += key + ":" + collection[key] + "\r\n";\r
+                       var logname = files[i];\r
+                       if(logname.match(pattern))\r
+                               text += files[i] + "\n";\r
                }\r
+               socket.emit("req pastloglist",text);\r
+       });\r
+}\r
+\r
+function ParseGetPastLog(socket,file)\r
+{\r
+       if(file == "")\r
+               return;\r
+       var path = $log_directory + "/" + file;\r
+       var log = new ChatLog(path);\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.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
+                               .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,rno){\r
+               var text = GetTextFromMessage(msg,ip);\r
+\r
+               SplitLog(rno,function(){\r
+                       WritePastLog(path,text);\r
+               });\r
+       };\r
+\r
+       function GetTextFromMessage(msg,ip)\r
+       {\r
+               var text = msg.name + "<>" +\r
+                               msg.date + "<>" +\r
+                               ip + "<>" +\r
+                               msg.message +\r
+                               ";";\r
                return text;\r
        }\r
-       this.Update = function(text,callfunc){\r
+\r
+       function SplitLog(rno,callback)\r
+       {\r
+               var state = fs.stat(path,function(err,state){\r
+                       if(err && typeof(callback) == "function")\r
+                       {\r
+                               callback();\r
+                               return;\r
+                       }\r
+                       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,dateString);\r
+                               fs.rename(path,newpath,callback);\r
+                       }else{\r
+                               if(typeof(callback) == "function")\r
+                                       callback();\r
+                       }\r
+               });\r
+       }\r
+\r
+       function WritePastLog(path,text)\r
+       {\r
                async.waterfall([\r
                        function(callback){\r
-                               fs.open($ip_ban_list_file_name,"w",callback);\r
+                               fs.open(path,"a",callback);\r
                        },\r
                        function(fd,callback){\r
                                var buf = new Buffer(text);\r
@@ -849,40 +783,33 @@ function IpBanCollecion()
                                        callback(null,fd);\r
                                });\r
                        },\r
-                       function(fd,callback){\r
-                               fs.close(fd,function(){\r
-                                       GetIpBanList(callfunc);\r
-                               });\r
+                       function(fd){\r
+                               fs.close(fd);\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
+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:name,\r
+               date:date,\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
diff --git a/init.sql b/init.sql
new file mode 100644 (file)
index 0000000..bc45162
--- /dev/null
+++ b/init.sql
@@ -0,0 +1,21 @@
+CREATE DATABASE IF NOT EXISTS profile;
+grant select,
+       insert,
+       delete,
+       update,
+       create,
+       drop,
+       file,
+       alter,
+       index on *.* to user identified by 'user';
+flush privileges;
+use profile;
+create table list(name VARCHAR(64) NOT NULL,
+       age INT,
+       height INT,
+       weight INT,
+       race VARCHAR(64),
+       look TEXT,
+       password VARCHAR(16),
+       etc TEXT,
+       PRIMARY KEY(name));
diff --git a/main.js b/main.js
new file mode 100644 (file)
index 0000000..04e9a91
--- /dev/null
+++ b/main.js
@@ -0,0 +1,57 @@
+\r
+//\r
+//設定\r
+//\r
+$enable_profile = true;        //プロファイル機能を使用するなら真。そうでないなら、偽\r
+\r
+$port = process.env.port || 3000;      //ポート\r
+$redisHost = "localhost";      //redisサーバのアドレス\r
+$redisPort = 6379;     //redisサーバのポート\r
+$redisPassword = "";   //redisサーバのパスワード\r
+\r
+//\r
+//\r
+//\r
+$secret = "5514EA2B-C9B2-4D65-8D81-1F33A180A0C2";      //cookie用秘密鍵\r
+\r
+\r
+// Server\r
+var express = require("express");\r
+var app = express();\r
+var http = require("http");\r
+var RedisStore = require("connect-redis")(express);\r
+var sessionStore = new RedisStore({host:$redisHost,port:$redisPort,pass:$redisPassword});\r
+\r
+// Configuration\r
+\r
+app.configure(function(){\r
+       app.disabled("view cache");\r
+       app.set("view options", { layout: false })\r
+       app.set("views", __dirname + "/public");\r
+       app.set("view engine", "ejs");\r
+       app.use(express.bodyParser());\r
+       app.use(express.methodOverride());\r
+       app.use(express.cookieParser($secret));\r
+       app.use(express.session({\r
+               store:sessionStore,\r
+               cookie: { httpOnly: false }\r
+       }));\r
+       app.use(app.router);\r
+       app.use(express.static(__dirname + "/public"));\r
+});\r
+\r
+app.configure("development", function(){\r
+  app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); \r
+});\r
+\r
+app.configure("production", function(){\r
+  app.use(express.errorHandler()); \r
+});\r
+\r
+if($enable_profile)\r
+       require("./profile")(app);\r
+\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
+require("./chat")(app,server,express,sessionStore);\r
index 64fec03..705298c 100644 (file)
@@ -8,5 +8,6 @@
     , "ejs": "0.8.3"
     , "express": "3.0.1"
     , "socket.io": "0.9.11"
+    , "mysql" : "2.0.0-alpha4"
   }
 }
diff --git a/profile.js b/profile.js
new file mode 100644 (file)
index 0000000..1a4a937
--- /dev/null
@@ -0,0 +1,355 @@
+$db_user = "user";\r
+$db_password = "user";\r
+$db_limit = 50;\r
+\r
+$unmatch_password = "パスワードが一致しません";\r
+$invaild_parameter = "パラメーターが正しくありません";\r
+$success_registor = "登録に成功しました";\r
+$success_remove = "削除に成功しました";\r
+$success_edit = "編集に成功しました";\r
+$notfound_name = "該当名が存在しません";\r
+\r
+var util = require("util");\r
+\r
+var async = require("async");\r
+\r
+var security = require("./security.js");\r
+\r
+var collection = new ProfileCollection();\r
+\r
+module.exports = function(app){\r
+       app.get("/profile",list_proc);\r
+       app.get("/profile/detail",detail_proc);\r
+       app.post("/profile/detail",detail_postproc);\r
+       app.post("/profile/edit",edit_postproc); \r
+       app.get("/profile/registor",registor_proc); \r
+       app.post("/profile/registor",registor_postproc); \r
+};\r
+\r
+function list_proc(req, res)\r
+{\r
+       var limit = $db_limit;\r
+       var start = 0;\r
+       var parttern = "";\r
+       if(typeof(req.query.start) != "undefined")\r
+               start = parseInt(req.query.start);\r
+       if(typeof(req.query.limit) != "undefined")\r
+               limit = parseInt(req.query.limit);\r
+\r
+       async.waterfall([\r
+               function(cb){\r
+                       if(typeof(req.query.search) != "undefined")\r
+                       {\r
+                               parttern = req.query.search;\r
+                               collection.FindByNameAsync(parttern,start,limit,cb);\r
+                       }else{\r
+                               collection.ToArrayAsync(start,limit,cb);\r
+                       }\r
+               }\r
+       ],function(err,result){\r
+               if(err != null){\r
+                       res.render("profile\\message",{message:err});\r
+               }else{\r
+                       var next = start + limit;\r
+                       var prev = start - limit;\r
+                       if(prev < 0)\r
+                               prev = 0;\r
+                       res.render("profile\\list",{list:result,search:parttern,next:next,prev:prev,limit:limit});\r
+               }\r
+       });\r
+}\r
+\r
+function detail_proc(req, res)\r
+{\r
+       if(typeof(req.query.name) == "undefined")\r
+       {\r
+               res.render("profile\\message",{message:$invaild_parameter});\r
+               return;\r
+       }\r
+\r
+       var info = new security.SessionInfomation(false);\r
+       req.session.items = info;\r
+\r
+       async.waterfall([\r
+               function(cb){\r
+                       collection.GetAsync(req.query.name,cb);\r
+               },\r
+       ],function(err,result){\r
+               if(err != null)\r
+                       res.render("profile\\message",{message:err});\r
+               else if(result.length == 0)\r
+                       res.render("profile\\message",{message:$notfound_name});\r
+               else\r
+                       res.render("profile\\detail",{list:result,token:info.token});\r
+       });\r
+}\r
+\r
+function detail_postproc(req, res)\r
+{\r
+       if(req.session.items.token != req.body.token){\r
+               res.render("profile\\message",{message:$invaild_parameter});\r
+               return;\r
+       }\r
+       if(typeof(req.body.remove) != "undefined"){\r
+               async.waterfall([\r
+                       function(cb){\r
+                               collection.AuthAsync(req.body.name,req.body.password,cb);\r
+                       },\r
+                       function(result,cb){\r
+                               if(result)\r
+                                       collection.RemoveAsync(req.body.name,cb);\r
+                               else\r
+                                       cb(null,null);\r
+                       }\r
+               ],function(err,result){\r
+                       if(err != null)\r
+                               res.render("profile\\message",{message:err});\r
+                       else if(result == null)\r
+                               res.render("profile\\message",{message:$unmatch_password});\r
+                       else\r
+                               res.render("profile\\message",{message:$success_remove});\r
+               });\r
+       }else if(typeof(req.body.edit) != "undefined"){\r
+               async.waterfall([\r
+                       function(cb){\r
+                               collection.AuthAsync(req.body.name,req.body.password,cb);\r
+                       },\r
+                       function(result,cb){\r
+                               if(result)\r
+                                       collection.GetAsync(req.body.name,cb);\r
+                               else\r
+                                       cb(null,null);\r
+                       }\r
+               ],function(err,result){\r
+                       if(err != null){\r
+                               res.render("profile\\message",{message:err});\r
+                       }else if(result != null){\r
+                               res.render("profile\\edit",{list:result,token:req.body.token});\r
+                       }else{\r
+                               res.render("profile\\message",{message:$unmatch_password});\r
+                       }\r
+               });\r
+       }else{\r
+               res.render("profile\\message",{message:$invaild_parameter});\r
+       }\r
+}\r
+\r
+function edit_postproc(req, res)\r
+{\r
+       if(req.session.items.token != req.body.token){\r
+               res.render("profile\\message",{message:$invaild_parameter});\r
+               return;\r
+       }\r
+       if(typeof(req.body.name) == "undefined")\r
+       {\r
+               res.render("profile\\message",{message:$invaild_parameter});\r
+               return;\r
+       }else if(typeof(req.body.edit) != "undefined"){\r
+               async.waterfall([\r
+                       function(cb){\r
+                               collection.UpdatAsync(req.body.name,req.body,cb);\r
+                       }\r
+               ],function(err,result){\r
+                       if(err != null)\r
+                               res.render("profile\\message",{message:err});\r
+                       else\r
+                               res.render("profile\\message",{message:$success_edit});\r
+               });\r
+       }else{\r
+               res.render("profile\\message",{message:$invaild_parameter});\r
+       }\r
+}\r
+\r
+function registor_postproc(req, res)\r
+{\r
+       if(req.session.items.token != req.body.token){\r
+               res.render("profile\\message",{message:$invaild_parameter});\r
+               return;\r
+       }\r
+       if(typeof(req.body.registor) != "undefined"){\r
+               async.waterfall([\r
+                       function(cb){\r
+                               collection.AddAsync(req.body,cb);\r
+                       }\r
+               ],function(err,result){\r
+                       if(err != null)\r
+                               res.render("profile\\message",{message:err});\r
+                       else\r
+                               res.render("profile\\message",{message:$success_registor});\r
+               });\r
+       }else{\r
+               res.render("profile\\message",{message:$invaild_parameter});\r
+       }\r
+}\r
+function registor_proc(req, res)\r
+{\r
+       var info = new security.SessionInfomation(false);\r
+       req.session.items = info;\r
+\r
+       res.render("profile\\registor",{token:info.token});\r
+}\r
+\r
+//\r
+// ProfileCollectionクラス\r
+//\r
+function ProfileCollection()\r
+{\r
+       var pool = new MySQLPool();\r
+       this.AuthAsync = function(name,password,cb){\r
+               async.waterfall([\r
+                       function(callback){\r
+                               pool.acquire(callback);\r
+                       },\r
+                       function(client,callback){\r
+                               client.query("SELECT * FROM list WHERE name = ?",[name],function(err,result){\r
+                                       callback(err,result,client);\r
+                               });\r
+                       },\r
+                       function(result,client,callback){\r
+                               pool.release(client);\r
+                               if(result[0].password == password)\r
+                                       callback(null,true);\r
+                               else\r
+                                       callback(null,false);\r
+                       }\r
+               ],cb);\r
+       }\r
+       this.GetAsync = function(name,cb){\r
+               async.waterfall([\r
+                       function(callback){\r
+                               pool.acquire(callback);\r
+                       },\r
+                       function(client,callback){\r
+                               client.query("SELECT * FROM list WHERE name = ?",[name],function(err,result){\r
+                                       callback(err,result,client);\r
+                               });\r
+                       },\r
+                       function(result,client,callback){\r
+                               pool.release(client);\r
+                               callback(null,result);\r
+                       }\r
+               ],cb);\r
+       }\r
+       this.AddAsync = function(data,cb){\r
+               var item = {\r
+                       name:data.name,\r
+                       age:data.age,\r
+                       height:data.height,\r
+                       weight:data.weight,\r
+                       race:data.race,\r
+                       look:data.look,\r
+                       password:data.password,\r
+                       etc:data.etc\r
+               };\r
+               async.waterfall([\r
+                       function(callback){\r
+                               pool.acquire(callback);\r
+                       },\r
+                       function(client,callback){\r
+                               client.query("INSERT INTO list SET ?",[item],function(err,result){\r
+                                       callback(err,result,client);\r
+                               });\r
+                       },\r
+                       function(result,client,callback){\r
+                               pool.release(client);\r
+                               callback(null,result);\r
+                       }\r
+               ],cb);\r
+       }\r
+       this.UpdatAsync = function(name,data,cb){\r
+               var item = {\r
+                       name:data.name,\r
+                       age:data.age,\r
+                       height:data.height,\r
+                       weight:data.weight,\r
+                       race:data.race,\r
+                       look:data.look,\r
+                       etc:data.etc\r
+               };\r
+               async.waterfall([\r
+                       function(callback){\r
+                               pool.acquire(callback);\r
+                       },\r
+                       function(client,callback){\r
+                               client.query("UPDATE list SET ? WHERE name = ?",[item,name],function(err,result){\r
+                                       callback(err,result,client);\r
+                               });\r
+                       },\r
+                       function(result,client,callback){\r
+                               pool.release(client);\r
+                               callback(null,result);\r
+                       }\r
+               ],cb);\r
+       }\r
+       this.RemoveAsync = function(name,cb){\r
+               async.waterfall([\r
+                       function(callback){\r
+                               pool.acquire(callback);\r
+                       },\r
+                       function(client,callback){\r
+                               client.query("DELETE FROM list WHERE name = ?",[name],function(err,result){\r
+                                       callback(err,result,client);\r
+                               });\r
+                       },\r
+                       function(result,client,callback){\r
+                               pool.release(client);\r
+                               callback(null,result);\r
+                       }\r
+               ],cb);\r
+       }\r
+       this.FindByNameAsync = function(pattern,start,count,cb){\r
+               async.waterfall([\r
+                       function(callback){\r
+                               pool.acquire(callback);\r
+                       },\r
+                       function(client,callback){\r
+                               client.query("SELECT * FROM list WHERE name LIKE ? LIMIT ?,?",[pattern+"%",start,count],function(err,result){\r
+                                       callback(err,result,client);\r
+                               });\r
+                       },\r
+                       function(result,client,callback){\r
+                               pool.release(client);\r
+                               callback(null,result);\r
+                       }\r
+               ],cb);\r
+       }\r
+       this.ToArrayAsync = function(start,count,cb){\r
+               async.waterfall([\r
+                       function(callback){\r
+                               pool.acquire(callback);\r
+                       },\r
+                       function(client,callback){\r
+                               client.query("SELECT * FROM list LIMIT ?,?",[start,count],function(err,result){\r
+                                       callback(err,result,client);\r
+                               });\r
+                       },\r
+                       function(result,client,callback){\r
+                               pool.release(client);\r
+                               callback(null,result);\r
+                       }\r
+               ],cb);\r
+       }\r
+}\r
+\r
+function MySQLPool()\r
+{\r
+       var generic_pool = require("generic-pool");\r
+       var mysql      = require("mysql");\r
+       return generic_pool.Pool({\r
+               name : "mysql",\r
+               max : 10,\r
+               create : function(cb){\r
+                       var connection = mysql.createConnection({\r
+                               host     : "localhost",\r
+                               user     : $db_user,\r
+                               password : $db_password,\r
+                               database : "profile",\r
+                       });\r
+                       connection.connect();\r
+                       cb(null,connection);\r
+               },\r
+               destroy : function(db){\r
+                       db.end();\r
+               }\r
+       });\r
+}\r
diff --git a/public/profile/detail.ejs b/public/profile/detail.ejs
new file mode 100644 (file)
index 0000000..4dc77d8
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r
+<meta http-equiv="cache-control" content="no-cache">\r
+<title>詳細画面</title>\r
+</head>\r
+<body>\r
+<h1>詳細画面</h1>\r
+<div id="content">\r
+       <table>\r
+               <tr>\r
+                       <td>名前</td>\r
+                       <td><%= list[0].name %></td>\r
+               </tr>\r
+               <tr>\r
+                       <td>年齢</td>\r
+                       <td><%= list[0].age %></td>\r
+               </tr>\r
+               <tr>\r
+                       <td>身長</td>\r
+                       <td><%= list[0].height %></td>\r
+               </tr>\r
+               <tr>\r
+                       <td>体重</td>\r
+                       <td><%= list[0].weight %></td>\r
+               </tr>\r
+               <tr>\r
+                       <td>種族</td>\r
+                       <td><%= list[0].race %></td>\r
+               </tr>\r
+               <tr>\r
+                       <td>外見</td>\r
+                       <td><%= list[0].look %></td>\r
+               </tr>\r
+               <tr>\r
+                       <td>備考</td>\r
+                       <td><%= list[0].etc %></td>\r
+               </tr>\r
+       </table>\r
+       <form action="/profile/detail" method="POST">\r
+               <input type="hidden" name="token" value="<%= token %>"></input>\r
+               <input type="hidden" value="<%= list[0].name %>" name="name"/>\r
+               <input type="submit" value="編集" name="edit"/>\r
+               <input type="submit" value="削除" name="remove"/>\r
+               <input type="text" value="" name="password"/>\r
+       </form>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/public/profile/edit.ejs b/public/profile/edit.ejs
new file mode 100644 (file)
index 0000000..c975cb7
--- /dev/null
@@ -0,0 +1,47 @@
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r
+<meta http-equiv="cache-control" content="no-cache">\r
+<title>詳細画面</title>\r
+</head>\r
+<body>\r
+<h1>詳細画面</h1>\r
+<div id="content">\r
+       <form action="/profile/edit" method="POST">\r
+               <table>\r
+                       <tr>\r
+                               <td>名前</td>\r
+                               <td><input type="text" value="<%= list[0].name %>" name="name"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>年齢</td>\r
+                               <td><input type="text" value="<%= list[0].age %>" name="age"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>身長</td>\r
+                               <td><input type="text" value="<%= list[0].height %>" name="height"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>体重</td>\r
+                               <td><input type="text" value="<%= list[0].weight %>" name="weight"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>種族</td>\r
+                               <td><input type="text" value="<%= list[0].race %>" name="race"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>外見</td>\r
+                               <td><textarea name="look" rows="4" cols="50"><%= list[0].look %></textarea></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>備考</td>\r
+                               <td><textarea name="etc" rows="4" cols="50"><%= list[0].etc %></textarea></td>\r
+                       </tr>\r
+               </table>\r
+               <input type="hidden" name="token" value="<%= token %>"></input>\r
+               <input type="submit" value="編集" name="edit"/>\r
+       </form>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/public/profile/list.ejs b/public/profile/list.ejs
new file mode 100644 (file)
index 0000000..6184b85
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r
+<meta http-equiv="cache-control" content="no-cache">\r
+<title>プロファイルリスト</title>\r
+</head>\r
+<body>\r
+<h1>プロフィール</h1>\r
+<div id="content">\r
+<form action="/profile" method="GET">\r
+       <select name="field" size="1">\r
+               <option value="name">名前</option>\r
+       </select>\r
+       <input type="text" value="<%= encodeURIComponent(search) %>" name="search"/>\r
+       <input type="submit" value="検索"/>\r
+       <a href="profile/registor">登録</a>\r
+</form>\r
+<table>\r
+       <tr>\r
+               <th>名前</th>\r
+               <th>年齢</th>\r
+       </tr>\r
+<% for(var i=0; i<list.length; i++) {%>\r
+       <tr>\r
+               <td><a href="profile/detail?name=<%= encodeURIComponent(list[i].name) %>"><%= list[i].name %></a></td>\r
+               <td><%= list[i].age %></td>\r
+       </tr>\r
+<% } %>\r
+</table>\r
+<a href="profile?start=<%= prev %>&limit=<%= limit %>&search=<%= encodeURIComponent(search) %>"><前</a>\r
+<a href="profile?start=<%= next %>&limit=<%= limit %>&search=<%= encodeURIComponent(search) %>">次></a>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/public/profile/message.ejs b/public/profile/message.ejs
new file mode 100644 (file)
index 0000000..b2ec31c
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r
+<meta http-equiv="cache-control" content="no-cache">\r
+<title>メッセージ</title>\r
+</head>\r
+<body>\r
+<h1>メッセージ</h1>\r
+<div id="content">\r
+       <p><%= message %></p>\r
+       <p><a href="/profile">TOP</a></p>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/public/profile/registor.ejs b/public/profile/registor.ejs
new file mode 100644 (file)
index 0000000..abc0ecf
--- /dev/null
@@ -0,0 +1,51 @@
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r
+<meta http-equiv="cache-control" content="no-cache">\r
+<title>登録</title>\r
+</head>\r
+<body>\r
+<h1>登録</h1>\r
+<div id="content">\r
+       <form action="/profile/registor" method="POST">\r
+               <table>\r
+                       <tr>\r
+                               <td>名前</td>\r
+                               <td><input type="text" value="" name="name"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>パスワード</td>\r
+                               <td><input type="text" value="" name="password"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>年齢</td>\r
+                               <td><input type="text" value="" name="age"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>身長</td>\r
+                               <td><input type="text" value="" name="height"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>体重</td>\r
+                               <td><input type="text" value="" name="weight"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>種族</td>\r
+                               <td><input type="text" value="" name="race"/></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>外見</td>\r
+                               <td><textarea name="look" rows="4" cols="50"></textarea></td>\r
+                       </tr>\r
+                       <tr>\r
+                               <td>備考</td>\r
+                               <td><textarea name="etc" rows="4" cols="50"></textarea></td>\r
+                       </tr>\r
+               </table>\r
+               <input type="hidden" name="token" value="<%= token %>"></input>\r
+               <input type="submit" value="登録" name="registor"/>\r
+       </form>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/readme.html b/readme.html
new file mode 100644 (file)
index 0000000..b77369a
--- /dev/null
@@ -0,0 +1,89 @@
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
+<meta http-equiv="content-language" content="ja">\r
+<meta name="keywords" content="WebChat,マニュアル,使い方">\r
+<meta name="description" content="WebChatの使い方を解説しています">\r
+<meta name="robots" content="ALL" />\r
+<title>MANUAL</title>\r
+</head>\r
+<div id="content">\r
+       <h2>動作環境</h2>\r
+       <ul>\r
+               <li>node.js 0.8.x</li>\r
+               <li>redis 2.4.6以降</li>\r
+       </ul>\r
+       <h2>インストール方法</h2>\r
+       <h3>Windows</h3>\r
+       <ol>\r
+               <li><a href="https://github.com/rgl/redis/downloads">ここ</a>からRedis Serverダウンロードし、インストールする</li>\r
+               <li><a href="http://nodejs.org/">ここ</a>のDownloadページからをnode.jsダウンロードし、インストールする</li>\r
+               <li><a href="http://www-jp.mysql.com/">ここ</a>のダウンロードからMySQLをダウンロードし、インストールする</li>\r
+               <li>mysql -u root -p &lt; init.sqlを実行する</li>\r
+               <li>npm installを実行する</li>\r
+               <li>chat.jsの$usernameと$passwordを適切なものに変更する</li>\r
+               <li>redisを起動し、main.jsを起動する</li>\r
+       </ol>\r
+       <h3>CentOS系列</h3>\r
+       <ol>\r
+               <li>yum groupinstall "Development Tools"を実行する</li>\r
+               <li>yum instlall gitを実行する</li>\r
+               <li>yum install wgetを実行する</li>\r
+               <li>yum install openssl-develを実行する</li>\r
+               <li><a href="http://redis.io/download">ここ</a>にアクセスし、redisをインストールする</li>\r
+               <li>redis-2.4.17/utils/install_server.shを実行する</li>\r
+               <li><a href="http://nodejs.org/dist/v0.8.14/node-v0.8.14.tar.gz">ここ</a>からダウンロードする</li>\r
+               <li>yum install mysql-serverを実行する</li>\r
+               <li>/etc/my.cnfのclient,mysql,mysqldumpセクションのdefault-character-setをutf8にする</li>\r
+               <li>chkconfig mysqld onを実行する</li>\r
+               <li>/etc/rc.d/init.d/mysqld startを実行する</li>\r
+               <li>tar xzf node-v0.8.14.tar.gzを実行する</li>\r
+               <li>cd node-v0.8.14を実行する</li>\r
+               <li>./configureを実行する</li>\r
+               <li>makeを実行し、make installも実行する</li>\r
+               <li>git clone git://git.sourceforge.jp/gitroot/webchat/WebChat.gitを実行する</li>\r
+               <li>npm installを実行する</li>\r
+               <li>chat.jsの$usernameと$passwordを適切なものに変更する</li>\r
+               <li>main.jsの$redisHost、$redisPort、$redisPasswordを変更する(ローカル内でRedisSeverを起動する場合は不要)</li>\r
+               <li>main.jsを起動する</li>\r
+       </ol>\r
+       <h2>管理サイト</h2>\r
+       <p>[設置しているサーバー]/adminとアドレスバーに入力することで管理用のページにアクセスできます</p>\r
+       <p>このページではログの削除、アクセスを禁止するIPアドレスの設定、ルームの設定を行うことができます。</p>\r
+       <p>IPアドレスの設定時に「IPアドレス:r」とすることで読み取りを禁止し、「IPアドレス」だけを記述することで書き込みを禁止します。</p>\r
+       <p>ルームの設定では「部屋番号:パスワード」とすることで固定パスワードを設定し、「部屋番号」と記載することで利用者にパスワードを設定させることができます。また、「部屋番号::true」とした場合はROMを禁止することができます</p>\r
+       <h2>チャットルームへのアクセス</h2>\r
+       <p>アドレスバーに[設置しているサーバー]/chatと入力することでチャットルームにアクセスできます。</p>\r
+       <p>[設置しているサーバー]/admin_chatと入力した場合はIPアドレスが表示されます</p>\r
+       <h2>複数のルームの設置</h2>\r
+       <p>URLを[設置しているサーバー]/chat?rno=[ルーム番号]とすることで複数のチャットルームを使い分けることができます。</p>\r
+       <p>なお、デフォルトではchatServer.jsの$max_room_numberの値が3になっているので、この値を設置したい個数にしてください。(設定を変えた後は再起動してください)</p>\r
+       <h2>ルームごとにスタイル変える方法</h2>\r
+       <p>&lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;stylesheets/&lt;%= rno %&gt;.css&amp;quot; type=&amp;quot;text/css&amp;quot; /&gt;</p>\r
+       <p>この記述をchat.ejsファイルの&lt;head&gt;から&lt;/head&gt;の間に追加し、[ルーム番号].cssという名前のファイルを用意することで部屋ごとにデザインを変えることができます</p>\r
+       <h2>プロファイルへのリンク方法</h2>\r
+       <p>chatclient.jsの$profile_linkをプロファイルの設定に合わせてください。(%nはurlencodeされた名前を表します)</p>\r
+       <p>例:$profile_link=http://localhost/profile.cgi?name=%n</p>\r
+       <h2>コマンドの追加方法</h2>\r
+       <p>WebChatでは必要に応じて外部コマンドを追加することができます。追加する場合はchat.ejsのcommandparser.jsを呼び出している行よりも後に追加してください。そうでない場合、正常に動作しないことがあります</p>\r
+       <h2>トラブルシューティング</h2>\r
+       <h3>500 Redis connection to [サイト名] failed - connect ECONNREFUSEDと表示される</h3>\r
+       <p>Redisサーバーが起動していない。もしくは$redisHost,$redisPort,$redisPasswordの設定が間違っていることが考えられます</h3>\r
+       <h3>\r
+       <h2>不具合報告</h2>\r
+       <p>不具合報告は<a href="http://sourceforge.jp/projects/webchat/">このサイト</a>にあるフォーラムもしくはチケットからお願いします</p>\r
+       <h2>著作権</h2>\r
+       <dl>\r
+               <dt>BellG@11.wav、BellG@11.mp3</dt>\r
+               <dd><a href="http://wwl.s-t-t.com/">WEB WAVE LIB</a>様</dd>\r
+       </dl>\r
+       <h2>ライセンス</h2>\r
+       <p>著作権で定義されたものを除き、すべてのファイルはBSDライセンスにより提供されるものとします</p>\r
+</div>\r
+<div id="footer">\r
+       <div id="copyright">Copyright (C) FooProject All Rights Reserved.</div>\r
+</div>\r
+<body>\r
+</body>\r
+</html>\r
diff --git a/readme.txt b/readme.txt
deleted file mode 100644 (file)
index 4c5c52a..0000000
Binary files a/readme.txt and /dev/null differ
diff --git a/security.js b/security.js
new file mode 100644 (file)
index 0000000..5e8ba8a
--- /dev/null
@@ -0,0 +1,15 @@
+var $token_length = 32;     //トークンの長さ\r
+\r
+module.exports.SessionInfomation = function(admin){\r
+       this.token = GetToken($token_length);\r
+       this.admin = admin;\r
+};\r
+\r
+function GetToken(length){\r
+       var RandomString = "";\r
+       var BaseString ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";\r
+       for(var i=0; i < length; i++) {\r
+               RandomString += BaseString.charAt( Math.floor( Math.random() * BaseString.length));\r
+       }\r
+       return RandomString;\r
+};\r