OSDN Git Service

部屋の設定を接続時に送るようにした
[webchat/WebChat.git] / chatServer.js
1 /*\r
2  * 設定\r
3  */\r
4 $max_room_number = 3;   //最大ルーム数\r
5 $spilt_size = 1024 * 512;       //分割するサイズ\r
6 $reset_password_diff = 1000 * 60 * 60;\r
7 $block_message = "メッセージの送信に失敗しました";       //ブロック時のメッセージ\r
8 $not_match_password = "パスワードが一致しませんでした";  //パスワードが一致しない場合に表示されるメッセージ\r
9 $password_setted_message = "パスワードを設定しました";      //パスワードが設定されたときに表示されるメッセージ\r
10 $password_resetted_message = "パスワードをリセットしました";      //パスワードが再設定されたときに表示されるメッセージ\r
11 $failed_set_password_message = "パスワードの設定に失敗しました"; //パスワードが再設定されたときに表示されるメッセージ\r
12 $free_password1 = "最初に入室する人が自由にパスワードを設定できます";   //自由パスワードメッセージ1\r
13 $free_password2 = "この部屋は使用されています。パスワードを入力してください";       //自由パスワードメッセージ2\r
14 $fixed_password = "この部屋にはパスワードが設定されています";       //固定パスワードルーム\r
15 $ip_ban_list_file_name = "ipbanlist.txt";       //アクセスを禁止するIPが記録されているファイル\r
16 $port = process.env.port || 3000;       //ポート\r
17 $username = "admin";    //管理者用のページにアクセスできるユーザ名\r
18 $password = "admin";    //管理者用のページにアクセスするのに必要なパスワード\r
19 $token_length = 32;     //トークンの長さ\r
20 $redisHost = "localhost";       //redisサーバのアドレス\r
21 $redisPort = 6379;      //redisサーバのポート\r
22 $redisPassword = "";    //redisサーバのパスワード\r
23 $system_name = "system";        //システム発言を表す名前\r
24 $log_directory = "log"; //ログファイルを置くフォルダー\r
25 $log_file_name = "logfile%d.txt";       //ログファイル名(%dはそのままにしておくこと)\r
26 $splited_log_file_name = "logfile%d_%s.txt"     //分割後のファイル名(%dと%sはそのままにしておくこと)\r
27 $pastlogfile_pattern = "logfile%d(_+.*)?\.txt"; //過去ログと判定する正規表現\r
28 $logfile_pattern = "logfile[0-9]+(_*.*)?\.txt"  //過去ログと判定する正規表現\r
29 //パスワードを自由に設定できる部屋のリスト\r
30 //      rno     設定したい部屋番号\r
31 //      password        パスワードを設定する。nullにすると利用者がパスワードの設定をすることができる\r
32 //記述例:\r
33 //      new RoomInfomationCollection(\r
34 //              {rno:"1",password:"test"},\r
35 //              {rno:"2",password:null}\r
36 //      )\r
37 $rooms = new RoomInfomationCollection(\r
38         {rno:"1",password:"test"},\r
39         {rno:"2",password:null}\r
40 );\r
41 \r
42 /**\r
43  * Module dependencies.\r
44  */\r
45 \r
46 // Server\r
47 var express = require('express');\r
48 \r
49 var app = module.exports = express.createServer();\r
50 \r
51 var util = require("util");\r
52 \r
53 var lazy = require("lazy");\r
54 \r
55 var fs = require("fs");\r
56 \r
57 var parseCookie = require("connect").utils.parseCookie;\r
58 \r
59 var RedisStore = require("connect-redis")(express);\r
60 var sessionStore = new RedisStore({host:$redisHost,port:$redisPort,pass:$redisPassword});\r
61 \r
62 var async = require("async");\r
63 \r
64 var path = require("path");\r
65 \r
66 // Configuration\r
67 \r
68 app.configure(function(){\r
69         app.disabled("view cache");\r
70         app.set("view options", { layout: false })\r
71         app.set("views", __dirname + "/public");\r
72         app.set("view engine", "ejs");\r
73         app.use(express.bodyParser());\r
74         app.use(express.methodOverride());\r
75         app.use(express.cookieParser());\r
76         app.use(express.session({\r
77                 store:sessionStore,\r
78                 secret: "5514EA2B-C9B2-4D65-8D81-1F33A180A0C2",\r
79                 cookie: { httpOnly: false }\r
80         }));\r
81         app.use(app.router);\r
82         app.use(express.static(__dirname + "/public"));\r
83 });\r
84 \r
85 app.configure('development', function(){\r
86   app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); \r
87 });\r
88 \r
89 app.configure('production', function(){\r
90   app.use(express.errorHandler()); \r
91 });\r
92 \r
93 // Routes\r
94 app.get("/chat", function(req, res){\r
95         var auth_string = getRandomString($token_length);\r
96         req.session.items = {token:auth_string};\r
97 \r
98         var room_number = 0;\r
99         if(typeof(req.query.rno) != "undefined")\r
100                 room_number = req.query.rno;\r
101         var msg = "";\r
102         if($rooms.IsFixedPassword(room_number))\r
103                 msg = $fixed_password;\r
104         else if($rooms.IsContains(room_number))\r
105                 msg = $free_password2;\r
106         if($rooms.IsFirstAuth(room_number))\r
107                 msg = $free_password1;\r
108         res.render("chat",{rno:room_number,token:auth_string,message:msg});\r
109 });\r
110 \r
111 app.all("/log/" + $logfile_pattern,express.basicAuth(function (user, pass) {\r
112         return user === $username && pass === $password;\r
113 }));\r
114 \r
115 app.get("/log/" + $logfile_pattern, function(req, res){\r
116         res.sendfile(__dirname + req.url);\r
117 });\r
118 \r
119 app.all("/admin",express.basicAuth(function (user, pass) {\r
120         return user === $username && pass === $password;\r
121 }));\r
122 \r
123 app.get("/admin", function(req, res){\r
124         renderAdmin(req,res);\r
125 });\r
126 \r
127 app.post("/admin",function(req,res){\r
128         if(req.session.items.token != req.body.token)\r
129         {\r
130                 res.send($invaild_token_message);\r
131                 return;\r
132         }\r
133         if(typeof(req.body.erase) != "undefined")\r
134         {\r
135                 removeLog(req.body.file,function(){\r
136                         renderAdmin(req,res);\r
137                 });\r
138         }\r
139         if(typeof(req.body.registor) != "undefined")\r
140         {\r
141                 updateIpBanList(req.body.newbanlist,function(){\r
142                         renderAdmin(req,res);\r
143                 });\r
144         }\r
145         if(typeof(req.body.updateroom) != "undefined")\r
146         {\r
147                 CreateRoomsFromString(req.body.newroomlist);\r
148                 renderAdmin(req,res);\r
149         }\r
150 });\r
151 \r
152 function renderAdmin(req,res)\r
153 {\r
154         var auth_string = getRandomString($token_length);\r
155         req.session.items = {token:auth_string};\r
156 \r
157         fs.readdir($log_directory,function(err,list){\r
158                 res.render("admin", {\r
159                         files: list,\r
160                         log_directory:$log_directory,\r
161                         ipbanlist:getTextFromIpBanlist(ipbanlist),\r
162                         token:auth_string,\r
163                         roomlist:$rooms.GetString()\r
164                 });\r
165         });\r
166 }\r
167 \r
168 function getRandomString(length)\r
169 {\r
170         var RandomString = "";\r
171         var BaseString ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&'()=~|-^\@[;:],./\`{+*}<>?_";\r
172         for(var i=0; i<length; i++) {\r
173                 RandomString += BaseString.charAt( Math.floor( Math.random() * BaseString.length));\r
174         }\r
175         return RandomString\r
176 }\r
177 \r
178 function removeLog(files,callback)\r
179 {\r
180         async.map(files,\r
181         function(item,callback){\r
182                 fs.unlink($log_directory + "/" + item,callback);\r
183         },\r
184         function(err,results){\r
185                 if(typeof(callback) == "function")\r
186                         callback();\r
187         });\r
188 }\r
189 \r
190 function getTextFromIpBanlist(list)\r
191 {\r
192         var text = "";\r
193         for(var key in ipbanlist)\r
194         {\r
195                 if(ipbanlist[key] == "")\r
196                         text += key + "\r\n";\r
197                 else\r
198                         text += key + ":" + ipbanlist[key] + "\r\n";\r
199         }\r
200         return text;\r
201 }\r
202 \r
203 function updateIpBanList(text,callfunc)\r
204 {\r
205         async.waterfall([\r
206                 function(callback){\r
207                         fs.open($ip_ban_list_file_name,"w",callback);\r
208                 },\r
209                 function(fd,callback){\r
210                         var buf = new Buffer(text);\r
211                         fs.write(fd,buf,0,Buffer.byteLength(text),null,function(){\r
212                                 callback(null,fd);\r
213                         });\r
214                 },\r
215                 function(fd,callback){\r
216                         fs.close(fd,function(){\r
217                                 getIpBanList(callfunc);\r
218                         });\r
219                 }\r
220         ]);\r
221 }\r
222 \r
223 app.listen($port);\r
224 console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);\r
225 \r
226 /*\r
227  * サーバー部分\r
228  */\r
229 \r
230 var io = require("socket.io").listen(app);\r
231 io.configure('production', function(){\r
232   io.enable('browser client minification');  // minified されたクライアントファイルを送信する\r
233   io.enable('browser client etag');          // バージョンによって etag によるキャッシングを有効にする\r
234   io.set('log level', 1);                    // ログレベルを設定(デフォルトより下げている)\r
235 });\r
236 var clients = new Array();\r
237 \r
238 var ipbanlist = {};\r
239 \r
240 createLogDirectory();\r
241 \r
242 getIpBanList();\r
243 \r
244 for(var i = 0; i < $max_room_number; i++)\r
245 {\r
246         clients[i] =io\r
247         .of(GetNameFromRoomNumber(i))\r
248         .authorization(ParseAuthorization)\r
249         .on("connection", function (socket) {\r
250                 console.log("connected from %s",GetClientIPAdress(socket));\r
251                 socket.json.emit("send roomlist",$rooms.GetKeys());\r
252                 socket.on("get pastLogList", function (msg) {\r
253                         ParseGetPastLogList(socket,msg);\r
254                 });\r
255                 socket.on("get pastLog", function (msg) {\r
256                         ParseGetPastLog(socket,msg);\r
257                 });\r
258                 socket.on("join",function(msg){\r
259                         ParseJoin(socket,msg);\r
260                 });\r
261                 socket.on("quit",function(msg){\r
262                         ParseQuit(socket,msg);\r
263                 });\r
264                 socket.on("set password",function(msg){\r
265                         ParseSetPassword(socket,msg);\r
266                 });\r
267                 socket.on("send msg", function (msg) {\r
268                         ParseSendMsg(socket,msg);\r
269                 });\r
270                 socket.on("disconnect", function (msg) {\r
271                         ParseDisconnect(socket,msg);\r
272                 });\r
273         });\r
274 }\r
275 \r
276 function createLogDirectory()\r
277 {\r
278         path.exists($log_directory,function(exists){\r
279                 if(exists == false)\r
280                         fs.mkdirSync($log_directory);\r
281         });\r
282 }\r
283 \r
284 function getIpBanList(callback)\r
285 {\r
286         ipbanlist = {};\r
287         path.exists($ip_ban_list_file_name,function(exists){\r
288                 if(exists == false)\r
289                 {\r
290                         if(typeof(callback) == "function")\r
291                                 callback();\r
292                         return;\r
293                 }\r
294                 var stream = fs.createReadStream($ip_ban_list_file_name);\r
295                 new lazy(stream)\r
296                         .lines\r
297                         .forEach(function(line){\r
298                                 var token = line.toString().split(":");\r
299                                 var ip = token[0].replace(/(\r|\n|\r\n)/gm, "");\r
300                                 if(token.length == 1)\r
301                                         ipbanlist[ip] = "";\r
302                                 else\r
303                                         ipbanlist[ip] = token[1];\r
304                         })\r
305                         .join(function(){\r
306                                 if(typeof(callback) == "function")\r
307                                         callback();\r
308                         });\r
309         });\r
310 }\r
311 \r
312 function ParseAuthorization(handshakeData, callback)\r
313 {\r
314         if(handshakeData.headers.cookie) {\r
315                 var cookie = handshakeData.headers.cookie;\r
316                 var sessionID = parseCookie(cookie)["connect.sid"];\r
317                 sessionStore.get(sessionID, function (err, session) {\r
318                         var result = null;\r
319                         if (err || ipbanlist[handshakeData.address.address] == "r")\r
320                                 result = "failed get from session store";\r
321                         else if(handshakeData.query.token != session.items.token)\r
322                                 result = "invaild token";\r
323                         sessionStore.destroy(sessionID);\r
324                         callback(result,result == null && !err);\r
325                 });\r
326         } else {\r
327                 return callback("failed get cookie", false);\r
328         }\r
329 }\r
330 \r
331 function ParseDisconnect(socket,msg)\r
332 {\r
333         console.log("disconnected");\r
334 }\r
335 \r
336 function ParseSetPassword(socket,msg)\r
337 {\r
338         var rno = GetRoomNumberFromName(socket.namespace.name);\r
339         var newMeg = {\r
340                 name:$system_name,\r
341                 message:null,\r
342         };\r
343         if($rooms.SetPassword(rno,msg.owner,msg.password))\r
344                 newMeg.message = $password_setted_message;\r
345         else\r
346                 newMeg.message = $failed_set_password_message;\r
347         ParseSendMsg(socket,newMeg);\r
348 }\r
349 \r
350 function ParseJoin(socket,msg)\r
351 {\r
352         var ip = GetClientIPAdress(socket);\r
353 \r
354         if(ip in ipbanlist)\r
355         {\r
356                 socket.emit("error",$block_message);\r
357                 return;\r
358         }\r
359 \r
360         var rno = GetRoomNumberFromName(socket.namespace.name);\r
361         if($rooms.IsContains(rno))\r
362         {\r
363                 if($rooms.IsTimeout(rno) ||\r
364                         $rooms.IsFirstAuth(rno))\r
365                 {\r
366                         $rooms.Reset(rno,msg.name);\r
367                         ParseGetPastLog(socket,util.format($log_file_name,rno));\r
368                 }\r
369                 else if($rooms.Auth(rno,msg.name,msg.password))\r
370                 {\r
371                         ParseGetPastLog(socket,util.format($log_file_name,rno));\r
372                 }\r
373                 else\r
374                 {\r
375                         socket.emit("error",$not_match_password);\r
376                         return;\r
377                 }\r
378         }\r
379 \r
380         var newMeg = {\r
381                 name:$system_name,\r
382                 message:util.format("/enteredby %s %s %s",msg.name,msg.color,msg.mailto),\r
383         };\r
384         ParseSendMsg(socket,newMeg);\r
385 }\r
386 \r
387 function ParseQuit(socket,msg)\r
388 {\r
389         var ip = GetClientIPAdress(socket);\r
390 \r
391         if(ip in ipbanlist)\r
392         {\r
393                 socket.emit("error",$block_message);\r
394                 return;\r
395         }\r
396 \r
397         var rno = GetRoomNumberFromName(socket.namespace.name);\r
398 \r
399         var newMeg = {\r
400                 name:$system_name,\r
401                 message:$password_resetted_message,\r
402         };\r
403         if($rooms.IsContains(rno))\r
404         {\r
405                 if($rooms.IsOwner(rno,msg.name))\r
406                 {\r
407                         $rooms.Reset(rno,null);\r
408                         ParseSendMsg(socket,newMeg);\r
409                 }\r
410                 if(!$rooms.IsFirstAuth(rno) &&\r
411                         !$rooms.IsAuthed(rno,msg.name))\r
412                         return;\r
413                 else\r
414                         $rooms.RemoveAuth(rno,msg.name);\r
415         }\r
416 \r
417         newMeg.message = util.format("/quitedby %s",msg.name);\r
418         ParseSendMsg(socket,newMeg);\r
419 }\r
420 \r
421 //socket 接続中のソケット\r
422 //msg msgクラス\r
423 function ParseSendMsg(socket,msg)\r
424 {\r
425         var ip = GetClientIPAdress(socket);\r
426 \r
427         if(ip in ipbanlist)\r
428         {\r
429                 socket.emit("error",$block_message);\r
430                 return;\r
431         }\r
432 \r
433         var rno = GetRoomNumberFromName(socket.namespace.name);\r
434 \r
435         if(msg.name != $system_name && \r
436                 $rooms.IsContains(rno) &&\r
437                 !$rooms.IsAuthed(rno,msg.name) &&\r
438                 !$rooms.IsOwner(rno,msg.name))\r
439         {\r
440                 return;\r
441         }\r
442 \r
443         var date = new Date();\r
444 \r
445         var repacked_msg = CreateMessage(msg.name,date,msg.message);\r
446 \r
447         socket.json.emit("req msg", repacked_msg);\r
448 \r
449         socket.json.broadcast.emit("req msg", repacked_msg);\r
450 \r
451         var path = $log_directory + "/" + util.format($log_file_name,rno);\r
452         var log = new ChatLog(path);\r
453         log.Save(repacked_msg,ip,rno);\r
454 }\r
455 \r
456 function GetNameFromRoomNumber(number)\r
457 {\r
458         return "/" + number;\r
459 }\r
460 \r
461 function GetRoomNumberFromName(name)\r
462 {\r
463         if(name.charAt(0) == "/")\r
464                 return parseInt(name.substr(1));\r
465         throw "GetRoomNumberFromName error";\r
466 }\r
467 \r
468 function ParseGetPastLogList(socket,msg)\r
469 {\r
470         var list = fs.readdir($log_directory,function(err,files){\r
471                 var text = "";\r
472                 var rno = GetRoomNumberFromName(socket.namespace.name);\r
473                 var pattern = $pastlogfile_pattern.replace("%d",rno);\r
474                 for(var i = 0; i < files.length; i++)\r
475                 {\r
476                         var logname = files[i];\r
477                         if(logname.match(pattern))\r
478                                 text += files[i] + "\n";\r
479                 }\r
480                 socket.emit("req pastloglist",text);\r
481         });\r
482 }\r
483 \r
484 function ParseGetPastLog(socket,file)\r
485 {\r
486         if(file == "")\r
487                 return;\r
488         var path = $log_directory + "/" + file;\r
489         var log = new ChatLog(path);\r
490         log.ToArray(function(array){\r
491                 socket.json.emit("req pastlog",array);\r
492         });\r
493 }\r
494 \r
495 function ChatLog(path)\r
496 {\r
497         this.ToArray = function(callback)\r
498         {\r
499                 var state = fs.stat(path,function(err,state){\r
500                         if(err)\r
501                                 return;\r
502                         var array = new Array();\r
503                         var stream = fs.createReadStream(path);\r
504                         new lazy(stream)\r
505                                 .lines\r
506                                 .forEach(function(line){\r
507                                         array.push(CreateMessageFromText(line.toString()));\r
508                                 })\r
509                                 .join(function(){\r
510                                         callback(array);\r
511                                 });\r
512                 });\r
513         }\r
514 \r
515         this.Save = function(msg,ip,rno){\r
516                 var text = GetTextFromMessage(msg,ip);\r
517 \r
518                 SplitLog(rno,function(){\r
519                         WritePastLog(path,text);\r
520                 });\r
521         };\r
522 \r
523         function GetTextFromMessage(msg,ip)\r
524         {\r
525                 var text = msg.name + "<>" +\r
526                                 msg.date + "<>" +\r
527                                 ip + "<>" +\r
528                                 msg.message +\r
529                                 "\n";\r
530                 return text;\r
531         }\r
532 \r
533         function SplitLog(rno,callback)\r
534         {\r
535                 var state = fs.stat(path,function(err,state){\r
536                         if(err && typeof(callback) == "function")\r
537                         {\r
538                                 callback();\r
539                                 return;\r
540                         }\r
541                         if(state.size > $spilt_size)\r
542                         {\r
543                                 var date = new Date();\r
544                                 var dateString = ""+date.getFullYear()+date.getMonth()+date.getDate()+date.getHours()+date.getMinutes()+date.getSeconds();\r
545 \r
546                                 var newpath = $log_directory + "/" +\r
547                                         util.format($splited_log_file_name,rno,dateString);\r
548                                 fs.rename(path,newpath,callback);\r
549                         }else{\r
550                                 if(typeof(callback) == "function")\r
551                                         callback();\r
552                         }\r
553                 });\r
554         }\r
555 \r
556         function WritePastLog(path,text)\r
557         {\r
558                 async.waterfall([\r
559                         function(callback){\r
560                                 fs.open(path,"a",callback);\r
561                         },\r
562                         function(fd,callback){\r
563                                 var buf = new Buffer(text);\r
564                                 fs.write(fd,buf,0,Buffer.byteLength(text),null,function(){\r
565                                         callback(null,fd);\r
566                                 });\r
567                         },\r
568                         function(fd){\r
569                                 fs.close(fd);\r
570                         }\r
571                 ]);\r
572         }\r
573 }\r
574 \r
575 function GetClientIPAdress(socket)\r
576 {\r
577         return socket.handshake.headers["x-forwarded-for"] || socket.handshake.address.address;\r
578 }\r
579 \r
580 // Message クラス\r
581 function CreateMessage(name,date,message)\r
582 {\r
583         var result = {name:name,\r
584                 date:date,\r
585                 message:message};\r
586         return result;\r
587 }\r
588 function CreateMessageFromText(text)\r
589 {\r
590         var data = text.split("<>");\r
591         var msg = {name:data[0],\r
592                 date:data[1],\r
593                 message:data[3]};\r
594         return msg;\r
595 }\r
596 \r
597 //RoomInfomationCollecionクラス\r
598 function RoomInfomationCollection()\r
599 {\r
600         var collection = {};\r
601         this.Clear = function(){\r
602                 collection = {};\r
603         };\r
604         this.Add = function(rno,pass){\r
605                 collection[rno] = {time : null,\r
606                         password : pass,\r
607                         owner : null,\r
608                         authed_list : {}};\r
609                 if(pass != null)\r
610                         collection[rno].owner = $system_name;\r
611         };\r
612         this.Reset = function(rno,owner){\r
613                 var date = new Date();\r
614                 var time = date.getTime();\r
615                 collection[rno].password = null;\r
616                 collection[rno].authed_list = {};\r
617                 collection[rno].owner = owner;\r
618                 collection[rno].time = time;\r
619                 console.log(util.format("password is reseted in %s",rno));\r
620         };\r
621         this.IsContains = function(rno){\r
622                 return rno in collection;\r
623         };\r
624         this.IsFirstAuth = function(rno){\r
625                 if(!this.IsContains(rno) || typeof(collection[rno].owner) == "undefined")\r
626                         return false;\r
627                 return collection[rno].owner == null;\r
628         }\r
629         this.IsAuthed = function(rno,name){\r
630                 if(!this.IsContains(rno))\r
631                         return false;\r
632                 console.log(util.inspect(collection[rno].authed_list));\r
633                 return name == collection[rno].owner ||\r
634                         name in collection[rno].authed_list;\r
635         };\r
636         this.IsFixedPassword = function(rno){\r
637                 if(!this.IsContains(rno))\r
638                         return false;\r
639                 return collection[rno].owner == $system_name;\r
640         };\r
641         this.IsOwner = function(rno,name){\r
642                 return this.IsContains(rno) &&\r
643                         typeof(collection[rno].owner) != "undefined" &&\r
644                         collection[rno].owner == name;\r
645         }\r
646         this.IsTimeout = function(rno){\r
647                 var date = new Date();\r
648                 var time = date.getTime();\r
649                 return this.IsContains(rno) &&\r
650                         !this.IsFixedPassword(rno) &&\r
651                         (typeof(collection[rno].time) != "undefined" &&\r
652                         time - collection[rno].time >= $reset_password_diff);\r
653         };\r
654         this.RemoveAuth = function(rno,name)\r
655         {\r
656                 delete collection[rno].authed_list[name];\r
657         }\r
658         this.Auth = function(rno,name,password){\r
659                 if(typeof(collection[rno].password) != "undefined" &&\r
660                         collection[rno].password != password)\r
661                         return false;\r
662                 var date = new Date();\r
663                 var time = date.getTime();\r
664                 collection[rno].time = time;\r
665                 collection[rno].authed_list[name] = "";\r
666                 return true;\r
667         }\r
668         this.SetPassword = function(rno,owner,password){\r
669                 if(this.IsContains(rno) && \r
670                         owner == collection[rno].owner &&\r
671                         !this.IsFixedPassword(rno))\r
672                 {\r
673                         var date = new Date();\r
674                         collection[rno].time = date.getTime();\r
675                         collection[rno].password = password;\r
676                         \r
677                         console.log(util.format("password is seted to %s in %s",password,rno));\r
678                         return true;\r
679                 }\r
680                 return false;\r
681         };\r
682         this.GetString = function(){\r
683                 var retval = "";\r
684                 for(var rno in collection)\r
685                 {\r
686                         var pass = collection[rno].password;\r
687                         if(pass == null)\r
688                                 pass = "";\r
689                         retval += rno + ":" + pass + "\r\n";\r
690                 }\r
691                 return retval;\r
692         };\r
693         this.GetKeys = function(){\r
694                 var retval = {};\r
695                 for(var rno in collection)\r
696                 {\r
697                         retval[rno] = {};\r
698                 }\r
699                 return retval;\r
700         }\r
701 \r
702         for(var i=0; i<arguments.length; i++)\r
703         {\r
704                 this.Add(arguments[i].rno,arguments[i].password);\r
705         }       \r
706 }\r
707 \r
708 function CreateRoomsFromString(str)\r
709 {\r
710         $rooms.Clear();\r
711         var lines = str.split("\r\n");\r
712         for(var i in lines)\r
713         {\r
714                 var token = lines[i].split(":");\r
715                 console.log(util.inspect(token));\r
716                 if(token.length == 1)\r
717                 {\r
718                         $rooms.Add(token[0],null);\r
719                 }\r
720                 else if(token.length == 2)\r
721                 {\r
722                         var rno = token[0];\r
723                         var pass = token[1];\r
724                         if(pass == "")\r
725                                 pass = null;\r
726                         $rooms.Add(rno, pass);\r
727                 }\r
728         }\r
729 }\r