Index: openacs-4/packages/chat/chat.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/chat.info,v diff -u -N -r1.20 -r1.21 --- openacs-4/packages/chat/chat.info 12 Jul 2018 12:43:09 -0000 1.20 +++ openacs-4/packages/chat/chat.info 28 Sep 2018 11:44:23 -0000 1.21 @@ -9,7 +9,7 @@ f t - + Peter Alberer Server based chat with an html and ajax client. 2017-08-06 @@ -18,9 +18,9 @@ Adapted by Tekne 2006/03/01 to replace JAVA server with AJAX; make use of generalized chat class from xotcl-core. 0 - + - + Index: openacs-4/packages/chat/tcl/chat-ajax-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/tcl/chat-ajax-procs.tcl,v diff -u -N -r1.19 -r1.20 --- openacs-4/packages/chat/tcl/chat-ajax-procs.tcl 20 Sep 2018 13:28:30 -0000 1.19 +++ openacs-4/packages/chat/tcl/chat-ajax-procs.tcl 28 Sep 2018 11:44:23 -0000 1.20 @@ -8,78 +8,30 @@ } namespace eval ::chat { - ::xo::ChatClass Chat -superclass ::xo::Chat + ::xo::ChatClass Chat -superclass ::xowiki::Chat + Chat instproc initialize_nsvs {} { + next + + # read the last_activity information at server start into a nsv array + ::xo::dc foreach get_rooms { + select room_id, to_char(max(creation_date),'HH24:MI:SS YYYY-MM-DD') as last_activity + from chat_msgs group by room_id + } { + ::xo::clusterwide nsv_set [self]-$room_id-seen last [clock scan $last_activity] + } + } + Chat instproc init {} { - :instvar chat_id - if {[chat_room_exists_p $chat_id]} { - chat_room_get -room_id $chat_id -array c + if {[chat_room_exists_p ${:chat_id}]} { + chat_room_get -room_id ${:chat_id} -array c set :login_messages_p $c(login_messages_p) set :logout_messages_p $c(logout_messages_p) set :timewindow $c(messages_time_window) } next } - Chat proc login {-chat_id -package_id} { - auth::require_login - if {![info exists package_id]} { - set package_id [ad_conn package_id] - } - if {![info exists chat_id]} { - set chat_id $package_id - } - - set path [lindex [site_node::get_url_from_object_id -object_id $package_id] 0] - set base_url ${path}ajax/chat - template::head::add_javascript -src ${base_url}.js - set base_url [export_vars -base ${base_url} {{id $chat_id} {s "[ad_conn session_id].[clock seconds]"}}] - - set login_url [ns_quotehtml "${base_url}&m=login"] - set send_url "${base_url}&m=add_msg&msg=" - set users_url [ns_quotehtml "${base_url}&m=get_users"] - set html_url [ns_quotehtml [ad_conn url]?[ad_conn query]] - regsub {client=ajax} $html_url {client=html} html_url - - return [subst { - -
- - - - <p>#chat.Your_browser_doesnt_support_#</p> - <p><a href='$html_url'>#chat.Go_to_html_version#</a></p> - -
- #chat.message# - -
-
- - - }] - } - # if chat doesn't exist anymore, send a message that will inform # the user of being looking at an invalid chat Chat instproc check_valid_room {} { Index: openacs-4/packages/chat/www/ajax-chat-script.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/Attic/ajax-chat-script.adp,v diff -u -N --- openacs-4/packages/chat/www/ajax-chat-script.adp 18 Sep 2018 14:42:10 -0000 1.8 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,30 +0,0 @@ - -@context;literal@ -doc -ichat_form.msg - - - -

@doc.title@

-

-#chat.Log_off# -#chat.Transcript# -#chat.Hml# -

- -@chat_frame;noquote@ Index: openacs-4/packages/chat/www/ajax-chat-script.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/Attic/ajax-chat-script.tcl,v diff -u -N --- openacs-4/packages/chat/www/ajax-chat-script.tcl 9 Nov 2008 23:29:23 -0000 1.7 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,14 +0,0 @@ -ad_page_contract { - a tiny chat client - - @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at) - @creation-date Jan 31, 2006 - @cvs-id $Id: ajax-chat-script.tcl,v 1.7 2008/11/09 23:29:23 donb Exp $ -} -query { - msg:optional -} - -set html_room_url [export_vars -base "room-enter" {room_id {client html}}] - -set chat_frame [ ::chat::Chat login -chat_id $room_id] - Index: openacs-4/packages/chat/www/chat.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/chat.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/chat/www/chat.adp 28 Sep 2018 11:44:23 -0000 1.1 @@ -0,0 +1,12 @@ + +@context;literal@ +doc +ichat_form.msg + +

@doc.title@

+

+#chat.Log_off# +#chat.Transcript# +

+ +@chat_frame;noquote@ Index: openacs-4/packages/chat/www/chat.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/chat.tcl,v diff -u -N -r1.17 -r1.18 --- openacs-4/packages/chat/www/chat.tcl 7 Aug 2017 23:48:07 -0000 1.17 +++ openacs-4/packages/chat/www/chat.tcl 28 Sep 2018 11:44:23 -0000 1.18 @@ -8,8 +8,6 @@ @cvs-id $Id$ } { room_id:naturalnum,notnull - {client "ajax"} - {message:html ""} } -properties { context:onevalue user_id:onevalue @@ -55,24 +53,8 @@ ad_script_abort } -# Get chat screen name. -set user_name [chat_user_name $user_id] +template::head::add_css -href resources/chat.css -# Determine which template to use for html or ajax client -switch $client { - "html" { - set template_use "html-chat" - # forward to ajax if necessary - if { $message ne "" } { - set session_id [ad_conn session_id] - ::chat::Chat c1 -volatile -chat_id $room_id -session_id $session_id - c1 add_msg $message - } - } - "ajax" { - set template_use "ajax-chat-script" - } -} - -ad_return_template $template_use - +set chat_frame [::chat::Chat login \ + -package_id [ad_conn package_id] \ + -chat_id $room_id] Index: openacs-4/packages/chat/www/html-chat.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/Attic/html-chat.adp,v diff -u -N --- openacs-4/packages/chat/www/html-chat.adp 17 Jun 2016 17:48:21 -0000 1.12 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,30 +0,0 @@ - -@context;literal@ -doc - -

@doc.title@

-

-#chat.Log_off# -#chat.Transcript# -@richclient.title@ -

- -
-@html_chat;noquote@ - -
- -
- @html_users;noquote@
-
- -

- -
-#chat.message#: - - - - -
- Index: openacs-4/packages/chat/www/html-chat.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/Attic/html-chat.tcl,v diff -u -N --- openacs-4/packages/chat/www/html-chat.tcl 7 Aug 2017 23:48:07 -0000 1.7 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,47 +0,0 @@ -ad_page_contract { - mostra mensagens do chat -} { - page:optional -} -properties { - room_id:onevalue -} - -set user_id [ad_conn user_id] -set read_p [permission::permission_p -object_id $room_id -privilege "chat_read"] -set write_p [permission::permission_p -object_id $room_id -privilege "chat_write"] -set ban_p [permission::permission_p -object_id $room_id -privilege "chat_ban"] -set active [room_active_status $room_id] - -# get the "rich" client settings -set richclient(short) [parameter::get -parameter "DefaultClient"] -set richclient(msg) "[_ chat.${richclient(short)}_client_msg]" -set richclient(title) "[_ chat.[string totitle $richclient(short)]]" - -if { ($read_p == 0 && $write_p == 0) || ($ban_p == 1) || ($active == "f") } { - #Display unauthorize privilege page. - ad_returnredirect unauthorized - ad_script_abort -} - -if { [catch {set room_name [chat_room_name $room_id]} errmsg] } { - ad_return_complaint 1 "[_ chat.Room_not_found]" - ad_script_abort -} - -::chat::Chat c1 -volatile -encoder noencode -chat_id $room_id -set html_chat [c1 get_all] -set html_users [c1 get_users] - -template::head::add_style -style "#messages { margin-right:15px; float:left; width:70%; height:250px; overflow:auto; border:1px solid black; padding:5px; font-size: 12px; color: #666666; font-family: Trebuchet MS, Lucida Grande, Lucida Sans Unicode, Arial, sans-serif; } -#messages .timestamp {vertical-align: top; color: #CCCCCC; } -#messages .user {margin: 0px 5px; text-align: right; vertical-align: top; font-weight:bold;} -#messages .message {vertical-align: top;} -#messages .line {margin:0px;} -#users { float:right; width:25%; height:250px; border:1px solid black; padding:5px; font-size: 12px; color: #666666; font-family: Trebuchet MS, Lucida Grande, Lucida Sans Unicode, Arial, sans-serif; } -#users .user {text-align: left; vertical-align: top; font-weight:bold; } -#users .timestamp {text-align: right; vertical-align: top; } -" - -set room_enter_url [export_vars -base "room-enter" {room_id {client $richclient(short)}}] - -ad_return_template Index: openacs-4/packages/chat/www/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/index.tcl,v diff -u -N -r1.16 -r1.17 --- openacs-4/packages/chat/www/index.tcl 9 May 2018 15:33:30 -0000 1.16 +++ openacs-4/packages/chat/www/index.tcl 28 Sep 2018 11:44:23 -0000 1.17 @@ -18,27 +18,20 @@ set user_id [ad_conn user_id] set actions [list] set room_create_p [permission::permission_p -object_id $package_id -privilege chat_room_create] -set default_client [parameter::get -parameter "DefaultClient" -default "ajax"] set warning "" -if { $default_client eq "ajax" && ![apm_package_installed_p xotcl-core] } { - set warning "[_ chat.xotcl_missing]" -} - if { $room_create_p } { lappend actions "#chat.Create_a_new_room#" room-edit "#chat.Create_a_new_room#" } -db_multirow -extend { active_users last_activity room_url room_html_url} rooms rooms_list {} { +db_multirow -extend { active_users last_activity room_url} rooms rooms_list {} { set room [::chat::Chat create new -volatile -chat_id $room_id] set active_users [$room nr_active_users] set last_activity [$room last_activity] if { $active_p } { - set room_url [export_vars -base "room-enter" {room_id {client $default_client}}] + set room_url [export_vars -base "room-enter" {room_id}] set room_url [ns_quotehtml $room_url] - set room_html_url [export_vars -base "room-enter" {room_id {client html}}] - set room_html_url [ns_quotehtml $room_html_url] } } @@ -67,7 +60,7 @@ label "#chat.Room_name#" display_template { - @rooms.pretty_name@ \[#chat.HTML_chat#\] + @rooms.pretty_name@ @rooms.pretty_name@ Index: openacs-4/packages/chat/www/room-enter.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/room-enter.tcl,v diff -u -N -r1.10 -r1.11 --- openacs-4/packages/chat/www/room-enter.tcl 7 Aug 2017 23:48:07 -0000 1.10 +++ openacs-4/packages/chat/www/room-enter.tcl 28 Sep 2018 11:44:23 -0000 1.11 @@ -8,8 +8,7 @@ @cvs-id $Id$ } { room_id:naturalnum,notnull - client:trim -} +} set user_id [ad_conn user_id] @@ -25,21 +24,4 @@ ad_script_abort } -set default_client [parameter::get -parameter "DefaultClient" -default "ajax"] - -if {$default_client eq "java"} { - chat_start_server -} - -switch $client { - "html" - "ajax" - "html-chat-script" { - ns_log Notice "YY room-enter: has_entered_the room" - # apisano: I don't think this code should be here anymore, as - # message about user entering the room is already issued by - # the parent chat class in xotcl-core when we issue the login - # method - # chat_message_post $room_id $user_id "[_ chat.has_entered_the_room]." "1" - } -} - -ad_returnredirect "chat?room_id=$room_id&client=$client" +ad_returnredirect "chat?room_id=$room_id" Index: openacs-4/packages/chat/www/room-exit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/room-exit.tcl,v diff -u -N -r1.8 -r1.9 --- openacs-4/packages/chat/www/room-exit.tcl 7 Aug 2017 23:48:07 -0000 1.8 +++ openacs-4/packages/chat/www/room-exit.tcl 28 Sep 2018 11:44:23 -0000 1.9 @@ -20,16 +20,9 @@ ad_script_abort } -# apisano: I don't think this code should be here anymore, as -# message about user leaving the room is already issued by -# the parent chat class in xotcl-core when we issue the logout -# method -# chat_message_post $room_id $user_id "[_ chat.has_left_the_room]." "1" - # send to AJAX set session_id [ad_conn session_id] ::chat::Chat c1 -volatile -chat_id $room_id -session_id $session_id c1 logout ad_returnredirect index -#ad_returnredirect [dotlrn::get_url] Index: openacs-4/packages/chat/www/ajax/chat.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/ajax/Attic/chat.adp,v diff -u -N --- openacs-4/packages/chat/www/ajax/chat.adp 18 Sep 2018 15:08:16 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,53 +0,0 @@ - - - - -
@message_output;literal@
-
- - @user_output;literal@
-
- - Index: openacs-4/packages/chat/www/ajax/chat.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/ajax/Attic/chat.js,v diff -u -N --- openacs-4/packages/chat/www/ajax/chat.js 7 Aug 2017 23:48:07 -0000 1.5 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,274 +0,0 @@ -// small cross browser function to get an HTTP object for making -// AJAX style http requests in the background -// -gustaf neumann Jan, 2006 -// exended for dotlrn-chat, message coloring and listing of users -// -peter alberer March, 2006 - -// global variables -var msgcount = 0; // hack to overcome IE -var dataConnections = new Object; // variable to find all the registered datasources -// var inactivityTimeout = setTimeout(stopUpdates,300000); - -// helper function to get a new http request object -function getHttpObject() { - var http_request = false; - if (window.XMLHttpRequest) { // Mozilla, Safari,... - http_request = new XMLHttpRequest(); - if (http_request.overrideMimeType) { - http_request.overrideMimeType('text/xml'); - } - } else if (window.ActiveXObject) { // IE - try { - http_request = new ActiveXObject("Msxml2.XMLHTTP"); - } catch (e) { - try { - http_request = new ActiveXObject("Microsoft.XMLHTTP"); - } catch (e) {} - } - } - if (!http_request) { - alert('Cannot create an instance of XMLHTTP'); - } - return http_request; -} - -if (typeof DOMParser == "undefined") { - DOMParser = function () {} - DOMParser.prototype.parseFromString = function (str, contentType) { - if (typeof ActiveXObject != "undefined") { - var d = new ActiveXObject("MSXML.DomDocument"); - d.loadXML(str); - return d; - } - } -} - -// functions that handle the incoming xml/html data -function messagesReceiver(node,doc,div) { - var tr, td, e, s; - var msgCount = 0; - for (var i = 0 ; i < node.childNodes.length ; i++) { - if (node.childNodes[i].nodeType == 3 ) { - // if this is a textnode, skip it - continue; - } - msgCount++; - p = doc.createElement('p'); - p.className = 'line'; - e = node.childNodes[i].getElementsByTagName('span'); - span = doc.createElement('span'); - span.innerHTML = e[0].innerHTML; - span.className = 'timestamp'; - p.appendChild(span); - - span = doc.createElement('span'); - s = e[1].firstChild.nodeValue; - span.innerHTML = e[1].innerHTML; - span.className = 'user'; - p.appendChild(span); - - span = doc.createElement('span'); - span.innerHTML = e[2].innerHTML; - span.className = 'message'; - p.appendChild(span); - - div.appendChild(p); - } - if ( msgCount > 0 ) { - frames['ichat'].window.scrollTo(0,div.offsetHeight); - } -} - -function pushReceiver(content) { - updateReceiver(content); - var msgField = document.getElementById('chatMsg'); - msgField.value = ''; - msgField.disabled = false; - msgField.focus(); -} - -function updateReceiver(content) { - var xmlobject = (new DOMParser()).parseFromString(content, 'application/xhtml+xml'); - var body = xmlobject.getElementsByTagName('body'); - - for (var i = 0 ; i < body[0].childNodes.length ; i++) { - if (body[0].childNodes[i].nodeType == 3 ) { - // if this is a textnode, skip it - continue; - } - var attribute = body[0].childNodes[i].getAttribute('id'); - switch (attribute) { - case "messages": - var messagesNode = body[0].childNodes[i]; - if (messagesNode.hasChildNodes()) { - var messagesDoc = frames['ichat'].document; - var messagesDiv = messagesDoc.getElementById('messages'); - if (messagesDiv == null) { - messagesDiv = messagesDoc.createElement('div'); - messagesDiv.id = 'messages'; - messagesDoc.body.appendChild(messagesDiv); - } - messagesReceiver(messagesNode,messagesDoc,messagesDiv); - } - break; - case "users": - var usersNode = body[0].childNodes[i].childNodes[0]; - var usersDoc = frames['ichat-users'].document; - var usersTbody = usersDoc.getElementById('users').tBodies[0]; - usersReceiver(usersNode,usersDoc,usersTbody); - break; - } - } -} - -function usersReceiver(node,doc,tbody) { - var tr, td, e, s, nbody; - nbody = doc.createElement('tbody'); - for (var i = 0 ; i < node.childNodes.length ; i++) { - if (node.childNodes[i].nodeType == 3 ){ - // if this is a textnode, skip it - continue; - } - tr = doc.createElement('tr'); - e = node.childNodes[i].getElementsByTagName('TD'); - - td = doc.createElement('td'); - // 2017-04-06: - // - td.innerHTML = e[0].innerHTML: Explorer 11 will show - // undefined instead of username - // - td.appendChild(e[0].firstChild): Chrome loses href and - // style - // copying by hand is currently the only solution I have found - ea = e[0].firstChild; - a = doc.createElement('a'); - a.setAttribute('target', ea.getAttribute('target')); - a.setAttribute('href', ea.getAttribute('href')); - a.setAttribute('style', ea.getAttribute('style')); - a.textContent = ea.textContent; - td.appendChild(a); - td.className = 'user'; - tr.appendChild(td); - - td = doc.createElement('td'); - td.appendChild(e[1].firstChild); - td.className = 'timestamp'; - tr.appendChild(td); - - nbody.appendChild(tr); - } - tbody.parentNode.replaceChild(nbody,tbody); -} - -function DataConnection() {}; - -DataConnection.prototype = { - handler: null, - url: null, - connection: null, - busy: null, - autoConnect: null, - - httpSendCmd: function(url) { - // if (!this.connection) { - this.busy = true; - this.connection = getHttpObject(); - // } - this.connection.open('GET', url + '&mc=' + msgcount++, true); - var self = this; - this.connection.onreadystatechange = function() { - self.httpReceiver(self); - } - this.connection.send(''); - }, - - httpReceiver: function(obj) { - if (obj.connection.readyState == 4) { - if (obj.connection.status == 200) { - obj.handler(obj.connection.responseText); - obj.busy = false; - } else { - clearInterval(updateInterval); - var errmsg = obj.connection.responseText.trim(); - if (!errmsg.match("^chat-errmsg: .*")) { - errmsg = 'Something wrong in HTTP request, status code = ' + obj.connection.status; - } else { - errmsg = errmsg.substr(13); - } - alert(errmsg); - } - } - }, - - chatSendMsg: function(send_url) { - // if (inactivityTimeout) { - // clearTimeout(inactivityTimeout); - // alert("Clearing inactivityTimeout"); - // } - // if (!updateInterval) { - // alert("Rescheduling updateInterval"); - // updateInterval = setInterval(updateDataConnections,5000); - // } - if (this.busy) { - alert("chatSendMsg conflict! Maybe banned?"); - } - var msgField = document.getElementById('chatMsg'); - msg = encodeURIComponent(msgField.value); - if (msg == '') { - return; - } - msgField.disabled = true; - this.httpSendCmd(send_url + msg); - msgField.value = '#chat.sending_message#'; - // alert("Reseting inactivityTimeout"); - // inactivityTimeout = setTimeout(stopUpdates,300000); - }, - - updateBackground: function() { - //alert("binda = " + this); - if (this.busy) { - //alert("Message update function cannot run because the last connection is still busy!"); - return; - } else { - this.httpSendCmd(this.url); - } - } -} - -function registerDataConnection(handler,url,autoConnect) { - // var ds = new DataConnection(handler,url,autoConnect); - var ds = new DataConnection(); - ds.handler = handler; - ds.url = url; - ds.autoConnect = autoConnect; - ds.busy = false; - dataConnections[url] = ds; - return ds; -} - -function updateDataConnections() { - for (var ds in dataConnections) { - if (dataConnections[ds].autoConnect) { - // alert("updating " + dataConnections[ds].url); - dataConnections[ds].updateBackground(); - } - } -} - -function stopUpdates() { - // alert("Stopping all update operations"); - clearInterval(updateInterval); - updateInterval = null; - clearTimeout(inactivityTimeout); - inactivityTimeout = null; -} - -function startProc() { - document.getElementById('chatMsg').focus(); - var messagesDiv = frames['ichat'].document.getElementById('messages'); - if (messagesDiv) { - frames['ichat'].window.scrollTo(0,messagesDiv.offsetHeight); - } -} - -window.onload = startProc; - Index: openacs-4/packages/chat/www/ajax/chat.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/ajax/Attic/chat.tcl,v diff -u -N -r1.8 -r1.9 --- openacs-4/packages/chat/www/ajax/chat.tcl 18 Sep 2018 15:08:16 -0000 1.8 +++ openacs-4/packages/chat/www/ajax/chat.tcl 28 Sep 2018 11:44:23 -0000 1.9 @@ -5,10 +5,11 @@ @creation-date Jan 31, 2006 @cvs-id $Id$ } -query { - m - id + m:word + id:integer s - {msg:optional,allhtml ""} + msg:optional,allhtml + {mode ""} } set ban_p [permission::permission_p -object_id $id -privilege "chat_ban"] @@ -17,27 +18,25 @@ ad_script_abort } -set message_output "" -set user_output "" - -::chat::Chat c1 -volatile -chat_id $id -session_id $s - +#ns_log notice "--chat m=$m session_id=$s [clock format [lindex [split $s .] 1] -format %H:%M:%S] mode=$mode" +::chat::Chat create c1 -destroy_on_cleanup -chat_id $id -session_id $s -mode $mode switch -- $m { add_msg { - set message_output [c1 add_msg $msg] + #ns_log notice "--c call c1 $m '$msg'" + ns_return 200 application/json [c1 $m $msg] + ad_script_abort + #ns_log notice "--c add_msg returns '$_'" } - login - get_new - get_all { - set message_output [c1 $m] + get_new { + ns_return 200 application/json [c1 $m] + ad_script_abort } - get_updates { - set message_output [c1 get_new] - set user_output [c1 get_users] - } - get_users { - c1 encoder noencode - set user_output [c1 get_users] - } - default { - ns_log error "--c unknown method $m called." - } + login - + subscribe - + get_all {set _ [c1 $m]} + default {ns_log error "--c unknown method $m called."} } + +#ns_log notice "--chat.tcl $m: returns '$_'" + +ns_return 200 text/html [subst {$_}] Index: openacs-4/packages/chat/www/ajax/scripted-streaming-chat.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/chat/www/ajax/Attic/scripted-streaming-chat.js,v diff -u -N --- openacs-4/packages/chat/www/ajax/scripted-streaming-chat.js 15 Jun 2016 15:40:57 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,73 +0,0 @@ -// simple javascript support for streaming ajax based chat interface -// $Id: scripted-streaming-chat.js,v 1.1 2016/06/15 15:40:57 hectorr Exp $ -// -gustaf neumann April 2006 - -function getHttpObject() { - var http_request = false; - if (window.XMLHttpRequest) { // Mozilla, Safari,... - http_request = new XMLHttpRequest(); - } else if (window.ActiveXObject) { // IE - try { - http_request = new ActiveXObject('Msxml2.XMLHTTP'); - } catch (e) { - try { - http_request = new ActiveXObject('Microsoft.XMLHTTP'); - } catch (e) {} - } - } - - if (!http_request) { - alert('Cannot create and instance of XMLHTTP'); - } - return http_request; -} - -function getData(data) { - var messages = document.getElementById('messages'); - for (var i=0;i 300} { :logout -user_id $user -msg "auto logout" + # ns_log warning "-user_id $user auto logout" try {::bgdelivery do ::Subscriber sweep chat-[:chat_id]} } } + :broadcast_msg [Message new -volatile -type "users" -time [clock seconds]] :log "-- ending" } @@ -163,9 +164,9 @@ ns_log Notice "--core-chat User $user_id logging out of chat" if {${:logout_messages_p}} { if {$msg eq ""} {set msg [_ chat.has_left_the_room].} - :add_msg -get_new false $msg + :add_msg -uid $user_id -get_new false $msg } - + # These values could already not be here. Just ignore when we don't # find them try { @@ -192,15 +193,7 @@ } Chat instproc get_users {} { - set output "" - foreach {user_id timestamp} [:active_user_list] { - if {$user_id > 0} { - set diff [clock format [expr {[clock seconds] - $timestamp}] -format "%H:%M:%S" -gmt 1] - set userlink [:user_link -user_id $user_id] - append output "$userlink$diff\n" - } - } - return $output + return [:json_encode_msg [Message new -volatile -type "users" -time [clock seconds]]] } Chat instproc user_active {user_id} { @@ -212,8 +205,8 @@ Chat instproc login {} { :log "--chat login" if {${:login_messages_p} && ![:user_active ${:user_id}]} { - :add_msg -get_new false [_ xotcl-core.has_entered_the_room] - } elseif {![nsv_exists ${:array}-login ${:user_id}]} { + :add_msg -uid ${:user_id} -get_new false [_ xotcl-core.has_entered_the_room] + } elseif {${:user_id} > 0 && ![nsv_exists ${:array}-login ${:user_id}]} { # give some proof of our presence to the chat system when we # don't issue the login message ::xo::clusterwide nsv_set ${:array}-login ${:user_id} [clock seconds] @@ -253,7 +246,7 @@ } else { set creator "System" } - return [:encode $creator] + return $creator } Chat instproc urlencode {string} {ns_urlencode $string} @@ -264,25 +257,48 @@ } Chat instproc json_encode_msg {msg} { - set old [:encoder] - :encoder noencode ;# just for user_link - set userlink [:user_link -user_id [$msg user_id] -color [$msg color]] - :encoder $old - set timeshort [clock format [$msg time] -format {[%H:%M:%S]}] - set text [:json_encode [$msg msg]] - foreach var {userlink timeshort} {set $var [:json_encode [set $var]]} - return [subst -nocommands {{"messages": [ - {"user": "$userlink", "time": "$timeshort", "msg": "$text"} - ]\n} - }] + set type [$msg type] + switch $type { + "message" { + set message [$msg msg] + set user_id [$msg user_id] + set color [$msg color] + set user [:user_link -user_id $user_id -color $color] + set timestamp [clock format [$msg time] -format {[%H:%M:%S]}] + foreach var {message user timestamp} { + set $var [:json_encode [set $var]] + } + return [subst {{"type": "$type", "message": "$message", "timestamp": "$timestamp", "user": "$user"}\n}] + } + "users" { + set message [list] + foreach {user_id timestamp} [:active_user_list] { + if {$user_id < 0} continue + set timestamp [clock format [expr {[clock seconds] - $timestamp}] -format "%H:%M:%S" -gmt 1] + set user [:user_link -user_id $user_id] + foreach var {user timestamp} { + set $var [:json_encode [set $var]] + } + lappend message [subst {{"timestamp": "$timestamp", "user": "$user"}}] + } + set message "\[[join $message ,]\]" + return [subst {{"type": "$type", "chat_id": "[:chat_id]", "message": $message}\n}] + } + } } Chat instproc js_encode_msg {msg} { - set json [:json_encode_msg $msg] - return "\n" + set json [string trim [:json_encode_msg $msg]] + if {$json ne ""} { + return [subst { + \n + }] + } else { + return + } } Chat instproc broadcast_msg {msg} { @@ -295,34 +311,18 @@ set user_id [expr {[info exists uid] ? $uid : ${:user_id}}] set color [:user_color $user_id] bgdelivery subscribe chat-[:chat_id] "" [:mode] - if {${:login_messages_p} && ![:user_active $user_id]} { - :broadcast_msg [Message new -volatile -time [clock seconds] \ - -user_id $user_id -color $color \ - -msg [_ xotcl-core.has_entered_the_room] ] - } - #my get_all } Chat instproc render {} { :orderby time - set result "" + set result [list] + # Piggyback the users list in every rendering, this way we don't + # need a separate ajax request for the polling interface. + :add [Message new -type "users" -time [clock seconds]] foreach child [:children] { - set msg [$child msg] - set user_id [$child user_id] - set color [$child color] - set timelong [clock format [$child time]] - set timeshort [clock format [$child time] -format {[%H:%M:%S]}] - set userlink [:user_link -user_id $user_id -color $color] - ns_log notice "encode <$msg> using encoder [:encoder] gives <[:encode $msg]>" - append result [subst { -

- $timeshort - $userlink: - [:encode $msg] -

- }] + lappend result [:json_encode_msg $child] } - return $result + return "\[[join $result ,]\]" } ############################################################################ @@ -341,13 +341,7 @@ } ChatClass method initialize_nsvs {} { - # read the last_activity information at server start into a nsv array - ::xo::dc foreach get_rooms { - select room_id, to_char(max(creation_date),'HH24:MI:SS YYYY-MM-DD') as last_activity - from chat_msgs group by room_id - } { - ::xo::clusterwide nsv_set [self]-$room_id-seen last [clock scan $last_activity] - } + # empty stub for subclasses to extend } ChatClass method flush_messages {-chat_id:required} { Index: openacs-4/packages/xowiki/xowiki.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/xowiki.info,v diff -u -N -r1.173 -r1.174 --- openacs-4/packages/xowiki/xowiki.info 5 Aug 2018 22:08:18 -0000 1.173 +++ openacs-4/packages/xowiki/xowiki.info 28 Sep 2018 11:44:23 -0000 1.174 @@ -10,7 +10,7 @@ t xowiki - + Gustaf Neumann A xotcl-based enterprise wiki system with multiple object types 2017-08-06 @@ -55,7 +55,7 @@ BSD-Style 2 - + Index: openacs-4/packages/xowiki/tcl/chat-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/chat-procs.tcl,v diff -u -N -r1.29 -r1.30 --- openacs-4/packages/xowiki/tcl/chat-procs.tcl 20 Sep 2018 13:12:27 -0000 1.29 +++ openacs-4/packages/xowiki/tcl/chat-procs.tcl 28 Sep 2018 11:44:23 -0000 1.30 @@ -5,27 +5,46 @@ @author Gustaf Neumann @cvs-id $Id$ } + namespace eval ::xowiki { ::xo::ChatClass create Chat -superclass ::xo::Chat - Chat proc login {-chat_id -package_id {-mode ""} {-path ""}} { + ::xo::ChatClass instproc login {-chat_id -package_id {-mode ""} {-path ""}} { #:log "--chat" if {![ns_conn isconnected]} return auth::require_login - if {![info exists package_id]} {set package_id [ad_conn package_id] } - if {![info exists chat_id]} {set chat_id $package_id } - set session_id [ad_conn session_id].[clock seconds] - set context id=$chat_id&s=$session_id - set base_url ${path}ajax/chat?${context} + if {[ad_conn package_key] eq "xowiki"} { + set xowiki_package_id [ad_conn package_id] + } else { + set main_node_id [site_node::get_node_id -url "/"] + set xowiki_package_id [lindex [site_node::get_children -all \ + -package_key xowiki \ + -element object_id \ + -node_id $main_node_id] 0] + } + if {![info exists package_id]} { + set package_id $xowiki_package_id + } + #:log "chat_id=$chat_id, path=$path" if {$path eq ""} { - set path [lindex [site_node::get_url_from_object_id -object_id $package_id] 0] + set path [lindex [site_node::get_url_from_object_id \ + -object_id $package_id] 0] } elseif {[string index $path end] ne "/"} { append path / } + set xowiki_path [lindex [site_node::get_url_from_object_id \ + -object_id $xowiki_package_id] 0] + + if {![info exists chat_id]} {set chat_id $package_id} + + set session_id [ad_conn session_id].[clock seconds] + set context id=$chat_id&s=$session_id + set base_url ${path}ajax/chat?${context} + if {$mode eq ""} { # # The parameter "mode" was not specified, we try to guess the @@ -74,118 +93,110 @@ :log "--chat mode $mode" } - # small JavaScript library to obtain a portable ajax request object - ::xo::Page requireJS urn:ad:js:get-http-object - switch -- $mode { polling { - set jspath ${path}ajax/chat.js - set login_url ${base_url}&m=login - set get_update "chatSendCmd(\"${base_url}&m=get_new\",chatReceiver)" - set get_all "chatSendCmd(\"${base_url}&m=get_all\",chatReceiver)" + set jspath ${xowiki_path}ajax/chat.js + set subscribe_url ${base_url}&m=get_new } streaming { - set jspath ${path}ajax/streaming-chat.js + set jspath ${xowiki_path}ajax/streaming-chat.js set subscribe_url ${base_url}&m=subscribe } scripted-streaming { - set jspath ${path}ajax/scripted-streaming-chat.js + set jspath ${xowiki_path}ajax/scripted-streaming-chat.js set subscribe_url ${base_url}&m=subscribe&mode=scripted } default { error "mode $mode unknown, valid are: polling, streaming and scripted-streaming" } } - ::xo::Page requireJS $jspath - set users_url [ns_quotehtml ${base_url}&m=get_users] + # small JavaScript library to obtain a portable ajax request object + template::head::add_javascript -src urn:ad:js:get-http-object -order 10 + template::head::add_javascript -src ${xowiki_path}ajax/chat-common.js -order 20 + template::head::add_javascript -src $jspath -order 30 + set send_url ${base_url}&m=add_msg&msg= :log "--CHAT mode=$mode" - # TODO: styling should happen in some template - # set style { - # margin:1.5em 0 1.5em 0; - # padding:1em 0 1em 1em; - # background-color: #f9f9f9; - # border:1px solid #dedede; - # height:150px; - # font-size:.95em; - # line-height:.7em; - # color:#333; - # overflow:auto; - # } - template::add_body_script -script { - document.getElementById('chatMsg').focus(); + document.getElementById('xowiki-chat-send').focus(); } - if {$mode ne "polling"} { - ::xowiki::Chat create c1 \ + set html "" + + if {[apm_package_installed_p chat]} { + set message_label [_ chat.message] + set send_label [_ chat.Send_Refresh] + } else { + set message_label "Message" + set send_label "Send" + } + + # TODO: it is currently not possible to embed multiple chats in + # the same page. + append html [subst { +
+
+
+
+
+ $message_label + +
+ }] + + [self] create c1 \ -destroy_on_cleanup \ -chat_id $chat_id \ -session_id $session_id \ -mode $mode + + set data [c1 login] + if {$data ne ""} { + append html [subst { + + }] } - set html "" switch -- $mode { "polling" { - set r [subst { - - }] - template::add_event_listener \ - -id "messages-form" \ - -event "submit" \ - -script [subst { - chatSendMsg('$send_url',chatReceiver); - }] append html [subst -nocommands { }] + set send_msg_handler pollingSendMsgHandler } "streaming" { - set r [ns_urldecode [c1 get_all]] - template::add_event_listener \ - -id "messages-form" -event "submit" \ - -script {chatSendMsg();} append html [subst { }] + set send_msg_handler streamingSendMsgHandler } "scripted-streaming" { - set r [ns_urldecode [c1 get_all]] - template::add_event_listener \ - -id "messages-form" -event "submit" \ - -script {chatSendMsg();} append html [subst { - }] + set send_msg_handler scriptedStreamingSendMsgHandler } } - append html [subst { -
$r
-
- -
- }] + template::add_event_listener \ + -id "xowiki-chat-messages-form" -event "submit" \ + -script [subst {chatSendMsg('${send_url}', ${send_msg_handler});}] return $html } Index: openacs-4/packages/xowiki/www/ajax/chat-common.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/ajax/Attic/chat-common.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/xowiki/www/ajax/chat-common.js 28 Sep 2018 11:44:23 -0000 1.1 @@ -0,0 +1,63 @@ +// Common xowiki chat functions, mainly for data rendering. + +function renderData(json) { + if (json.type == "message") { + renderMessage(json); + } else if (json.type == "users") { + renderUsers(json); + } +} + +function renderMessage(msg) { + var messages = document.getElementById('xowiki-chat-messages'); + p = document.createElement('p'); + span = document.createElement('span'); + span.innerHTML = msg.timestamp; + span.className = 'xowiki-chat-timestamp'; + p.appendChild(span); + + span = document.createElement('span'); + var user = msg.user.replace("\\'", "'"); + span.innerHTML = ' ' + user + ': '; + span.className = 'xowiki-chat-user'; + p.appendChild(span); + + span = document.createElement('span'); + span.innerHTML = msg.message; + span.className = 'xowiki-chat-message'; + p.appendChild(span); + + messages.appendChild(p); + messages.scrollTop = messages.scrollHeight; +} + +function renderUsers(msg) { + var users = document.getElementById('xowiki-chat-users'); + while (users.hasChildNodes()) { + users.removeChild(users.firstChild); + } + for (var i = 0; i < msg.message.length; i++) { + p = document.createElement('p'); + span = document.createElement('span'); + span.innerHTML = msg.message[i].timestamp; + span.className = 'xowiki-chat-timestamp'; + p.appendChild(span); + + span = document.createElement('span'); + var user = msg.message[i].user.replace("\\'", "'"); + span.innerHTML = ' ' + user + ' '; + span.className = 'xowiki-chat-user'; + p.appendChild(span); + users.appendChild(p); + } +} + +function chatSendMsg(send_url, handler) { + var msgField = document.getElementById('xowiki-chat-send'); + var msg = msgField.value; + if (msg == '') {return;} + http_send.open('GET', send_url + encodeURIComponent(msg), true); + http_send.onreadystatechange = handler; + http_send.send(null); + msgField.value = ''; +} Index: openacs-4/packages/xowiki/www/ajax/chat.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/ajax/Attic/chat.js,v diff -u -N -r1.8 -r1.9 --- openacs-4/packages/xowiki/www/ajax/chat.js 29 Jul 2013 08:56:44 -0000 1.8 +++ openacs-4/packages/xowiki/www/ajax/chat.js 28 Sep 2018 11:44:23 -0000 1.9 @@ -3,50 +3,38 @@ // -gustaf neumann April 2006 var http = getHttpObject(); +var http_send = getHttpObject(); -function chatReceiver() { - if (http.readyState == 4) { - // alert('status code =' + http.status); - if (http.status == 200) { - appendToMessages(http.responseText); - } else { - clearInterval(); - alert('Something wrong in HTTP request, status code = ' + http.status); - } - } +function chatSubscribe(subscribe_url) { + setInterval(function () { + http.open('GET', subscribe_url); + http.onreadystatechange = function () { + if (http.readyState == 4) { + // alert('status code =' + http.status); + if (http.status == 200) { + var json = JSON.parse(http.responseText); + for (var i = 0; i < json.length; i++) { + renderData(json[i]); + } + } else { + clearInterval(); + alert('Something wrong in HTTP request, status code = ' + http.status); + } + } + }; + http.send(null); + }, 5000); } -function appendToMessages(content) { - var xmlobject = (new DOMParser()).parseFromString(content, 'application/xhtml+xml'); - var items = xmlobject.getElementsByTagName('div')[0].children; - - //console.debug("items: " + items.length); - //if (items.length > 0) {console.log(content);} - //if (items.length > 0) {console.log(items[0].innerHTML);} - - var doc = frames['ichat'].document; - var messages = frames['ichat'].document.getElementsByTagName('div')[0]; - for (var i = 0 ; i < items.length ; i++) { - var p = doc.createElement('p'); // add class 'line' - var att = doc.createAttribute("class"); - att.value = 'line'; - p.setAttributeNode(att); - p.innerHTML = decodeURIComponent(items[i].innerHTML).replace(/\+/g,' '); - messages.appendChild(p); +function pollingSendMsgHandler() { + if (http_send.readyState == 4) { + if (http_send.status != 200) { + alert('Something wrong in HTTP request, status code = ' + http_send.status); + } else { + var json = JSON.parse(http_send.responseText); + for (var i = 0; i < json.length; i++) { + renderData(json[i]); + } + } } - frames['ichat'].window.scrollTo(0,messages.offsetHeight); -} - - -function chatSendMsg(send_url,handler) { - var msgField = document.getElementById('chatMsg'); - chatSendCmd(send_url + encodeURIComponent(msgField.value),handler); - msgField.value = ''; -} - -var msgcount = 0; // hack to overcome IE -function chatSendCmd(url,handler) { - http.open('GET', url + '&mc=' + msgcount++, true); - http.onreadystatechange = handler; - http.send(null); -} +}; Index: openacs-4/packages/xowiki/www/ajax/chat.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/ajax/Attic/chat.tcl,v diff -u -N -r1.9 -r1.10 --- openacs-4/packages/xowiki/www/ajax/chat.tcl 7 Aug 2017 23:48:31 -0000 1.9 +++ openacs-4/packages/xowiki/www/ajax/chat.tcl 28 Sep 2018 11:44:23 -0000 1.10 @@ -17,39 +17,24 @@ switch -- $m { add_msg { #ns_log notice "--c call c1 $m '$msg'" - set _ [c1 $m $msg] + ns_return 200 application/json [c1 $m $msg] + ad_script_abort #ns_log notice "--c add_msg returns '$_'" } + get_new { + ns_return 200 application/json [c1 $m] + ad_script_abort + } login - subscribe - - get_new - get_all {set _ [c1 $m]} - default {ns_log error "--c unknown method $m called."} + default {ns_log error "--c unknown method $m called."} } #ns_log notice "--chat.tcl $m: returns '$_'" -set style { - padding:1em 0 1em 1em; - background-color: #f9f9f9; - font-size:.95em; - color:#333; - overflow:auto; -} +ns_return 200 text/html [subst {$_}] -ns_return 200 text/html " - - - -$_ - -" - # Local variables: # mode: tcl # tcl-indent-level: 2 Index: openacs-4/packages/xowiki/www/ajax/scripted-streaming-chat.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/ajax/Attic/scripted-streaming-chat.js,v diff -u -N -r1.7 -r1.8 --- openacs-4/packages/xowiki/www/ajax/scripted-streaming-chat.js 20 Sep 2018 13:25:24 -0000 1.7 +++ openacs-4/packages/xowiki/www/ajax/scripted-streaming-chat.js 28 Sep 2018 11:44:23 -0000 1.8 @@ -4,43 +4,17 @@ var http_send = getHttpObject(); +// This function MUST be there as in +// xotcl-core/tcl/bgdelivery-procs.tcl we expect getData to elaborate +// data coming from the continuos javascript iframe. function getData(data) { - var messages = document.getElementById('messages'); - for (var i=0;i