invitation patch by Fedor Fetisov

This commit is contained in:
Evgeny Gryaznov 2011-04-07 10:34:04 +02:00
parent 5bba5ed824
commit 84f37eb14c
44 changed files with 1463 additions and 35 deletions

View File

@ -25,6 +25,7 @@ require_once('libs/operator.php');
require_once('libs/groups.php'); require_once('libs/groups.php');
require_once('libs/expand.php'); require_once('libs/expand.php');
require_once('libs/captcha.php'); require_once('libs/captcha.php');
require_once('libs/invitation.php');
loadsettings(); loadsettings();
if($settings['enablessl'] == "1" && $settings['forcessl'] == "1") { if($settings['enablessl'] == "1" && $settings['forcessl'] == "1") {
@ -115,6 +116,13 @@ if( !isset($_GET['token']) || !isset($_GET['thread']) ) {
$thread = create_thread($groupid,$visitor['name'], $remoteHost, $referrer,$current_locale,$visitor['id'], $userbrowser,$state_loading,$link); $thread = create_thread($groupid,$visitor['name'], $remoteHost, $referrer,$current_locale,$visitor['id'], $userbrowser,$state_loading,$link);
$_SESSION['threadid'] = $thread['threadid']; $_SESSION['threadid'] = $thread['threadid'];
$operator = invitation_accept($_SESSION['visitorid'], $thread['threadid'], $link);
if ($operator) {
$operator = operator_by_id_($operator, $link);
$operatorName = ($current_locale == $home_locale) ? $operator['vclocalename'] : $operator['vccommonname'];
post_message_($thread['threadid'], $kind_for_agent, getstring2('chat.visitor.invitation.accepted', array($operatorName)), $link);
}
if( $referrer ) { if( $referrer ) {
post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.came.from',array($referrer)),$link); post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.came.from',array($referrer)),$link);
} }

View File

@ -899,3 +899,17 @@ table.awaiting td.visitor {
float:left; float:left;
padding-left:10px; padding-left:10px;
} }
/* invitation wait */
.ajaxWait {
z-index: -1;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(images/ajax-loader.gif);
background-repeat: no-repeat;
background-position: center;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

View File

@ -109,7 +109,24 @@ $dbtables = array(
"locale" => "varchar(8)", "locale" => "varchar(8)",
"groupid" => "int references ${mysqlprefix}chatgroup(groupid)", "groupid" => "int references ${mysqlprefix}chatgroup(groupid)",
"vcvalue" => "varchar(1024) NOT NULL", "vcvalue" => "varchar(1024) NOT NULL",
) ),
"${mysqlprefix}chatsitevisitor" => array(
"visitorid" => "INT NOT NULL auto_increment PRIMARY KEY",
"userid" => "varchar(64) NOT NULL",
"username" => "varchar(255)",
"firsttime" => "datetime NOT NULL DEFAULT 0",
"lasttime" => "datetime NOT NULL DEFAULT 0",
"entry" => "text NOT NULL",
"path" => "text NOT NULL",
"details" => "text NOT NULL",
"invited" => "tinyint(1) NOT NULL DEFAULT 0",
"invitationtime" => "datetime",
"invitedby" => "INT references ${mysqlprefix}chatoperator(operatorid) on delete set null",
"invitations" => "INT NOT NULL DEFAULT 0",
"chats" => "INT NOT NULL DEFAULT 0",
"threadid" => "INT references ${mysqlprefix}chatthread(threadid) on delete set null"
),
); );
$memtables = array(); $memtables = array();
@ -122,6 +139,7 @@ $dbtables_can_update = array(
"${mysqlprefix}chatgroup" => array("vcemail"), "${mysqlprefix}chatgroup" => array("vcemail"),
"${mysqlprefix}chatgroupoperator" => array(), "${mysqlprefix}chatgroupoperator" => array(),
"${mysqlprefix}chatresponses" => array(), "${mysqlprefix}chatresponses" => array(),
"${mysqlprefix}chatsitevisitor" => array(),
); );
function show_install_err($text) function show_install_err($text)

View File

@ -158,6 +158,11 @@ if ($act == "silentcreateall") {
if ($res && mysql_num_rows($res) == 0) { if ($res && mysql_num_rows($res) == 0) {
runsql("ALTER TABLE ${mysqlprefix}chatmessage ADD INDEX idx_agentid (agentid)", $link); runsql("ALTER TABLE ${mysqlprefix}chatmessage ADD INDEX idx_agentid (agentid)", $link);
} }
$res = mysql_query("select null from information_schema.statistics where table_name = '${mysqlprefix}chatsitevisitor' and index_name = 'threadid'", $link);
if ($res && mysql_num_rows($res) == 0) {
runsql("ALTER TABLE ${mysqlprefix}chatsitevisitor ADD INDEX (threadid)", $link);
}
} }
} }

View File

@ -0,0 +1,65 @@
/*
This file is part of Mibew Messenger project.
Copyright (c) 2005-2011 Mibew Messenger Community
All rights reserved. The contents of this file are subject to the terms of
the Eclipse Public License v1.0 which accompanies this distribution, and
is available at http://www.eclipse.org/legal/epl-v10.html
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 or later (the "GPL"), in which case
the provisions of the GPL are applicable instead of those above. If you wish
to allow use of your version of this file only under the terms of the GPL, and
not to allow others to use your version of this file under the terms of the
EPL, indicate your decision by deleting the provisions above and replace them
with the notice and other provisions required by the GPL.
*/
#mibewinvitationpopup {
border: 1px solid #aaa;
background-color: #ddd;
padding: 5px;
position: fixed;
top: 50%;
left: 0;
width: 400px;
}
#mibewinvitationpopup h1, #mibewinvitationpopup p, #mibewinvitationclose a {
cursor: pointer;
}
#mibewinvitationclose {
float: right;
background-color: red;
padding: 1px;
margin: 0;
}
#mibewinvitationclose a {
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
font-size: 20px;
font-weight: bold;
color: white;
margin: 0 4px 0 4px;
}
#mibewinvitationclose a, #mibewinvitationclose a:link, #mibewinvitationclose a:hover {
text-decoration: none;
}
#mibewinvitationpopup h1 {
text-align: center;
}
#mibewinvitationpopup p {
padding: 2px;
margin: 2px;
}
#mibewinvitationavatar {
margin: 2px;
margin-right: 5px;
cursor: pointer;
float: left;
}

View File

@ -0,0 +1,68 @@
<?php
/*
* This file is part of Mibew Messenger project.
*
* Copyright (c) 2005-2011 Mibew Messenger Community
* All rights reserved. The contents of this file are subject to the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and
* is available at http://www.eclipse.org/legal/epl-v10.html
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which case
* the provisions of the GPL are applicable instead of those above. If you wish
* to allow use of your version of this file only under the terms of the GPL, and
* not to allow others to use your version of this file under the terms of the
* EPL, indicate your decision by deleting the provisions above and replace them
* with the notice and other provisions required by the GPL.
*
* Contributors:
* Fedor Fetisov - tracking and inviting implementation
*/
require_once('libs/common.php');
require_once('libs/invitation.php');
require_once('libs/operator.php');
require_once('libs/track.php');
loadsettings();
$invited = FALSE;
$operator = array();
if ($settings['enabletracking'] == '1') {
$entry = isset($_GET['entry']) ? $_GET['entry'] : "";
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : "";
$link = connect();
if (isset($_SESSION['visitorid']) && preg_match('/^[0-9]+$/', $_SESSION['visitorid'])) {
$invited = invitation_check($_SESSION['visitorid'], $link);
$visitorid = track_visitor($_SESSION['visitorid'], $entry, $referer, $link);
}
else {
$visitorid = track_visitor_start($entry, $referer, $link);
}
if ($visitorid) {
$_SESSION['visitorid'] = $visitorid;
}
if ($invited !== FALSE) {
$operator = operator_by_id_($invited, $link);
}
mysql_close($link);
}
start_xml_output();
if ($invited !== FALSE) {
$locale = isset($_GET['lang']) ? $_GET['lang'] : '';
$operatorName = ($locale == $home_locale) ? $operator['vclocalename'] : $operator['vccommonname'];
echo "<invitation><operator>" . htmlspecialchars($operatorName) . "</operator><message>" . getlocal("invitation.message") . "</message><avatar>" . htmlspecialchars($operator['vcavatar']) . "</avatar></invitation>";
}
else {
echo "<empty/>";
}
exit;
?>

View File

@ -15,7 +15,7 @@ update:function(){this.updateOptions("refresh");this.updater=new Ajax.Request(th
var b={}.extend(this._options);b.parameters+="&message="+encodeURIComponent(a);b.onComplete=function(a){this.requestComplete(a);if(this._options.message)this._options.message.value="",this._options.message.focus()}.bind(this);myRealAgent!="opera"&&this.enableInput(!1);this.updater=new Ajax.Request(this._options.servl,b)}},changeName:function(a){this.skipNextsound=!0;new Ajax.Request(this._options.servl,{parameters:"act=rename&thread="+(this._options.threadid||0)+"&token="+(this._options.token||0)+ var b={}.extend(this._options);b.parameters+="&message="+encodeURIComponent(a);b.onComplete=function(a){this.requestComplete(a);if(this._options.message)this._options.message.value="",this._options.message.focus()}.bind(this);myRealAgent!="opera"&&this.enableInput(!1);this.updater=new Ajax.Request(this._options.servl,b)}},changeName:function(a){this.skipNextsound=!0;new Ajax.Request(this._options.servl,{parameters:"act=rename&thread="+(this._options.threadid||0)+"&token="+(this._options.token||0)+
"&name="+encodeURIComponent(a)})},onThreadClosed:function(a){var b=Ajax.getXml(a);b&&b.tagName=="closed"?setTimeout("window.close()",2E3):this.handleError(a,b,"cannot close")},closeThread:function(){var a="act=close&thread="+(this._options.threadid||0)+"&token="+(this._options.token||0);this._options.user&&(a+="&user=true");new Ajax.Request(this._options.servl,{parameters:a,onComplete:this.onThreadClosed.bind(this)})},processMessage:function(a,b){var c=NodeUtils.getNodeText(b);FrameUtils.insertIntoFrame(a, "&name="+encodeURIComponent(a)})},onThreadClosed:function(a){var b=Ajax.getXml(a);b&&b.tagName=="closed"?setTimeout("window.close()",2E3):this.handleError(a,b,"cannot close")},closeThread:function(){var a="act=close&thread="+(this._options.threadid||0)+"&token="+(this._options.token||0);this._options.user&&(a+="&user=true");new Ajax.Request(this._options.servl,{parameters:a,onComplete:this.onThreadClosed.bind(this)})},processMessage:function(a,b){var c=NodeUtils.getNodeText(b);FrameUtils.insertIntoFrame(a,
c)},showTyping:function(a){if($("typingdiv"))$("typingdiv").style.display=a?"inline":"none"},setupAvatar:function(a){a=NodeUtils.getNodeText(a);if(this._options.avatar&&this._options.user)this._options.avatar.innerHTML=a!=""?'<img src="'+Chat.webimRoot+'/images/free.gif" width="7" height="1" border="0" alt="" /><img src="'+a+'" border="0" alt=""/>':""},updateContent:function(a){var b=!1,c=this._options.container,d=NodeUtils.getAttrValue(a,"lastid");if(d)this._options.lastid=d;(d=NodeUtils.getAttrValue(a, c)},showTyping:function(a){if($("typingdiv"))$("typingdiv").style.display=a?"inline":"none"},setupAvatar:function(a){a=NodeUtils.getNodeText(a);if(this._options.avatar&&this._options.user)this._options.avatar.innerHTML=a!=""?'<img src="'+Chat.webimRoot+'/images/free.gif" width="7" height="1" border="0" alt="" /><img src="'+a+'" border="0" alt=""/>':""},updateContent:function(a){var b=!1,c=this._options.container,d=NodeUtils.getAttrValue(a,"lastid");if(d)this._options.lastid=d;(d=NodeUtils.getAttrValue(a,
"typing"))&&this.showTyping(d=="1");if((d=NodeUtils.getAttrValue(a,"canpost"))&&(d=="1"&&!this.ownThread||this.ownThread&&d!="1"))window.location.href=window.location.href;for(d=0;d<a.childNodes.length;d++){var e=a.childNodes[d];e.tagName=="message"?(b=!0,this.processMessage(c,e)):e.tagName=="avatar"&&this.setupAvatar(e)}window.location.search.indexOf("trace=on")>=0?(a="updated",this.lastupdate>0&&(c=((new Date).getTime()-this.lastupdate)/1E3,a=a+", "+c+" secs",c>10&&alert(a)),this.lastupdate=(new Date).getTime(), "typing"))&&this.showTyping(d=="1");if((d=NodeUtils.getAttrValue(a,"canpost"))&&(d=="1"&&!this.ownThread||this.ownThread&&d!="1"))window.location.href=window.location.href;for(d=0;d<a.childNodes.length;d++){var f=a.childNodes[d];f.tagName=="message"?(b=!0,this.processMessage(c,f)):f.tagName=="avatar"&&this.setupAvatar(f)}window.location.search.indexOf("trace=on")>=0?(a="updated",this.lastupdate>0&&(c=((new Date).getTime()-this.lastupdate)/1E3,a=a+", "+c+" secs",c>10&&alert(a)),this.lastupdate=(new Date).getTime(),
this.setStatus(a)):this.clearStatus();b&&(FrameUtils.scrollDown(this._options.container),this.skipNextsound||(b=$("soundimg"),(b==null||b.className.match(/\bisound\b/))&&playSound(Chat.webimRoot+"/sounds/new_message.wav")),this.focused||window.focus())},isSendkey:function(a,b){return b==13&&(a||this._options.ignorectrl)||b==10},handleKeyDown:function(a){a?(ctrl=a.ctrlKey,a=a.which):(a=event.keyCode,ctrl=event.ctrlKey);if(this._options.message&&this.isSendkey(ctrl,a))return a=this._options.message.value, this.setStatus(a)):this.clearStatus();b&&(FrameUtils.scrollDown(this._options.container),this.skipNextsound||(b=$("soundimg"),(b==null||b.className.match(/\bisound\b/))&&playSound(Chat.webimRoot+"/sounds/new_message.wav")),this.focused||window.focus())},isSendkey:function(a,b){return b==13&&(a||this._options.ignorectrl)||b==10},handleKeyDown:function(a){a?(ctrl=a.ctrlKey,a=a.which):(a=event.keyCode,ctrl=event.ctrlKey);if(this._options.message&&this.isSendkey(ctrl,a))return a=this._options.message.value,
this._options.ignorectrl&&(a=a.replace(/[\r\n]+$/,"")),this.postMessage(a),!1;return!0},handleError:function(a,b){b&&b.tagName=="error"?this.setStatus(NodeUtils.getNodeValue(b,"descr")):this.setStatus("reconnecting")},showStatusDiv:function(a){if($("engineinfo"))$("engineinfo").style.display="inline",$("engineinfo").innerHTML=a},setStatus:function(a){this.statusTimeout&&clearTimeout(this.statusTimeout);this.showStatusDiv(a);this.statusTimeout=setTimeout(this.clearStatus.bind(this),4E3)},clearStatus:function(){$("engineinfo").style.display= this._options.ignorectrl&&(a=a.replace(/[\r\n]+$/,"")),this.postMessage(a),!1;return!0},handleError:function(a,b){b&&b.tagName=="error"?this.setStatus(NodeUtils.getNodeValue(b,"descr")):this.setStatus("reconnecting")},showStatusDiv:function(a){if($("engineinfo"))$("engineinfo").style.display="inline",$("engineinfo").innerHTML=a},setStatus:function(a){this.statusTimeout&&clearTimeout(this.statusTimeout);this.showStatusDiv(a);this.statusTimeout=setTimeout(this.clearStatus.bind(this),4E3)},clearStatus:function(){$("engineinfo").style.display=
"none"}});var Chat={threadUpdater:{},applyName:function(){Chat.threadUpdater.changeName($("uname").value);$("changename1").style.display="none";$("changename2").style.display="inline";$("unamelink").innerHTML=htmlescape($("uname").value)},showNameField:function(){$("changename1").style.display="inline";$("changename2").style.display="none"}}; "none"}});var Chat={threadUpdater:{},applyName:function(){Chat.threadUpdater.changeName($("uname").value);$("changename1").style.display="none";$("changename2").style.display="inline";$("unamelink").innerHTML=htmlescape($("uname").value)},showNameField:function(){$("changename1").style.display="inline";$("changename2").style.display="none"}};

View File

@ -18,8 +18,8 @@ setTimeout(this.handleTimeout.bind(this),this._options.timeout);this.setRequestH
clearTimeout(this.transportTimer),(this._options.onComplete||Ajax.emptyFunction)(this.transport)}catch(b){this.dispatchException(b)}this.transport.onreadystatechange=Ajax.emptyFunction}},dispatchException:function(a){(this._options.onException||Ajax.emptyFunction)(this,a)}}); clearTimeout(this.transportTimer),(this._options.onComplete||Ajax.emptyFunction)(this.transport)}catch(b){this.dispatchException(b)}this.transport.onreadystatechange=Ajax.emptyFunction}},dispatchException:function(a){(this._options.onException||Ajax.emptyFunction)(this,a)}});
var EventHelper={register:function(a,b,c){var d=a[b];a[b]=typeof d!="function"?c:function(){d();c()}}},Behaviour={list:[],register:function(a){Behaviour.list.push(a)},init:function(){EventHelper.register(window,"onload",function(){Behaviour.apply()})},apply:function(){for(h=0;sheet=Behaviour.list[h];h++)for(selector in sheet)if(list=document.getElementsBySelector(selector))for(i=0;element=list[i];i++)sheet[selector](element)}};Behaviour.init(); var EventHelper={register:function(a,b,c){var d=a[b];a[b]=typeof d!="function"?c:function(){d();c()}}},Behaviour={list:[],register:function(a){Behaviour.list.push(a)},init:function(){EventHelper.register(window,"onload",function(){Behaviour.apply()})},apply:function(){for(h=0;sheet=Behaviour.list[h];h++)for(selector in sheet)if(list=document.getElementsBySelector(selector))for(i=0;element=list[i];i++)sheet[selector](element)}};Behaviour.init();
function getAllChildren(a){return a.all?a.all:a.getElementsByTagName("*")} function getAllChildren(a){return a.all?a.all:a.getElementsByTagName("*")}
document.getElementsBySelector=function(a){if(!document.getElementsByTagName)return[];for(var a=a.split(" "),b=Array(document),c=0;c<a.length;c++)if(token=a[c].replace(/^\s+/,"").replace(/\s+$/,""),token.indexOf("#")>-1){var d=token.split("#"),e=d[0],b=document.getElementById(d[1]);if(b==null||e&&b.nodeName.toLowerCase()!=e)return[];b=Array(b)}else if(token.indexOf(".")>-1){d=token.split(".");e=d[0];d=d[1];e||(e="*");for(var l=[],j=0,n=0;n<b.length;n++){var g;g=e=="*"?getAllChildren(b[n]):b[n].getElementsByTagName(e); document.getElementsBySelector=function(a){if(!document.getElementsByTagName)return[];for(var a=a.split(" "),b=Array(document),c=0;c<a.length;c++)if(token=a[c].replace(/^\s+/,"").replace(/\s+$/,""),token.indexOf("#")>-1){var d=token.split("#"),f=d[0],b=document.getElementById(d[1]);if(b==null||f&&b.nodeName.toLowerCase()!=f)return[];b=Array(b)}else if(token.indexOf(".")>-1){d=token.split(".");f=d[0];d=d[1];f||(f="*");for(var g=[],j=0,n=0;n<b.length;n++){var m;m=f=="*"?getAllChildren(b[n]):b[n].getElementsByTagName(f);
if(g!=null)for(var o=0;o<g.length;o++)l[j++]=g[o]}b=[];for(j=e=0;j<l.length;j++)l[j].className&&l[j].className.match(RegExp("\\b"+d+"\\b"))&&(b[e++]=l[j])}else{if(!b[0])return;e=token;l=[];for(n=j=0;n<b.length;n++){g=b[n].getElementsByTagName(e);for(o=0;o<g.length;o++)l[j++]=g[o]}b=l}return b}; if(m!=null)for(var o=0;o<m.length;o++)g[j++]=m[o]}b=[];for(j=f=0;j<g.length;j++)g[j].className&&g[j].className.match(RegExp("\\b"+d+"\\b"))&&(b[f++]=g[j])}else{if(!b[0])return;f=token;g=[];for(n=j=0;n<b.length;n++){m=b[n].getElementsByTagName(f);for(o=0;o<m.length;o++)g[j++]=m[o]}b=g}return b};
var NodeUtils={getNodeValue:function(a,b){var c=a.getElementsByTagName(b);if(c.length==0)return"";var c=c[0].childNodes,d="";for(i=0;i<c.length;i++)d+=c[i].nodeValue;return d},getNodeText:function(a){var a=a.childNodes,b="";for(i=0;i<a.length;i++)b+=a[i].nodeValue;return b},getAttrValue:function(a,b){for(k=0;k<a.attributes.length;k++)if(a.attributes[k].nodeName==b)return a.attributes[k].nodeValue;return null}},CommonUtils={getRow:function(a,b){var c=b.rows[a];if(c!=null)return c;if(b.rows.head!=null)return null; var NodeUtils={getNodeValue:function(a,b){var c=a.getElementsByTagName(b);if(c.length==0)return"";var c=c[0].childNodes,d="";for(i=0;i<c.length;i++)d+=c[i].nodeValue;return d},getNodeText:function(a){var a=a.childNodes,b="";for(i=0;i<a.length;i++)b+=a[i].nodeValue;return b},getAttrValue:function(a,b){for(k=0;k<a.attributes.length;k++)if(a.attributes[k].nodeName==b)return a.attributes[k].nodeValue;return null}},CommonUtils={getRow:function(a,b){var c=b.rows[a];if(c!=null)return c;if(b.rows.head!=null)return null;
for(k=0;k<b.rows.length;k++)if(b.rows[k].id==a)return b.rows[k];return null},getCell:function(a,b,c){var d=b.cells[a];if(d!=null)return d;if(c.rows.head!=null)return null;for(k=0;k<b.cells.length;k++)if(b.cells[k].id==a)return b.cells[k];return null},insertCell:function(a,b,c,d,e,l){a=a.insertCell(-1);a.id=b;if(d)a.align=d;a.className=c;if(e)a.height=e;a.innerHTML=l}}; for(k=0;k<b.rows.length;k++)if(b.rows[k].id==a)return b.rows[k];return null},getCell:function(a,b,c){var d=b.cells[a];if(d!=null)return d;if(c.rows.head!=null)return null;for(k=0;k<b.cells.length;k++)if(b.cells[k].id==a)return b.cells[k];return null},insertCell:function(a,b,c,d,f,g){a=a.insertCell(-1);a.id=b;if(d)a.align=d;a.className=c;if(f)a.height=f;a.innerHTML=g}};
function playSound(a){var b=document.createElement("div");if(navigator.userAgent.toLowerCase().indexOf("opera")!=-1)b.style="position: absolute; left: 0px; top: -200px;";document.body.appendChild(b);b.innerHTML='<embed src="'+a+'" hidden="true" autostart="true" loop="false">'}function htmlescape(a){return a.replace("&","&amp;").replace("<","&lt;").replace(">","&gt;").replace('"',"&quot;")}; function playSound(a){var b=document.createElement("div");if(navigator.userAgent.toLowerCase().indexOf("opera")!=-1)b.style="position: absolute; left: 0px; top: -200px;";document.body.appendChild(b);b.innerHTML='<embed src="'+a+'" hidden="true" autostart="true" loop="false">'}function htmlescape(a){return a.replace("&","&amp;").replace("<","&lt;").replace(">","&gt;").replace('"',"&quot;")};

View File

@ -0,0 +1,12 @@
/*
This file is part of Mibew Messenger project.
http://mibew.org
Copyright (c) 2005-2011 Mibew Messenger Community
License: http://mibew.org/license.php
*/
Ajax.InviteUpdater=Class.create();
Class.inherit(Ajax.InviteUpdater,Ajax.Base,{initialize:function(a){this.setOptions(a);this._options.onComplete=this.requestComplete.bind(this);this._options.onException=this.handleException.bind(this);this._options.onTimeout=this.handleTimeout.bind(this);this._options.updateParams=this.updateParams.bind(this);this._options.handleError=this.handleError.bind(this);this._options.updateContent=this.updateContent.bind(this);this._options.timeout=5E3;this.frequency=this._options.frequency||2;this.updater=
{};this.update()},handleException:function(){this._options.handleError&&this._options.handleError("offline, reconnecting");this.stopUpdate();this.timer=setTimeout(this.update.bind(this),1E3)},handleTimeout:function(){this._options.handleError&&this._options.handleError("timeout, reconnecting");this.stopUpdate();this.timer=setTimeout(this.update.bind(this),1E3)},stopUpdate:function(){if(this.updater._options)this.updater._options.onComplete=void 0;clearTimeout(this.timer)},update:function(){if(this._options.updateParams)this._options.parameters=
this._options.updateParams();this.updater=new Ajax.Request(this._options.url,this._options)},requestComplete:function(a){try{var b=Ajax.getXml(a);b?(this._options.updateContent||Ajax.emptyFunction)(b):this._options.handleError&&this._options.handleError("reconnecting")}catch(c){}this.timer=setTimeout(this.update.bind(this),this.frequency*1E3)},updateParams:function(){return"visitor="+this._options.visitor},handleError:function(){},updateContent:function(a){if(a.tagName=="invitation"){var b=NodeUtils.getNodeValue(a,
"invited"),a=NodeUtils.getNodeValue(a,"threadid");if(b=="0")this.stopUpdate(),window.close();else if(a!="0")this.stopUpdate(),window.name="ImCenter"+a,window.location=this._options.agentservl+"?thread="+a}}});EventHelper.register(window,"onload",function(){new Ajax.InviteUpdater({}.extend(updaterOptions||{}))});

View File

@ -9,19 +9,27 @@ Ajax.PeriodicalUpdater=Class.create();
Class.inherit(Ajax.PeriodicalUpdater,Ajax.Base,{initialize:function(a){this.setOptions(a);this._options.onComplete=this.requestComplete.bind(this);this._options.onException=this.handleException.bind(this);this._options.onTimeout=this.handleTimeout.bind(this);this._options.timeout=5E3;this.frequency=this._options.frequency||2;this.updater={};this.update()},handleException:function(){this._options.handleError&&this._options.handleError("offline, reconnecting");this.stopUpdate();this.timer=setTimeout(this.update.bind(this), Class.inherit(Ajax.PeriodicalUpdater,Ajax.Base,{initialize:function(a){this.setOptions(a);this._options.onComplete=this.requestComplete.bind(this);this._options.onException=this.handleException.bind(this);this._options.onTimeout=this.handleTimeout.bind(this);this._options.timeout=5E3;this.frequency=this._options.frequency||2;this.updater={};this.update()},handleException:function(){this._options.handleError&&this._options.handleError("offline, reconnecting");this.stopUpdate();this.timer=setTimeout(this.update.bind(this),
1E3)},handleTimeout:function(){this._options.handleError&&this._options.handleError("timeout, reconnecting");this.stopUpdate();this.timer=setTimeout(this.update.bind(this),1E3)},stopUpdate:function(){if(this.updater._options)this.updater._options.onComplete=void 0;clearTimeout(this.timer)},update:function(){if(this._options.updateParams)this._options.parameters=this._options.updateParams();this.updater=new Ajax.Request(this._options.url,this._options)},requestComplete:function(a){try{var b=Ajax.getXml(a); 1E3)},handleTimeout:function(){this._options.handleError&&this._options.handleError("timeout, reconnecting");this.stopUpdate();this.timer=setTimeout(this.update.bind(this),1E3)},stopUpdate:function(){if(this.updater._options)this.updater._options.onComplete=void 0;clearTimeout(this.timer)},update:function(){if(this._options.updateParams)this._options.parameters=this._options.updateParams();this.updater=new Ajax.Request(this._options.url,this._options)},requestComplete:function(a){try{var b=Ajax.getXml(a);
b?(this._options.updateContent||Ajax.emptyFunction)(b):this._options.handleError&&this._options.handleError("reconnecting")}catch(c){}this.timer=setTimeout(this.update.bind(this),this.frequency*1E3)}}); b?(this._options.updateContent||Ajax.emptyFunction)(b):this._options.handleError&&this._options.handleError("reconnecting")}catch(c){}this.timer=setTimeout(this.update.bind(this),this.frequency*1E3)}});
var HtmlGenerationUtils={popupLink:function(a,b,c,d,e,l,j){return'<a href="'+a+'"'+(j!=null?' class="'+j+'"':"")+' target="_blank" title="'+b+'" onclick="this.newWindow = window.open(\''+a+"', '"+c+"', 'toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width="+e+",height="+l+",resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;\">"+d+"</a>"},generateOneRowTable:function(a){return'<table class="inner"><tr>'+a+"</tr></table>"},viewOpenCell:function(a,b,c,d,e,l,j,n){var l= var HtmlGenerationUtils={popupLink:function(a,b,c,d,f,g,j){return'<a href="'+a+'"'+(j!=null?' class="'+j+'"':"")+' target="_blank" title="'+b+'" onclick="this.newWindow = window.open(\''+a+"', '"+c+"', 'toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width="+f+",height="+g+",resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;\">"+d+"</a>"},generateOneRowTable:function(a){return'<table class="inner"><tr>'+a+"</tr></table>"},viewOpenCell:function(a,b,c,d,f,g,j,n,m,o){var g=
2,b=b+"?thread="+c,g="<td>";g+=e||d?HtmlGenerationUtils.popupLink(n||!d?b:b+"&viewonly=true",localized[e?0:1],"ImCenter"+c,a,640,480,null):'<a href="#">'+a+"</a>";g+="</td>";e&&(g+='<td class="icon">',g+=HtmlGenerationUtils.popupLink(b,localized[0],"ImCenter"+c,'<img src="'+webimRoot+'/images/tbliclspeak.gif" width="15" height="15" border="0" alt="'+localized[0]+'">',640,480,null),g+="</td>",l++);d&&(g+='<td class="icon">',g+=HtmlGenerationUtils.popupLink(b+"&viewonly=true",localized[1],"ImCenter"+ 2,b=b+"?thread="+c,e="<td>";e+=f||d?HtmlGenerationUtils.popupLink(n||!d?b:b+"&viewonly=true",localized[f?0:1],"ImCenter"+c,a,640,480,null):'<a href="#">'+a+"</a>";e+="</td>";f&&(e+='<td class="icon">',e+=HtmlGenerationUtils.popupLink(b,localized[0],"ImCenter"+c,'<img src="'+webimRoot+'/images/tbliclspeak.gif" width="15" height="15" border="0" alt="'+localized[0]+'">',640,480,null),e+="</td>",g++);d&&(e+='<td class="icon">',e+=HtmlGenerationUtils.popupLink(b+"&viewonly=true",localized[1],"ImCenter"+
c,'<img src="'+webimRoot+'/images/tbliclread.gif" width="15" height="15" border="0" alt="'+localized[1]+'">',640,480,null),g+="</td>",l++);j!=""&&(g+='</tr><tr><td class="firstmessage" colspan="'+l+'"><a href="javascript:void(0)" title="'+j+'" onclick="alert(this.title);return false;">',g+=j.length>30?j.substring(0,30)+"...":j,g+="</a></td>");return HtmlGenerationUtils.generateOneRowTable(g)},banCell:function(a,b){return'<td class="icon">'+HtmlGenerationUtils.popupLink(webimRoot+"/operator/ban.php?"+ c,'<img src="'+webimRoot+'/images/tbliclread.gif" width="15" height="15" border="0" alt="'+localized[1]+'">',640,480,null),e+="</td>",g++);m&&(e+='<td class="icon">',e+=HtmlGenerationUtils.popupLink(o+"?thread="+c,localized[6],"ImTracked"+c,'<img src="'+webimRoot+'/images/tblictrack.gif" width="15" height="15" border="0" alt="'+localized[6]+'">',640,480,null),e+="</td>",g++);j!=""&&(e+='</tr><tr><td class="firstmessage" colspan="'+g+'"><a href="javascript:void(0)" title="'+j+'" onclick="alert(this.title);return false;">',
(b?"id="+b:"thread="+a),localized[2],"ban"+a,'<img src="'+webimRoot+'/images/ban.gif" width="15" height="15" border="0" alt="'+localized[2]+'">',720,480,null)+"</td>"}};Ajax.ThreadListUpdater=Class.create(); e+=j.length>30?j.substring(0,30)+"...":j,e+="</a></td>");return HtmlGenerationUtils.generateOneRowTable(e)},banCell:function(a,b){return'<td class="icon">'+HtmlGenerationUtils.popupLink(webimRoot+"/operator/ban.php?"+(b?"id="+b:"thread="+a),localized[2],"ban"+a,'<img src="'+webimRoot+'/images/ban.gif" width="15" height="15" border="0" alt="'+localized[2]+'">',720,480,null)+"</td>"},viewVisOpenCell:function(a,b,c,d,f){var g="<td>";g+=f?HtmlGenerationUtils.popupLink(b+"?visitor="+c,localized[7],"ImCenter"+
Class.inherit(Ajax.ThreadListUpdater,Ajax.Base,{initialize:function(a){this.setOptions(a);this._options.updateParams=this.updateParams.bind(this);this._options.handleError=this.handleError.bind(this);this._options.updateContent=this.updateContent.bind(this);this._options.lastrevision=0;this.threadTimers={};this.delta=0;this.t=this._options.table;this.periodicalUpdater=new Ajax.PeriodicalUpdater(this._options)},updateParams:function(){return"since="+this._options.lastrevision+"&status="+this._options.istatus+ c,a,640,480,null):'<a href="#">'+a+"</a>";g+="</td>";g+='<td class="icon">';a=HtmlGenerationUtils.popupLink(d+"?visitor="+c,localized[6],"ImTracked"+c,'<img src="'+webimRoot+'/images/tblictrack.gif" width="15" height="15" border="0" alt="'+localized[6]+'">',640,480,null);a=a.replace("scrollbars=0","scrollbars=1");g+=a;g+="</td>";return HtmlGenerationUtils.generateOneRowTable(g)}};Ajax.ThreadListUpdater=Class.create();
(this._options.showonline?"&showonline=1":"")},setStatus:function(a){this._options.status.innerHTML=a},handleError:function(a){this.setStatus(a)},updateThread:function(a){function b(a,b,c,d){if(a=CommonUtils.getCell(c,b,a))a.innerHTML=d}for(var c,d,e,l=!1,j=!1,n=!1,g=null,o=null,f=0;f<a.attributes.length;f++){var m=a.attributes[f];if(m.nodeName=="id")c=m.nodeValue;else if(m.nodeName=="stateid")d=m.nodeValue;else if(m.nodeName=="state")e=m.nodeValue;else if(m.nodeName=="canopen")j=!0;else if(m.nodeName== Class.inherit(Ajax.ThreadListUpdater,Ajax.Base,{initialize:function(a){this.setOptions(a);this._options.updateParams=this.updateParams.bind(this);this._options.handleError=this.handleError.bind(this);this._options.updateContent=this.updateContent.bind(this);this._options.lastrevision=0;this.threadTimers={};this.delta=0;this.t=this._options.table;this.t2=this._options.visitors_table;this.periodicalUpdater=new Ajax.PeriodicalUpdater(this._options);this.old_visitors={};this.visitors={};this.visitorTimers=
"canview")l=!0;else if(m.nodeName=="canban")n=!0;else if(m.nodeName=="ban")g=m.nodeValue;else if(m.nodeName=="banid")o=m.nodeValue}f=CommonUtils.getRow("thr"+c,this.t);if(d=="closed")f&&this.t.deleteRow(f.rowIndex),this.threadTimers[c]=null;else{var m=NodeUtils.getNodeValue(a,"name"),s=NodeUtils.getNodeValue(a,"addr"),q=NodeUtils.getNodeValue(a,"time"),t=NodeUtils.getNodeValue(a,"agent"),r=NodeUtils.getNodeValue(a,"modified"),u=NodeUtils.getNodeValue(a,"message"),p="<td>"+NodeUtils.getNodeValue(a, {}},updateParams:function(){return"since="+this._options.lastrevision+"&status="+this._options.istatus+(this._options.showonline?"&showonline=1":"")+(this._options.showvisitors?"&showvisitors=1":"")},setStatus:function(a){this._options.status.innerHTML=a},handleError:function(a){this.setStatus(a)},updateThread:function(a){function b(a,b,c,d){if(a=CommonUtils.getCell(c,b,a))a.innerHTML=d}for(var c,d,f,g=!1,j=!1,n=!1,m=null,o=null,e=0;e<a.attributes.length;e++){var l=a.attributes[e];if(l.nodeName==
"useragent")+"</td>";g!=null&&(p="<td>"+NodeUtils.getNodeValue(a,"reason")+"</td>");n&&(p+=HtmlGenerationUtils.banCell(c,o));p=HtmlGenerationUtils.generateOneRowTable(p);a=CommonUtils.getRow("t"+d,this.t);n=CommonUtils.getRow("t"+d+"end",this.t);if(f!=null&&(f.rowIndex<=a.rowIndex||f.rowIndex>=n.rowIndex))this.t.deleteRow(f.rowIndex),f=this.threadTimers[c]=null;if(f==null){if(f=this.t.insertRow(a.rowIndex+1),f.className=g=="blocked"&&d!="chat"?"ban":"in"+d,f.id="thr"+c,this.threadTimers[c]=[q,r,d], "id")c=l.nodeValue;else if(l.nodeName=="stateid")d=l.nodeValue;else if(l.nodeName=="state")f=l.nodeValue;else if(l.nodeName=="canopen")j=!0;else if(l.nodeName=="canview")g=!0;else if(l.nodeName=="canban")n=!0;else if(l.nodeName=="ban")m=l.nodeValue;else if(l.nodeName=="banid")o=l.nodeValue}e=CommonUtils.getRow("thr"+c,this.t);if(d=="closed")e&&this.t.deleteRow(e.rowIndex),this.threadTimers[c]=null;else{var l=NodeUtils.getNodeValue(a,"name"),q=NodeUtils.getNodeValue(a,"addr"),p=NodeUtils.getNodeValue(a,
CommonUtils.insertCell(f,"name","visitor",null,null,HtmlGenerationUtils.viewOpenCell(m,this._options.agentservl,c,l,j,g,u,d!="chat")),CommonUtils.insertCell(f,"contid","visitor","center",null,s),CommonUtils.insertCell(f,"state","visitor","center",null,e),CommonUtils.insertCell(f,"op","visitor","center",null,t),CommonUtils.insertCell(f,"time","visitor","center",null,this.getTimeSince(q)),CommonUtils.insertCell(f,"wait","visitor","center",null,d!="chat"?this.getTimeSince(r):"-"),CommonUtils.insertCell(f, "time"),t=NodeUtils.getNodeValue(a,"agent"),s=NodeUtils.getNodeValue(a,"modified"),u=NodeUtils.getNodeValue(a,"message"),r="<td>"+NodeUtils.getNodeValue(a,"useragent")+"</td>";m!=null&&(r="<td>"+NodeUtils.getNodeValue(a,"reason")+"</td>");n&&(r+=HtmlGenerationUtils.banCell(c,o));r=HtmlGenerationUtils.generateOneRowTable(r);a=CommonUtils.getRow("t"+d,this.t);n=CommonUtils.getRow("t"+d+"end",this.t);if(e!=null&&(e.rowIndex<=a.rowIndex||e.rowIndex>=n.rowIndex))this.t.deleteRow(e.rowIndex),e=this.threadTimers[c]=
"etc","visitor","center",null,p),d=="wait"||d=="prio")return!0}else this.threadTimers[c]=[q,r,d],f.className=g=="blocked"&&d!="chat"?"ban":"in"+d,b(this.t,f,"name",HtmlGenerationUtils.viewOpenCell(m,this._options.agentservl,c,l,j,g,u,d!="chat")),b(this.t,f,"contid",s),b(this.t,f,"state",e),b(this.t,f,"op",t),b(this.t,f,"time",this.getTimeSince(q)),b(this.t,f,"wait",d!="chat"?this.getTimeSince(r):"-"),b(this.t,f,"etc",p);return!1}},updateQueueMessages:function(){function a(a,b){var c=$(b),j=$(b+"end"); null;if(e==null){if(e=this.t.insertRow(a.rowIndex+1),e.className=m=="blocked"&&d!="chat"?"ban":"in"+d,e.id="thr"+c,this.threadTimers[c]=[p,s,d],CommonUtils.insertCell(e,"name","visitor",null,null,HtmlGenerationUtils.viewOpenCell(l,this._options.agentservl,c,g,j,m,u,d!="chat",this._options.showvisitors,this._options.trackedservl)),CommonUtils.insertCell(e,"contid","visitor","center",null,q),CommonUtils.insertCell(e,"state","visitor","center",null,f),CommonUtils.insertCell(e,"op","visitor","center",
if(c==null||j==null)return!1;return c.rowIndex+1<j.rowIndex}var b=$("statustd");if(b){var c=a(this.t,"twait")||a(this.t,"tprio")||a(this.t,"tchat");b.innerHTML=c?"":this._options.noclients;b.height=c?5:30}},getTimeSince:function(a){var a=Math.floor(((new Date).getTime()-a-this.delta)/1E3),b=Math.floor(a/60),c="";a%=60;a<10&&(a="0"+a);b>=60&&(c=Math.floor(b/60),b%=60,b<10&&(b="0"+b),c+=":");return c+b+":"+a},updateTimers:function(){for(var a in this.threadTimers)if(this.threadTimers[a]!=null){var b= null,t),CommonUtils.insertCell(e,"time","visitor","center",null,this.getTimeSince(p)),CommonUtils.insertCell(e,"wait","visitor","center",null,d!="chat"?this.getTimeSince(s):"-"),CommonUtils.insertCell(e,"etc","visitor","center",null,r),d=="wait"||d=="prio")return!0}else this.threadTimers[c]=[p,s,d],e.className=m=="blocked"&&d!="chat"?"ban":"in"+d,b(this.t,e,"name",HtmlGenerationUtils.viewOpenCell(l,this._options.agentservl,c,g,j,m,u,d!="chat",this._options.showvisitors,this._options.trackedservl)),
this.threadTimers[a],c=CommonUtils.getRow("thr"+a,this.t);if(c!=null){var d=function(a,b,c,d){if(a=CommonUtils.getCell(c,b,a))a.innerHTML=d};d(this.t,c,"time",this.getTimeSince(b[0]));d(this.t,c,"wait",b[2]!="chat"?this.getTimeSince(b[1]):"-")}}},updateThreads:function(a){var b=!1,c=NodeUtils.getAttrValue(a,"time"),d=NodeUtils.getAttrValue(a,"revision");if(c)this.delta=(new Date).getTime()-c;if(d)this._options.lastrevision=d;for(c=0;c<a.childNodes.length;c++)d=a.childNodes[c],d.tagName=="thread"&& b(this.t,e,"contid",q),b(this.t,e,"state",f),b(this.t,e,"op",t),b(this.t,e,"time",this.getTimeSince(p)),b(this.t,e,"wait",d!="chat"?this.getTimeSince(s):"-"),b(this.t,e,"etc",r);return!1}},updateQueueMessages:function(){function a(a,b){var c=$(b),j=$(b+"end");if(c==null||j==null)return!1;return c.rowIndex+1<j.rowIndex}var b=$("statustd");if(b){var c=a(this.t,"twait")||a(this.t,"tprio")||a(this.t,"tchat");b.innerHTML=c?"":this._options.noclients;b.height=c?5:30}},getTimeSince:function(a){var a=Math.floor(((new Date).getTime()-
this.updateThread(d)&&(b=!0);this.updateQueueMessages();this.updateTimers();this.setStatus(this._options.istatus?"Away":"Up to date");b&&(playSound(webimRoot+"/sounds/new_user.wav"),window.focus(),updaterOptions.showpopup&&alert(localized[5]))},updateOperators:function(a){var b=$("onlineoperators");if(b){for(var c=[],d=0;d<a.childNodes.length;d++){var e=a.childNodes[d];if(e.tagName=="operator"){var l=NodeUtils.getAttrValue(e,"name"),e=NodeUtils.getAttrValue(e,"away")!=null;c[c.length]='<img src="'+ a-this.delta)/1E3),b=Math.floor(a/60),c="";a%=60;a<10&&(a="0"+a);b>=60&&(c=Math.floor(b/60),b%=60,b<10&&(b="0"+b),c+=":");return c+b+":"+a},updateTimers:function(){for(var a in this.threadTimers)if(this.threadTimers[a]!=null){var b=this.threadTimers[a],c=CommonUtils.getRow("thr"+a,this.t);if(c!=null){var d=function(a,b,c,d){if(a=CommonUtils.getCell(c,b,a))a.innerHTML=d};d(this.t,c,"time",this.getTimeSince(b[0]));d(this.t,c,"wait",b[2]!="chat"?this.getTimeSince(b[1]):"-")}}},updateThreads:function(a){var b=
webimRoot+"/images/op"+(e?"away":"online")+'.gif" width="12" height="12" border="0" alt="'+localized[1]+'"> '+l}}b.innerHTML=c.join(", ")}},updateContent:function(a){if(a.tagName=="update")for(var b=0;b<a.childNodes.length;b++){var c=a.childNodes[b];c.tagName=="threads"?this.updateThreads(c):c.tagName=="operators"&&this.updateOperators(c)}else a.tagName=="error"?this.setStatus(NodeUtils.getNodeValue(a,"descr")):this.setStatus("reconnecting")}}); !1,c=NodeUtils.getAttrValue(a,"time"),d=NodeUtils.getAttrValue(a,"revision");if(c)this.delta=(new Date).getTime()-c;if(d)this._options.lastrevision=d;for(c=0;c<a.childNodes.length;c++)d=a.childNodes[c],d.tagName=="thread"&&this.updateThread(d)&&(b=!0);this.updateQueueMessages();this.updateTimers();this.setStatus(this._options.istatus?"Away":"Up to date");b&&(playSound(webimRoot+"/sounds/new_user.wav"),window.focus(),updaterOptions.showpopup&&alert(localized[5]))},updateOperators:function(a){var b=
$("onlineoperators");if(b){for(var c=[],d=0;d<a.childNodes.length;d++){var f=a.childNodes[d];if(f.tagName=="operator"){var g=NodeUtils.getAttrValue(f,"name"),f=NodeUtils.getAttrValue(f,"away")!=null;c[c.length]='<img src="'+webimRoot+"/images/op"+(f?"away":"online")+'.gif" width="12" height="12" border="0" alt="'+localized[1]+'"> '+g}}b.innerHTML=c.join(", ")}},updateVisitorsTimers:function(){for(var a in this.visitorTimers)if(this.visitorTimers[a]!=null){var b=this.visitorTimers[a],c=CommonUtils.getRow("vis"+
a,this.t2);if(c!=null){var d=function(a,b,c,d){if(a=CommonUtils.getCell(c,b,a))a.innerHTML=d};d(this.t2,c,"time",this.getTimeSince(b[0]));d(this.t2,c,"modified",this.getTimeSince(b[1]));b[2]!=null&&d(this.t2,c,"invitationtime",this.getTimeSince(b[2]))}}},updateVisitor:function(a){function b(a,b,c,d){if(a=CommonUtils.getCell(c,b,a))a.innerHTML=d}for(var c,d=0;d<a.attributes.length;d++){var f=a.attributes[d];if(f.nodeName=="id")c=f.nodeValue}for(var f=NodeUtils.getNodeValue(a,"addr"),g=NodeUtils.getNodeValue(a,
"username"),j=NodeUtils.getNodeValue(a,"useragent"),n=NodeUtils.getNodeValue(a,"time"),m=NodeUtils.getNodeValue(a,"modified"),o=NodeUtils.getNodeValue(a,"invitations"),e=NodeUtils.getNodeValue(a,"chats"),l=null,q=null,a=a.getElementsByTagName("invitation")[0],d=0;d<a.childNodes.length;d++){var p=a.childNodes[d];if(p.tagName=="operator")l=p.firstChild.nodeValue;else if(p.tagName=="invitationtime")q=p.firstChild.nodeValue}p=l==null?"free":"invited";d=CommonUtils.getRow("vis"+c,this.t2);a=CommonUtils.getRow("vis"+
p,this.t2);p=CommonUtils.getRow("vis"+p+"end",this.t2);if(d!=null&&(d.rowIndex<=a.rowIndex||d.rowIndex>=p.rowIndex))this.t2.deleteRow(d.rowIndex),d=this.visitorTimers[c]=null;d==null?(d=this.t2.insertRow(a.rowIndex+1),d.id="vis"+c,this.visitorTimers[c]=[n,m,q],CommonUtils.insertCell(d,"username","visitor",null,null,HtmlGenerationUtils.viewVisOpenCell(g,this._options.inviteservl,c,this._options.trackedservl,l==null)),CommonUtils.insertCell(d,"addr","visitor","center",null,f),CommonUtils.insertCell(d,
"time","visitor","center",null,this.getTimeSince(n)),CommonUtils.insertCell(d,"modified","visitor","center",null,this.getTimeSince(m)),CommonUtils.insertCell(d,"operator","visitor","center",null,l!=null?l:"-"),CommonUtils.insertCell(d,"invitationtime","visitor","center",null,l!=null?this.getTimeSince(q):"-"),CommonUtils.insertCell(d,"invitations","visitor","center",null,o+" / "+e),CommonUtils.insertCell(d,"useragent","visitor","center",null,j)):(this.visitorTimers[c]=[n,m,q],b(this.t2,d,"username",
HtmlGenerationUtils.viewVisOpenCell(g,this._options.inviteservl,c,this._options.trackedservl,l==null)),b(this.t2,d,"addr",f),b(this.t2,d,"operator",l!=null?l:"-"),b(this.t2,d,"time",this.getTimeSince(n)),b(this.t2,d,"modified",this.getTimeSince(m)),b(this.t2,d,"invitationtime",l!=null?this.getTimeSince(q):"-"),b(this.t2,d,"invitations",o+" / "+e),b(this.t2,d,"useragent",j));this.visitors[c]=1;return!1},removeOldVisitors:function(){for(id in this.old_visitors)if(this.visitors[id]===void 0){var a=CommonUtils.getRow("vis"+
id,this.t2);a&&this.t2.deleteRow(a.rowIndex);this.visitorTimers[id]=null}},updateVisitorsList:function(a){var b=$("visstatustd");if(b)b.innerHTML=a>0?"":this._options.novisitors,b.height=a>0?5:30},updateVisitors:function(a){this.old_visitors=this.visitors;this.visitors={};for(var b=0,c=0;c<a.childNodes.length;c++){var d=a.childNodes[c];d.tagName=="visitor"&&(b++,this.updateVisitor(d))}this.updateVisitorsTimers();this.removeOldVisitors();this.updateVisitorsList(b)},updateContent:function(a){if(a.tagName==
"update")for(var b=0;b<a.childNodes.length;b++){var c=a.childNodes[b];c.tagName=="threads"?this.updateThreads(c):c.tagName=="operators"?this.updateOperators(c):c.tagName=="visitors"&&this.updateVisitors(c)}else a.tagName=="error"?this.setStatus(NodeUtils.getNodeValue(a,"descr")):this.setStatus("reconnecting")}});
function togglemenu(){if($("sidebar")&&$("wcontent")&&$("togglemenu"))$("wcontent").className=="contentnomenu"?($("sidebar").style.display="block",$("wcontent").className="contentinner",$("togglemenu").innerHTML=localized[4]):($("sidebar").style.display="none",$("wcontent").className="contentnomenu",$("togglemenu").innerHTML=localized[3])}var webimRoot="";Behaviour.register({"#togglemenu":function(a){a.onclick=function(){togglemenu()}}}); function togglemenu(){if($("sidebar")&&$("wcontent")&&$("togglemenu"))$("wcontent").className=="contentnomenu"?($("sidebar").style.display="block",$("wcontent").className="contentinner",$("togglemenu").innerHTML=localized[4]):($("sidebar").style.display="none",$("wcontent").className="contentnomenu",$("togglemenu").innerHTML=localized[3])}var webimRoot="";Behaviour.register({"#togglemenu":function(a){a.onclick=function(){togglemenu()}}});
EventHelper.register(window,"onload",function(){webimRoot=updaterOptions.wroot;new Ajax.ThreadListUpdater({table:$("threadlist"),status:$("connstatus"),istatus:0}.extend(updaterOptions||{}));updaterOptions.havemenu||togglemenu()}); EventHelper.register(window,"onload",function(){webimRoot=updaterOptions.wroot;new Ajax.ThreadListUpdater({table:$("threadlist"),status:$("connstatus"),istatus:0,visitors_table:$("visitorslist")}.extend(updaterOptions||{}));updaterOptions.havemenu||togglemenu()});

View File

@ -0,0 +1,6 @@
var mibewinviterequest,mibewinviteurl,mibewinvitetimeout,mibewinvitetimer,style=document.createElement("style");document.getElementsByTagName("head")[0].appendChild(style);window.createPopup||(style.appendChild(document.createTextNode("")),style.setAttribute("type","text/css"));var sheet=document.styleSheets[document.styleSheets.length-1];if(window.createPopup)sheet.cssText=mibewInviteStyle;else{var node=document.createTextNode(mibewInviteStyle);style.appendChild(node)}
function mibewInviteMakeRequest(a,b){mibewinviteurl=a;mibewinvitetimeout=b;window.XMLHttpRequest?mibewinviterequest=new XMLHttpRequest:window.ActiveXObject&&(mibewinviterequest=new ActiveXObject("MSXML2.XMLHTTP"));if(mibewinviterequest)mibewinviterequest.onreadystatechange=mibewInviteOnResponse;mibewInviteSendRequest(a)}function mibewInviteSendRequest(a){clearTimeout(mibewinvitetimer);mibewinviterequest.open("GET",a+"&rnd="+Math.random(1),!0);mibewinviterequest.send()}
function mibewInviteCheckReadyState(a){if(a.readyState==4&&(a.status==200||a.status==304))return!0}
function mibewInviteOnResponse(){if(mibewInviteCheckReadyState(mibewinviterequest)){var a=mibewinviterequest.responseXML.documentElement,b=a.getElementsByTagName("message");if(b[0]){var b=b[0].firstChild.data,c=a.getElementsByTagName("operator")[0]&&a.getElementsByTagName("operator")[0].firstChild!=null?a.getElementsByTagName("operator")[0].firstChild.data:void 0,d=a.getElementsByTagName("avatar")[0]&&a.getElementsByTagName("avatar")[0].firstChild!=null?a.getElementsByTagName("avatar")[0].firstChild.data:
void 0,a='<div id="mibewinvitationpopup">';a+='<div id="mibewinvitationclose"><a href="javascript:void(0);" onclick="mibewHideInvitation();">&times;</a></div>';c&&(a+='<h1 onclick="mibewOpenAgent();">'+c+"</h1>");d&&(a+='<img id="mibewinvitationavatar" src="'+d+'" title="'+c+'" alt="'+c+'" onclick="mibewOpenAgent();" />');a+='<p onclick="mibewOpenAgent();">'+b+"</p>";a+='<div style="clear: both;"></div>';if(b=document.getElementById("mibewinvitation"))b.innerHTML=a}mibewinvitetimer=setTimeout(function(){mibewInviteMakeRequest(mibewinviteurl,
mibewinvitetimeout)},mibewinvitetimeout)}}function mibewHideInvitation(){if(document.getElementById("mibewinvitationpopup"))document.getElementById("mibewinvitationpopup").style.display="none"}function mibewOpenAgent(){document.getElementById("mibewAgentButton")&&(document.getElementById("mibewAgentButton").onclick(),mibewHideInvitation())};

View File

@ -28,6 +28,19 @@
<arg value="soundcheck:1:common"/> <arg value="soundcheck:1:common"/>
<arg value="--js"/> <arg value="--js"/>
<arg value="soundcheck.js"/> <arg value="soundcheck.js"/>
<arg value="--module"/>
<arg value="invite_op:1:common"/>
<arg value="--js"/>
<arg value="invite_op.js"/>
</java>
<java jar="${closure.c}" fork="true">
<arg value="--module_output_path_prefix"/>
<arg value="../"/>
<arg value="--module"/>
<arg value="invite:1"/>
<arg value="--js"/>
<arg value="invite.js"/>
</java> </java>
</target> </target>

View File

@ -0,0 +1,94 @@
var mibewinviterequest;
var mibewinviteurl;
var mibewinvitetimeout;
var mibewinvitetimer;
var style = document.createElement('style');
document.getElementsByTagName('head')[0].appendChild(style);
if (!window.createPopup) {
style.appendChild(document.createTextNode(''));
style.setAttribute("type", "text/css");
}
var sheet = document.styleSheets[document.styleSheets.length - 1];
if (!window.createPopup) {
var node = document.createTextNode(mibewInviteStyle);
style.appendChild(node);
} else {
sheet.cssText = mibewInviteStyle;
}
function mibewInviteMakeRequest(url, timeout)
{
mibewinviteurl = url;
mibewinvitetimeout = timeout;
if(window.XMLHttpRequest)
{
mibewinviterequest = new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
mibewinviterequest = new ActiveXObject("MSXML2.XMLHTTP");
}
if (mibewinviterequest) {
mibewinviterequest.onreadystatechange = mibewInviteOnResponse;
}
mibewInviteSendRequest(url);
}
function mibewInviteSendRequest(url)
{
clearTimeout(mibewinvitetimer);
mibewinviterequest.open("GET", url + '&rnd=' + Math.random(1), true);
mibewinviterequest.send();
}
function mibewInviteCheckReadyState(obj)
{
if ((obj.readyState == 4) && ((obj.status == 200) || (obj.status == 304))) {return true;}
}
function mibewInviteOnResponse()
{
if(mibewInviteCheckReadyState(mibewinviterequest))
{
var response = mibewinviterequest.responseXML.documentElement;
var invite = response.getElementsByTagName('message');
if (invite[0]) {
var message = invite[0].firstChild.data;
var operator = response.getElementsByTagName('operator')[0] && response.getElementsByTagName('operator')[0].firstChild != null ? response.getElementsByTagName('operator')[0].firstChild.data : undefined;
var avatar = response.getElementsByTagName('avatar')[0] && response.getElementsByTagName('avatar')[0].firstChild != null ? response.getElementsByTagName('avatar')[0].firstChild.data : undefined;
var popuptext = '<div id="mibewinvitationpopup">';
popuptext += '<div id="mibewinvitationclose"><a href="javascript:void(0);" onclick="mibewHideInvitation();">&times;</a></div>';
if (operator) {
popuptext += '<h1 onclick="mibewOpenAgent();">' + operator + '</h1>';
}
if (avatar) {
popuptext += '<img id="mibewinvitationavatar" src="' + avatar + '" title="' + operator + '" alt="' + operator + '" onclick="mibewOpenAgent();" />';
}
popuptext += '<p onclick="mibewOpenAgent();">' + message + '</p>';
popuptext += '<div style="clear: both;"></div>';
var invitationdiv = document.getElementById("mibewinvitation");
if (invitationdiv) {
invitationdiv.innerHTML = popuptext;
}
}
mibewinvitetimer = setTimeout( function(){ mibewInviteMakeRequest(mibewinviteurl, mibewinvitetimeout) }, mibewinvitetimeout);
}
}
function mibewHideInvitation() {
if (document.getElementById('mibewinvitationpopup')) {
document.getElementById('mibewinvitationpopup').style.display='none';
}
}
function mibewOpenAgent() {
if (document.getElementById('mibewAgentButton')) {
document.getElementById('mibewAgentButton').onclick();
mibewHideInvitation();
}
}

View File

@ -0,0 +1,95 @@
/**
* @preserve This file is part of Mibew Messenger project.
* http://mibew.org
*
* Copyright (c) 2005-2011 Mibew Messenger Community
* License: http://mibew.org/license.php
*/
Ajax.InviteUpdater = Class.create();
Class.inherit( Ajax.InviteUpdater, Ajax.Base, {
initialize: function(_options) {
this.setOptions(_options);
this._options.onComplete = this.requestComplete.bind(this);
this._options.onException = this.handleException.bind(this);
this._options.onTimeout = this.handleTimeout.bind(this);
this._options.updateParams = this.updateParams.bind(this);
this._options.handleError = this.handleError.bind(this);
this._options.updateContent = this.updateContent.bind(this);
this._options.timeout = 5000;
this.frequency = (this._options.frequency || 2);
this.updater = {};
this.update();
},
handleException: function(_request, ex) {
if( this._options.handleError )
this._options.handleError("offline, reconnecting");
this.stopUpdate();
this.timer = setTimeout(this.update.bind(this), 1000);
},
handleTimeout: function(_request) {
if( this._options.handleError )
this._options.handleError("timeout, reconnecting");
this.stopUpdate();
this.timer = setTimeout(this.update.bind(this), 1000);
},
stopUpdate: function() {
if( this.updater._options )
this.updater._options.onComplete = undefined;
clearTimeout(this.timer);
},
update: function() {
if( this._options.updateParams )
this._options.parameters = (this._options.updateParams)();
this.updater = new Ajax.Request(this._options.url, this._options);
},
requestComplete: function(presponse) {
try {
var xmlRoot = Ajax.getXml(presponse);
if( xmlRoot ) {
(this._options.updateContent || Ajax.emptyFunction)( xmlRoot );
} else {
if( this._options.handleError )
this._options.handleError("reconnecting");
}
} catch(e) {
}
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
},
updateParams: function() {
return "visitor=" + this._options.visitor;
},
handleError: function(s) {
},
updateContent: function(root) {
if( root.tagName == 'invitation' ) {
var invited = NodeUtils.getNodeValue(root, "invited");
var threadid = NodeUtils.getNodeValue(root, "threadid");
if (invited == "0") {
this.stopUpdate();
window.close();
}
else if (threadid != "0") {
this.stopUpdate();
window.name = 'ImCenter' + threadid;
window.location=this._options.agentservl + '?thread=' + threadid;
}
}
}
});
EventHelper.register(window, 'onload', function(){
new Ajax.InviteUpdater(({}).extend(updaterOptions || {}));
});

View File

@ -73,7 +73,7 @@ var HtmlGenerationUtils = {
return '<table class="inner"><tr>' + content + '</tr></table>'; return '<table class="inner"><tr>' + content + '</tr></table>';
}, },
viewOpenCell: function(username,servlet,id,canview,canopen,ban,message,cantakenow) { viewOpenCell: function(username,servlet,id,canview,canopen,ban,message,cantakenow,tracked,trackedlink) {
var cellsCount = 2; var cellsCount = 2;
var link = servlet+"?thread="+id; var link = servlet+"?thread="+id;
var gen = '<td>'; var gen = '<td>';
@ -95,17 +95,40 @@ var HtmlGenerationUtils = {
gen += '</td>'; gen += '</td>';
cellsCount++; cellsCount++;
} }
if ( tracked ) {
gen += '<td class="icon">';
gen += HtmlGenerationUtils.popupLink( trackedlink+"?thread="+id, localized[6], "ImTracked"+id, '<img src="'+webimRoot+'/images/tblictrack.gif" width="15" height="15" border="0" alt="'+localized[6]+'">', 640, 480, null);
gen += '</td>';
cellsCount++;
}
if( message != "" ) { if( message != "" ) {
gen += '</tr><tr><td class="firstmessage" colspan="'+cellsCount+'"><a href="javascript:void(0)" title="'+message+'" onclick="alert(this.title);return false;">'; gen += '</tr><tr><td class="firstmessage" colspan="'+cellsCount+'"><a href="javascript:void(0)" title="'+message+'" onclick="alert(this.title);return false;">';
gen += message.length > 30 ? message.substring(0,30) + '...' : message; gen += message.length > 30 ? message.substring(0,30) + '...' : message;
gen += '</a></td>'; gen += '</a></td>';
} }
return HtmlGenerationUtils.generateOneRowTable(gen); return HtmlGenerationUtils.generateOneRowTable(gen);
}, },
banCell: function(id,banid){ banCell: function(id,banid){
return '<td class="icon">'+ return '<td class="icon">'+
HtmlGenerationUtils.popupLink( webimRoot+'/operator/ban.php?'+(banid ? 'id='+banid : 'thread='+id), localized[2], "ban"+id, '<img src="'+webimRoot+'/images/ban.gif" width="15" height="15" border="0" alt="'+localized[2]+'">', 720, 480, null)+ HtmlGenerationUtils.popupLink( webimRoot+'/operator/ban.php?'+(banid ? 'id='+banid : 'thread='+id), localized[2], "ban"+id, '<img src="'+webimRoot+'/images/ban.gif" width="15" height="15" border="0" alt="'+localized[2]+'">', 720, 480, null)+
'</td>'; '</td>';
},
viewVisOpenCell: function(username, inviteservlet, userid, trackedservlet, caninvite) {
var cellsCount = 2;
var gen = '<td>';
if(caninvite) {
gen += HtmlGenerationUtils.popupLink( inviteservlet+"?visitor="+userid, localized[7], "ImCenter"+userid, username, 640, 480, null);
} else {
gen += '<a href="#">' + username + '</a>';
}
gen += '</td>';
gen += '<td class="icon">';
var tr_link = HtmlGenerationUtils.popupLink( trackedservlet+"?visitor="+userid, localized[6], "ImTracked"+userid, '<img src="'+webimRoot+'/images/tblictrack.gif" width="15" height="15" border="0" alt="'+localized[6]+'">', 640, 480, null);
tr_link = tr_link.replace("scrollbars=0","scrollbars=1");
gen += tr_link;
gen += '</td>';
return HtmlGenerationUtils.generateOneRowTable(gen);
} }
}; };
@ -121,11 +144,15 @@ Class.inherit( Ajax.ThreadListUpdater, Ajax.Base, {
this.threadTimers = new Object(); this.threadTimers = new Object();
this.delta = 0; this.delta = 0;
this.t = this._options.table; this.t = this._options.table;
this.t2 = this._options.visitors_table;
this.periodicalUpdater = new Ajax.PeriodicalUpdater(this._options); this.periodicalUpdater = new Ajax.PeriodicalUpdater(this._options);
this.old_visitors = new Object();
this.visitors = new Object();
this.visitorTimers = new Object();
}, },
updateParams: function() { updateParams: function() {
return "since=" + this._options.lastrevision + "&status=" + this._options.istatus + (this._options.showonline ? "&showonline=1" : ""); return "since=" + this._options.lastrevision + "&status=" + this._options.istatus + (this._options.showonline ? "&showonline=1" : "") + (this._options.showvisitors ? "&showvisitors=1" : "");
}, },
setStatus: function(msg) { setStatus: function(msg) {
@ -204,7 +231,7 @@ Class.inherit( Ajax.ThreadListUpdater, Ajax.Base, {
row.className = (ban == "blocked" && stateid != "chat") ? "ban" : "in"+stateid; row.className = (ban == "blocked" && stateid != "chat") ? "ban" : "in"+stateid;
row.id = "thr"+id; row.id = "thr"+id;
this.threadTimers[id] = new Array(vtime,modified,stateid); this.threadTimers[id] = new Array(vtime,modified,stateid);
CommonUtils.insertCell(row, "name", "visitor", null, null, HtmlGenerationUtils.viewOpenCell(vname,this._options.agentservl,id,canview,canopen,ban,message,stateid!='chat')); CommonUtils.insertCell(row, "name", "visitor", null, null, HtmlGenerationUtils.viewOpenCell(vname,this._options.agentservl,id,canview,canopen,ban,message,stateid!='chat',this._options.showvisitors, this._options.trackedservl));
CommonUtils.insertCell(row, "contid", "visitor", "center", null, vaddr ); CommonUtils.insertCell(row, "contid", "visitor", "center", null, vaddr );
CommonUtils.insertCell(row, "state", "visitor", "center", null, vstate ); CommonUtils.insertCell(row, "state", "visitor", "center", null, vstate );
CommonUtils.insertCell(row, "op", "visitor", "center", null, agent ); CommonUtils.insertCell(row, "op", "visitor", "center", null, agent );
@ -217,7 +244,7 @@ Class.inherit( Ajax.ThreadListUpdater, Ajax.Base, {
} else { } else {
this.threadTimers[id] = new Array(vtime,modified,stateid); this.threadTimers[id] = new Array(vtime,modified,stateid);
row.className = (ban == "blocked" && stateid != "chat") ? "ban" : "in"+stateid; row.className = (ban == "blocked" && stateid != "chat") ? "ban" : "in"+stateid;
setcell(this.t, row,"name",HtmlGenerationUtils.viewOpenCell(vname,this._options.agentservl,id,canview,canopen,ban,message,stateid!='chat')); setcell(this.t, row,"name",HtmlGenerationUtils.viewOpenCell(vname,this._options.agentservl,id,canview,canopen,ban,message,stateid!='chat',this._options.showvisitors, this._options.trackedservl));
setcell(this.t, row,"contid",vaddr); setcell(this.t, row,"contid",vaddr);
setcell(this.t, row,"state",vstate); setcell(this.t, row,"state",vstate);
setcell(this.t, row,"op",agent); setcell(this.t, row,"op",agent);
@ -332,6 +359,144 @@ Class.inherit( Ajax.ThreadListUpdater, Ajax.Base, {
div.innerHTML = names.join(', '); div.innerHTML = names.join(', ');
}, },
updateVisitorsTimers: function() {
for (var i in this.visitorTimers) {
if (this.visitorTimers[i] != null) {
var value = this.visitorTimers[i];
var row = CommonUtils.getRow("vis"+i, this.t2);
if( row != null ) {
function setcell(_table, row,id,pcontent) {
var cell = CommonUtils.getCell( id, row, _table );
if( cell )
cell.innerHTML = pcontent;
}
setcell(this.t2, row,"time",this.getTimeSince(value[0]));
setcell(this.t2, row,"modified",this.getTimeSince(value[1]));
if (value[2] != null)
setcell(this.t2, row,"invitationtime",this.getTimeSince(value[2]));
}
}
}
},
updateVisitor: function(node) {
var id, invited = false;
for( var i = 0; i < node.attributes.length; i++ ) {
var attr = node.attributes[i];
if( attr.nodeName == "id" )
id = attr.nodeValue;
}
function setcell(_table, row,id,pcontent) {
var cell = CommonUtils.getCell( id, row, _table );
if( cell )
cell.innerHTML = pcontent;
}
var addr = NodeUtils.getNodeValue(node,"addr");
var username = NodeUtils.getNodeValue(node,"username");
var useragent = NodeUtils.getNodeValue(node,"useragent");
var time = NodeUtils.getNodeValue(node,"time");
var modified = NodeUtils.getNodeValue(node,"modified");
var invitations = NodeUtils.getNodeValue(node,"invitations");
var chats = NodeUtils.getNodeValue(node,"chats");
var operator = null;
var invitationtime = null;
var invitation = node.getElementsByTagName("invitation")[0];
for( var i = 0; i < invitation.childNodes.length; i++ ) {
var childnode = invitation.childNodes[i];
if( childnode.tagName == 'operator' ) {
operator = childnode.firstChild.nodeValue;
}
else if ( childnode.tagName == 'invitationtime' ) {
invitationtime = childnode.firstChild.nodeValue;
}
}
var state = (operator == null) ? 'free' : 'invited';
var row = CommonUtils.getRow("vis"+id, this.t2);
var startRow = CommonUtils.getRow("vis" + state, this.t2);
var endRow = CommonUtils.getRow("vis" + state + "end", this.t2);
if( row != null && (row.rowIndex <= startRow.rowIndex || row.rowIndex >= endRow.rowIndex ) ) {
this.t2.deleteRow(row.rowIndex);
this.visitorTimers[id] = null;
row = null;
}
if (row == null) {
row = this.t2.insertRow(startRow.rowIndex+1);
row.id = "vis"+id;
this.visitorTimers[id] = new Array(time, modified, invitationtime);
CommonUtils.insertCell(row, "username", "visitor", null, null, HtmlGenerationUtils.viewVisOpenCell(username, this._options.inviteservl, id, this._options.trackedservl, operator==null));
CommonUtils.insertCell(row, "addr", "visitor", "center", null, addr);
CommonUtils.insertCell(row, "time", "visitor", "center", null, this.getTimeSince(time) );
CommonUtils.insertCell(row, "modified", "visitor", "center", null, this.getTimeSince(modified) );
CommonUtils.insertCell(row, "operator", "visitor", "center", null, (operator != null) ? operator : '-');
CommonUtils.insertCell(row, "invitationtime", "visitor", "center", null, (operator != null ? this.getTimeSince(invitationtime) : '-') );
CommonUtils.insertCell(row, "invitations", "visitor", "center", null, invitations + ' / ' + chats);
CommonUtils.insertCell(row, "useragent", "visitor", "center", null, useragent);
}
else {
this.visitorTimers[id] = new Array(time, modified, invitationtime);
setcell(this.t2, row, "username",HtmlGenerationUtils.viewVisOpenCell(username, this._options.inviteservl, id, this._options.trackedservl, operator==null));
setcell(this.t2, row, "addr", addr);
setcell(this.t2, row, "operator", (operator != null) ? operator : '-');
setcell(this.t2, row, "time", this.getTimeSince(time) );
setcell(this.t2, row, "modified", this.getTimeSince(modified) );
setcell(this.t2, row, "invitationtime", (operator != null ? this.getTimeSince(invitationtime) : '-') );
setcell(this.t2, row, "invitations", invitations + ' / ' + chats);
setcell(this.t2, row, "useragent", useragent);
}
this.visitors[id] = 1;
return false;
},
removeOldVisitors: function() {
for (id in this.old_visitors) {
if (this.visitors[id] === undefined) {
var row = CommonUtils.getRow("vis"+id, this.t2);
if( row ) {
this.t2.deleteRow(row.rowIndex);
}
this.visitorTimers[id] = null;
}
}
},
updateVisitorsList: function(visitors) {
var _status = $("visstatustd");
if( _status) {
_status.innerHTML = (visitors > 0) ? "" : this._options.novisitors;
_status.height = (visitors > 0) ? 5 : 30;
}
},
updateVisitors: function(root) {
this.old_visitors = this.visitors;
this.visitors = new Object();
var visitors_cnt = 0;
for( var i = 0; i < root.childNodes.length; i++ ) {
var node = root.childNodes[i];
if( node.tagName == 'visitor' ) {
visitors_cnt++;
this.updateVisitor(node);
}
}
this.updateVisitorsTimers();
this.removeOldVisitors();
this.updateVisitorsList(visitors_cnt);
},
updateContent: function(root) { updateContent: function(root) {
if( root.tagName == 'update' ) { if( root.tagName == 'update' ) {
for( var i = 0; i < root.childNodes.length; i++ ) { for( var i = 0; i < root.childNodes.length; i++ ) {
@ -341,6 +506,8 @@ Class.inherit( Ajax.ThreadListUpdater, Ajax.Base, {
this.updateThreads(node); this.updateThreads(node);
} else if (node.tagName == 'operators') { } else if (node.tagName == 'operators') {
this.updateOperators(node); this.updateOperators(node);
} else if (node.tagName == 'visitors') {
this.updateVisitors(node);
} }
} }
} else if( root.tagName == 'error' ) { } else if( root.tagName == 'error' ) {
@ -377,7 +544,7 @@ Behaviour.register({
EventHelper.register(window, 'onload', function(){ EventHelper.register(window, 'onload', function(){
webimRoot = updaterOptions.wroot; webimRoot = updaterOptions.wroot;
new Ajax.ThreadListUpdater(({table:$("threadlist"),status:$("connstatus"),istatus:0}).extend(updaterOptions || {})); new Ajax.ThreadListUpdater(({table:$("threadlist"),status:$("connstatus"),istatus:0,visitors_table:$("visitorslist")}).extend(updaterOptions || {}));
if(!updaterOptions.havemenu) { if(!updaterOptions.havemenu) {
togglemenu(); togglemenu();
} }

View File

@ -20,6 +20,8 @@
* Pavel Petroshenko - history search * Pavel Petroshenko - history search
*/ */
require_once(dirname(__FILE__).'/track.php');
$connection_timeout = 30; // sec $connection_timeout = 30; // sec
$namecookie = "WEBIM_Data"; $namecookie = "WEBIM_Data";
@ -88,7 +90,7 @@ function post_message($threadid, $kind, $message, $from = null, $agentid = null)
function prepare_html_message($text) function prepare_html_message($text)
{ {
$escaped_text = htmlspecialchars($text); $escaped_text = htmlspecialchars($text);
$text_w_links = preg_replace('/(http|ftp):\/\/\S*/', '<a href="$0" target="_blank">$0</a>', $escaped_text); $text_w_links = preg_replace('/(https?|ftp):\/\/\S*/', '<a href="$0" target="_blank">$0</a>', $escaped_text);
$multiline = str_replace("\n", "<br/>", $text_w_links); $multiline = str_replace("\n", "<br/>", $text_w_links);
return $multiline; return $multiline;
} }
@ -445,6 +447,13 @@ function setup_chatview_for_operator($thread, $operator)
$page['neediframesrc'] = needsFramesrc(); $page['neediframesrc'] = needsFramesrc();
$page['historyParams'] = array("userid" => "" . $thread['userid']); $page['historyParams'] = array("userid" => "" . $thread['userid']);
$page['historyParamsLink'] = add_params($webimroot . "/operator/userhistory.php", $page['historyParams']); $page['historyParamsLink'] = add_params($webimroot . "/operator/userhistory.php", $page['historyParams']);
if ($settings['enabletracking']) {
$link = connect();
$visitor = track_get_visitor_by_threadid($thread['threadid'], $link);
$page['trackedParams'] = array("visitor" => "" . $visitor['visitorid']);
$page['trackedParamsLink'] = add_params($webimroot . "/operator/tracked.php", $page['trackedParams']);
mysql_close($link);
}
$predefinedres = ""; $predefinedres = "";
$canned_messages = load_canned_messages($thread['locale'], $thread['groupid']); $canned_messages = load_canned_messages($thread['locale'], $thread['groupid']);
foreach ($canned_messages as $answer) { foreach ($canned_messages as $answer) {

View File

@ -626,6 +626,7 @@ $settings = array(
'usercanchangename' => '1', 'usercanchangename' => '1',
'enablegroups' => '0', 'enablegroups' => '0',
'enablestatistics' => '1', 'enablestatistics' => '1',
'enabletracking' => '0',
'enablepresurvey' => '1', 'enablepresurvey' => '1',
'surveyaskmail' => '0', 'surveyaskmail' => '0',
'surveyaskgroup' => '1', 'surveyaskgroup' => '1',
@ -638,6 +639,12 @@ $settings = array(
'updatefrequency_operator' => 2, 'updatefrequency_operator' => 2,
'updatefrequency_chat' => 2, 'updatefrequency_chat' => 2,
'updatefrequency_oldchat' => 7, 'updatefrequency_oldchat' => 7,
'updatefrequency_tracking' => 10,
'visitors_limit' => 20, /* Number of visitors to look over */
'invitation_lifetime' => 60, /* Lifetime for invitation to chat */
'tracking_lifetime' => 600, /* Time to store tracked old visitors' data */
); );
$settingsloaded = false; $settingsloaded = false;
$settings_in_db = array(); $settings_in_db = array();

View File

@ -21,6 +21,7 @@
function generate_button($title, $locale, $style, $group, $inner, $showhost, $forcesecure, $modsecurity) function generate_button($title, $locale, $style, $group, $inner, $showhost, $forcesecure, $modsecurity)
{ {
global $settings;
$link = get_app_location($showhost, $forcesecure) . "/client.php"; $link = get_app_location($showhost, $forcesecure) . "/client.php";
if ($locale) if ($locale)
$link = append_query($link, "locale=$locale"); $link = append_query($link, "locale=$locale");
@ -33,6 +34,15 @@ function generate_button($title, $locale, $style, $group, $inner, $showhost, $fo
$jslink = append_query("'" . $link, "url='+escape(document.location.href$modsecfix)+'&amp;referrer='+escape(document.referrer$modsecfix)"); $jslink = append_query("'" . $link, "url='+escape(document.location.href$modsecfix)+'&amp;referrer='+escape(document.referrer$modsecfix)");
$temp = get_popup($link, "$jslink", $temp = get_popup($link, "$jslink",
$inner, $title, "webim", "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width=640,height=480,resizable=1"); $inner, $title, "webim", "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width=640,height=480,resizable=1");
if ($settings['enabletracking']) {
$temp = preg_replace('/^(<a )/', '\1id="mibewAgentButton" ', $temp);
$temp .= '<div id="mibewinvitation"></div><script type="text/javascript">var mibewInviteStyle = \'@import url(';
$temp .= get_app_location($showhost, $forcesecure);
$temp .= '/invite.css);\';</script><script type="text/javascript" src="';
$temp .= get_app_location($showhost, $forcesecure);
$temp .= '/js/invite.js"></script><script type="text/javascript">mibewInviteMakeRequest(\'';
$temp .= get_app_location($showhost, $forcesecure) . '/invite.php?entry=\' + escape(document.referrer) + \'&lang=ru\', ' . $settings['updatefrequency_tracking'] . '*1000);</script>';
}
return "<!-- mibew button -->" . $temp . "<!-- / mibew button -->"; return "<!-- mibew button -->" . $temp . "<!-- / mibew button -->";
} }

View File

@ -0,0 +1,77 @@
<?php
/*
* This file is part of Mibew Messenger project.
*
* Copyright (c) 2005-2011 Mibew Messenger Community
* All rights reserved. The contents of this file are subject to the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and
* is available at http://www.eclipse.org/legal/epl-v10.html
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which case
* the provisions of the GPL are applicable instead of those above. If you wish
* to allow use of your version of this file only under the terms of the GPL, and
* not to allow others to use your version of this file under the terms of the
* EPL, indicate your decision by deleting the provisions above and replace them
* with the notice and other provisions required by the GPL.
*
* Contributors:
* Fedor Fetisov - tracking and inviting implementation
*/
function invitation_state($visitorid, $link)
{
global $mysqlprefix;
$query = "select invited, threadid from ${mysqlprefix}chatsitevisitor where visitorid = '" . mysql_real_escape_string($visitorid) . "'";
$result = select_one_row($query, $link);
if (!$result) {
$result['invited'] = 0;
$result['threadid'] = 0;
}
return $result;
}
function invitation_invite($visitorid, $operatorid, $link)
{
global $mysqlprefix;
if (!invitation_check($visitorid, $link)) {
$query = "update ${mysqlprefix}chatsitevisitor set invited = 1, invitedby = '" . mysql_real_escape_string($operatorid) . "', invitationtime = now(), invitations = invitations + 1 where visitorid = '" . mysql_real_escape_string($visitorid) . "'";
perform_query($query, $link);
return invitation_check($visitorid, $link);
}
else {
return FALSE;
}
}
function invitation_check($visitorid, $link)
{
global $mysqlprefix;
$query = "select invitedby from ${mysqlprefix}chatsitevisitor where invited and visitorid = '" . mysql_real_escape_string($visitorid) . "'" .
" and lasttime < invitationtime and threadid is null";
$result = select_one_row($query, $link);
return ($result && isset($result['invitedby']) && $result['invitedby']) ? $result['invitedby'] : FALSE;
}
function invitation_accept($visitorid, $threadid, $link)
{
global $mysqlprefix;
$query = "update ${mysqlprefix}chatsitevisitor set threadid = " . $threadid . ", chats = chats + 1 where visitorid = '" . mysql_real_escape_string($visitorid) . "'";
perform_query($query, $link);
$query = "select invitedby from ${mysqlprefix}chatsitevisitor where visitorid = '" . mysql_real_escape_string($visitorid) . "'";
$result = select_one_row($query, $link);
if ($result && isset($result['invitedby']) && $result['invitedby']) {
return $result['invitedby'];
}
else {
return FALSE;
}
}
?>

View File

@ -0,0 +1,121 @@
<?php
/*
* This file is part of Mibew Messenger project.
*
* Copyright (c) 2005-2011 Mibew Messenger Community
* All rights reserved. The contents of this file are subject to the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and
* is available at http://www.eclipse.org/legal/epl-v10.html
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which case
* the provisions of the GPL are applicable instead of those above. If you wish
* to allow use of your version of this file only under the terms of the GPL, and
* not to allow others to use your version of this file under the terms of the
* EPL, indicate your decision by deleting the provisions above and replace them
* with the notice and other provisions required by the GPL.
*
* Contributors:
* Fedor Fetisov - tracking and inviting implementation
*/
require_once(dirname(__FILE__).'/chat.php');
function track_visitor($visitorid, $entry, $referer, $link)
{
global $mysqlprefix;
$visitor = track_get_visitor_by_id($visitorid, $link);
if (FALSE === $visitor) {
$visitor = track_visitor_start($entry, $referer, $link);
return $visitor;
}
else {
perform_query(sprintf("update ${mysqlprefix}chatsitevisitor set lasttime = CURRENT_TIMESTAMP, path = '%s' where visitorid=" . $visitor['visitorid'],
mysql_real_escape_string(track_build_path($referer, $visitor['path']))), $link);
return $visitor['visitorid'];
}
}
function track_visitor_start($entry, $referer, $link)
{
global $mysqlprefix;
$visitor = visitor_from_request();
perform_query(sprintf("insert into ${mysqlprefix}chatsitevisitor (userid, username, firsttime, lasttime, entry, path, details) values ('%s', '%s', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, '%s', '%s', '%s')",
mysql_real_escape_string($visitor['id']),
mysql_real_escape_string($visitor['name']),
mysql_real_escape_string($entry),
mysql_real_escape_string(track_build_path($referer, '')),
mysql_real_escape_string(track_build_details())), $link);
$id = mysql_insert_id($link);
return $id ? $id : 0;
}
function track_get_visitor_by_id($visitorid, $link)
{
global $mysqlprefix;
$visitor = select_one_row(
"select * from ${mysqlprefix}chatsitevisitor where visitorid = $visitorid", $link);
return $visitor;
}
function track_get_visitor_by_threadid($threadid, $link)
{
global $mysqlprefix;
$visitor = select_one_row(
"select * from ${mysqlprefix}chatsitevisitor where threadid = $threadid", $link);
return $visitor;
}
function track_build_path($referer, $path)
{
if ($path !== '') {
$path = unserialize($path);
krsort($path);
list($lasttime, $lastpage) = each($path);
if ($referer != $lastpage) {
$path[time()] = $referer;
}
}
else {
$path[time()] = $referer;
}
$path = serialize($path);
return $path;
}
function track_retrieve_path($visitor)
{
return unserialize($visitor['path']);
}
function track_build_details()
{
$result = array(
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'remote_host' => get_remote_host()
);
return serialize($result);
}
function track_retrieve_details($visitor)
{
return unserialize($visitor['details']);
}
?>

View File

@ -78,6 +78,7 @@ chat.thread.state_wait=In queue
chat.thread.state_wait_for_another_agent=Waiting for operator chat.thread.state_wait_for_another_agent=Waiting for operator
chat.visitor.email=E-Mail: {0} chat.visitor.email=E-Mail: {0}
chat.visitor.info=Info: {0} chat.visitor.info=Info: {0}
chat.visitor.invitation.accepted=Visitor accepted invitation from operator {0}
chat.wait=Thank you for contacting us. An operator will be with you shortly... chat.wait=Thank you for contacting us. An operator will be with you shortly...
chat.window.chatting_with=You chat with: chat.window.chatting_with=You chat with:
chat.window.close_title=Close chat chat.window.close_title=Close chat
@ -92,6 +93,7 @@ chat.window.title.user=Mibew Messenger
chat.window.toolbar.mail_history=Send chat history by e-mail chat.window.toolbar.mail_history=Send chat history by e-mail
chat.window.toolbar.redirect_user=Redirect visitor to another operator chat.window.toolbar.redirect_user=Redirect visitor to another operator
chat.window.toolbar.refresh=Refresh chat.window.toolbar.refresh=Refresh
chat.window.toolbar.mute=Sound on/off
clients.how_to=To answer the visitor click on his/her name in the list. clients.how_to=To answer the visitor click on his/her name in the list.
clients.intro=This page displays a list of awaiting visitors. clients.intro=This page displays a list of awaiting visitors.
clients.no_clients=The list of awaiting visitors is empty clients.no_clients=The list of awaiting visitors is empty
@ -200,6 +202,9 @@ install.updatedb=Please, run <a href="{0}">Update wizard</a> to adjust your data
installed.login_link=Proceed to login page installed.login_link=Proceed to login page
installed.message=<b>Application installed successfully.</b> installed.message=<b>Application installed successfully.</b>
installed.notice=You can logon as <b>admin</b> with empty password.<br/><br/><font color="#c13030"><b>!!! For security reasons, please change your password immediately and remove {0} folder from your server.</b></font> installed.notice=You can logon as <b>admin</b> with empty password.<br/><br/><font color="#c13030"><b>!!! For security reasons, please change your password immediately and remove {0} folder from your server.</b></font>
invitation.message=Hello, how can I help you?
invitation.sent=Invitation sent to visitor. Please wait for a while.
invitation.title=Invitation
lang.choose=Choose your language lang.choose=Choose your language
leavemail.body=Your have a message from {0}:\n\n{2}\n\nHis email: {1}\n{3}\n--- \nYours site messenger leavemail.body=Your have a message from {0}:\n\n{2}\n\nHis email: {1}\n{3}\n--- \nYours site messenger
leavemail.subject=Question from {0} leavemail.subject=Question from {0}
@ -248,6 +253,7 @@ page.analysis.search.head_messages=Visitor's messages
page.analysis.search.head_name=Name page.analysis.search.head_name=Name
page.analysis.search.head_operator=Operator page.analysis.search.head_operator=Operator
page.analysis.search.head_time=Time in chat page.analysis.search.head_time=Time in chat
page.analysis.trackedpath.title=Tracked visitor's path
page.analysis.userhistory.intro=You can find chat history of your visitors here. page.analysis.userhistory.intro=You can find chat history of your visitors here.
page.analysis.userhistory.title=Visits history page.analysis.userhistory.title=Visits history
page.chat.old_browser.close=Close... page.chat.old_browser.close=Close...
@ -366,7 +372,9 @@ pending.table.head.operator=Operator
pending.table.head.state=State pending.table.head.state=State
pending.table.head.total=Total time pending.table.head.total=Total time
pending.table.head.waittime=Waiting time pending.table.head.waittime=Waiting time
pending.table.invite=Invite to chat
pending.table.speak=Click to chat with the visitor pending.table.speak=Click to chat with the visitor
pending.table.tracked=Tracked visitor's path
pending.table.view=Watch the chat pending.table.view=Watch the chat
permission.admin=System administration: settings, operators management, button generation permission.admin=System administration: settings, operators management, button generation
permission.modifyprofile=Ability to modify profile permission.modifyprofile=Ability to modify profile
@ -430,6 +438,8 @@ settings.enablessl.description=Please, note that your web server should be confi
settings.enablessl=Allow secure connections (SSL) settings.enablessl=Allow secure connections (SSL)
settings.enablestatistics.description=Adds page with messenger usage reports. settings.enablestatistics.description=Adds page with messenger usage reports.
settings.enablestatistics=Enable "Statistics" settings.enablestatistics=Enable "Statistics"
settings.enabletracking.description=Enable tracking of visitors' activity on your site and ability to invite visitors to chat.
settings.enabletracking=Enable "Tracking and inviting"
settings.forcessl.description=Show chats only through https connection settings.forcessl.description=Show chats only through https connection
settings.forcessl=Force all chats to be secure settings.forcessl=Force all chats to be secure
settings.frequencychat.description=Specify the poll interval in seconds. Default is 2 seconds. settings.frequencychat.description=Specify the poll interval in seconds. Default is 2 seconds.
@ -438,12 +448,16 @@ settings.frequencyoldchat.description=Old browsers need to refresh the whole pag
settings.frequencyoldchat=Page refresh time for old browsers settings.frequencyoldchat=Page refresh time for old browsers
settings.frequencyoperator.description=Specify the poll interval in seconds. Default is 2 seconds. settings.frequencyoperator.description=Specify the poll interval in seconds. Default is 2 seconds.
settings.frequencyoperator=Operator's console refresh time settings.frequencyoperator=Operator's console refresh time
settings.frequencytracking.description=Specify the poll interval in seconds. Default is 10 seconds.
settings.frequencytracking=Tracking refresh time
settings.geolink.description=Each IP becomes a link opening in new window. {ip} is substituted with a real ip. settings.geolink.description=Each IP becomes a link opening in new window. {ip} is substituted with a real ip.
settings.geolink=Link to an external geolocation service settings.geolink=Link to an external geolocation service
settings.geolinkparams.description=Window size and toolbars hiding settings.geolinkparams.description=Window size and toolbars hiding
settings.geolinkparams=Geolocation window options settings.geolinkparams=Geolocation window options
settings.host.description=Destination for you company name or logo link settings.host.description=Destination for you company name or logo link
settings.host=URL of your website settings.host=URL of your website
settings.invitationlifetime.description=Specify the lifetime of invitation in seconds. Default is 60 seconds.
settings.invitationlifetime=Invitation lifetime
settings.leavemessage_captcha.description=Protection against automated spam (captcha) settings.leavemessage_captcha.description=Protection against automated spam (captcha)
settings.leavemessage_captcha=Force visitor to enter verification code when leaving message settings.leavemessage_captcha=Force visitor to enter verification code when leaving message
settings.logo.description=Enter http address of your company logo settings.logo.description=Enter http address of your company logo
@ -466,10 +480,14 @@ settings.survey.askmail=Ask visitor e-mail
settings.survey.askmessage.description=Show/hide initial question field in the survey settings.survey.askmessage.description=Show/hide initial question field in the survey
settings.survey.askmessage=Show initial question field settings.survey.askmessage=Show initial question field
settings.title=Messenger settings settings.title=Messenger settings
settings.trackinglifetime.description=Specify the lifetime of old visitor's tracks in seconds. Default is 600 seconds.
settings.trackinglifetime=Track lifetime
settings.usercanchangename.description=Turn off to hide edit box from chat window settings.usercanchangename.description=Turn off to hide edit box from chat window
settings.usercanchangename=Allows users to change their names settings.usercanchangename=Allows users to change their names
settings.usernamepattern.description=How to build visitor identifying string from {name}, {id} or {addr}. Default: {name} settings.usernamepattern.description=How to build visitor identifying string from {name}, {id} or {addr}. Default: {name}
settings.usernamepattern=Visitor's identifier settings.usernamepattern=Visitor's identifier
settings.visitorslimit.description=Specify the number of items to display in tracked visitors list. Default is 20. Set 0 for all visitors (not recommended).
settings.visitorslimit=Limit for tracked visitors list
settings.wrong.email=Enter proper email address settings.wrong.email=Enter proper email address
settings.wrong.onehostconnections="Max number of threads" field should be number settings.wrong.onehostconnections="Max number of threads" field should be number
site.title=mibew.org site.title=mibew.org
@ -499,6 +517,12 @@ topMenu.logoff=Exit
topMenu.main=Home topMenu.main=Home
topMenu.users.nomenu=without menu topMenu.users.nomenu=without menu
topMenu.users=Visitors topMenu.users=Visitors
tracked.date=Visit time
tracked.empty.referrer=direct visit
tracked.intro=This page displays tracked history of visitor's activity on site.
tracked.link=Visited page
tracked.path=Tracked path of visitor
tracked.visitor.came.from=Visitor came from
translate.direction=Direction: translate.direction=Direction:
translate.show.all=All strings translate.show.all=All strings
translate.show.foradmin=Strings for administrator translate.show.foradmin=Strings for administrator
@ -516,3 +540,15 @@ updates.intro=Messenger updates.
updates.latest=Latest version: updates.latest=Latest version:
updates.news=News: updates.news=News:
updates.title=Updates updates.title=Updates
visitors.how_to=To invite the visitor to chat click on his/her name in the list.
visitors.intro=The table below represents a list of visitors ready to chat on your site.
visitors.no_visitors=There are no visitors ready to chat on your site at present time
visitors.table.head.contactid=Visitor's address
visitors.table.head.etc=Misc
visitors.table.head.firsttimeonsite=First seen
visitors.table.head.invitations=Invitations / Chats
visitors.table.head.invitationtime=Invitation time
visitors.table.head.invited.by=Invited by
visitors.table.head.lasttimeonsite=Last seen
visitors.table.head.name=Name
visitors.title=Visitors on site

View File

@ -33,6 +33,7 @@ chat.window.send_message_short
chat.window.title.agent chat.window.title.agent
chat.window.title.user chat.window.title.user
chat.window.toolbar.mail_history chat.window.toolbar.mail_history
chat.window.toolbar.mute
chat.window.toolbar.redirect_user chat.window.toolbar.redirect_user
chat.window.toolbar.refresh chat.window.toolbar.refresh
company.title company.title
@ -46,6 +47,7 @@ harderrors.header
image.chat.history image.chat.history
image.chat.message image.chat.message
image.chat.sprite image.chat.sprite
invitation.message
leavemail.body leavemail.body
leavemail.subject leavemail.subject
leavemessage.close leavemessage.close

View File

@ -43,6 +43,7 @@ chat.thread.state_closed
chat.thread.state_loading chat.thread.state_loading
chat.thread.state_wait chat.thread.state_wait
chat.thread.state_wait_for_another_agent chat.thread.state_wait_for_another_agent
chat.visitor.invitation.accepted
clients.how_to clients.how_to
clients.intro clients.intro
clients.no_clients clients.no_clients
@ -75,6 +76,8 @@ image.button.save
image.button.search image.button.search
install.newfeatures install.newfeatures
install.updatedb install.updatedb
invitation.sent
invitation.title
lang.choose lang.choose
leftMenu.client_agents leftMenu.client_agents
leftMenu.client_gen_button leftMenu.client_gen_button
@ -102,6 +105,7 @@ page.analysis.search.head_messages
page.analysis.search.head_name page.analysis.search.head_name
page.analysis.search.head_operator page.analysis.search.head_operator
page.analysis.search.head_time page.analysis.search.head_time
page.analysis.trackedpath.title
page.analysis.userhistory.intro page.analysis.userhistory.intro
page.analysis.userhistory.title page.analysis.userhistory.title
page.gen_button.default_group page.gen_button.default_group
@ -136,7 +140,9 @@ pending.table.head.operator
pending.table.head.state pending.table.head.state
pending.table.head.total pending.table.head.total
pending.table.head.waittime pending.table.head.waittime
pending.table.invite
pending.table.speak pending.table.speak
pending.table.tracked
pending.table.view pending.table.view
permission.admin permission.admin
permission.takeover permission.takeover
@ -197,3 +203,21 @@ topMenu.logoff
topMenu.main topMenu.main
topMenu.users topMenu.users
topMenu.users.nomenu topMenu.users.nomenu
tracked.date
tracked.empty.referrer
tracked.intro
tracked.link
tracked.path
tracked.visitor.came.from
visitors.how_to
visitors.intro
visitors.no_visitors
visitors.table.head.contactid
visitors.table.head.etc
visitors.table.head.firsttimeonsite
visitors.table.head.invitations
visitors.table.head.invitationtime
visitors.table.head.invited.by
visitors.table.head.lasttimeonsite
visitors.table.head.name
visitors.title

View File

@ -78,6 +78,7 @@ chat.thread.state_wait=
chat.thread.state_wait_for_another_agent=Ожидание оператора chat.thread.state_wait_for_another_agent=Ожидание оператора
chat.visitor.email=E-Mail: {0} chat.visitor.email=E-Mail: {0}
chat.visitor.info=О Посетителе: {0} chat.visitor.info=О Посетителе: {0}
chat.visitor.invitation.accepted=Посетитель принял приглашение от оператора {0}
chat.wait=Пожалуйста, подождите немного, к Вам присоединится оператор.. chat.wait=Пожалуйста, подождите немного, к Вам присоединится оператор..
chat.window.chatting_with=Вы общаетесь с: chat.window.chatting_with=Вы общаетесь с:
chat.window.close_title=Закрыть диалог chat.window.close_title=Закрыть диалог
@ -92,6 +93,7 @@ chat.window.title.user=Mibew
chat.window.toolbar.mail_history=Отправить историю диалога по электронной почте chat.window.toolbar.mail_history=Отправить историю диалога по электронной почте
chat.window.toolbar.redirect_user=Перенаправить посетителя другому оператору chat.window.toolbar.redirect_user=Перенаправить посетителя другому оператору
chat.window.toolbar.refresh=Обновить содержимое диалога chat.window.toolbar.refresh=Обновить содержимое диалога
chat.window.toolbar.mute=Вкл/выкл звук
clients.how_to=Для ответа посетителю кликните на соответствующее имя в списке. clients.how_to=Для ответа посетителю кликните на соответствующее имя в списке.
clients.intro=На этой странице можно просмотреть список ожидающих ответа посетителей. clients.intro=На этой странице можно просмотреть список ожидающих ответа посетителей.
clients.no_clients=В этой очереди ожидающих посетителей нет clients.no_clients=В этой очереди ожидающих посетителей нет
@ -151,6 +153,7 @@ form.field.login.description=
form.field.login=Логин form.field.login=Логин
form.field.mail.description=Для уведомлений и восстановления пароля. form.field.mail.description=Для уведомлений и восстановления пароля.
form.field.mail=Адрес электронной почты form.field.mail=Адрес электронной почты
form.field.mail.description=Для получения извещений и восстановления пароля.
form.field.message=Сообщение form.field.message=Сообщение
form.field.name=Ваше имя form.field.name=Ваше имя
form.field.password.description=Введите новый пароль или оставьте поле пустым, чтобы сохранить старый. form.field.password.description=Введите новый пароль или оставьте поле пустым, чтобы сохранить старый.
@ -200,6 +203,9 @@ install.updatedb=
installed.login_link=Войти в систему installed.login_link=Войти в систему
installed.message=<b>Установка успешно завершена. </b> installed.message=<b>Установка успешно завершена. </b>
installed.notice=Вы можете войти в систему как <b>admin</b> с пустым паролем.<br/><br/><font color="#c13030"><b>!!! В целях безопасности, удалите, пожалуйста, каталог {0} с вашего сервера и поменяйте пароль.</b></font> installed.notice=Вы можете войти в систему как <b>admin</b> с пустым паролем.<br/><br/><font color="#c13030"><b>!!! В целях безопасности, удалите, пожалуйста, каталог {0} с вашего сервера и поменяйте пароль.</b></font>
invitation.message=Здравствуйте! Могу ли я Вам помочь?
invitation.sent=Приглашение отправлено посетителю. Пожалуйста, немного подождите.
invitation.title=Приглашение
lang.choose=Выберите ваш язык lang.choose=Выберите ваш язык
leavemail.body=Ваш посетитель '{0}' оставил сообщение:\n\n{2}\n\nЕmail: {1}\n{3}\n--- \nС уважением,\nВаш Веб Мессенджер leavemail.body=Ваш посетитель '{0}' оставил сообщение:\n\n{2}\n\nЕmail: {1}\n{3}\n--- \nС уважением,\nВаш Веб Мессенджер
leavemail.subject=Вопрос от {0} leavemail.subject=Вопрос от {0}
@ -248,6 +254,7 @@ page.analysis.search.head_messages=
page.analysis.search.head_name=Имя page.analysis.search.head_name=Имя
page.analysis.search.head_operator=Оператор page.analysis.search.head_operator=Оператор
page.analysis.search.head_time=Время в диалоге page.analysis.search.head_time=Время в диалоге
page.analysis.trackedpath.title=Отслеженный путь посетителя
page.analysis.userhistory.intro=На данной странице Вы можете увидеть все диалоги с Вашим посетителем. page.analysis.userhistory.intro=На данной странице Вы можете увидеть все диалоги с Вашим посетителем.
page.analysis.userhistory.title=История диалогов page.analysis.userhistory.title=История диалогов
page.chat.old_browser.close=Закрыть... page.chat.old_browser.close=Закрыть...
@ -366,7 +373,9 @@ pending.table.head.operator=
pending.table.head.state=Состояние pending.table.head.state=Состояние
pending.table.head.total=Общее время pending.table.head.total=Общее время
pending.table.head.waittime=Время ожидания pending.table.head.waittime=Время ожидания
pending.table.invite=Отправить приглашение к диалогу
pending.table.speak=Нажмите для того, чтобы обслужить посетителя pending.table.speak=Нажмите для того, чтобы обслужить посетителя
pending.table.tracked=Отслеженный путь посетителя
pending.table.view=Подключиться к диалогу в режиме просмотра pending.table.view=Подключиться к диалогу в режиме просмотра
permission.admin=Администрирование системы: настройка, управление операторами, генерация кнопки permission.admin=Администрирование системы: настройка, управление операторами, генерация кнопки
permission.modifyprofile=Возможность изменять свой профиль permission.modifyprofile=Возможность изменять свой профиль
@ -422,6 +431,8 @@ settings.enablessl.description=
settings.enablessl=Разрешать защищенные соединения (SSL) settings.enablessl=Разрешать защищенные соединения (SSL)
settings.enablestatistics.description=Добавляет страницу с отчетами по использованию мессенджера. settings.enablestatistics.description=Добавляет страницу с отчетами по использованию мессенджера.
settings.enablestatistics=Включить функцию "Статистика" settings.enablestatistics=Включить функцию "Статистика"
settings.enabletracking.description=Добавляет функцию отслеживания перемещений посетителей по Вашему сайту и возможность отправки им приглашений к диалогу.
settings.enabletracking=Включить функцию "Отслеживание и приглашение"
settings.forcessl.description=Показывать чаты используя только защищенное соединение settings.forcessl.description=Показывать чаты используя только защищенное соединение
settings.forcessl=Принудительно переводить все чаты в защищенный режим settings.forcessl=Принудительно переводить все чаты в защищенный режим
settings.frequencychat.description=Укажите частоту опроса сервера в секундах. По умолчанию, 2 секунды. settings.frequencychat.description=Укажите частоту опроса сервера в секундах. По умолчанию, 2 секунды.
@ -430,12 +441,16 @@ settings.frequencyoldchat.description=
settings.frequencyoldchat=Периодичность обновления всего диалога для старых браузеров settings.frequencyoldchat=Периодичность обновления всего диалога для старых браузеров
settings.frequencyoperator.description=Укажите частоту опроса сервера в секундах. По умолчанию, 2 секунды. settings.frequencyoperator.description=Укажите частоту опроса сервера в секундах. По умолчанию, 2 секунды.
settings.frequencyoperator=Периодичность обновления консоли оператора settings.frequencyoperator=Периодичность обновления консоли оператора
settings.frequencytracking.description=Укажите частоту опроса блока слежения за посетителями в секундах. По умолчанию, 10 секунд.
settings.frequencytracking=Периодичность опроса блока слежения
settings.geolink.description=На любом IP адресе можно будет открыть небольшое окно с геоинформацией. Можно использовать {ip}. settings.geolink.description=На любом IP адресе можно будет открыть небольшое окно с геоинформацией. Можно использовать {ip}.
settings.geolink=Ссылка на внешний geolocation сервис settings.geolink=Ссылка на внешний geolocation сервис
settings.geolinkparams.description=Размер окна и наличие тулбаров settings.geolinkparams.description=Размер окна и наличие тулбаров
settings.geolinkparams=Опции для окна с геоинформацией settings.geolinkparams=Опции для окна с геоинформацией
settings.host.description=Будет открываться по нажатию на логотип или название компании в чат окне settings.host.description=Будет открываться по нажатию на логотип или название компании в чат окне
settings.host=Ссылка на ваш веб сайт settings.host=Ссылка на ваш веб сайт
settings.invitationlifetime.description=Укажите срок действия приглашения к диалогу в секундах. По умолчанию, 60 секунд.
settings.invitationlifetime=Срок действия приглашения
settings.leavemessage_captcha.description=Защита от автоматизированного спама (captcha) settings.leavemessage_captcha.description=Защита от автоматизированного спама (captcha)
settings.leavemessage_captcha=Разрешать оставлять сообщение только после ввода специального кода с картинки settings.leavemessage_captcha=Разрешать оставлять сообщение только после ввода специального кода с картинки
settings.logo.description=Введите ссылку на логотип компании settings.logo.description=Введите ссылку на логотип компании
@ -458,10 +473,14 @@ settings.survey.askmail=
settings.survey.askmessage.description=Показать/спрятать поле ввода первого вопроса settings.survey.askmessage.description=Показать/спрятать поле ввода первого вопроса
settings.survey.askmessage=Предлагать сразу же задать вопрос settings.survey.askmessage=Предлагать сразу же задать вопрос
settings.title=Настройки мессенджера settings.title=Настройки мессенджера
settings.trackinglifetime.description=Укажите срок хранения старых отслеженных путей в секундах. По умолчанию, 600 секунд.
settings.trackinglifetime=Срок хранения отслеженных путей
settings.usercanchangename.description=Возможность убрать поле смены имени из чат окна settings.usercanchangename.description=Возможность убрать поле смены имени из чат окна
settings.usercanchangename=Разрешать посетителям менять имена settings.usercanchangename=Разрешать посетителям менять имена
settings.usernamepattern.description=Укажите как отобразить имя посетителя операторам. Можно использовать {name}, {id} и {addr}. По умолчанию: {name} settings.usernamepattern.description=Укажите как отобразить имя посетителя операторам. Можно использовать {name}, {id} и {addr}. По умолчанию: {name}
settings.usernamepattern=Отображаемое имя посетителя settings.usernamepattern=Отображаемое имя посетителя
settings.visitorslimit.description=Укажите количество выводимых в списке отслеживаемых посетителей сайта. По умолчанию, 20. Укажите 0 для снятия ограничения (не рекомендуется).
settings.visitorslimit=Ограничение на число выводимых в списке отслеживаемых посетителей
settings.wrong.email=Введите правильный адрес электронной почты settings.wrong.email=Введите правильный адрес электронной почты
settings.wrong.onehostconnections=Поле "Максимальное количество диалогов" должно быть числом settings.wrong.onehostconnections=Поле "Максимальное количество диалогов" должно быть числом
site.title=mibew.org site.title=mibew.org
@ -491,6 +510,12 @@ topMenu.logoff=
topMenu.main=Главная topMenu.main=Главная
topMenu.users.nomenu=без меню topMenu.users.nomenu=без меню
topMenu.users=Посетители topMenu.users=Посетители
tracked.date=Время визита
tracked.empty.referrer=прямое посещение
tracked.intro=На этой странице отображается отслеженная история активности посетителя сайта.
tracked.link=Посещённая страница
tracked.path=Отслеженный путь посетителя
tracked.visitor.came.from=Посетитель пришёл со страницы
translate.direction=Направление перевода: translate.direction=Направление перевода:
translate.show.all=Все строки translate.show.all=Все строки
translate.show.foradmin=Строки для администратора translate.show.foradmin=Строки для администратора
@ -508,3 +533,15 @@ updates.intro=
updates.latest=Последняя версия: updates.latest=Последняя версия:
updates.news=Новости: updates.news=Новости:
updates.title=Обновления updates.title=Обновления
visitors.how_to=Для приглашения посетителя к диалогу кликните на его или её имя в списке.
visitors.intro=В рсположенной ниже таблице представлен список готовых к диалогу посетителей на Вашем сайте.
visitors.no_visitors=В настоящее время на Вашем сайте нет готовых к диалогу посетителей
visitors.table.head.contactid=Адрес посетителя
visitors.table.head.etc=Разное
visitors.table.head.firsttimeonsite=Впервые замечен
visitors.table.head.invitations=Приглашений / Диалогов
visitors.table.head.invitationtime=Время приглашения
visitors.table.head.invited.by=Кем приглашён
visitors.table.head.lasttimeonsite=Последний раз замечен
visitors.table.head.name=Имя
visitors.title=Посетители на сайте

View File

@ -29,7 +29,7 @@ $page = array('agentId' => '');
$errors = array(); $errors = array();
$options = array( $options = array(
'enableban', 'usercanchangename', 'enablegroups', 'enablestatistics', 'enableban', 'usercanchangename', 'enablegroups', 'enablestatistics', 'enabletracking',
'enablessl', 'forcessl', 'enablessl', 'forcessl',
'enablepresurvey', 'surveyaskmail', 'surveyaskgroup', 'surveyaskmessage', 'enablepresurvey', 'surveyaskmail', 'surveyaskgroup', 'surveyaskmessage',
'enablepopupnotification', 'showonlineoperators', 'enablepopupnotification', 'showonlineoperators',

View File

@ -0,0 +1,45 @@
<?php
/*
* This file is part of Mibew Messenger project.
*
* Copyright (c) 2005-2011 Mibew Messenger Community
* All rights reserved. The contents of this file are subject to the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and
* is available at http://www.eclipse.org/legal/epl-v10.html
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which case
* the provisions of the GPL are applicable instead of those above. If you wish
* to allow use of your version of this file only under the terms of the GPL, and
* not to allow others to use your version of this file under the terms of the
* EPL, indicate your decision by deleting the provisions above and replace them
* with the notice and other provisions required by the GPL.
*
* Contributors:
* Fedor Fetisov - tracking and inviting implementation
*/
require_once('../libs/common.php');
require_once('../libs/invitation.php');
require_once('../libs/operator.php');
$operator = check_login();
loadsettings();
$visitorid = verifyparam("visitor", "/^\d{1,8}$/");
$errors = array();
$link = connect();
$invitation = invitation_state($visitorid, $link);
mysql_close($link);
start_xml_output();
echo '<invitation>';
echo '<invited>' . ($invitation['invited'] ? $invitation['invited'] : '0') . '</invited>';
echo '<threadid>' . ($invitation['threadid'] ? $invitation['threadid'] : '0') . '</threadid>';
echo '</invitation>';
exit;
?>

View File

@ -0,0 +1,44 @@
<?php
/*
* This file is part of Mibew Messenger project.
*
* Copyright (c) 2005-2011 Mibew Messenger Community
* All rights reserved. The contents of this file are subject to the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and
* is available at http://www.eclipse.org/legal/epl-v10.html
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which case
* the provisions of the GPL are applicable instead of those above. If you wish
* to allow use of your version of this file only under the terms of the GPL, and
* not to allow others to use your version of this file under the terms of the
* EPL, indicate your decision by deleting the provisions above and replace them
* with the notice and other provisions required by the GPL.
*
* Contributors:
* Fedor Fetisov - tracking and inviting implementation
*/
require_once('../libs/common.php');
require_once('../libs/invitation.php');
require_once('../libs/operator.php');
$operator = check_login();
loadsettings();
$visitorid = verifyparam("visitor", "/^\d{1,8}$/");
$link = connect();
if (!invitation_invite($visitorid, $operator['operatorid'], $link)) {
die("Invitation failed!");
}
mysql_close($link);
$page = array();
$page['visitor'] = $visitorid;
$page['frequency'] = $settings['updatefrequency_operator'];
start_html_output();
require('../view/invite.php');
?>

View File

@ -30,7 +30,9 @@ $errors = array();
$options = array( $options = array(
'online_timeout', 'updatefrequency_operator', 'updatefrequency_chat', 'online_timeout', 'updatefrequency_operator', 'updatefrequency_chat',
'updatefrequency_oldchat', 'max_connections_from_one_host'); 'updatefrequency_oldchat', 'max_connections_from_one_host',
'updatefrequency_tracking', 'visitors_limit', 'invitation_lifetime',
'tracking_lifetime' );
loadsettings(); loadsettings();
$params = array(); $params = array();
@ -64,6 +66,30 @@ if (isset($_POST['onlinetimeout'])) {
$errors[] = getlocal("settings.wrong.onehostconnections"); $errors[] = getlocal("settings.wrong.onehostconnections");
} }
if ($settings['enabletracking']) {
$params['updatefrequency_tracking'] = getparam('frequencytracking');
if (!is_numeric($params['updatefrequency_tracking'])) {
$errors[] = wrong_field("settings.frequencytracking");
}
$params['visitors_limit'] = getparam('visitorslimit');
if (!is_numeric($params['visitors_limit'])) {
$errors[] = wrong_field("settings.visitorslimit");
}
$params['invitation_lifetime'] = getparam('invitationlifetime');
if (!is_numeric($params['invitation_lifetime'])) {
$errors[] = wrong_field("settings.invitationlifetime");
}
$params['tracking_lifetime'] = getparam('trackinglifetime');
if (!is_numeric($params['tracking_lifetime'])) {
$errors[] = wrong_field("settings.trackinglifetime");
}
}
if (count($errors) == 0) { if (count($errors) == 0) {
foreach ($options as $opt) { foreach ($options as $opt) {
$settings[$opt] = $params[$opt]; $settings[$opt] = $params[$opt];
@ -79,6 +105,18 @@ $page['formfrequencyoperator'] = $params['updatefrequency_operator'];
$page['formfrequencychat'] = $params['updatefrequency_chat']; $page['formfrequencychat'] = $params['updatefrequency_chat'];
$page['formfrequencyoldchat'] = $params['updatefrequency_oldchat']; $page['formfrequencyoldchat'] = $params['updatefrequency_oldchat'];
$page['formonehostconnections'] = $params['max_connections_from_one_host']; $page['formonehostconnections'] = $params['max_connections_from_one_host'];
if ($settings['enabletracking']) {
$page['formfrequencytracking'] = $params['updatefrequency_tracking'];
$page['formvisitorslimit'] = $params['visitors_limit'];
$page['forminvitationlifetime'] = $params['invitation_lifetime'];
$page['formtrackinglifetime'] = $params['tracking_lifetime'];
}
$page['enabletracking'] = $settings['enabletracking'];
$page['stored'] = isset($_GET['stored']); $page['stored'] = isset($_GET['stored']);
prepare_menu($operator); prepare_menu($operator);

View File

@ -0,0 +1,69 @@
<?php
/*
* This file is part of Mibew Messenger project.
*
* Copyright (c) 2005-2011 Mibew Messenger Community
* All rights reserved. The contents of this file are subject to the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and
* is available at http://www.eclipse.org/legal/epl-v10.html
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which case
* the provisions of the GPL are applicable instead of those above. If you wish
* to allow use of your version of this file only under the terms of the GPL, and
* not to allow others to use your version of this file under the terms of the
* EPL, indicate your decision by deleting the provisions above and replace them
* with the notice and other provisions required by the GPL.
*
* Contributors:
* Fedor Fetisov - tracking and inviting implementation
*/
require_once('../libs/chat.php');
require_once('../libs/common.php');
require_once('../libs/operator.php');
require_once('../libs/track.php');
$operator = check_login();
loadsettings();
setlocale(LC_TIME, getstring("time.locale"));
if ($settings['enabletracking'] == "0") {
die("Tracking disabled!");
}
if (isset($_GET['thread'])) {
$threadid = verifyparam("thread", "/^\d{1,8}$/");
}
else {
$visitorid = verifyparam("visitor", "/^\d{1,8}$/");
}
$link = connect();
if (isset($threadid)) {
$visitor = track_get_visitor_by_threadid($threadid, $link);
if (!$visitor) {
die("Wrong thread!");
}
}
else {
$visitor = track_get_visitor_by_id($visitorid, $link);
if (!$visitor) {
die("Wrong visitor!");
}
}
mysql_close($link);
$path = track_retrieve_path($visitor);
$page['entry'] = htmlspecialchars($visitor['entry']);
$page['history'] = array();
ksort($path);
foreach ($path as $k => $v) {
$page['history'][] = array( 'date' => date_to_text($k),
'link' => htmlspecialchars($v) );
}
start_html_output();
require('../view/tracked.php');
?>

View File

@ -24,6 +24,7 @@ require_once('../libs/chat.php');
require_once('../libs/userinfo.php'); require_once('../libs/userinfo.php');
require_once('../libs/operator.php'); require_once('../libs/operator.php');
require_once('../libs/groups.php'); require_once('../libs/groups.php');
require_once('../libs/track.php');
$operator = get_logged_in(); $operator = get_logged_in();
if (!$operator) { if (!$operator) {
@ -167,9 +168,97 @@ function print_operators()
echo "</operators>"; echo "</operators>";
} }
function visitor_to_xml($visitor, $link)
{
$result = "<visitor id=\"" . $visitor['visitorid'] . "\">";
// $result .= "<userid>" . htmlspecialchars($visitor['userid']) . "</userid>";
$result .= "<username>" . htmlspecialchars($visitor['username']) . "</username>";
$result .= "<time>" . $visitor['unix_timestamp(firsttime)'] . "000</time>";
$result .= "<modified>" . $visitor['unix_timestamp(lasttime)'] . "000</modified>";
// $result .= "<entry>" . htmlspecialchars($visitor['entry']) . "</entry>";
// $result .= "<path>";
// $path = track_retrieve_path($visitor);
// ksort($path);
// foreach ($path as $k => $v) {
// $result .= "<url visited=\"" . $k . "000\">" . htmlspecialchars($v) . "</url>";
// }
// $result .= "</path>";
$details = track_retrieve_details($visitor);
$userAgent = get_useragent_version($details['user_agent']);
$result .= "<useragent>" . $userAgent . "</useragent>";
$result .= "<addr>" . htmlspecialchars(get_user_addr($details['remote_host'])) . "</addr>";
$result .= "<invitations>" . $visitor['invitations'] . "</invitations>";
$result .= "<chats>" . $visitor['chats'] . "</chats>";
$result .= "<invitation>";
if ($visitor['invited']) {
$result .= "<invitationtime>" . $visitor['unix_timestamp(invitationtime)'] . "000</invitationtime>";
$operator = get_operator_name(operator_by_id_($visitor['invitedby'], $link));
$result .= "<operator>" . htmlspecialchars(htmlspecialchars($operator)) . "</operator>";
}
$result .= "</invitation>";
$result .= "</visitor>";
return $result;
}
function print_visitors()
{
global $webim_encoding, $settings, $state_closed, $state_left, $mysqlprefix;
$link = connect();
// Remove old visitors' tracks
$query = "DELETE FROM ${mysqlprefix}chatsitevisitor WHERE (UNIX_TIMESTAMP(CURRENT_TIMESTAMP) - UNIX_TIMESTAMP(lasttime)) > " . $settings['tracking_lifetime'] .
" AND (threadid IS NULL OR (SELECT count(*) FROM ${mysqlprefix}chatthread WHERE threadid = ${mysqlprefix}chatsitevisitor.threadid" .
" AND istate <> $state_closed AND istate <> $state_left) = 0)";
perform_query($query, $link);
// Remove old invitations
$query = "UPDATE ${mysqlprefix}chatsitevisitor SET invited = 0, invitationtime = NULL, invitedby = NULL" .
" WHERE threadid IS NULL AND (UNIX_TIMESTAMP(CURRENT_TIMESTAMP) - UNIX_TIMESTAMP(invitationtime)) > " .
$settings['invitation_lifetime'];
perform_query($query, $link);
// Remove associations of visitors with closed threads
$query = "UPDATE ${mysqlprefix}chatsitevisitor SET threadid = NULL WHERE threadid IS NOT NULL AND" .
" (SELECT count(*) FROM ${mysqlprefix}chatthread WHERE threadid = ${mysqlprefix}chatsitevisitor.threadid" .
" AND istate <> $state_closed AND istate <> $state_left) = 0";
perform_query($query, $link);
$output = array();
$query = "SELECT visitorid, userid, username, unix_timestamp(firsttime), unix_timestamp(lasttime), " .
"entry, path, details, invited, unix_timestamp(invitationtime), invitedby, invitations, chats " .
"FROM ${mysqlprefix}chatsitevisitor " .
"WHERE threadid IS NULL " .
"ORDER BY invited, lasttime DESC, invitations";
$query .= ($settings['visitors_limit'] == '0') ? "" : " LIMIT " . $settings['visitors_limit'];
$rows = select_multi_assoc($query, $link);
foreach ($rows as $row) {
$visitor = visitor_to_xml($row, $link);
$output[] = $visitor;
}
mysql_close($link);
echo "<visitors>";
foreach ($output as $thr) {
print myiconv($webim_encoding, "utf-8", $thr);
}
echo "</visitors>";
}
$since = verifyparam("since", "/^\d{1,9}$/", 0); $since = verifyparam("since", "/^\d{1,9}$/", 0);
$status = verifyparam("status", "/^\d{1,2}$/", 0); $status = verifyparam("status", "/^\d{1,2}$/", 0);
$showonline = verifyparam("showonline", "/^1$/", 0); $showonline = verifyparam("showonline", "/^1$/", 0);
$showvisitors = verifyparam("showvisitors", "/^1$/", 0);
$link = connect(); $link = connect();
loadsettings_($link); loadsettings_($link);
@ -185,6 +274,9 @@ if ($showonline) {
print_operators(); print_operators();
} }
print_pending_threads($groupids, $since); print_pending_threads($groupids, $since);
if ($showvisitors) {
print_visitors();
}
echo '</update>'; echo '</update>';
notify_operator_alive($operator['operatorid'], $status); notify_operator_alive($operator['operatorid'], $status);
exit; exit;

View File

@ -39,6 +39,7 @@ $page['showpopup'] = $settings['enablepopupnotification'] == '1' ? "1" : "0";
$page['frequency'] = $settings['updatefrequency_operator']; $page['frequency'] = $settings['updatefrequency_operator'];
$page['istatus'] = $status; $page['istatus'] = $status;
$page['showonline'] = $settings['showonlineoperators'] == '1' ? "1" : "0"; $page['showonline'] = $settings['showonlineoperators'] == '1' ? "1" : "0";
$page['showvisitors'] = $settings['enabletracking'] == '1' ? "1" : "0";
prepare_menu($operator); prepare_menu($operator);
start_html_output(); start_html_output();

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -60,6 +60,13 @@ var threadParams = { servl:"${webimroot}/thread.php",wroot:"${webimroot}",freque
} }
.ilog { background-position: 0px 0px;width: 20px; height: 80px; } .ilog { background-position: 0px 0px;width: 20px; height: 80px; }
.imessage { background-position: 0px -82px;width: 20px; height: 85px; } .imessage { background-position: 0px -82px;width: 20px; height: 85px; }
.itracked {
background: transparent url(${tplroot}/images/buttons/tracked.gif) no-repeat scroll 0px 0px;
width: 25px; height: 25px;
-moz-background-clip: -moz-initial;
-moz-background-origin: -moz-initial;
-moz-background-inline-policy: -moz-initial;
}
</style> </style>
</head> </head>
@ -175,8 +182,11 @@ ${endif:canpost}
${if:historyParams} ${if:historyParams}
<td><a href="${page:historyParamsLink}" target="_blank" title="${msg:page.analysis.userhistory.title}" onclick="this.newWindow = window.open('${page:historyParamsLink}', 'UserHistory', 'toolbar=0,scrollbars=0,location=0,statusbar=1,menubar=0,width=720,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;"><img class="tplimage ihistory" src="${webimroot}/images/free.gif" border="0" alt="History&nbsp;"/></a></td> <td><a href="${page:historyParamsLink}" target="_blank" title="${msg:page.analysis.userhistory.title}" onclick="this.newWindow = window.open('${page:historyParamsLink}', 'UserHistory', 'toolbar=0,scrollbars=0,location=0,statusbar=1,menubar=0,width=720,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;"><img class="tplimage ihistory" src="${webimroot}/images/free.gif" border="0" alt="History&nbsp;"/></a></td>
${endif:historyParams} ${endif:historyParams}
${if:trackedParams}
<td><a href="${page:trackedParamsLink}" target="_blank" title="${msg:page.analysis.trackedpath.title}" onclick="this.newWindow = window.open('${page:trackedParamsLink}', 'UserTrackedPath', 'toolbar=0,scrollbars=1,location=0,statusbar=1,menubar=0,width=640,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;"><img class="itracked" src="${webimroot}/images/free.gif" border="0" alt="Tracked&nbsp;path&nbsp;"/></a></td>
${endif:trackedParams}
${endif:agent} ${endif:agent}
<td><a id="togglesound" href="javascript:void(0)" onclick="return false;" title="Turn off sound"> <td><a id="togglesound" href="javascript:void(0)" onclick="return false;" title="${msg:chat.window.toolbar.mute}">
<img id="soundimg" class="tplimage isound" src="${webimroot}/images/free.gif" border="0" alt="Sound&nbsp;" /></a></td> <img id="soundimg" class="tplimage isound" src="${webimroot}/images/free.gif" border="0" alt="Sound&nbsp;" /></a></td>
<td><a id="refresh" href="javascript:void(0)" onclick="return false;" title="${msg:chat.window.toolbar.refresh}"> <td><a id="refresh" href="javascript:void(0)" onclick="return false;" title="${msg:chat.window.toolbar.refresh}">

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -40,6 +40,13 @@ var threadParams = { servl:"${webimroot}/thread.php",wroot:"${webimroot}",freque
} }
.ilog { background-position: 0px 0px;width: 20px; height: 80px; } .ilog { background-position: 0px 0px;width: 20px; height: 80px; }
.imessage { background-position: 0px -82px;width: 20px; height: 85px; } .imessage { background-position: 0px -82px;width: 20px; height: 85px; }
.itracked {
background: transparent url(${tplroot}/images/buttons/tracked.gif) no-repeat scroll 0px 0px;
width: 25px; height: 25px;
-moz-background-clip: -moz-initial;
-moz-background-origin: -moz-initial;
-moz-background-inline-policy: -moz-initial;
}
</style> </style>
</head> </head>
<body bgcolor="#FFFFFF" style="background-image: url(${tplroot}/images/bg.gif); margin: 0px;" text="#000000" link="#C28400" vlink="#C28400" alink="#C28400"> <body bgcolor="#FFFFFF" style="background-image: url(${tplroot}/images/bg.gif); margin: 0px;" text="#000000" link="#C28400" vlink="#C28400" alink="#C28400">
@ -172,8 +179,11 @@ ${endif:canpost}
${if:historyParams} ${if:historyParams}
<td><a href="${page:historyParamsLink}" target="_blank" title="${msg:page.analysis.userhistory.title}" onclick="this.newWindow = window.open('${page:historyParamsLink}', 'UserHistory', 'toolbar=0,scrollbars=0,location=0,statusbar=1,menubar=0,width=720,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;"><img class="tplimage ihistory" src="${webimroot}/images/free.gif" border="0" alt="History&nbsp;"/></a></td> <td><a href="${page:historyParamsLink}" target="_blank" title="${msg:page.analysis.userhistory.title}" onclick="this.newWindow = window.open('${page:historyParamsLink}', 'UserHistory', 'toolbar=0,scrollbars=0,location=0,statusbar=1,menubar=0,width=720,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;"><img class="tplimage ihistory" src="${webimroot}/images/free.gif" border="0" alt="History&nbsp;"/></a></td>
${endif:historyParams} ${endif:historyParams}
${if:trackedParams}
<td><a href="${page:trackedParamsLink}" target="_blank" title="${msg:page.analysis.trackedpath.title}" onclick="this.newWindow = window.open('${page:trackedParamsLink}', 'UserTrackedPath', 'toolbar=0,scrollbars=1,location=0,statusbar=1,menubar=0,width=640,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;"><img class="itracked" src="${webimroot}/images/free.gif" border="0" alt="Tracked&nbsp;path&nbsp;"/></a></td>
${endif:trackedParams}
${endif:agent} ${endif:agent}
<td><a id="togglesound" href="javascript:void(0)" onclick="return false;" title="Turn off sound"> <td><a id="togglesound" href="javascript:void(0)" onclick="return false;" title="${msg:chat.window.toolbar.mute}">
<img id="soundimg" class="tplimage isound" src="${webimroot}/images/free.gif" border="0" alt="Sound&nbsp;" /></a></td> <img id="soundimg" class="tplimage isound" src="${webimroot}/images/free.gif" border="0" alt="Sound&nbsp;" /></a></td>
<td><a id="refresh" href="javascript:void(0)" onclick="return false;" title="${msg:chat.window.toolbar.refresh}"> <td><a id="refresh" href="javascript:void(0)" onclick="return false;" title="${msg:chat.window.toolbar.refresh}">

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

View File

@ -80,9 +80,14 @@ var threadParams = { servl:"${webimroot}/thread.php",wroot:"${webimroot}",freque
<a href="${page:historyParamsLink}" target="_blank" title="${msg:page.analysis.userhistory.title}" onClick="this.newWindow = window.open('${page:historyParamsLink}', 'UserHistory', 'toolbar=0,scrollbars=0,location=0,statusbar=1,menubar=0,width=720,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;"><img src="${tplroot}/images/buttons/history.gif" border="0" alt="${msg:page.analysis.userhistory.title}"/></a> <a href="${page:historyParamsLink}" target="_blank" title="${msg:page.analysis.userhistory.title}" onClick="this.newWindow = window.open('${page:historyParamsLink}', 'UserHistory', 'toolbar=0,scrollbars=0,location=0,statusbar=1,menubar=0,width=720,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;"><img src="${tplroot}/images/buttons/history.gif" border="0" alt="${msg:page.analysis.userhistory.title}"/></a>
</td> </td>
${endif:historyParams} ${endif:historyParams}
${if:trackedParams}
<td>
<a href="${page:trackedParamsLink}" target="_blank" title="${msg:page.analysis.trackedpath.title}" onclick="this.newWindow = window.open('${page:trackedParamsLink}', 'UserTrackedPath', 'toolbar=0,scrollbars=1,location=0,statusbar=1,menubar=0,width=640,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;"><img src="${tplroot}/images/buttons/tracked.gif" border="0" alt="${msg:page.analysis.trackedpath.title}"/></a>
</td>
${endif:trackedParams}
${endif:agent} ${endif:agent}
<td> <td>
<a id="togglesound" href="javascript:void(0)" onClick="return false;" title="Sound On/Off"><img id="soundimg" class="isound" src="${webimroot}/images/free.gif" border="0" alt="Sound On/Off" /></a> <a id="togglesound" href="javascript:void(0)" onClick="return false;" title="${msg:chat.window.toolbar.mute}"><img id="soundimg" class="isound" src="${webimroot}/images/free.gif" border="0" alt="${msg:chat.window.toolbar.mute}" /></a>
</td> </td>
<td> <td>
<a id="refresh" href="javascript:void(0)" onClick="return false;" title="${msg:chat.window.toolbar.refresh}"><img src="${tplroot}/images/buttons/refresh.gif" border="0" alt="${msg:chat.window.toolbar.refresh}" /></a> <a id="refresh" href="javascript:void(0)" onClick="return false;" title="${msg:chat.window.toolbar.refresh}"><img src="${tplroot}/images/buttons/refresh.gif" border="0" alt="${msg:chat.window.toolbar.refresh}" /></a>

View File

@ -124,6 +124,15 @@ require_once('inc_errors.php');
<br clear="all"/> <br clear="all"/>
</div> </div>
<div class="field">
<div class="flabel"><?php echo getlocal('settings.enabletracking') ?></div>
<div class="fvalue">
<input type="checkbox" name="enabletracking" value="on"<?php echo form_value_cb('enabletracking') ? " checked=\"checked\"" : "" ?><?php echo $page['canmodify'] ? "" : " disabled=\"disabled\"" ?>/>
</div>
<div class="fdescr"> &mdash; <?php echo getlocal('settings.enabletracking.description') ?></div>
<br clear="all"/>
</div>
<div class="field"> <div class="field">
<div class="flabel"><?php echo getlocal('settings.enableban') ?></div> <div class="flabel"><?php echo getlocal('settings.enableban') ?></div>
<div class="fvalue"> <div class="fvalue">

View File

@ -0,0 +1,48 @@
<?php
/*
* This file is part of Mibew Messenger project.
*
* Copyright (c) 2005-2011 Mibew Messenger Community
* All rights reserved. The contents of this file are subject to the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and
* is available at http://www.eclipse.org/legal/epl-v10.html
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which case
* the provisions of the GPL are applicable instead of those above. If you wish
* to allow use of your version of this file only under the terms of the GPL, and
* not to allow others to use your version of this file under the terms of the
* EPL, indicate your decision by deleting the provisions above and replace them
* with the notice and other provisions required by the GPL.
*
* Contributors:
* Fedor Fetisov - tracking and inviting implementation
*/
$page['title'] = getlocal("invitation.title");
function tpl_header() { global $page, $webimroot, $jsver;
?>
<script type="text/javascript" language="javascript" src="<?php echo $webimroot ?>/js/<?php echo $jsver ?>/common.js"></script>
<script type="text/javascript" language="javascript"><!--
var updaterOptions = {
url:"<?php echo $webimroot ?>/operator/invitationstate.php",wroot:"<?php echo $webimroot ?>",
agentservl:"<?php echo $webimroot ?>/operator/agent.php", frequency:<?php echo $page['frequency'] ?>,
visitor: "<?php echo $page['visitor'] ?>" };
//--></script>
<script type="text/javascript" language="javascript" src="<?php echo $webimroot ?>/js/<?php echo $jsver ?>/invite_op.js"></script>
<?php
}
function tpl_content() { global $page, $webimroot;
?>
<?php echo getlocal("invitation.sent"); ?>
<div class="ajaxWait"></div>
<?php
} /* content */
require_once('inc_main.php');
?>

View File

@ -34,12 +34,16 @@ var localized = new Array(
"<?php echo getlocal("pending.table.ban") ?>", "<?php echo getlocal("pending.table.ban") ?>",
"<?php echo htmlspecialchars(getlocal("pending.menu.show")) ?>", "<?php echo htmlspecialchars(getlocal("pending.menu.show")) ?>",
"<?php echo htmlspecialchars(getlocal("pending.menu.hide")) ?>", "<?php echo htmlspecialchars(getlocal("pending.menu.hide")) ?>",
"<?php echo htmlspecialchars(getlocal("pending.popup_notification")) ?>" "<?php echo htmlspecialchars(getlocal("pending.popup_notification")) ?>",
"<?php echo getlocal("pending.table.tracked") ?>",
"<?php echo getlocal("pending.table.invite") ?>"
); );
var updaterOptions = { var updaterOptions = {
url:"<?php echo $webimroot ?>/operator/update.php",wroot:"<?php echo $webimroot ?>", url:"<?php echo $webimroot ?>/operator/update.php",wroot:"<?php echo $webimroot ?>",
agentservl:"<?php echo $webimroot ?>/operator/agent.php", frequency:<?php echo $page['frequency'] ?>, istatus:<?php echo $page['istatus'] ?>, agentservl:"<?php echo $webimroot ?>/operator/agent.php", frequency:<?php echo $page['frequency'] ?>, istatus:<?php echo $page['istatus'] ?>,
noclients:"<?php echo getlocal("clients.no_clients") ?>", havemenu: <?php echo $page['havemenu'] ?>, showpopup: <?php echo $page['showpopup'] ?>, showonline: <?php echo $page['showonline'] ?> }; noclients:"<?php echo getlocal("clients.no_clients") ?>", havemenu: <?php echo $page['havemenu'] ?>, showpopup: <?php echo $page['showpopup'] ?>,
showonline: <?php echo $page['showonline'] ?>, showvisitors: <?php echo $page['showvisitors'] ?>, novisitors: "<?php echo getlocal("visitors.no_visitors") ?>",
trackedservl:"<?php echo $webimroot ?>/operator/tracked.php", inviteservl:"<?php echo $webimroot ?>/operator/invite.php" };
//--></script> //--></script>
<script type="text/javascript" language="javascript" src="<?php echo $webimroot ?>/js/<?php echo $jsver ?>/users.js"></script> <script type="text/javascript" language="javascript" src="<?php echo $webimroot ?>/js/<?php echo $jsver ?>/users.js"></script>
<?php <?php
@ -84,6 +88,36 @@ function tpl_content() { global $page, $webimroot;
</tbody> </tbody>
</table> </table>
<?php if ($page['showvisitors']) { ?>
<div class="tabletitle"><?php echo getlocal("visitors.title") ?></div>
<?php echo getlocal("visitors.intro") ?>
<br/>
<?php echo getlocal("visitors.how_to") ?>
<table id="visitorslist" class="awaiting" border="0">
<thead>
<tr>
<th class="first"><?php echo getlocal("visitors.table.head.name") ?></th>
<th><?php echo getlocal("visitors.table.head.contactid") ?></th>
<th><?php echo getlocal("visitors.table.head.firsttimeonsite") ?></th>
<th><?php echo getlocal("visitors.table.head.lasttimeonsite") ?></th>
<th><?php echo getlocal("visitors.table.head.invited.by") ?></th>
<th><?php echo getlocal("visitors.table.head.invitationtime") ?></th>
<th><?php echo getlocal("visitors.table.head.invitations") ?></th>
<th><?php echo getlocal("visitors.table.head.etc") ?></th>
</tr>
</thead>
<tbody>
<tr id="visfree"><td colspan="8"></td></tr>
<tr id="visfreeend"><td colspan="8"></td></tr>
<tr id="visinvited"><td colspan="8"></td></tr>
<tr id="visinvitedend"><td colspan="8"></td></tr>
<tr><td id="visstatustd" colspan="8" height="30">Loading....</td></tr>
</tbody>
</table>
<hr/>
<?php } ?>
<div id="connstatus"> <div id="connstatus">
</div> </div>

View File

@ -90,6 +90,44 @@ require_once('inc_errors.php');
<br clear="all"/> <br clear="all"/>
</div> </div>
<?php if ($page['enabletracking']) { ?>
<div class="field">
<div class="flabel"><?php echo getlocal('settings.frequencytracking') ?></div>
<div class="fvalue">
<input type="text" name="frequencytracking" size="40" value="<?php echo form_value('frequencytracking') ?>" class="formauth"/>
</div>
<div class="fdescr"> &mdash; <?php echo getlocal('settings.frequencytracking.description') ?></div>
<br clear="all"/>
</div>
<div class="field">
<div class="flabel"><?php echo getlocal('settings.visitorslimit') ?></div>
<div class="fvalue">
<input type="text" name="visitorslimit" size="40" value="<?php echo form_value('visitorslimit') ?>" class="formauth"/>
</div>
<div class="fdescr"> &mdash; <?php echo getlocal('settings.visitorslimit.description') ?></div>
<br clear="all"/>
</div>
<div class="field">
<div class="flabel"><?php echo getlocal('settings.invitationlifetime') ?></div>
<div class="fvalue">
<input type="text" name="invitationlifetime" size="40" value="<?php echo form_value('invitationlifetime') ?>" class="formauth"/>
</div>
<div class="fdescr"> &mdash; <?php echo getlocal('settings.invitationlifetime.description') ?></div>
<br clear="all"/>
</div>
<div class="field">
<div class="flabel"><?php echo getlocal('settings.trackinglifetime') ?></div>
<div class="fvalue">
<input type="text" name="trackinglifetime" size="40" value="<?php echo form_value('trackinglifetime') ?>" class="formauth"/>
</div>
<div class="fdescr"> &mdash; <?php echo getlocal('settings.trackinglifetime.description') ?></div>
<br clear="all"/>
</div>
<?php } ?>
<div class="fbutton"> <div class="fbutton">
<input type="image" name="save" value="" src='<?php echo $webimroot.getlocal("image.button.save") ?>' alt='<?php echo getlocal("button.save") ?>'/> <input type="image" name="save" value="" src='<?php echo $webimroot.getlocal("image.button.save") ?>' alt='<?php echo getlocal("button.save") ?>'/>
</div> </div>

View File

@ -0,0 +1,89 @@
<?php
/*
* This file is part of Mibew Messenger project.
*
* Copyright (c) 2005-2011 Mibew Messenger Community
* All rights reserved. The contents of this file are subject to the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and
* is available at http://www.eclipse.org/legal/epl-v10.html
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which case
* the provisions of the GPL are applicable instead of those above. If you wish
* to allow use of your version of this file only under the terms of the GPL, and
* not to allow others to use your version of this file under the terms of the
* EPL, indicate your decision by deleting the provisions above and replace them
* with the notice and other provisions required by the GPL.
*
* Contributors:
* Fedor Fetisov - tracking and inviting implementation
*/
$page['title'] = getlocal("tracked.path");
function tpl_content() { global $page;
?>
<?php echo getlocal("tracked.intro") ?>
<br/><br/>
<div class="logpane">
<div class="header">
<div class="wlabel">
<?php echo getlocal("tracked.visitor.came.from") ?>:
</div>
<div class="wvalue">
<?php if ($page['entry']) { ?>
<a href="<?php echo $page['entry'] ?>"><?php echo $page['entry'] ?></a>
<?php } else { ?>
<?php echo getlocal("tracked.empty.referrer") ?>
<?php } ?>
</div>
<br clear="all"/>
</div>
<div class="message">
<table class="list">
<thead>
<tr class="header">
<th>
<?php echo getlocal("tracked.date") ?>
</th><th>
<?php echo getlocal("tracked.link") ?>
</th>
</tr>
</thead>
<tbody>
<?php
if(count($page['history']) > 0) {
foreach( $page['history'] as $step ) {
?>
<tr>
<td class="notlast">
<?php echo $step['date']; ?>
</td>
<td>
<a href="<?php echo $step['link']; ?>"><?php echo $step['link']; ?></a>
</td>
</tr>
<?php
}
}
?>
</tbody>
</table>
</div>
</div>
<?php
} /* content */
require_once('inc_main.php');
?>