';
- },
-
- viewOpenCell: function(username,servlet,id,canview,canopen,ban,message,cantakenow,tracked,trackedlink) {
- var link = servlet+"?thread="+id;
- var gen = '
',f})})()
\ No newline at end of file
diff --git a/src/messenger/webim/js/templates/source/users/agent.handlebars b/src/messenger/webim/js/templates/source/users/agent.handlebars
new file mode 100644
index 00000000..a482a764
--- /dev/null
+++ b/src/messenger/webim/js/templates/source/users/agent.handlebars
@@ -0,0 +1 @@
+{{name}}{{#unless isLast}},{{/unless}}
\ No newline at end of file
diff --git a/src/messenger/webim/js/templates/source/users/no_threads.handlebars b/src/messenger/webim/js/templates/source/users/no_threads.handlebars
new file mode 100644
index 00000000..7a629f6e
--- /dev/null
+++ b/src/messenger/webim/js/templates/source/users/no_threads.handlebars
@@ -0,0 +1 @@
+
{{L10n "clients.no_clients"}}
\ No newline at end of file
diff --git a/src/messenger/webim/js/templates/source/users/no_visitors.handlebars b/src/messenger/webim/js/templates/source/users/no_visitors.handlebars
new file mode 100644
index 00000000..17e3f3da
--- /dev/null
+++ b/src/messenger/webim/js/templates/source/users/no_visitors.handlebars
@@ -0,0 +1 @@
+
{{L10n "visitors.no_visitors"}}
\ No newline at end of file
diff --git a/src/messenger/webim/js/templates/source/users/queued_thread.handlebars b/src/messenger/webim/js/templates/source/users/queued_thread.handlebars
new file mode 100644
index 00000000..d3e82c1b
--- /dev/null
+++ b/src/messenger/webim/js/templates/source/users/queued_thread.handlebars
@@ -0,0 +1,27 @@
+
\ No newline at end of file
diff --git a/src/messenger/webim/js/templates/source/users/status_panel.handlebars b/src/messenger/webim/js/templates/source/users/status_panel.handlebars
new file mode 100644
index 00000000..4f8ec934
--- /dev/null
+++ b/src/messenger/webim/js/templates/source/users/status_panel.handlebars
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/messenger/webim/js/templates/source/users/threads_collection.handlebars b/src/messenger/webim/js/templates/source/users/threads_collection.handlebars
new file mode 100644
index 00000000..ede4845f
--- /dev/null
+++ b/src/messenger/webim/js/templates/source/users/threads_collection.handlebars
@@ -0,0 +1,17 @@
+
+
+
+
{{L10n "pending.table.head.name"}}
+
{{L10n "pending.table.head.actions"}}
+
{{L10n "pending.table.head.contactid"}}
+
{{L10n "pending.table.head.state"}}
+
{{L10n "pending.table.head.operator"}}
+
{{L10n "pending.table.head.total"}}
+
{{L10n "pending.table.head.waittime"}}
+
{{L10n "pending.table.head.etc"}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/messenger/webim/js/templates/source/users/visitor.handlebars b/src/messenger/webim/js/templates/source/users/visitor.handlebars
new file mode 100644
index 00000000..0f831313
--- /dev/null
+++ b/src/messenger/webim/js/templates/source/users/visitor.handlebars
@@ -0,0 +1,16 @@
+
\ No newline at end of file
diff --git a/src/messenger/webim/js/templates/source/users/visitors_collection.handlebars b/src/messenger/webim/js/templates/source/users/visitors_collection.handlebars
new file mode 100644
index 00000000..cf263b83
--- /dev/null
+++ b/src/messenger/webim/js/templates/source/users/visitors_collection.handlebars
@@ -0,0 +1,17 @@
+
+
+
+
{{L10n "visitors.table.head.name"}}
+
{{L10n "visitors.table.head.actions"}}
+
{{L10n "visitors.table.head.contactid"}}
+
{{L10n "visitors.table.head.firsttimeonsite"}}
+
{{L10n "visitors.table.head.lasttimeonsite"}}
+
{{L10n "visitors.table.head.invited.by"}}
+
{{L10n "visitors.table.head.invitationtime"}}
+
{{L10n "visitors.table.head.invitations"}}
+
{{L10n "visitors.table.head.etc"}}
+
+
+
+
+
\ No newline at end of file
diff --git a/src/messenger/webim/libs/classes/mibew_api_users_interaction.php b/src/messenger/webim/libs/classes/mibew_api_users_interaction.php
new file mode 100644
index 00000000..663c3599
--- /dev/null
+++ b/src/messenger/webim/libs/classes/mibew_api_users_interaction.php
@@ -0,0 +1,51 @@
+ array(
+ 'agentId' => null,
+ 'references' => array(),
+ 'return' => array()
+ ),
+ 'updateThreads' => array(
+ 'revision' => 0
+ ),
+ 'result' => array(
+ 'errorCode' => 0
+ )
+ );
+
+ /**
+ * Reserved function's names
+ * @var array
+ * @see MibewAPIInteraction::$reservedFunctionNames
+ */
+ public $reservedFunctionNames = array(
+ 'result'
+ );
+}
+
+?>
\ No newline at end of file
diff --git a/src/messenger/webim/libs/classes/users_processor.php b/src/messenger/webim/libs/classes/users_processor.php
new file mode 100644
index 00000000..ffd80b47
--- /dev/null
+++ b/src/messenger/webim/libs/classes/users_processor.php
@@ -0,0 +1,578 @@
+ '',
+ 'trusted_signatures' => array(''),
+ 'event_prefix' => 'users'
+ ));
+ }
+
+ /**
+ * Creates and returns an instance of the MibewAPI class.
+ *
+ * @return MibewAPI
+ */
+ protected function getMibewAPIInstance() {
+ return MibewAPI::getAPI('MibewAPIUsersInteraction');
+ }
+
+ /**
+ * Sends asynchronous request
+ *
+ * @param array $request The 'request' array. See Mibew API for details
+ * @return boolean true on success or false on failure
+ */
+ protected function sendAsyncRequest($request) {
+ // Define empty agent id
+ $agent_id = null;
+ foreach ($request['functions'] as $function) {
+ // Save agent id from first function in package
+ if (is_null($agent_id)) {
+ $agent_id = $function['arguments']['agentId'];
+ continue;
+ }
+ // Check agent id for the remaining functions
+ if ($agent_id != $function['arguments']['agentId']) {
+ throw new UsersProcessorException(
+ 'Various agent ids in different functions in one package!',
+ UsersProcessorException::VARIOUS_AGENT_ID
+ );
+ }
+ }
+ // Store request in buffer
+ $this->addRequestToBuffer('users_'.$agent_id, $request);
+ return true;
+ }
+
+ /**
+ * Check operator id equals to $operatorId is current logged in operator
+ *
+ * @param int $operatorId Operator id to check
+ * @return array Operators info array
+ *
+ * @throws UsersProcessorException If operators not logged in or if
+ * $operatorId varies from current logged in operator.
+ */
+ protected static function checkOperator($operatorId) {
+ $operator = get_logged_in();
+ if (!$operator) {
+ throw new UsersProcessorException(
+ getstring("agent.not_logged_in"),
+ UsersProcessorException::ERROR_AGENT_NOT_LOGGED_IN
+ );
+ }
+ if ($operatorId != $operator['operatorid']) {
+ throw new UsersProcessorException(
+ "Wrong agent id: '{$operatorId}' instead of {$operator['operatorid']}",
+ UsersProcessorException::ERROR_WRONG_AGENT_ID
+ );
+ }
+ return $operator;
+ }
+
+ /**
+ * Mark operator as away. API function
+ *
+ * @param array $args Associative array of arguments. It must contains
+ * following keys:
+ * - 'agentId': Id of the agent related to users window
+ */
+ protected function apiAway($args) {
+ $operator = self::checkOperator($args['agentId']);
+ notify_operator_alive($operator['operatorid'], 1);
+ }
+
+ /**
+ * Mark operator as available. API function
+ *
+ * @param array $args Associative array of arguments. It must contains
+ * following keys:
+ * - 'agentId': Id of the agent related to users window
+ */
+ protected function apiAvailable($args) {
+ $operator = self::checkOperator($args['agentId']);
+ notify_operator_alive($operator['operatorid'], 0);
+ }
+
+ /**
+ * Return updated threads list. API function
+ *
+ * @global string $mysqlprefix Database tables prefix
+ * @global int $can_viewthreads View threads permission code
+ * @global int $can_takeover Take threads over permission code
+ * @param array $args Associative array of arguments. It must contains
+ * following keys:
+ * - 'agentId': Id of the agent related to users window
+ * - 'revision': last revision number at client side
+ * @return array Array of results. It contains following keys:
+ * - 'threads': array of threads changes
+ */
+ protected function apiUpdateThreads($args) {
+ global $mysqlprefix, $can_viewthreads, $can_takeover;
+
+ $operator = self::checkOperator($args['agentId']);
+
+ $since = $args['revision'];
+ // Get operator groups
+ if (!isset($_SESSION["${mysqlprefix}operatorgroups"])) {
+ $_SESSION["${mysqlprefix}operatorgroups"]
+ = get_operator_groupslist($operator['operatorid']);
+ }
+ $groupids = $_SESSION["${mysqlprefix}operatorgroups"];
+
+ $db = Database::getInstance();
+ $query = "select t.*, " .
+ " g.vclocalname as group_localname, " .
+ " g.vccommonname as group_commonname " .
+ " from {chatthread} t left outer join {chatgroup} g on " .
+ " t.groupid = g.groupid " .
+ " where t.lrevision > :since " .
+ ($since == 0
+ // Select only active threads at first time when lrevision = 0
+ ? " AND t.istate <> " . Thread::STATE_CLOSED .
+ " AND t.istate <> " . Thread::STATE_LEFT
+ // Select all threads at when lrevision > 0. It provides the
+ // ability to update(and probably hide) closed threads at the
+ // clien side.
+ : ""
+ ) .
+ (Settings::get('enablegroups') == '1'
+ // If groups are enabled select only threads with empty groupid
+ // or groups related to current operator
+ ? " AND (g.groupid is NULL" . ($groupids
+ ? " OR g.groupid IN ($groupids) OR g.groupid IN " .
+ "(SELECT parent FROM {chatgroup} " .
+ "WHERE groupid IN ($groupids)) "
+ : "") .
+ ") "
+ : ""
+ ) .
+ " ORDER BY t.threadid";
+ $rows = $db->query(
+ $query,
+ array(':since' => $since),
+ array('return_rows' => Database::RETURN_ALL_ROWS)
+ );
+
+ $revision = $since;
+ $threads = array();
+ foreach($rows as $row) {
+ // Create thread instance
+ $thread = Thread::createFromDbInfo($row);
+
+ // Calculate agent permissions
+ $can_open = !($thread->state == Thread::STATE_CHATTING
+ && $thread->agentId != $operator['operatorid']
+ && !is_capable($can_takeover, $operator));
+
+ $can_view = ($thread->agentId != $operator['operatorid']
+ && $thread->nextAgent != $operator['operatorid']
+ && is_capable($can_viewthreads, $operator));
+
+ $can_ban = (Settings::get('enableban') == "1");
+
+
+ // Get ban info
+ $ban_info = (Settings::get('enableban') == "1")
+ ? ban_for_addr($thread->remote)
+ : false;
+ if ($ban_info !== false) {
+ $ban = array(
+ 'id' => $ban_info['banid'],
+ 'reason' => $ban_info['comment']
+ );
+ } else {
+ $ban = false;
+ }
+
+ // Get user name
+ $user_name = get_user_name(
+ $thread->userName,
+ $thread->remote,
+ $thread->userId
+ );
+
+ // Get user ip
+ if (preg_match("/(\\d+\\.\\d+\\.\\d+\\.\\d+)/", $thread->remote, $matches) != 0) {
+ $user_ip = $matches[1];
+ } else {
+ $user_ip = false;
+ }
+
+ // Get thread operartor name
+ $nextagent = $thread->nextAgent != 0
+ ? operator_by_id($thread->nextAgent)
+ : false;
+ if ($nextagent) {
+ $agent_name = get_operator_name($nextagent);
+ } else {
+ if ($thread->agentName) {
+ $agent_name = $thread->agentName;
+ } else {
+ $group_name = get_group_name(array(
+ 'vccommonname' => $row['group_commonname'],
+ 'vclocalname' => $row['group_localname']
+ ));
+ if($group_name) {
+ $agent_name = '-' . $group_name . '-';
+ } else {
+ $agent_name = '-';
+ }
+ }
+ }
+
+ // Get first message
+ $first_message = null;
+ if ($thread->shownMessageId != 0) {
+ $line = $db->query(
+ "select tmessage from {chatmessage} " .
+ " where messageid = ? limit 1",
+ array($thread->shownMessageId),
+ array('return_rows' => Database::RETURN_ONE_ROW)
+ );
+ if ($line) {
+ $first_message = preg_replace(
+ "/[\r\n\t]+/",
+ " ",
+ $line["tmessage"]
+ );
+ }
+ }
+
+ $threads[] = array(
+ 'id' => $thread->id,
+ 'token' => $thread->lastToken,
+ 'userName' => $user_name,
+ 'userIp' => $user_ip,
+ 'remote' => $thread->remote,
+ 'userAgent' => get_useragent_version($thread->userAgent),
+ 'agentName' => $agent_name,
+ 'canOpen' => $can_open,
+ 'canView' => $can_view,
+ 'canBan' => $can_ban,
+ 'ban' => $ban,
+ 'state' => $thread->state,
+ 'totalTime' => $thread->created,
+ 'waitingTime' => $thread->modified,
+ 'firstMessage' => $first_message
+ );
+
+ // Get max revision
+ if ($thread->lastRevision > $revision) {
+ $revision = $thread->lastRevision;
+ }
+
+ // Clean up
+ unset($thread);
+ }
+
+ // Send results back to the client
+ return array(
+ 'threads' => $threads,
+ 'lastRevision' => $revision
+ );
+ }
+
+ /**
+ * Return updated visitors list. API function
+ *
+ * @param array $args Associative array of arguments. It must contains
+ * following keys:
+ * - 'agentId': Id of the agent related to users window
+ * @return array Array of results. It contains following keys:
+ * - 'visitors': array of visitors on the site
+ */
+ protected function apiUpdateVisitors($args) {
+ // Check access
+ self::checkOperator($args['agentId']);
+
+ $db = Database::getInstance();
+
+ // Remove old visitors
+ $db->query(
+ "DELETE FROM {chatsitevisitor} " .
+ "WHERE (:now - lasttime) > :lifetime ".
+ "AND (threadid IS NULL OR " .
+ "(SELECT count(*) FROM {chatthread} " .
+ "WHERE threadid = {chatsitevisitor}.threadid " .
+ "AND istate <> " . Thread::STATE_CLOSED . " " .
+ "AND istate <> " . Thread::STATE_LEFT . ") = 0)",
+ array(
+ ':lifetime' => Settings::get('tracking_lifetime'),
+ ':now' => time()
+ )
+ );
+
+ // Remove old invitations
+ $db->query(
+ "UPDATE {chatsitevisitor} SET invited = 0, " .
+ "invitationtime = NULL, invitedby = NULL".
+ " WHERE threadid IS NULL AND (:now - invitationtime) > :lifetime",
+ array(
+ ':lifetime' => Settings::get('invitation_lifetime'),
+ ':now' => time()
+ )
+ );
+
+ // Remove associations of visitors with closed threads
+ $db->query(
+ "UPDATE {chatsitevisitor} SET threadid = NULL " .
+ "WHERE threadid IS NOT NULL AND " .
+ " (SELECT count(*) FROM {chatthread} " .
+ "WHERE threadid = {chatsitevisitor}.threadid" .
+ " AND istate <> " . Thread::STATE_CLOSED . " " .
+ " AND istate <> " . Thread::STATE_LEFT . ") = 0"
+ );
+
+ // Remove old visitors' tracks
+ $db->query(
+ "DELETE FROM {visitedpage} WHERE (:now - visittime) > :lifetime " .
+ " AND visitorid NOT IN (SELECT visitorid FROM {chatsitevisitor})",
+ array(
+ ':lifetime' => Settings::get('tracking_lifetime'),
+ ':now' => time()
+ )
+ );
+
+ // Load visitors
+ $query = "SELECT visitorid, userid, username, firsttime, lasttime, " .
+ "entry, details, invited, invitationtime, invitedby, " .
+ "invitations, chats " .
+ "FROM {chatsitevisitor} " .
+ "WHERE threadid IS NULL " .
+ "ORDER BY invited, lasttime DESC, invitations";
+ $query .= (Settings::get('visitors_limit') == '0')
+ ? ""
+ : " LIMIT " . Settings::get('visitors_limit');
+
+ $rows = $db->query(
+ $query,
+ NULL,
+ array('return_rows' => Database::RETURN_ALL_ROWS)
+ );
+
+ $visitors = array();
+ foreach ($rows as $row) {
+
+ // Get visitor details
+ $details = track_retrieve_details($row);
+
+ // Get user agent
+ $user_agent = get_useragent_version($details['user_agent']);
+
+ // Get user ip
+ if (preg_match("/(\\d+\\.\\d+\\.\\d+\\.\\d+)/", $details['remote_host'], $matches) != 0) {
+ $user_ip = $matches[1];
+ } else {
+ $user_ip = false;
+ }
+
+ // Get invitation info
+ if ($row['invited']) {
+ $agent_name = get_operator_name(
+ operator_by_id($row['invitedby'])
+ );
+ $invitation_info = array(
+ 'time' => $row['invitationtime'],
+ 'agentName' => $agent_name
+ );
+ } else {
+ $invitation_info = false;
+ }
+
+ // Create resulting visitor structure
+ $visitors[] = array(
+ 'id' => (int)$row['visitorid'],
+ 'userName' => $row['username'],
+ 'userAgent' => $user_agent,
+ 'userIp' => $user_ip,
+ 'remote' => $details['remote_host'],
+ 'firstTime' => $row['firsttime'],
+ 'lastTime' => $row['lasttime'],
+ 'invitations' => (int)$row['invitations'],
+ 'chats' => (int)$row['chats'],
+ 'invitationInfo' => $invitation_info
+ );
+ }
+
+ return array(
+ 'visitors' => $visitors
+ );
+ }
+
+ /**
+ * Return updated operators list. API function
+ *
+ * @global string $webim_encoding Encoding for the current locale
+ * @param array $args Associative array of arguments. It must contains
+ * following keys:
+ * - 'agentId': Id of the agent related to users window
+ * @return array Array of results. It contains following keys:
+ * - 'operators': array of online operators
+ */
+ protected function apiUpdateOperators($args) {
+ global $webim_encoding;
+
+ // Check access and get operators info
+ $operator = self::checkOperator($args['agentId']);
+
+ // Return empty array if show operators option disabled
+ if (Settings::get('showonlineoperators') != '1') {
+ return array(
+ 'operators' => array()
+ );
+ }
+
+ // Check if curent operator is in isolation
+ $list_options = in_isolation($operator)
+ ? array('isolated_operator_id' => $operator['operatorid'])
+ : array();
+
+ // Get operators list
+ $operators = get_operators_list($list_options);
+
+ // Create resulting list of operators
+ $result_list = array();
+ foreach ($operators as $item) {
+ if (!operator_is_online($item)) {
+ continue;
+ }
+
+ $result_list[] = array(
+ 'id' => (int)$item['operatorid'],
+ // Convert name to UTF-8
+ 'name' => myiconv(
+ $webim_encoding,
+ "utf-8",
+ htmlspecialchars($item['vclocalename'])
+ ),
+ 'away' => (bool)operator_is_away($item)
+ );
+ }
+
+ // Send operators list to the client side
+ return array(
+ 'operators' => $result_list
+ );
+ }
+
+ /**
+ * Update chat window state. API function
+ *
+ * Call periodically by chat window
+ * @param array $args Associative array of arguments. It must contains
+ * following keys:
+ * - 'agentId': Id of the agent related to users window
+ */
+ protected function apiUpdate($args) {
+ // Check access and get operator array
+ $operator = self::checkOperator($args['agentId']);
+
+ // Update operator status
+ notify_operator_alive($operator['operatorid'], $operator['istatus']);
+
+ // Close old threads
+ Thread::closeOldThreads();
+
+ // Load stored requests
+ $stored_requests = $this->getRequestsFromBuffer('users_'.$args['agentId']);
+ if ($stored_requests !== false) {
+ $this->responses = array_merge($this->responses, $stored_requests);
+ }
+ }
+
+ /**
+ * Returns current server time. API function
+ *
+ * @param array $args Associative array of arguments. It must contains
+ * following keys:
+ * - 'agentId': Id of the agent related to users window
+ * @return array Array of results. It contains following keys:
+ * - 'time': current server time
+ */
+ protected function apiCurrentTime($args) {
+ // Check access
+ self::checkOperator($args['agentId']);
+
+ // Return time
+ return array(
+ 'time' => time()
+ );
+ }
+}
+
+/**
+ * Class for users processor exceptions
+ */
+class UsersProcessorException extends RequestProcessorException {
+ /**
+ * Operator is not logged in
+ */
+ const ERROR_AGENT_NOT_LOGGED_IN = 1;
+ /**
+ * Wrong agent id
+ */
+ const ERROR_WRONG_AGENT_ID = 2;
+ /**
+ * Various agent ids in different functions in one package
+ */
+ const VARIOUS_AGENT_ID = 3;
+}
+
+?>
\ No newline at end of file
diff --git a/src/messenger/webim/libs/common/configurations.php b/src/messenger/webim/libs/common/configurations.php
index c0d0a89e..edc5a60e 100644
--- a/src/messenger/webim/libs/common/configurations.php
+++ b/src/messenger/webim/libs/common/configurations.php
@@ -46,6 +46,20 @@ function get_core_style_config() {
$config += array(
'history' => array(
'window_params' => ''
+ ),
+ 'users' => array(
+ 'thread_tag' => 'div',
+ 'visitor_tag' => 'div'
+ ),
+ 'tracked' => array(
+ 'user_window_params' => '',
+ 'visitor_window_params' => ''
+ ),
+ 'invitation' => array(
+ 'window_params' => ''
+ ),
+ 'ban' => array(
+ 'window_params' => ''
)
);
diff --git a/src/messenger/webim/locales/en/properties b/src/messenger/webim/locales/en/properties
index ba4aa9ff..771f905a 100644
--- a/src/messenger/webim/locales/en/properties
+++ b/src/messenger/webim/locales/en/properties
@@ -40,7 +40,7 @@ char.redirect.operator.online_suff=(online)
chat.came.from=Vistor came from page {0}
chat.client.changename=Change name
chat.client.name=You are
-chat.client.spam.prefix=[spam]
+chat.client.spam.prefix=[spam]
chat.client.visited.page=Visitor navigated to {0}
chat.close.confirmation=Are you sure want to leave chat?
chat.default.username=Guest
@@ -615,6 +615,7 @@ 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.actions=Actions
visitors.table.head.contactid=Visitor's address
visitors.table.head.etc=Misc
visitors.table.head.firsttimeonsite=First seen
diff --git a/src/messenger/webim/locales/ru/properties b/src/messenger/webim/locales/ru/properties
index e0d884e5..10461abe 100644
--- a/src/messenger/webim/locales/ru/properties
+++ b/src/messenger/webim/locales/ru/properties
@@ -40,7 +40,7 @@ char.redirect.operator.online_suff=(
chat.came.from=Посетитель пришел со страницы {0}
chat.client.changename=Изменить имя
chat.client.name=Вы
-chat.client.spam.prefix=[спам]
+chat.client.spam.prefix=[спам]
chat.client.visited.page=Посетитель перешел на {0}
chat.close.confirmation=Вы действительно хотите покинуть диалог?
chat.default.username=Посетитель
@@ -617,6 +617,7 @@ updates.title=
visitors.how_to=Для приглашения посетителя к диалогу кликните на его или её имя в списке.
visitors.intro=В расположенной ниже таблице представлен список готовых к диалогу посетителей на Вашем сайте.
visitors.no_visitors=В настоящее время на Вашем сайте нет готовых к диалогу посетителей
+visitors.table.head.actions=Действия
visitors.table.head.contactid=Адрес посетителя
visitors.table.head.etc=Разное
visitors.table.head.firsttimeonsite=Впервые замечен
diff --git a/src/messenger/webim/operator/update.php b/src/messenger/webim/operator/update.php
index 8ebbd3a9..b47a7a97 100644
--- a/src/messenger/webim/operator/update.php
+++ b/src/messenger/webim/operator/update.php
@@ -22,298 +22,14 @@ require_once('../libs/operator.php');
require_once('../libs/groups.php');
require_once('../libs/track.php');
require_once('../libs/classes/thread.php');
+require_once('../libs/classes/mibew_api.php');
+require_once('../libs/classes/mibew_api_interaction.php');
+require_once('../libs/classes/mibew_api_users_interaction.php');
+require_once('../libs/classes/mibew_api_execution_context.php');
+require_once('../libs/classes/client_side_processor.php');
+require_once('../libs/classes/users_processor.php');
-$operator = get_logged_in();
-if (!$operator) {
- start_xml_output();
- echo "" . myiconv($webim_encoding, "utf-8", escape_with_cdata(getstring("agent.not_logged_in"))) . "";
- exit;
-}
-
-$threadstate_to_string = array(
- Thread::STATE_QUEUE => "wait",
- Thread::STATE_WAITING => "prio",
- Thread::STATE_CHATTING => "chat",
- Thread::STATE_CLOSED => "closed",
- Thread::STATE_LOADING => "wait",
- Thread::STATE_LEFT => "closed"
-);
-
-$threadstate_key = array(
- Thread::STATE_QUEUE => "chat.thread.state_wait",
- Thread::STATE_WAITING => "chat.thread.state_wait_for_another_agent",
- Thread::STATE_CHATTING => "chat.thread.state_chatting_with_agent",
- Thread::STATE_CLOSED => "chat.thread.state_closed",
- Thread::STATE_LOADING => "chat.thread.state_loading"
-);
-
-function thread_to_xml($thread_info)
-{
- global $threadstate_to_string, $threadstate_key,
- $webim_encoding, $operator, $can_viewthreads, $can_takeover;
-
- $thread = $thread_info['thread'];
-
- $state = $threadstate_to_string[$thread->state];
- $result = "id . "\" stateid=\"$state\"";
- if ($state == "closed")
- return $result . "/>";
-
- $state = getstring($threadstate_key[$thread->state]);
- $nextagent = $thread->nextAgent != 0 ? operator_by_id($thread->nextAgent) : null;
- $threadoperator = $nextagent ? get_operator_name($nextagent)
- : ($thread->agentName ? $thread->agentName : "-");
-
- if ($threadoperator == "-" && ! empty($thread_info['groupname'])) {
- $threadoperator = "- " . $thread_info['groupname'] . " -";
- }
-
- if (!($thread->state == Thread::STATE_CHATTING && $thread->agentId != $operator['operatorid'] && !is_capable($can_takeover, $operator))) {
- $result .= " canopen=\"true\"";
- }
- if ($thread->agentId != $operator['operatorid'] && $thread->nextAgent != $operator['operatorid']
- && is_capable($can_viewthreads, $operator)) {
- $result .= " canview=\"true\"";
- }
- if (Settings::get('enableban') == "1") {
- $result .= " canban=\"true\"";
- }
-
- $banForThread = Settings::get('enableban') == "1" ? ban_for_addr($thread->remote) : false;
- if ($banForThread) {
- $result .= " ban=\"blocked\" banid=\"" . $banForThread['banid'] . "\"";
- }
-
- $result .= " state=\"$state\" typing=\"" . $thread->userTyping . "\">";
- $result .= "";
- if ($banForThread) {
- $result .= htmlspecialchars(getstring('chat.client.spam.prefix'));
- }
- $result .= htmlspecialchars(
- htmlspecialchars(get_user_name($thread->userName, $thread->remote, $thread->userId))
- ) . "";
- $result .= "" . htmlspecialchars(get_user_addr($thread->remote)) . "";
- $result .= "" . htmlspecialchars(htmlspecialchars($threadoperator)) . "";
- $result .= "";
- $result .= "" . $thread->modified . "000";
-
- if ($banForThread) {
- $result .= "" . $banForThread['comment'] . "";
- }
-
- $userAgent = get_useragent_version($thread->userAgent);
- $result .= "" . $userAgent . "";
- if ($thread->shownMessageId != 0) {
- $db = Database::getInstance();
- $line = $db->query(
- "select tmessage from {chatmessage} where messageid = ?",
- array($thread->shownMessageId),
- array('return_rows' => Database::RETURN_ONE_ROW)
- );
- if ($line) {
- $message = preg_replace("/[\r\n\t]+/", " ", $line["tmessage"]);
- $result .= "" . htmlspecialchars(htmlspecialchars($message)) . "";
- }
- }
- $result .= "";
- return $result;
-}
-
-function print_pending_threads($groupids, $since)
-{
- global $webim_encoding;
- $db = Database::getInstance();
-
- $revision = $since;
- $query = "select {chatthread}.*, " .
- "(select vclocalname from {chatgroup} where {chatgroup}.groupid = {chatthread}.groupid) as groupname " .
- "from {chatthread} where lrevision > :since " .
- ($since <= 0
- ? "AND istate <> " . Thread::STATE_CLOSED . " AND istate <> " . Thread::STATE_LEFT . " "
- : "") .
- (Settings::get('enablegroups') == '1'
- ? "AND (groupid is NULL" . ($groupids
- ? " OR groupid IN ($groupids) OR groupid IN (SELECT parent FROM {chatgroup} WHERE groupid IN ($groupids)) "
- : "") .
- ") "
- : "") .
- "ORDER BY threadid";
- $rows = $db->query(
- $query,
- array(':since' => $since),
- array('return_rows' => Database::RETURN_ALL_ROWS)
- );
-
- $output = array();
- foreach ($rows as $row) {
- $thread = Thread::createFromDbInfo($row);
- $thread_info = array(
- 'thread' => $thread,
- 'groupname' => $row['groupname']
- );
- $thread_as_xml = thread_to_xml($thread_info);
- $output[] = $thread_as_xml;
- if ($thread->lastRevision > $revision) {
- $revision = $thread->lastRevision;
- }
- }
-
- echo "";
- foreach ($output as $thr) {
- print myiconv($webim_encoding, "utf-8", $thr);
- }
- echo "";
-}
-
-function print_operators($operator)
-{
- global $webim_encoding;
- echo "";
-
- $list_options = in_isolation($operator)?array('isolated_operator_id' => $operator['operatorid']):array();
- $operators = get_operators_list($list_options);
-
- foreach ($operators as $operator) {
- if (!operator_is_online($operator))
- continue;
-
- $name = myiconv($webim_encoding, "utf-8", htmlspecialchars(htmlspecialchars($operator['vclocalename'])));
- $away = operator_is_away($operator) ? " away=\"1\"" : "";
-
- echo "";
- }
- echo "";
-}
-
-function visitor_to_xml($visitor)
-{
- $result = "";
-
-// $result .= "" . htmlspecialchars($visitor['userid']) . "";
- $result .= "" . htmlspecialchars($visitor['username']) . "";
-
- $result .= "";
- $result .= "" . $visitor['lasttime'] . "000";
-// $result .= "" . htmlspecialchars($visitor['entry']) . "";
-
-// $result .= "";
-// $path = track_retrieve_path($visitor);
-// ksort($path);
-// foreach ($path as $k => $v) {
-// $result .= "" . htmlspecialchars($v) . "";
-// }
-// $result .= "";
-
- $details = track_retrieve_details($visitor);
- $userAgent = get_useragent_version($details['user_agent']);
- $result .= "" . $userAgent . "";
- $result .= "" . htmlspecialchars(get_user_addr($details['remote_host'])) . "";
-
- $result .= "" . $visitor['invitations'] . "";
- $result .= "" . $visitor['chats'] . "";
-
- $result .= "";
- if ($visitor['invited']) {
- $result .= "" . $visitor['invitationtime'] . "000";
- $operator = get_operator_name(operator_by_id($visitor['invitedby']));
- $result .= "" . htmlspecialchars(htmlspecialchars($operator)) . "";
- }
- $result .= "";
-
- $result .= "";
- return $result;
-}
-
-function print_visitors()
-{
- global $webim_encoding;
-
- $db = Database::getInstance();
-
-// Remove old visitors
- $db->query(
- "DELETE FROM {chatsitevisitor} " .
- "WHERE (:now - lasttime) > :lifetime ".
- "AND (threadid IS NULL OR " .
- "(SELECT count(*) FROM {chatthread} WHERE threadid = {chatsitevisitor}.threadid " .
- "AND istate <> " . Thread::STATE_CLOSED . " AND istate <> " . Thread::STATE_LEFT . ") = 0)",
- array(
- ':lifetime' => Settings::get('tracking_lifetime'),
- ':now' => time()
- )
- );
-
-// Remove old invitations
- $db->query(
- "UPDATE {chatsitevisitor} SET invited = 0, invitationtime = NULL, invitedby = NULL".
- " WHERE threadid IS NULL AND (:now - invitationtime) > :lifetime",
- array(
- ':lifetime' => Settings::get('invitation_lifetime'),
- ':now' => time()
- )
- );
-
-// Remove associations of visitors with closed threads
- $db->query(
- "UPDATE {chatsitevisitor} SET threadid = NULL WHERE threadid IS NOT NULL AND" .
- " (SELECT count(*) FROM {chatthread} WHERE threadid = {chatsitevisitor}.threadid" .
- " AND istate <> " . Thread::STATE_CLOSED . " AND istate <> " . Thread::STATE_LEFT . ") = 0"
- );
-
-// Remove old visitors' tracks
- $db->query(
- "DELETE FROM {visitedpage} WHERE (:now - visittime) > :lifetime " .
- " AND visitorid NOT IN (SELECT visitorid FROM {chatsitevisitor})",
- array(
- ':lifetime' => Settings::get('tracking_lifetime'),
- ':now' => time()
- )
- );
-
- $query = "SELECT visitorid, userid, username, firsttime, lasttime, " .
- "entry, details, invited, invitationtime, invitedby, invitations, chats " .
- "FROM {chatsitevisitor} " .
- "WHERE threadid IS NULL " .
- "ORDER BY invited, lasttime DESC, invitations";
- $query .= (Settings::get('visitors_limit') == '0') ? "" : " LIMIT " . Settings::get('visitors_limit');
-
- $rows = $db->query($query, NULL, array('return_rows' => Database::RETURN_ALL_ROWS));
-
- $output = array();
- foreach ($rows as $row) {
- $visitor = visitor_to_xml($row);
- $output[] = $visitor;
- }
-
- echo "";
- foreach ($output as $thr) {
- print myiconv($webim_encoding, "utf-8", $thr);
- }
- echo "";
-}
-
-$since = verifyparam("since", "/^\d{1,9}$/", 0);
-$status = verifyparam("status", "/^\d{1,2}$/", 0);
-$showonline = verifyparam("showonline", "/^1$/", 0);
-$showvisitors = verifyparam("showvisitors", "/^1$/", 0);
-
-if (!isset($_SESSION["${mysqlprefix}operatorgroups"])) {
- $_SESSION["${mysqlprefix}operatorgroups"] = get_operator_groupslist($operator['operatorid']);
-}
-Thread::closeOldThreads();
-$groupids = $_SESSION["${mysqlprefix}operatorgroups"];
-
-start_xml_output();
-echo '';
-if ($showonline) {
- print_operators($operator);
-}
-print_pending_threads($groupids, $since);
-if ($showvisitors) {
- print_visitors();
-}
-echo '';
-notify_operator_alive($operator['operatorid'], $status);
-exit;
+$processor = UsersProcessor::getInstance();
+$processor->receiveRequest($_POST['data']);
?>
\ No newline at end of file
diff --git a/src/messenger/webim/operator/users.php b/src/messenger/webim/operator/users.php
index 00e96173..7ae813a2 100644
--- a/src/messenger/webim/operator/users.php
+++ b/src/messenger/webim/operator/users.php
@@ -35,6 +35,22 @@ $page['frequency'] = Settings::get('updatefrequency_operator');
$page['istatus'] = $status;
$page['showonline'] = Settings::get('showonlineoperators') == '1' ? "1" : "0";
$page['showvisitors'] = Settings::get('enabletracking') == '1' ? "1" : "0";
+$page['agentId'] = $operator['operatorid'];
+$page['geoLink'] = Settings::get('geolink');
+$page['geoWindowParams'] = Settings::get('geolinkparams');
+
+// Load dialogs style options
+$style_config = get_dialogs_style_config(getchatstyle());
+$page['chatStyles.chatWindowParams'] = $style_config['chat']['window_params'];
+
+// Load core style options
+$style_config = get_core_style_config();
+$page['coreStyles.threadTag'] = $style_config['users']['thread_tag'];
+$page['coreStyles.visitorTag'] = $style_config['users']['visitor_tag'];
+$page['coreStyles.trackedUserWindowParams'] = $style_config['tracked']['user_window_params'];
+$page['coreStyles.trackedVisitorWindowParams'] = $style_config['tracked']['visitor_window_params'];
+$page['coreStyles.inviteWindowParams'] = $style_config['invitation']['window_params'];
+$page['coreStyles.banWindowParams'] = $style_config['ban']['window_params'];
prepare_menu($operator);
start_html_output();
diff --git a/src/messenger/webim/view/config.ini b/src/messenger/webim/view/config.ini
index 4e5e849c..606968be 100644
--- a/src/messenger/webim/view/config.ini
+++ b/src/messenger/webim/view/config.ini
@@ -4,3 +4,22 @@
[history]
; window_param use as param string in JavaScript window.open method
window_params = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width=720,height=560,resizable=1"
+
+[users]
+; Use as wrap tag for the thread element
+thread_tag = "tr"
+; Use as wrap tag for the visitor element
+visitor_tag = "tr"
+
+[tracked]
+; window_param use as param string in JavaScript window.open method
+user_window_params = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width=640,height=480,resizable=1"
+visitor_window_params = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,width=640,height=480,resizable=1"
+
+[invitation]
+; window_param use as param string in JavaScript window.open method
+window_params = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width=640,height=480,resizable=1"
+
+[ban]
+; window_param use as param string in JavaScript window.open method
+window_params = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width=720,height=480,resizable=1"
diff --git a/src/messenger/webim/view/inc_main.php b/src/messenger/webim/view/inc_main.php
index 0bb8c446..fc524514 100644
--- a/src/messenger/webim/view/inc_main.php
+++ b/src/messenger/webim/view/inc_main.php
@@ -30,6 +30,7 @@ $isrtl = getlocal("localedirection") == 'rtl';
-
+
style="min-width: 400px;">
diff --git a/src/messenger/webim/view/pending_users.php b/src/messenger/webim/view/pending_users.php
index e844a4ae..39d759fb 100644
--- a/src/messenger/webim/view/pending_users.php
+++ b/src/messenger/webim/view/pending_users.php
@@ -21,29 +21,98 @@ $page['menuid'] = "users";
function tpl_header() { global $page, $webimroot;
-?>
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+