Skip to content

Custom integration howto

Philip Nicolcev edited this page Nov 7, 2013 · 3 revisions

Custom integration howto

AJAX Chat provides integrations for phpBB2, phpBB3, MyBB, PunBB, SMF, vBulletin and a standalone version.
This guide shows you how to integrate AJAX Chat in any existing system.
Integration means taking over user authentication, permission system and channel list from the existing system.

Table of Contents

The integration versions differ only in a small number of files:

  1. readme.txt
  2. version.txt
  3. lib/config.php
  4. lib/custom.php
  5. lib/class/CustomAJAXChat.php
  6. lib/template/loggedOut.html
The standalone version includes an additional directory /lib/data/ with example datasources - this directory is not needed for a complete custom integration.

1. readme.txt

readme.txt contains setup instructions and general information about AJAX Chat.

2. version.txt

version.txt contains version information.

3. lib/config.php

lib/config.php is the server-side configuration file. The differences between the integration versions for this config file consist only of a small number of settings:

Database settings

The database settings are explained on the Database Connection Wiki Page.

Style settings

The style settings are explained on the Layout customization Wiki Page.

Encoding settings

The encoding settings consist of two configuration options:

// The encoding used for the XHTML content:
$config['contentEncoding'] = 'UTF-8';
// The encoding of the data source, like userNames and channelNames:
$config['sourceEncoding'] = 'UTF-8';

AJAX Chat uses UTF-8 internally, for the database storage and for the AJAX (Asynchronous JavaScript and XML) communication.
The sourceEncoding setting is used to convert the encoding of the data sources to UTF-8 - the userNames and channelNames taken from the existing system. It must be set to the encoding used by the existing system - e.g. phpBB2 stores userNames and forum names (which are used as channel names) in ISO-8859-1 encoding, while phpBB3 uses UTF-8 encoding.
The contentEncoding setting is used for the HTML output of the chat. AJAX Chat automatically converts the HTML content from UTF-8 to the desired encoding. Characters that cannot be displayed with this encoding are converted to HTML entities.
The JavaScript files are always included in UTF-8 encoding and don't need any encoding conversion. The same applies for the chat data which is retrieved through AJAX communication.
The contentEncoding setting should as well be set to the encoding of the existing system. If the chat is included as a shoutbox it must have the same encoding of the including website. The second reason is the encoding of the login data, which is set by the user browser to the encoding of the login page. AJAX Chat directs users attempting to login through the chat login page to the existing system which expects the login data in its own encoding setting.

4. lib/custom.php

lib/custom.php is used to include custom libraries used for user authentication and the permission system of the existing system.
This is specific for the system you wish to write the integration for and you should consult the available documentation for this system.
As an example, this is the content of lib/custom.php for the phpBB3 integration version:

// phpBB initialization:
define('IN_PHPBB', true);
$phpbb_root_path = AJAX_CHAT_PATH.'../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
require($phpbb_root_path.'common.'.$phpEx);

// phpBB session management:
$user->session_begin();
$auth->acl($user->data);
?>

5. lib/class/CustomAJAXChat.php

lib/class/CustomAJAXChat.php is the main file for a custom integration of AJAX Chat.
It contains the class CustomAJAXChat which extends the class AJAXChat and overrides some important methods.
The class AJAXChat contains the main chat logic.
An instance of the class CustomAJAXChat (which inherits the main chat logic from AJAXChat) is used to initialize the chat in index.php:

<?php
/*
 * @package AJAX_Chat
 * @author Sebastian Tschan
 * @copyright (c) Sebastian Tschan
 * @license GNU Affero General Public License
 * @link https://blueimp.net/ajax/
 */

// Show all errors:
error_reporting(E_ALL);

// Path to the chat directory:
define('AJAX_CHAT_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/');

// Include custom libraries and initialization code:
require(AJAX_CHAT_PATH.'lib/custom.php');

// Include Class libraries:
require(AJAX_CHAT_PATH.'lib/classes.php');

// Initialize the chat:
$ajaxChat = new CustomAJAXChat();
?>

The methods that must be overriden inside the class CustomAJAXChat for a custom integration are the following:

  • getValidLoginUserData()
  • getAllChannels()
  • getChannels()

getValidLoginUserData()

This method is called on chat login to retrieve valid authentication data.
It must return an associative array with the following values:

  1. 'userID' => the userID of the logged in user
  2. 'userName' => the (trimmed) userName of the logged in user
  3. 'userRole' => the userRole of the logged in user
If the user is logged in to the existing system it should return the userID and the ("trimmed") userName of this user.
The method $this->trimUserName($userName) returns a "trimmed" version of the userName which ensures UTF-8 encoding and avoids invalid characters (e.g. it replaces spaces with the underscore).
The userRole must be one of the following constants:
  1. AJAX_CHAT_ADMIN
  2. AJAX_CHAT_MODERATOR
  3. AJAX_CHAT_USER
If the user is not logged in to the existing system, the method can just return with a call to $this->getGuestUser().
If guest access is allowed, $this->getGuestUser() returns an associative array with a unique guest userID, a guest userName and the userRole constant AJAX_CHAT_GUEST.
If guest access is disabled, $this->getGuestUser() just returns null, which means login is denied.

The following is the getValidLoginUserData() method of the phpBB3 integration version:

    // Returns an associative array containing userName, userID and userRole
    // Returns null if login is invalid
    function getValidLoginUserData() {
        global $auth,$user;

        // Return false if given user is a bot:
        if($user->data['is_bot']) {
            return false;
        }

        // Check if we have a valid registered user:
        if($user->data['is_registered']) {
            $userData = array();
            $userData['userID'] = $user->data['user_id'];

            $userData['userName'] = $this->trimUserName($user->data['username']);

            if($auth->acl_get('a_'))
                $userData['userRole'] = AJAX_CHAT_ADMIN;
            elseif($auth->acl_get('m_'))
                $userData['userRole'] = AJAX_CHAT_MODERATOR;
            else
                $userData['userRole'] = AJAX_CHAT_USER;

            return $userData;

        } else {
            // Guest users:
            return $this->getGuestUser();
        }
    }

getAllChannels()

This method returns a reference to an associative array of all available chat channels.
The array must use the channelNames as keys and the channelIDs as values, e.g. Channel_12' => 12.
Alike the userName returned by the getValidLoginUserData() method, the channelNames must be "trimmed". The method $this->trimChannelName($channelName) returns a "trimmed" version of the channelName which ensures UTF-8 encoding and avoids invalid characters (e.g. it replaces spaces with the underscore).
The official integration versions of AJAX Chat are all written for forum communities - so the channels are just taken from the list of subforums, e.g. a forum with the subforums "Forum 1", "Forum 2" and "Forum 3" will have the chat channels "Forum 1", "Forum 2" and "Forum 3".
If the default channel (which can be configured in lib/config.php) is not set to one of the existing channelIDs it must be added as well before returning the reference to the channels array.

The following is the getAllChannels() method of the phpBB3 integration version:

    // Store all existing channels
    // Make sure channel names don't contain any whitespace
    function &getAllChannels() {
        if($this->_allChannels === null) {
            global $db;

            $this->_allChannels = array();

            // Get valid phpBB forums:
            $sql = 'SELECT
                            forum_id,
                            forum_name
                        FROM
                            '.FORUMS_TABLE.'
                        WHERE
                            forum_type=1
                        AND
                            forum_password=\'\';';
            $result = $db->sql_query($sql);

            $defaultChannelFound = false;

            while ($row = $db->sql_fetchrow($result)) {
                $forumName = $this->trimChannelName($row['forum_name']);

                $this->_allChannels[$forumName] = $row['forum_id'];

                if(!$defaultChannelFound && $row['forum_id'] == $this->getConfig('defaultChannelID')) {
                    $defaultChannelFound = true;
                }
            }
            $db->sql_freeresult($result);

            if(!$defaultChannelFound) {
                // Add the default channel as first array element to the channel list:
                $this->_allChannels = array_merge(
                    array(
                        $this->trimChannelName($this->getConfig('defaultChannelName'))=>$this->getConfig('defaultChannelID')
                    ),
                    $this->_allChannels
                );
            }
        }
        return $this->_allChannels;
    }

getChannels()

This method returns a reference to an associative array of all chat channels the current user has access to.
It is a subset of the array returned by the getAllChannels() method with those channels skipped that the current user may not access.
Access rights are taken from the existing authentication system, e.g. if a user has no access to a certain forum access to the related chat channel is denied as well.
This method must also take into account the configuration option limitChannelList which can be set in lib/config.php and allows to limit the channel list in addition to the permission system.
The referenced array must always include the default channel.

The following is the getChannels() method of the phpBB3 integration version:

    // Store the channels the current user has access to
    // Make sure channel names don't contain any whitespace
    function &getChannels() {
        if($this->_channels === null) {
            global $auth;

            $this->_channels = array();

            $allChannels = $this->getAllChannels();

            foreach($allChannels as $key=>$value) {
                // Check if we have to limit the available channels:
                if($this->getConfig('limitChannelList') && !in_array($value, $this->getConfig('limitChannelList'))) {
                    continue;
                }

                // Add the valid channels to the channel list (the defaultChannelID is always valid):
                if($value == $this->getConfig('defaultChannelID') || $auth->acl_get('f_read', $value)) {
                    $this->_channels[$key] = $value;
                }
            }
        }
        return $this->_channels;
    }


Additional methods which are overriden by CustomAJAXChat for the integration versions are the following:

  • initCustomConfig()
  • initCustomRequestVars()
  • replaceCustomTemplateTags($tag, $tagContent)
  • setStyle()
These methods don't have to be overriden for a custom integration but allow a more complete integration.

initCustomConfig()

Custom configuration options can be initialized using this method.
e.g. the following is the initCustomConfig() method of the phpBB3 version and allows to reuse the phpBB3 database connection:

    // Initialize custom configuration settings
    function initCustomConfig() {
        global $db;

        // Use the existing phpBB database connection:
        $this->setConfig('dbConnection', 'link', $db->db_connect_id);
    }

initCustomRequestVars()

This method allows to initialize custom request vars.
e.g. the following is the initCustomRequestVars() method of the phpBB3 version and allows to autologin authenticated phpBB users to the chat:

    // Initialize custom request variables:
    function initCustomRequestVars() {
        global $user;

        // Auto-login phpBB users:
        if(!$this->getRequestVar('logout') && ($user->data['user_id'] != ANONYMOUS)) {
            $this->setRequestVar('login', true);
        }
    }

replaceCustomTemplateTags($tag, $tagContent)

This method allows to define custom template tags. Template tags are used to insert dynamic data into the HTML templates (the files under lib/template/). They are replaced dynamically before the template content is served to the clients.
The method accepts two parameters:

  1. $tag - the actual template tag, e.g. "LANG" for language tags.
  2. $tagContent - the tag content, is only set for enclosing tags like the LANG tags you can find in the template files.
The method must return the content that is used as replacement for the template tags or null, if the template tag couldn't be replaced.

The phpBB3 version of this method introcudes two new template tags for dynamic URL's to allow the redirection of users before and after login to the authentication system (they're used for the lib/template/loggedOut.html template):

    // Replace custom template tags:
    function replaceCustomTemplateTags($tag, $tagContent) {
        global $user;

        switch($tag) {

            case 'FORUM_LOGIN_URL':
                if($user->data['is_registered']) {
                    return ($this->getRequestVar('view') == 'logs') ? './?view=logs' : './';
                } else {
                    return $this->htmlEncode(generate_board_url().'/ucp.php?mode=login');
                }

            case 'REDIRECT_URL':
                if($user->data['is_registered']) {
                    return '';
                } else {
                    return $this->htmlEncode($this->getRequestVar('view') == 'logs' ? $this->getChatURL().'?view=logs' : $this->getChatURL());
                }

            default:
                return null;
        }
    }

setStyle()

This method can be used to set a style cookie using the user style setting of the existing system.
e.g. if the user has a the style "mystyle" set for the forum system and a style with the same name is available for the chat it can be set on first chat load using the style cookie.
The style cookie is a cookie with the AJAX Chat sessionName (can be set on lib/config.php) and the string _style appended and contains the styleName as content.
The following is the phpBB3 version of this method:

    // Method to set the style cookie depending on the phpBB user style
    function setStyle() {
        global $config,$user,$db;

        if(isset($_COOKIE[$this->getConfig('sessionName').'_style']) && in_array($_COOKIE[$this->getConfig('sessionName').'_style'], $this->getConfig('styleAvailable')))
            return;

        $styleID = (!$config['override_user_style'] && $user->data['user_id'] != ANONYMOUS) ? $user->data['user_style'] : $config['default_style'];
        $sql = 'SELECT
                        style_name
                    FROM
                        '.STYLES_TABLE.'
                    WHERE
                        style_id = \''.$db->sql_escape($styleID).'\';';
        $result = $db->sql_query($sql);
        $styleName = $db->sql_fetchfield('style_name');
        $db->sql_freeresult($result);

        if(!in_array($styleName, $this->getConfig('styleAvailable'))) {
            $styleName = $this->getConfig('styleDefault');
        }

        setcookie(
            $this->getConfig('sessionName').'_style',
            $styleName,
            time()+60*60*24*$this->getConfig('sessionCookieLifeTime'),
            $this->getConfig('sessionCookiePath'),
            $this->getConfig('sessionCookieDomain'),
            $this->getConfig('sessionCookieSecure')
        );
        return;
    }

6. lib/template/loggedOut.html

This is the template file for users not currently logged into the chat or the forum or website the integration is written for.
It is used to allow guest logins and to redirect registered users to the login script of the forum/website. "login script" in this context means the script that is handling the login data sent by the user. The login script is expected to redirect the user back to the chat after successful login.

The login form must be adjusted so the form element names match the form element names of a standard login page of the forum/website the integration is written for.
e.g. if the login script expects the userName value as POST parameter with the name User-Name, the userName field must have the attribute name="User-Name".
The same applies for the password field and additional parameters expected by the login script.
The action attribute of the form must be set to the URL of the login script - this can be done by using custom template tags (see section above).

The following is the HTML form of the phpBB3 version of lib/template/loggedOut.html:

    <form id="loginForm" action="[FORUM_LOGIN_URL/]" method="post" enctype="application/x-www-form-urlencoded" onsubmit="return handleLogin();">
            <div id="loginFormContainer">
                <input type="hidden" name="login" id="loginField" value="login"/>
                <input type="hidden" name="redirect" id="redirectField" value="[REDIRECT_URL/]"/>
                <div><label for="userNameField">[LANG]userName[/LANG]:</label><br />
                <input type="text" name="username" id="userNameField" maxlength="[USER_NAME_MAX_LENGTH/]"/></div>
                <div><label for="passwordField">[LANG]password[/LANG]*:</label><br />
                <input type="password" name="password" id="passwordField"/></div>
                <div><label for="channelField">[LANG]channel[/LANG]:</label><br />
                <select name="channelName" id="channelField">[CHANNEL_OPTIONS/]</select></div>
                <div><label for="languageSelection">[LANG]language[/LANG]:</label><br />
                <select id="languageSelection" name="lang" onchange="ajaxChat.switchLanguage(this.value);">[LANGUAGE_OPTIONS/]</select></div>
                <div><input type="submit" name="submit" id="loginButton" value="[LANG]login[/LANG]"/></div>
                <div id="loginRegisteredUsers">* [LANG]registeredUsers[/LANG]</div>
            </div>
        </form>

Note the different userName and password "name" attributes (compared to the standalone version) and the additional hidden fields required by the phpBB3 login script.

You will also notice the call to the JavaScript method handleLogin() on form submit. This methods allows guest logins by changing the action attribute to the chat URL and by readjusting the "name" attributes to the parameters expected by the chat login script if no password has been entered.
It also adds the channelName to the redirect parameter given to the phpBB3 login script. This parameter tells the phpBB3 login script to redirect the user back to the chat after successful login.

The following is the handleLogin() method of the phpBB3 version (which is similar on all integration versions):

    function handleLogin() {
                var loginForm = document.getElementById('loginForm');
                var userNameField = document.getElementById('userNameField');
                var passwordField = document.getElementById('passwordField');
                var channelField = document.getElementById('channelField');
                var redirectField = document.getElementById('redirectField');
                if(passwordField.value.length == 0) {
                    loginForm.setAttribute('action', '[LOGIN_URL/]');
                    userNameField.setAttribute('name', 'userName');
                } else {
                    var channelRequest = 'channelName=' + encodeURIComponent(channelField.value);
                    var regExp = /\?/;
                    if(regExp.test(redirectField.value)) {
                        redirectField.value += '&';
                    } else {
                        redirectField.value += '?';
                    }
                    redirectField.value += channelRequest;
                }
                return true;
            }


That's it. You finished the custom integration tutorial and should now be able to integrate AJAX Chat into your website.

Clone this wiki locally