Welcome Guest, Not a member yet? Register   Sign In
Integrating CI with SMF (Simple Machines Forum)
#1

[eluser]Vik[/eluser]
Per the request of forum poster MrPrise, I am starting a new topic for this discussion - continued from this thread.

[quote author="MrPrise" date="1195275835"][quote author="Vik" date="1195274885"]Do you use ssi.php and also smf.api, or just one or the other?[/quote]
I just use ssi.php.

[quote author="Vik" date="1195274885"]Can you register users on your site's home page, without sending them to the SMF registration page?[/quote]
Well, I have not went this far yet ;-) I just started to play with CI a few days ago. My first goal was to use my SMF template (I mean the CSS and the header and footer so the generated pages will look similar no matter which system generate them) from my CI and show the login box to log into SMF from CI. I'm glad, because these are already working.

I'm not sure if we can continue to talk about SMF-CI integration in this topic.
If there is a topic for that we can continue to share our experiences there.[/quote]

I've got ssi.php working too. It's really easy. You just include this at the top of the controller.

Code:
require("../forum/SSI.php");

I'm curious if it's possible to register people to SMF (ideally with email confirmation), without having them leave my home page and go to the SMF page.
#2

[eluser]MrPrise[/eluser]
Why do you want to allow registration from both system? I think it is hard to achieve that. It is easier to use SMF's function for the authentication and then use its datas on your CI portal.
#3

[eluser]Vik[/eluser]
I agree. I do want to use the SMF registration function and database. But I don't want to take the user away from my home page and over to the SMF registration page to do it. Smile I want them to stay on my main site.
#4

[eluser]MrPrise[/eluser]
[quote author="Vik" date="1195283230"]I agree. I do want to use the SMF registration function and database. But I don't want to take the user away from my home page and over to the SMF registration page to do it. Smile I want them to stay on my main site.[/quote]
Ah, I see. Maybe I misunderstood you. So, you want to use SMF's registration form on your portal? I think that is possible.
#5

[eluser]Vik[/eluser]
Here's an update, for reference by others who may be interested in this topic. I got my CI app and my SMF forum connected, as others on this site have done as well. Here's some info on how I did it.

I took the approach that, rather than having one unified database shared by both CI and SMF, I would have two separate databases, one used by my CI app, and one used by SMF. If someone logs in to the forum, they are automatically logged in to my CI app, and vice versa. Same thing if they log out. They can register on one side and automatically be registered on the other side as well. Same thing if they change their password.

It seems to me that SMF is one of the best (if not the best) forums for integrating with other systems, like a CI app. They provide lots of facilities to assist. Their own user forum even has a topic devoted to the subject ("Portals, Bridges, and Integrations").

On their forum, you will find a topic (stickied), called A guide to the SMF integration hooks. This discusses the hook system built into SMF. This hook system can be used to get SMF to call your own PHP code at most of the times relevant to system integration. For example, you can have SMF call your own code when a user logs in, logs out, registers, etc. Then you can have your CI app log the user in or out, register, etc.

Of course, these hooks can't launch CI and call a CI object's method, so your PHP code called by these hooks has to be in a vanilla PHP file. This is usually easy to deal with as the vanilla PHP code for looking up something in your database is very easy to use.

You may also want to load some of your CI config files, and that's easy too - I used this approach:

Code:
//    LOAD CONFIG INFO
$system_folder = "your_system";
define('BASEPATH', $system_folder.'/');
include($_SERVER['DOCUMENT_ROOT'] .  '/' . $system_folder . '/application/config/config.php');
include($_SERVER['DOCUMENT_ROOT'] .  '/' . $system_folder . '/application/config/database.php');

Notice that reference to $_SERVER['DOCUMENT_ROOT'] - it gets the correct path info for server.

The trickiest thing is getting a user logged in to your CI app, without launching CI! That took me a day to figure out. It turns out that to do this, you just need to set a cookie, and put a matching entry into your ci_sessions database. Here's the code I'm using for this. I'm using FreakAuth light for my authentication, but this code should be easy to adapt for other authentication systems.

(Out of space -- continued in next post).
#6

[eluser]Vik[/eluser]
(Continued from previous post).

Code:
//SMF calls this routine and provides the $username as a parameter.
function login_to_CI_App($username, $hash_password, $cookieTime)
{
//    SMF has validated the user. So, log the user in, by
//    setting a cookie and putting a matching entry in the ci_sessions database.
//    
//    ACCESS GLOBALS FROM SMF
    global $user_settings, $db_name, $system_folder;
    
//    LOAD CONFIG INFO
    define('BASEPATH', $system_folder.'/');
    
    include($_SERVER['DOCUMENT_ROOT'] .  '/' . $system_folder . '/application/config/config.php');
    include($_SERVER['DOCUMENT_ROOT'] .  '/' . $system_folder . '/application/config/database.php');

//    SET THE COOKIE
    $theCookieName = $config['sess_cookie_name'];
    
    $theSessionID = '';
    while (strlen($theSessionID) < 32)
    {    
        $theSessionID .= mt_rand(0, mt_getrandmax());
    }
    $theSessionID = md5(uniqid($sessid, TRUE));
    
    $now = get_current_time($config);
        
    $theExpireTime = $config['sess_expiration'] + $now;
    
    $theCookiePath = $config['cookie_path'];
    $theDomain = $config['cookie_domain'];
    
    setcookie(
        $theCookieName,
        $theSessionID,
        $theExpireTime,
        $theCookiePath,
        $theDomain,
        0
        );    
            
//    INSERT THE MATCHING ENTRY INTO THE CI_SESSIONS DATABASE    
    $hostname = $db['default']['hostname'];
    $user = $db['default']['username'];
    $password = $db['default']['password'];
    $thedatabase = $db['default']['database'];    
    
//    $db_link = mysql_connect($hostname, $user, $password);
    mysql_select_db($thedatabase);
    
//    Get the info that needs to go into the ci_sessions database.
//    Some of it we can get from the browser.
    $theIPAddress = get_ip_address();
    $theUserAgent = ( ! isset($_SERVER['HTTP_USER_AGENT']) ? FALSE : $_SERVER['HTTP_USER_AGENT']);
    $theUserAgent = substr($theUserAgent, 0, 50);
                        
//    Some of it we get from the fa_user database
    $email = $user_settings['emailAddress'];
    $theQuery = "SELECT id, user_name, country_id, email, role, last_visit, created, modified FROM fa_user WHERE email = '$email'";
    $result = mysql_query($theQuery);
    $theUserData = mysql_fetch_array($result, MYSQL_ASSOC);
    $theSerializedUserData = serialize($theUserData);
    
//    Insert the data into the ci_sessions table
    $theQuery = "INSERT INTO ci_sessions (session_id, ip_address, user_agent, last_activity, session_data) VALUES ('$theSessionID', '$theIPAddress', '$theUserAgent', '$now', '$theSerializedUserData')";
    $result = mysql_query($theQuery);
            
//    return database to SMF in a state it expects
    mysql_select_db($db_name);
        
//    mysql_close($db_link);        
}


    //This is the valid_ip function in system/libraries/input.php
    function valid_ip($ip)
    {
        $ip_segments = explode('.', $ip);
        
        // Always 4 segments needed
        if (count($ip_segments) != 4)
        {
            return FALSE;
        }
        // IP can not start with 0
        if (substr($ip_segments[0], 0, 1) == '0')
        {
            return FALSE;
        }
        // Check each segment
        foreach ($ip_segments as $segment)
        {
            // IP segments must be digits and can not be
            // longer than 3 digits or greater then 255
            if (preg_match("/[^0-9]/", $segment) OR $segment > 255 OR strlen($segment) > 3)
            {
                return FALSE;
            }
        }
        
        return TRUE;
    }

     //Adapted from the ip_address function in system/libraries/input.php
    function get_ip_address()
    {
        $ip_address = FALSE;
        
        if (isset($_SERVER['REMOTE_ADDR']) AND isset($_SERVER['HTTP_CLIENT_IP']))
        {
             $ip_address = $_SERVER['HTTP_CLIENT_IP'];
        }
        elseif (isset($_SERVER['REMOTE_ADDR']))
        {
             $ip_address = $_SERVER['REMOTE_ADDR'];
        }
        elseif (isset($_SERVER['HTTP_CLIENT_IP']))
        {
             $ip_address = $_SERVER['HTTP_CLIENT_IP'];
        }
        elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        {
             $ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
        
        if ($ip_address === FALSE)
        {
            $ip_address = '0.0.0.0';
            return $ip_address;
        }
        
        if (strstr($ip_address, ','))
        {
            $x = explode(',', $ip_address);
            $ip_address = end($x);
        }
        
        if ( !valid_ip($ip_address))
        {
            $ip_address = '0.0.0.0';
        }
                
        return $ip_address;
    }

So that approach can be used to handle events that happen in the forum, so as to make sure your CI app is in sync with those events.

(Continued next post).
#7

[eluser]Vik[/eluser]
(Continued from previous post)

For events that happen in your CI app, you can keep your SMF forum up to date, by using another SMF system, called SMF_api.php. SMF_api is available for download on the SMF tools page. This is a set of functions for getting SMF to log a user in, log them out, register them, etc.

So that's pretty much it. I hope this may be useful to others who are considering integrating a CI app with SMF.
#8

[eluser]girir[/eluser]
Hi Vik, I was trying to understand why you didn't just use FreakAuth's user database and decided on keeping two separate tables for users. Wouldn't it be slower to have to update two user tables everytime a user registers/logs in/logs out etc? By looking at the SMF integration hooks page, it seems that these functions could be coded up to check against the FreakAuth user database and return the necessary information.
#9

[eluser]Vik[/eluser]
There is user information that I store for my users, that isn't kept by SMF. I didn't want to modify the SMF database to store that data, since those modifications might not work with a future update of SMF.
#10

[eluser]girir[/eluser]
Actually I was talking the other way around. Can't all information be kept in FreakAuth fa_user table and SMF just access that? Aren't the hooks provided by SMF used for that purpose - to talk to CI and return the appropriate values? Eg: SMF hook can be used to tap into CI database to see if user is logged in.

Thanks a lot!




Theme © iAndrew 2016 - Forum software by © MyBB