Raging Goblin

14 June 2010

Chat application in Egroupware

Filed under: Egroupware — Raging Goblin @ 18:31
Tags: ,

As groupware server for my contacts, notes, email and calender I use Egroupware. Me and my wife are happy users of this system, I can synchronize my agenda, contacts, todo and sticky notes with my pocket pc using the Funambol ppc plugin. On the desktop we both use Thunderbird. The only thing it really lacks is a chat application. On the forums you can find several people asking for it, e.g. here, and here. I posted my solution with PHPFreechat on a forum. Hans-Jürgen Tappe made this into a nice external patch that you can download from http://www.egroupware.org/egroupware/index.php?menuaction=tracker.tracker_ui.edit&tr_id=2131&no_popup=1.

The problem I have with this solution that the chat opens in a new window and this window handles the chat separately. So how can you inform someone that you want to chat to him or her when she has not opened the chat window? You then have to send the other person an email to inform him that you want him to join the chat.

In order to have a really integrated solution I changed the code of my egroupware system so that the chat loads in an embedded div inside the website. The disadvantage of this solution is that it will break your update schedule because with every update you have to redo it. To me that is the price I will pay to get what I want. (Another disadvantage counts only from a technical viewpoint, it is really a bit of a dirty hack). Still reading? Lets go!

1 Configure Apache
In order to let all Egroupware applications load the same instance of the chat we need to alter the configuration a bit. Apache must be allowed to follow symlinks (note that this is considered a security breach). Edit the file httpd.conf and add the option FollowSymLinks to the Directory section:

<Directory />
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
</Directory>

2 Download and install chat application
I have chosen phpfreechat as it provides a decent and pretty mature chat application. Any other might do as well, e.g. Chatty is another option and a little googling on the web will provide you with plenty alternatives.

Go to the egroupware directory on your server and issue the command:

svn co https://phpfreechat.svn.sourceforge.net/svnroot/phpfreechat/tags/1.3 phpfreechat

You can also download the zip file from the website and unzip it to your egroupware directory.

Grant write access to egroupware/phpfreechat/data/ for the web server (I am on OpenSuse):

chown -R wwwrun:www egroupware/phpfreechat/data/

Now if you point a browser to http://–your server–/egroupware/phpfreechat you will see a chat window indicating that your chat is functional. Of course we don’t want people into our chat room who are not logged in, so make some files unreadable:

chmod 000 egroupware/phpfreechat/index.php;
chmod -R 000 egroupware/phpfreechat/demo/;

3 Print the chat
In order to print the chat I wrote some PHP code that prints the chat. Adjust the commented parts and save it as chat.php in the Egroupware directory.

<?php
/** Prints the chat to the screen inside the 'chatter' div */
require_once '--full path to phpfreechat.class.php --'; // On my server this is /srv/www/htdocs/egroupware/phpfreechat/src/phpfreechat.class.php';
$params = array();
$params["serverid"] = md5("--your domain name--"); // e.g. example.com/egroupware
$params["title"] = "Chat to online users";
$params["height"] = "120px";
$params["showsmileys"] = false;
$params["displaytabclosebutton"] = false;
$params["theme"] = "msn";
$params["display_ping"] = false;
$params["channels"] = array("Public room");
$params["nick"] = $GLOBALS[egw_info_cache][user][account_firstname];
$params['admins'] = array('--admin account--'  => '--admin password--'); // Maybe a good idea to make this the same as your egroupware admin account?
$params["max_msg"] = 10;
$params["shownotice"] = 0;
$params["display_pfc_logo"] = false;
$chat = new phpFreeChat($params);
if(($GLOBALS[egw_info_cache][user][account_primary_group] == -1) &&
	(!strpos(getcwd(), 'admin')) &&
	(!strpos(getcwd(), 'home')) &&
	(!strpos(getcwd(), 'wiki'))){
	print("<div id='chatter' ondblclick='reFloatChatter()' style='position:fixed; bottom 160px; right:10px;  width:500px; height:100px; z-index:50;'>);
	$chat->printChat();
	print("</div>");	
}
?>

This script prints a div named ‘chatter‘ with a fully customized version of PHPFreechat, except when looking at the admin, home and wiki pages.

4 Create Symlinks
As I told earlier we need some symlinks. Create a symlink to the data directory of phpfreechat from the egroupware main directory:

cd /srv/www/htdocs/egroupware
ln -s phpfreechat/data data;

We also need symlinks to phpfreechat from applications for which the working directory is not the egroupware main directory. E.g. the infolog application, check in the url of a application if this is the case and create the links:

cd /srv/www/htdocs/egroupware/infolog
ln -s ../chat.php chat.php;
ln -s ../phpfreechat phpfreechat
ln -s ../phpfreechat/data data

5 Print the ‘chatter’ div
In order to move the chat around we need some javasript:

<script language="JavaScript" type="text/javascript">
var chatterOnTop = true;

function reFloatChatter() {
   var chatterDiv = document.getElementById('chatter');
   var currentPosition = parseInt(chatterDiv.style.top);
   if(chatterOnTop){
        document.getElementById('chatter').style.top='';
        document.getElementById('chatter').style.bottom='160px';
        chatterOnTop = false;
    } else {
        document.getElementById('chatter').style.top='10px';
        document.getElementById('chatter').style.bottom='';
        chatterOnTop = true;
    }
}

window.onload=function(){
    reFloatChatter();
}
</script>

This needs to be printed on every website of every page, so I put this inside /srv/www/htdocs/egroupware/phpgwapi/templates/default/footer.tpl right before the closing body tag.

6 Glue it together
What is left to do is create a call to the chat.php script. What we need is a php script in egroupware that is always printed. I selected /srv/www/htdocs/egroupware/phpgwapi/templates/idots/class.idots_framework.inc.php for this purpose. Currently I am using version 1.8.004. On line 685 inside the footer() function, while loading the previous mentioned footer.tpl I put the statement:

require_once '/srv/www/htdocs/egroupware/chat.php';

So that that the modified function looks like this:

	/**
	* Returns the html from the closing div of the main application area to the closing html-tag
	*
	* @return string html or null if no footer needed/wanted
	*/
	function footer()
	{
		static $footer_done;
		if ($footer_done++) return;	// prevent multiple footers, not sure we still need this (RalfBecker)

		if (!isset($GLOBALS['egw_info']['flags']['nofooter']) || !$GLOBALS['egw_info']['flags']['nofooter'])
		{
			// get the (depricated) application footer
			$content = $this->_get_app_footer();

			// run the hook navbar_end
			// ToDo: change to return the content
			ob_start();
			$GLOBALS['egw']->hooks->process('navbar_end');
			$content .= ob_get_contents();
			ob_end_clean();

			// eg. javascript, which need to be at the end of the page
			if ($GLOBALS['egw_info']['flags']['need_footer'])
			{
				$content .= $GLOBALS['egw_info']['flags']['need_footer'];
			}

			// do the template sets footer, former parse_navbar_end function
			// this closes the application area AND renders the closing body- and html-tag
			if (self::$navbar_done)
			{
				$this->tpl->set_file(array('footer' => 'footer.tpl'));
				$this->tpl->set_var($this->_get_footer());
				$content .= $this->tpl->fp('out','footer');
require_once '/srv/www/htdocs/egroupware/chat.php';
			}
			elseif (!isset($GLOBALS['egw_info']['flags']['noheader']) || !$GLOBALS['egw_info']['flags']['noheader'])
			{
				$content .= "</body>\n</html>\n";	// close body and html tag, eg. for popups
			}
			return $content;
		}
	}

The result is a floating box that displays a list of all online users. You can chat to these and if the box gets in your way dubble click it and it will move to the top of the page. It provides all functionality of phpfreechat, so if you want to configure it, turn to the website and read the fabulous documentation 🙂 The floating box is lined out as fits me well, but if you want other margins (e.g. the smiley box is out of range when the chat is at the bottom) you can change this in chat.php and the provided javascript.

Oh, and before I forget, here is a screenshot:
Egroupware with phpfreechat embedded

Blog at WordPress.com.