*/\r
$max_room_number = 3; //最大ルーム数\r
$spilt_size = 1024 * 512; //分割するサイズ\r
-$reset_password_diff = 1000 * 60 * 60;\r
+$reset_password_diff = 1000 * 60 * 60; //ルームパスワードをリセットする間隔\r
+$gc_time_interval = 1000 * 60 * 60; //ゴミ掃除を行う間隔\r
$block_message = "メッセージの送信に失敗しました"; //ブロック時のメッセージ\r
$not_match_password = "パスワードが一致しませんでした"; //パスワードが一致しない場合に表示されるメッセージ\r
$password_setted_message = "パスワードを設定しました"; //パスワードが設定されたときに表示されるメッセージ\r
$password_resetted_message = "パスワードをリセットしました"; //パスワードが再設定されたときに表示されるメッセージ\r
$failed_set_password_message = "パスワードの設定に失敗しました"; //パスワードが再設定されたときに表示されるメッセージ\r
-$free_password1 = "最初に入室する人が自由にパスワードを設定できます"; //自由パスワードメッセージ1\r
-$free_password2 = "この部屋は使用されています。パスワードを入力してください"; //自由パスワードメッセージ2\r
-$fixed_password = "この部屋にはパスワードが設定されています"; //固定パスワードルーム\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
$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
-$logfile_pattern = "logfile[0-9]+(_*.*)?\.txt" //過去ログと判定する正規表現\r
-//パスワードを自由に設定できる部屋のリスト\r
-// rno 設定したい部屋番号\r
-// password パスワードを設定する。nullにすると利用者がパスワードの設定をすることができる\r
-//記述例:\r
-// new RoomInfomationCollection(\r
-// {rno:"1",password:"test"},\r
-// {rno:"2",password:null}\r
-// )\r
-$rooms = new RoomInfomationCollection(\r
- {rno:"1",password:"test"},\r
- {rno:"2",password:null}\r
-);\r
-\r
+$secret = "5514EA2B-C9B2-4D65-8D81-1F33A180A0C2";\r
/**\r
* Module dependencies.\r
*/\r
\r
// Server\r
-var express = require('express');\r
+var express = require("express");\r
+\r
+var app = express();\r
\r
-var app = module.exports = express.createServer();\r
+var http = require("http");\r
\r
var util = require("util");\r
\r
-var lazy = require("lazy");\r
+var lazy = require("./lazy.js");\r
\r
var fs = require("fs");\r
\r
-var parseCookie = require("connect").utils.parseCookie;\r
+var cookie = require("express/node_modules/cookie");\r
+\r
+var connectUtils = require("express/node_modules/connect/lib/utils");\r
\r
var RedisStore = require("connect-redis")(express);\r
var sessionStore = new RedisStore({host:$redisHost,port:$redisPort,pass:$redisPassword});\r
app.set("view engine", "ejs");\r
app.use(express.bodyParser());\r
app.use(express.methodOverride());\r
- app.use(express.cookieParser());\r
+ app.use(express.cookieParser($secret));\r
app.use(express.session({\r
store:sessionStore,\r
- secret: "5514EA2B-C9B2-4D65-8D81-1F33A180A0C2",\r
cookie: { httpOnly: false }\r
}));\r
app.use(app.router);\r
app.use(express.errorHandler()); \r
});\r
\r
+function SessionInfomation(token,admin)\r
+{\r
+ this.token = token;\r
+ this.admin = admin;\r
+}\r
+\r
// Routes\r
app.get("/chat", function(req, res){\r
var auth_string = getRandomString($token_length);\r
- req.session.items = {token:auth_string};\r
+ req.session.items = new SessionInfomation(auth_string,false);\r
\r
var room_number = 0;\r
if(typeof(req.query.rno) != "undefined")\r
room_number = req.query.rno;\r
- var msg = "";\r
- if($rooms.IsFixedPassword(room_number))\r
- msg = $fixed_password;\r
- else if($rooms.IsContains(room_number))\r
- msg = $free_password2;\r
- if($rooms.IsFirstAuth(room_number))\r
- msg = $free_password1;\r
- res.render("chat",{rno:room_number,token:auth_string,message:msg});\r
+ res.render("chat",{rno:room_number,token:auth_string});\r
});\r
\r
-app.all("/log/" + $logfile_pattern,express.basicAuth(function (user, pass) {\r
+app.all("/log/*",express.basicAuth(function (user, pass) {\r
return user === $username && pass === $password;\r
}));\r
\r
-app.get("/log/" + $logfile_pattern, function(req, res){\r
+app.get("/log/*",function (req, res) {\r
res.sendfile(__dirname + req.url);\r
});\r
\r
+app.all("/admin_chat",express.basicAuth(function (user, pass) {\r
+ return user === $username && pass === $password;\r
+}));\r
+\r
+app.get("/admin_chat", function(req, res){\r
+ var auth_string = getRandomString($token_length);\r
+ req.session.items = new SessionInfomation(auth_string,true);\r
+\r
+ var room_number = 0;\r
+ if(typeof(req.query.rno) != "undefined")\r
+ room_number = req.query.rno;\r
+ res.render("chat",{rno:room_number,token:auth_string});\r
+});\r
+\r
app.all("/admin",express.basicAuth(function (user, pass) {\r
return user === $username && pass === $password;\r
}));\r
}\r
if(typeof(req.body.updateroom) != "undefined")\r
{\r
- CreateRoomsFromString(req.body.newroomlist);\r
- renderAdmin(req,res);\r
+ $rooms.Update(req.body.newroomlist,function(){\r
+ renderAdmin(req,res);\r
+ });\r
}\r
});\r
\r
});\r
}\r
\r
-app.listen($port);\r
-console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);\r
+var server = http.createServer(app).listen($port);\r
\r
/*\r
* サーバー部分\r
*/\r
\r
-var io = require("socket.io").listen(app);\r
+var io = require("socket.io").listen(server);\r
io.configure('production', function(){\r
io.enable('browser client minification'); // minified されたクライアントファイルを送信する\r
io.enable('browser client etag'); // バージョンによって etag によるキャッシングを有効にする\r
var clients = new Array();\r
\r
var ipbanlist = new IpBanCollecion();\r
+var $rooms = new RoomInfomationCollection();\r
\r
createLogDirectory();\r
\r
.of(GetNameFromRoomNumber(i))\r
.authorization(ParseAuthorization)\r
.on("connection", function (socket) {\r
- console.log("connected from %s",GetClientIPAdress(socket));\r
- socket.json.emit("send roomlist",$rooms.GetKeys());\r
+ var ip = GetClientIPAdress(socket);\r
+\r
+ console.log("connected from %s",ip);\r
+\r
+ var rno = GetRoomNumberFromName(socket.namespace.name);\r
+ var roomconfig = {};\r
+ $rooms.Get(rno).AddRom(ip);\r
+ if($rooms.Get(rno).IsVolatile() == false)\r
+ {\r
+ if($rooms.Get(rno).IsFixedPassword())\r
+ roomconfig.type = 2;\r
+ else if($rooms.Get(rno).IsHiddenLogFromRom())\r
+ roomconfig.type = 3;\r
+ else\r
+ roomconfig.type = 1;\r
+ roomconfig.IsOwned = !$rooms.Get(rno).IsFirstAuth();\r
+ }else{\r
+ roomconfig.type = 0;\r
+ }\r
+ roomconfig.admin = socket.handshake.admin;\r
+ socket.json.emit("send roominfo",roomconfig);\r
+\r
+ var romcount = $rooms.Get(rno).GetRomCount();\r
+ socket.json.emit("send romcount",romcount);\r
+ socket.json.broadcast.emit("send romcount",romcount);\r
+\r
socket.on("get pastLogList", function (msg) {\r
ParseGetPastLogList(socket,msg);\r
});\r
\r
function createLogDirectory()\r
{\r
- path.exists($log_directory,function(exists){\r
+ fs.exists($log_directory,function(exists){\r
if(exists == false)\r
fs.mkdirSync($log_directory);\r
});\r
function ParseAuthorization(handshakeData, callback)\r
{\r
if(handshakeData.headers.cookie) {\r
- var cookie = handshakeData.headers.cookie;\r
- var sessionID = parseCookie(cookie)["connect.sid"];\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 (err || ipbanlist.IsBaned(handshakeData.address.address))\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
- sessionStore.destroy(sessionID);\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
\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
name:$system_name,\r
message:null,\r
};\r
- if($rooms.SetPassword(rno,msg.owner,msg.password))\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
}\r
\r
var rno = GetRoomNumberFromName(socket.namespace.name);\r
- if($rooms.IsContains(rno))\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.IsTimeout(rno) ||\r
- $rooms.IsFirstAuth(rno))\r
+ if($rooms.Get(rno).IsTimeout() ||\r
+ $rooms.Get(rno).IsFirstAuth())\r
{\r
- $rooms.Reset(rno,msg.name);\r
+ $rooms.Get(rno).Reset(msg.name);\r
ParseGetPastLog(socket,util.format($log_file_name,rno));\r
}\r
- else if($rooms.Auth(rno,msg.name,msg.password))\r
+ else if($rooms.Get(rno).Auth(msg.name,msg.password))\r
{\r
ParseGetPastLog(socket,util.format($log_file_name,rno));\r
}\r
name:$system_name,\r
message:$password_resetted_message,\r
};\r
- if($rooms.IsContains(rno))\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.IsOwner(rno,msg.name))\r
+ if($rooms.Get(rno).IsOwner(msg.name))\r
{\r
- $rooms.Reset(rno,null);\r
+ $rooms.Get(rno).Reset(null);\r
ParseSendMsg(socket,newMeg);\r
}\r
- if(!$rooms.IsFirstAuth(rno) &&\r
- !$rooms.IsAuthed(rno,msg.name))\r
+ if(!$rooms.Get(rno).IsFirstAuth() &&\r
+ !$rooms.Get(rno).IsAuthed(msg.name))\r
return;\r
else\r
- $rooms.RemoveAuth(rno,msg.name);\r
+ $rooms.Get(rno).RemoveAuth(msg.name);\r
}\r
\r
newMeg.message = util.format("/quitedby %s",msg.name);\r
var rno = GetRoomNumberFromName(socket.namespace.name);\r
\r
if(msg.name != $system_name && \r
- $rooms.IsContains(rno) &&\r
- !$rooms.IsAuthed(rno,msg.name) &&\r
- !$rooms.IsOwner(rno,msg.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 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
return;\r
var path = $log_directory + "/" + file;\r
var log = new ChatLog(path);\r
- log.ToArray(function(array){\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(callback)\r
+ this.ToArray = function(hasIp,callback)\r
{\r
var state = fs.stat(path,function(err,state){\r
if(err)\r
var array = new Array();\r
var stream = fs.createReadStream(path);\r
new lazy(stream)\r
- .lines\r
+ .spilt(";")\r
.forEach(function(line){\r
- array.push(CreateMessageFromText(line.toString()));\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
msg.date + "<>" +\r
ip + "<>" +\r
msg.message +\r
- "\n";\r
+ ";";\r
return text;\r
}\r
\r
{\r
var result = {name:name,\r
date:date,\r
+ ip:"",\r
message:message};\r
return result;\r
}\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
function RoomInfomationCollection()\r
{\r
var collection = {};\r
- this.Clear = function(){\r
- collection = {};\r
- };\r
- this.Add = function(rno,pass){\r
- collection[rno] = {time : null,\r
- password : pass,\r
- owner : null,\r
- authed_list : {}};\r
- if(pass != null)\r
- collection[rno].owner = $system_name;\r
- };\r
- this.Reset = function(rno,owner){\r
- var date = new Date();\r
- var time = date.getTime();\r
- collection[rno].password = null;\r
- collection[rno].authed_list = {};\r
- collection[rno].owner = owner;\r
- collection[rno].time = time;\r
- console.log(util.format("password is reseted in %s",rno));\r
- };\r
+ this.Get = function(rno){\r
+ return collection[rno];\r
+ }\r
this.IsContains = function(rno){\r
return rno in collection;\r
};\r
- this.IsFirstAuth = function(rno){\r
- if(!this.IsContains(rno) || typeof(collection[rno].owner) == "undefined")\r
- return false;\r
- return collection[rno].owner == null;\r
- }\r
- this.IsAuthed = function(rno,name){\r
- if(!this.IsContains(rno))\r
- return false;\r
- return name == collection[rno].owner ||\r
- name in collection[rno].authed_list;\r
- };\r
- this.IsFixedPassword = function(rno){\r
- if(!this.IsContains(rno))\r
- return false;\r
- return collection[rno].owner == $system_name;\r
- };\r
- this.IsOwner = function(rno,name){\r
- return this.IsContains(rno) &&\r
- typeof(collection[rno].owner) != "undefined" &&\r
- collection[rno].owner == name;\r
- }\r
- this.IsTimeout = function(rno){\r
- var date = new Date();\r
- var time = date.getTime();\r
- return this.IsContains(rno) &&\r
- !this.IsFixedPassword(rno) &&\r
- (typeof(collection[rno].time) != "undefined" &&\r
- time - collection[rno].time >= $reset_password_diff);\r
- };\r
- this.RemoveAuth = function(rno,name)\r
- {\r
- delete collection[rno].authed_list[name];\r
- }\r
- this.Auth = function(rno,name,password){\r
- if(typeof(collection[rno].password) != "undefined" &&\r
- collection[rno].password != password)\r
- return false;\r
- var date = new Date();\r
- var time = date.getTime();\r
- collection[rno].time = time;\r
- collection[rno].authed_list[name] = "";\r
- return true;\r
- }\r
- this.SetPassword = function(rno,owner,password){\r
- if(this.IsContains(rno) && \r
- owner == collection[rno].owner &&\r
- !this.IsFixedPassword(rno))\r
- {\r
- var date = new Date();\r
- collection[rno].time = date.getTime();\r
- collection[rno].password = password;\r
- \r
- console.log(util.format("password is seted to %s in %s",password,rno));\r
- return true;\r
- }\r
- return false;\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
- retval += rno + ":" + pass + "\r\n";\r
+ var hiddenlog = collection[rno].hiddenlog;\r
+ retval += rno + ":" + pass + ":" + hiddenlog + "\r\n";\r
}\r
return retval;\r
};\r
}\r
return retval;\r
}\r
-\r
- for(var i=0; i<arguments.length; i++)\r
- {\r
- this.Add(arguments[i].rno,arguments[i].password);\r
- } \r
+ this.Update = function(text,callfunc){\r
+ async.waterfall([\r
+ function(callback){\r
+ fs.open($room_configure_file_name,"w",callback);\r
+ },\r
+ function(fd,callback){\r
+ var buf = new Buffer(text);\r
+ fs.write(fd,buf,0,Buffer.byteLength(text),null,function(){\r
+ callback(null,fd);\r
+ });\r
+ },\r
+ function(fd,callback){\r
+ fs.close(fd,function(){\r
+ GetRoomList(callfunc);\r
+ });\r
+ }\r
+ ]);\r
+ }\r
+ function GetRoomList(callback){\r
+ Clear();\r
+ fs.exists($room_configure_file_name,function(exists){\r
+ if(exists == false)\r
+ {\r
+ if(typeof(callback) == "function")\r
+ callback();\r
+ return;\r
+ }\r
+ var stream = fs.createReadStream($room_configure_file_name);\r
+ new lazy(stream)\r
+ .lines\r
+ .forEach(function(line){\r
+ var token = line.toString().replace(/(\r|\n|\r\n)/gm, "").split(":");\r
+ if(token.length == 1)\r
+ {\r
+ Add(token[0],null,false);\r
+ }\r
+ else if(token.length == 2)\r
+ {\r
+ var rno = token[0];\r
+ var pass = token[1];\r
+ if(pass == "")\r
+ pass = null;\r
+ Add(rno, pass,false);\r
+ }\r
+ else if(token.length == 3)\r
+ {\r
+ var rno = token[0];\r
+ var pass = token[1];\r
+ if(pass == "")\r
+ pass = null;\r
+ var hiddenlog = false;\r
+ if(token[2] == "true")\r
+ hiddenlog = true;\r
+ Add(rno, pass,hiddenlog);\r
+ }\r
+ })\r
+ .join(function(){\r
+ if(typeof(callback) == "function")\r
+ callback();\r
+ });\r
+ });\r
+ }\r
+ function Clear(){\r
+ collection = {};\r
+ for(var i = 0; i < $max_room_number; i++)\r
+ Add(i,null,null);\r
+ };\r
+ function Add(rno,pass,hiddenlogflag){\r
+ collection[rno] = new RoomInfomation(pass,hiddenlogflag);\r
+ if(pass != null)\r
+ collection[rno].owner = $system_name;\r
+ };\r
+ var $gc_interval_id = setInterval(function(){\r
+ for(var rno in this.rom_list)\r
+ collection[rno].GCRomList();\r
+ },$gc_time_interval);\r
+ GetRoomList();\r
}\r
\r
-function CreateRoomsFromString(str)\r
+//RoomInfomationクラス\r
+function RoomInfomation(pass,hiddenlogflag)\r
{\r
- $rooms.Clear();\r
- var lines = str.split("\r\n");\r
- for(var i in lines)\r
+ this.password = pass;\r
+ this.rom_list = {};\r
+ this.authed_list = {};\r
+ this.owner = null;\r
+ this.time = null;\r
+ this.hiddenlog = hiddenlogflag;\r
+ this.IsVolatile = function(){\r
+ return this.owner == null &&\r
+ this.password == null &&\r
+ this.time == null &&\r
+ this.hiddenlog == null;\r
+ }\r
+ this.GetRomCount = function(){\r
+ var count = 0;\r
+ for(var key in this.rom_list)\r
+ count++;\r
+ return count;\r
+ };\r
+ this.AddRom = function(ip){\r
+ var date = new Date();\r
+ this.rom_list[ip] = {time:date.getTime()};\r
+ };\r
+ this.RemoveRom = function(ip){\r
+ delete this.rom_list[ip];\r
+ };\r
+ this.Reset = function(owner){\r
+ var date = new Date();\r
+ var time = date.getTime();\r
+ this.password = null;\r
+ this.authed_list = {};\r
+ this.owner = owner;\r
+ this.time = time;\r
+ };\r
+ this.IsFirstAuth = function(){\r
+ return this.owner == null;\r
+ };\r
+ this.IsAuthed = function(name){\r
+ return name == this.owner ||\r
+ name in this.authed_list;\r
+ };\r
+ this.IsHiddenLogFromRom = function(){\r
+ return this.hiddenlog;\r
+ };\r
+ this.IsFixedPassword = function(){\r
+ return this.owner == $system_name;\r
+ };\r
+ this.IsOwner = function(name){\r
+ return this.owner == name;\r
+ };\r
+ this.IsTimeout = function(){\r
+ var date = new Date();\r
+ var current_time = date.getTime();\r
+ return !this.IsFixedPassword() &&\r
+ current_time - this.time >= $reset_password_diff;\r
+ };\r
+ this.RemoveAuth = function(name)\r
{\r
- var token = lines[i].split(":");\r
- if(token.length == 1)\r
+ delete this.authed_list[name];\r
+ };\r
+ this.Auth = function(name,password){\r
+ if(this.password != password)\r
+ return false;\r
+ var date = new Date();\r
+ var time = date.getTime();\r
+ this.time = time;\r
+ this.authed_list[name] = "";\r
+ return true;\r
+ };\r
+ this.SetPassword = function(owner,password){\r
+ if(owner == this.owner &&\r
+ !this.IsFixedPassword() &&\r
+ !this.IsHiddenLogFromRom())\r
{\r
- $rooms.Add(token[0],null);\r
+ var date = new Date();\r
+ this.time = date.getTime();\r
+ this.password = password;\r
+ return true;\r
}\r
- else if(token.length == 2)\r
+ return false;\r
+ };\r
+ this.GCRomList = function(){\r
+ var date = new Date();\r
+ var current_time = date.getTime();\r
+ for(var ip in this.rom_list)\r
{\r
- var rno = token[0];\r
- var pass = token[1];\r
- if(pass == "")\r
- pass = null;\r
- $rooms.Add(rno, pass);\r
+ if(current_time - this.rom_list[ip].time >= $gc_time_interval)\r
+ delete this.rom_list[ip];\r
}\r
- }\r
+ };\r
}\r
\r
//IPBANクラス\r
function GetIpBanList(callback)\r
{\r
collection = {};\r
- path.exists($ip_ban_list_file_name,function(exists){\r
+ fs.exists($ip_ban_list_file_name,function(exists){\r
if(exists == false)\r
{\r
if(typeof(callback) == "function")\r