CMS MS + phpBB = TRUE

Talk about writing modules and plugins for CMS Made Simple, or about specific core functionality. This board is for PHP programmers that are contributing to CMSMS not for site developers
Locked
Marcus

CMS MS + phpBB = TRUE

Post by Marcus »

CMS MS + phpBB = TRUE

Well... Almost anyway..

This might not be what you need at all. This is what I needed. But I'm showing it here hoping it will be of some use to someone.
Perhaps someone with more time on their hands than I have will write a mod out of this.

What isn't this tutorial?
This is not a mod. This is a hack.
This does not show how to integrate phpBB and CMS MS. It shows how to do remote authentication in phpBB and how you can have phpBB users as frontend users of your CMS MS site.


Here we go.

1. First of all we need to install our tools. This is how my docroot looks like. If yours doesn't match this you may have to change some of the paths in the scripts.

/root/cms    <- Here is my CMS MS installation
/root/forum  <- phpBB
/root/soap   <- nuSOAP, get it from http://dietrich.ganx4.com/nusoap/

2. Install the following mods in CMS MS:

UserID
ProtectedPages

3. Save the following script as /root/forum/mods/auth/auth.php

If you have done the installations as above you should not have to change anything in this script.

Code: Select all

<?php

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
// 
// This is an example on how to build an authentication server for phpBB 
// 
// Most of what is done here comes from the KB (http://www.phpbb.com/kb/article.php?article_id=143) 
// 
// The code looks like this: 
// 
// define('IN_PHPBB', true); 
// $phpbb_root_path = './'; 
// include($phpbb_root_path . 'extension.inc'); 
// include($phpbb_root_path . 'common.'.$phpEx); 
// 
// // 
// // Start session management 
// // 
// $userdata = session_pagestart($user_ip, PAGE_INDEX); 
// init_userprefs($userdata); 
// // 
// // End session management 
// 
// 
// Instead of calling session_pagestart I copy-pasted the code here. 
// 
// I've not had any problems with this code, but someone with more knowledge of the phpBB 
// authentication system should have a look at it. 
// 
// This file is placed in $phpbb_root_path/mods/auth/ 
// 
// 


/////////////////////////////////////////// 
// 
// phpBB includes 
// 

define('IN_PHPBB', true); 
$phpbb_root_path = '../../'; 
include($phpbb_root_path . 'extension.inc'); 
include($phpbb_root_path . 'common.'.$phpEx); 

/////////////////////////////////////////// 
// 
// Start the SOAP server. 
// 
// I've used NuSOAP, http://dietrich.ganx4.com/nusoap/ 
// 

include($phpbb_root_path . '../soap/nusoap.php'); 
$s = new soap_server; 
$s->register('authenticate'); 
$s->service($HTTP_RAW_POST_DATA); 


/////////////////////////////////////////// 
// 
// The authenticate function. 
// It is basically the session_pagestart function from phpBB 
// I've put comments so you can see what code I've added. 
// 

function authenticate($ip, $get_vars, $cookie_vars){ 

   /////////////////////////////////////////// 
   // 
   // Since session_pagestart wasn't called normally 
   // we have to set the variables needed. 
   //    

      $user_ip = $ip; 
      $thispage_id = PAGE_INDEX; 

   //////////////////////////////////////////// 

   global $db, $lang, $board_config; 
   global $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $SID; 

   /////////////////////////////////////////// 
   // 
   // Replace $HTTP_COOKIE_VARS and $HTTP_GET_VARS 
   // with information from the client 
   //    

      $HTTP_GET_VARS = unserialize($get_vars); 
      $HTTP_COOKIE_VARS = unserialize($cookie_vars); 

   /////////////////////////////////////////////// 

   $cookiename = $board_config['cookie_name']; 
   $cookiepath = $board_config['cookie_path']; 
   $cookiedomain = $board_config['cookie_domain']; 
   $cookiesecure = $board_config['cookie_secure']; 

   $current_time = time(); 
   unset($userdata); 

   if ( isset($HTTP_COOKIE_VARS[$cookiename . '_sid']) || isset($HTTP_COOKIE_VARS[$cookiename . '_data']) ) 
   { 
      $sessiondata = isset( $HTTP_COOKIE_VARS[$cookiename . '_data'] ) ? unserialize(stripslashes($HTTP_COOKIE_VARS[$cookiename . '_data'])) : array(); 
      $session_id = isset( $HTTP_COOKIE_VARS[$cookiename . '_sid'] ) ? $HTTP_COOKIE_VARS[$cookiename . '_sid'] : ''; 
      $sessionmethod = SESSION_METHOD_COOKIE; 
   } 
   else 
   { 
      $sessiondata = array(); 
      $session_id = ( isset($HTTP_GET_VARS['sid']) ) ? $HTTP_GET_VARS['sid'] : ''; 
      $sessionmethod = SESSION_METHOD_GET; 
   } 

   // 
   if (!preg_match('/^[A-Za-z0-9]*$/', $session_id)) 
   { 
      $session_id = ''; 
   } 

   $thispage_id = (int) $thispage_id; 

   // 
   // Does a session exist? 
   // 
   if ( !empty($session_id) ) 
   { 
      // 
      // session_id exists so go ahead and attempt to grab all 
      // data in preparation 
      // 
      $sql = "SELECT u.*, s.* 
         FROM " . SESSIONS_TABLE . " s, " . USERS_TABLE . " u 
         WHERE s.session_id = '$session_id' 
            AND u.user_id = s.session_user_id"; 
      if ( !($result = $db->sql_query($sql)) ) 
      { 
         message_die(CRITICAL_ERROR, 'Error doing DB query userdata row fetch', '', __LINE__, __FILE__, $sql); 
      } 

      $userdata = $db->sql_fetchrow($result); 

      // 
      // Did the session exist in the DB? 
      // 
      if ( isset($userdata['user_id']) ) 
      { 
         // 
         // Do not check IP assuming equivalence, if IPv4 we'll check only first 24 
         // bits ... I've been told (by vHiker) this should alleviate problems with 
         // load balanced et al proxies while retaining some reliance on IP security. 
         // 
         $ip_check_s = substr($userdata['session_ip'], 0, 6); 
         $ip_check_u = substr($user_ip, 0, 6); 

         if ($ip_check_s == $ip_check_u) 
         { 
            $SID = ($sessionmethod == SESSION_METHOD_GET || defined('IN_ADMIN')) ? 'sid=' . $session_id : ''; 

            // 
            // Only update session DB a minute or so after last update 
            // 
            if ( $current_time - $userdata['session_time'] > 60 ) 
            { 
               // A little trick to reset session_admin on session re-usage 
               $update_admin = (!defined('IN_ADMIN') && $current_time - $userdata['session_time'] > ($board_config['session_length']+60)) ? ', session_admin = 0' : ''; 

               $sql = "UPDATE " . SESSIONS_TABLE . " 
                  SET session_time = $current_time, session_page = $thispage_id$update_admin 
                  WHERE session_id = '" . $userdata['session_id'] . "'"; 
               if ( !$db->sql_query($sql) ) 
               { 
                  message_die(CRITICAL_ERROR, 'Error updating sessions table', '', __LINE__, __FILE__, $sql); 
               } 

               if ( $userdata['user_id'] != ANONYMOUS ) 
               { 
                  $sql = "UPDATE " . USERS_TABLE . " 
                     SET user_session_time = $current_time, user_session_page = $thispage_id 
                     WHERE user_id = " . $userdata['user_id']; 
                  if ( !$db->sql_query($sql) ) 
                  { 
                     message_die(CRITICAL_ERROR, 'Error updating sessions table', '', __LINE__, __FILE__, $sql); 
                  } 
               } 

               session_clean($userdata['session_id']); 

               setcookie($cookiename . '_data', serialize($sessiondata), $current_time + 31536000, $cookiepath, $cookiedomain, $cookiesecure); 
               setcookie($cookiename . '_sid', $session_id, 0, $cookiepath, $cookiedomain, $cookiesecure); 
            } 
            /////////////////////////////////////////// 
            // 
            // If we have come this far, the user is logged in. 
            // 
            // return userdata and cookies (are any new set?) 
            // to the client 
            // 
             

               init_userprefs($userdata); 

               if( $userdata['session_logged_in'] ) 
               { 
                  global $HTTP_COOKIE_VARS; 
       
                  $params = array( 
                     'cookie_vars' => serialize($HTTP_COOKIE_VARS), 
                     'userdata' => serialize($userdata),  
                     'logged_in' => 1 
                     ); 

                  return $params; 

               } 
               // old code 
               //return $userdata; 
            ////////////////////////////////////////// 

         } 
      } 
   } 

   // 
   // If we reach here then no (valid) session exists. So we'll create a new one, 
   // using the cookie user_id if available to pull basic user prefs. 
   // 
   $user_id = ( isset($sessiondata['userid']) ) ? intval($sessiondata['userid']) : ANONYMOUS; 

   if ( !($userdata = session_begin($user_id, $user_ip, $thispage_id, TRUE)) ) 
   { 
      message_die(CRITICAL_ERROR, 'Error creating user session', '', __LINE__, __FILE__, $sql); 
   } 

   /////////////////////////////////////////// 
   // 
   // If we reach here, the user is not logged in. 
   // 

      if( !$userdata['session_logged_in'] ) 
      { 

         $params = array('logged_in => 0' ); 

         return $params; 

      } 
    
   //////////////////////////////////////////// 

} 

?>
4. Save this script as /root/cms/plugins/function.phpbblogin.php


Remember to change $soap_server_url
If you don't have the same installation paths as I have, you have to change some paths in the forms.

Code: Select all

<?php


function smarty_cms_function_phpbblogin($params, &$smarty) {

	///////////////////////////////////////////////////////////////////////
	//
	// The URL should be the full URL to the server. Rembember, it's a HTTP request.
	//

	$soap_server_url = "http://www.yourdomain.com/forum/mods/auth/auth.php";
	

	////////////////////////////////////////////////////////////////////////
	//
	// A small example to show how you can use the authentication server
	//

	global $HTTP_GET_VARS;
	global $HTTP_COOKIE_VARS;

	////////////////////////////////////////////////////////////////////////
	//
	// The following three lines are from phpBB
	// This should be done at the server-side but this was easier.
	//
	
	$dotquad_ip = ( !empty($HTTP_SERVER_VARS['REMOTE_ADDR']) ) ? $HTTP_SERVER_VARS['REMOTE_ADDR'] : ( ( !empty($HTTP_ENV_VARS['REMOTE_ADDR']) ) ? $HTTP_ENV_VARS['REMOTE_ADDR'] : getenv('REMOTE_ADDR') );
	$ip_sep = explode('.', $dotquad_ip);
	$user_ip = sprintf('%02x%02x%02x%02x', $ip_sep[0], $ip_sep[1], $ip_sep[2], $ip_sep[3]);

	////////////////////////////////////////////////////////////////////////
	//
	// Include SOAP 
	// Create a client
	//	 The URL should be the full URL to the server. Rembember, it's a HTTP request.
	// Call the server
	//

	include('../soap/nusoap.php');
	$client = new soapclient($soap_server_url);
	$params = array(
		'ip' => $user_ip, 
		'get_vars' => serialize($HTTP_GET_VARS), 
		'cookie_vars' => serialize($HTTP_COOKIE_VARS));
	$reply = $client->call('authenticate', $params);


	if ($reply['logged_in']){
	
		$HTTP_COOKIE_VARS = unserialize($reply['cookie_vars']);
		$userdata = unserialize($reply['userdata']);

		/////////////////////////////////////////////
		//
		// Authenticated!
		//
		// And we have full access to $userdata
		//
		// We can do stuff like this:
		//

		global $phpbblogin;
		$phpbblogin = true;

		$r = "Logged in as: ".$userdata['username']; 
		$r .= "<br ><a href=\"../forum/login.php?logout=true&sid="; 
		$r .= $userdata['session_id']; 
		$r .= "&redirect=../cms/index.php"; 
		$r .= "\">Log out</a>"; 
    
		} 
		else{ 
    
		///////////////////////////////////////////// 
		// 
		// If the authentication fails we can for example 
		// make a login form. 
		// 

		$r = ""; 
		$r.='<form action="../forum/login.php" method="post" target="_top">'; 
		$r.='Username:<br />'; 
		$r.='<input type="text" name="username" size="20" maxlength="40" value="" /><br />'; 
		$r.='Password:<br />'; 
		$r.='<input type="password" name="password" size="20" maxlength="25" /><br />'; 
		$r.='<br /> <br />'; 
		$r.='<input type="hidden" name="redirect" value="../cms/index.php" />'; 
		$r.='<input type="hidden" name="outside" value="1" />'; 
		$r.='<span align="center"><input type="submit" class="mainoption" name="login" value="Log in" /></span'; 
		$r.='<br /> <br />'; 
		$r.='</form>'; 

		
	}


	return utf8_encode($r);
}

function smarty_cms_help_function_phpbblogin() {
	?>
	<h3>What does this do?</h3>
	<p>logs in to phpBB</p>
	<h3>How do I use it?</h3>
	<p>..</code>
	<h3>What parameters does it take?</h3>
	<p>..</p>
	<?php
}

function smarty_cms_about_function_phpbblogin() {
	?>
	<p>Author: Marcus Selin</p>
	<p>Version: 0.1</p>
	<p>
	Change History:<br/>
	None
	</p>
	<?php
}

?>
5. Now it's time for the real ugly part. As you can see we have a gobal variable called $phpbblogin. We just need to check the state of that variable to know if the user is logged in or not.

Open /root/cms/modules/UserID/UserID.module.php in your favourite editor.
Find the function LoggedIn(), and change it to this:

Code: Select all

function LoggedIn() {
		global $phpbblogin;
		if ($phpbblogin===true) return true; else return false;
	}
6. Just add {phpbblogin} where you want the login box to appear. I perfer in the menu. It has to be on all the pages to keep the login.
You can also use {cms_module module="protectedpages"} if you want to have protected pages.
Tip: Hide the pages from the menu and create links to them in the Authenticated!-section above. That way you can have a menu that is only visible to logged in members.

Comments.
As I have said this is a hack. You can't use any of UserID:s functions. All the user management has to be done in phpBB.

The soap client function should be rewritten as a module. Since we get access to the $userdata-array from phpBB we can make use of groups created in phpBB. It would also be nice with an option to make menulinks that only logged in members can see. Now you have to code those links by hand.

And a final note. I haven't got the slightest idea how secure or insecure this is. Use any of this information at your own risk.
Marcus

Re: CMS MS + phpBB = TRUE

Post by Marcus »

Another tip, if you want to display some data from the forum on your website you can try this: http://www.phpbbfetchall.com/
Locked

Return to “Developers Discussion”