<?php
/**
* Joomla/Mambo Community Builder
* @version $Id: cb.tables.php 1803 2012-06-19 20:46:12Z beat $
* @package Community Builder
* @subpackage cb.tables.php
* @author Beat
* @copyright (C) 2004-2011 www.joomlapolis.com
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU/GPL version 2
*/

// ensure this file is being included by a parent file
if ( ! ( defined( '_VALID_CB' ) || defined( '_JEXEC' ) || defined( '_VALID_MOS' ) ) ) { die( 'Direct Access to this location is not allowed.' ); }


class moscomprofilerPlugin extends comprofilerDBTable {
	/** @var int */
	var $id					=	null;
	/** @var varchar */
	var $name				=	null;
	/** @var varchar */
	var $element			=	null;
	/** @var varchar */
	var $type				=	null;
	/** @var varchar */
	var $folder				=	null;
	/** @var varchar */
	var $backend_menu		=	null;
	/** @var tinyint unsigned */
	var $access				=	null;
	/** @var int */
	var $ordering			=	null;
	/** @var tinyint */
	var $published			=	null;
	/** @var tinyint */
	var $iscore				=	null;
	/** @var tinyint */
	var $client_id			=	null;
	/** @var int unsigned */
	var $checked_out		=	null;
	/** @var datetime */
	var $checked_out_time	=	null;
	/** @var text */
	var $params				=	null;
	/**
	* Constructor
    * @param  CBdatabase  $db   A database connector object
	*/
	function moscomprofilerPlugin( &$db ) {
		$this->comprofilerDBTable( '#__comprofiler_plugin', 'id', $db );
	}
	function check() {
		$ok		=	( $this->name );
		if ( ! $ok ) {
			$this->_error	=	"Save not allowed";
		}
		return $ok;
	}
}
class moscomprofilerLists extends comprofilerDBTable {

	var $listid				=	null;
	var $title				=	null;
	var $description		=	null;
	var $published			=	null;
	var $default			=	null;
	var $viewaccesslevel	=	null;
	var $usergroupids		=	null;
	var $useraccessgroupid	=	null;
	var $sortfields			=	null;
	var $filterfields		=	null;
	var $ordering			=	null;
	var $col1title			=	null;
	var $col1enabled		=	null;
	var $col1fields			=	null;
	var $col1captions		=	null;
	var $col2title			=	null;
	var $col2enabled		=	null;
	var $col2fields			=	null;
	var $col2captions		=	null;
	var $col3title			=	null;
	var $col3enabled		=	null;
	var $col3fields			=	null;
	var $col3captions		=	null;
	var $col4title			=	null;
	var $col4enabled		=	null;
	var $col4fields			=	null;
	var $col4captions		=	null;
	/** @var text */
	var $params				=	null;

    /**
    * Constructor
    * @param  CBdatabase  $db   A database connector object
    */
	function moscomprofilerLists( &$db ) {

		$this->comprofilerDBTable( '#__comprofiler_lists', 'listid', $db );

	} //end func

	function store( $listid=0, $updateNulls=false) {
			global $_CB_database, $_POST;

		if ( ( ! isset( $_POST['listid'] ) ) || $_POST['listid'] == null || $_POST['listid'] == '' ) {
			$this->listid = (int) $listid;
		} else {
			$this->listid = (int) cbGetParam( $_POST, 'listid', 0 );
		}
		$sql="SELECT COUNT(*) FROM #__comprofiler_lists WHERE listid = ".  (int) $this->listid;
		$_CB_database->SetQuery($sql);
		$total = $_CB_database->LoadResult();
		if($this->default==1) {
			$sql="UPDATE #__comprofiler_lists SET `default` = 0";
			$_CB_database->SetQuery($sql);
			$_CB_database->query();
		}
		if ( $total > 0 ) {
			// existing record
			$ret = $this->_db->updateObject( $this->_tbl, $this, $this->_tbl_key, $updateNulls );

		} else {
			// new record
			$sql="SELECT MAX(ordering) FROM #__comprofiler_lists";
			$_CB_database->SetQuery($sql);
			$max = $_CB_database->LoadResult();
			$this->ordering=$max+1;
			$this->listid = null;
			$ret = $this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key );
		}
		if ( !$ret ) {
			$this->_error = get_class( $this )."::store failed <br />" . $this->_db->getErrorMsg();
			return false;
		} else {
			return true;
		}
	}


} //end class
class moscomprofilerFields extends comprofilerDBTable {

   var $fieldid			= null;
   var $name			= null;
   var $tablecolumns	= null;
   var $table			= null;
   var $title			= null;
   var $description		= null;
   var $type			= null;
   var $maxlength		= null;
   var $size			= null;
   var $required		= null;
   var $tabid			= null;
   var $ordering		= null;
   var $cols			= null;
   var $rows			= null;
   var $value			= null;
   var $default			= null;
   var $published		= null;
   var $registration	= null;
   var $profile			= null;
   var $displaytitle	= null;
   var $readonly		= null;
   var $searchable		= null;
   var $calculated		= null;
   var $sys				= null;
   var $pluginid		= null;
   /**
    * Field's params: once loaded properly contains:
    * @var cbParamsBase
    */
   var $params			= null;

    /**
    * Constructor
    * @param  CBdatabase  $db   A database connector object
    */
	function moscomprofilerFields( &$db ) {
		$this->comprofilerDBTable( '#__comprofiler_fields', 'fieldid', $db );
	}

	function store( $fieldid = 0, $updateNulls = false ) {
			global $_CB_database;

			$this->fieldid			=	$fieldid;

			$fieldHandler			=	new cbFieldHandler();

			$sql					=	'SELECT COUNT(*) FROM #__comprofiler_fields WHERE fieldid = ' . (int) $this->fieldid;
			$_CB_database->SetQuery( $sql );
			$total					=	$_CB_database->LoadResult();

			if ( $total > 0 ) {
				// existing record:
				$ret				=	$this->_db->updateObject( $this->_tbl, $this, $this->_tbl_key, $updateNulls );	// escapes values
				if ( $ret ) {
					$ret			=	$fieldHandler->adaptSQL( $this );
				}
			} else {
				// new record:

				$sql				=	'SELECT COUNT(*) FROM #__comprofiler_fields WHERE name = ' . $_CB_database->Quote( $this->name );
				$_CB_database->SetQuery($sql);
				if ( $_CB_database->LoadResult() > 0 ) {
					$this->_error	=	"The field name ".$this->name." is already in use!";
					return false;
				}
				$sql				=	'SELECT MAX(ordering) FROM #__comprofiler_fields WHERE tabid = ' . (int) $this->tabid;
				$_CB_database->SetQuery( $sql );
				$max				=	$_CB_database->LoadResult();
				$this->ordering		=	$max + 1;
				$this->fieldid		=	null;
				$this->table		=	$fieldHandler->getMainTable( $this );
				$this->tablecolumns	=	implode( ',', $fieldHandler->getMainTableColumns( $this ) );

				$ret				=	$fieldHandler->adaptSQL( $this );

				if ($ret) {
					$ret			=	$this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key );		// do inserObject last to keep insertId intact
				}
			}
			if ( ! $ret ) {
				$this->_error		=	get_class( $this ) . "::store failed: " . addslashes( str_replace( "\n", '\n', $this->_error . ' ' . $this->_db->getErrorMsg() ) );
				return false;
			} else {
				return true;
			}
	}
	/**
	*	Delete method for fields deleting also fieldvalues, but not the data column in the comprofiler table.
	*	For that, deleteColumn() method must be called separately.
	*
	*	@param id of row to delete
	*	@return true if successful otherwise returns and error message
	*/
	function deleteDataDescr( $oid = null ) {
		$fieldHandler				=	new cbFieldHandler();
		$ret						=	$fieldHandler->adaptSQL( $this, 'drop' );
		if ( $ret ) {
			$ret					=	$this->delete( $oid );
		}
		return $ret;
	}
	/**
	*	Delete method for fields deleting also fieldvalues, but not the data column in the comprofiler table.
	*	For that, deleteDataDescr() method must be called instead.
	*
	*	@param id of row to delete
	*	@return true if successful otherwise returns and error message
	*/
	function delete( $oid = null ) {
		$k							=	$this->_tbl_key;
		if ( $oid ) {
			$this->$k				=	(int) $oid;
		}

		$result					=	true;

		//Find all fieldValues related to the field
		$this->_db->setQuery( "SELECT `fieldvalueid` FROM #__comprofiler_field_values WHERE `fieldid`=" . (int) $this->$k );
		$fieldvalues				=	$this->_db->loadObjectList();
		$rowFieldValues				=	new moscomprofilerFieldValues($this->_db);
		if ( count( $fieldvalues ) > 0 ) {
			//delete each field value related to a field
			foreach ( $fieldvalues AS $fieldvalue ) {
				$result				=	$rowFieldValues->delete( $fieldvalue->fieldvalueid ) && $result;
			}
		}
		//Now delete the field itself without deleting the user data, preserving it for reinstall
		//$this->deleteColumn( $this->table, $this->name );	// this would delete the user data
		$result						=	parent::delete( $this->$k ) && $result;
		return $result;
	}
	/**
	 * Returns the database columns used by the field
	 *
	 * @return array    Names of columns
	 */
	function getTableColumns() {
		if ( $this->tablecolumns !== null ) {
			if ( $this->tablecolumns === '' ) {
				return array();
			} else {
				return explode( ',', $this->tablecolumns );
			}
		} else {
			return array( $this->name );		// pre-CB 1.2 database structure support
		}
	}
	/**
	 * OBSOLETE DO NOT USE: kept in 1.2 for compatibility reasons only
	 * @access private
	 */
	function createColumn( $table, $column, $type) {
		global $_CB_database;

		if ( ( $table == '' ) || ( $type == '' ) ) {
			return true;
		}
		$sql = "SELECT * FROM " . $_CB_database->NameQuote( $table );
		$_CB_database->setQuery( $sql, 0, 1 );
		$obj = null;
		if ( ! ( $_CB_database->loadObject( $obj ) && array_key_exists( $column, $obj ) ) ) {
			$sql = "ALTER TABLE " . $_CB_database->NameQuote( $table )
				 . "\n ADD " . $_CB_database->NameQuote( $column ) . " " . $type;		// don't escape type, as default text values are quoted
			$_CB_database->SetQuery( $sql );
			$ret = $_CB_database->query();
			if ( !$ret ) {
				$this->_error .= get_class( $this )."::createColumn failed <br />" . $this->_db->getErrorMsg();
				return false;
			} else {
				return true;
			}
		} else {
			return $this->changeColumn( $table, $column, $type);
		}
	}
	/**
	 * OBSOLETE DO NOT USE: kept in 1.2 for compatibility reasons only
	 * @access private
	 */
	function changeColumn( $table, $column, $type, $oldColName = null ) {
		global $_CB_database;

		if ( ( $table == '' ) || ( $type == '' ) ) {
			return true;
		}
		if ( $oldColName === null ) {
			$oldColName		=	$column;
		}
		$sql = "ALTER TABLE " . $_CB_database->NameQuote( $table )
				. "\n CHANGE " . $_CB_database->NameQuote( $oldColName )
				. " " . $_CB_database->NameQuote( $column )
				. " " . $type;														// don't escape type, as default text values are quoted
		$_CB_database->SetQuery( $sql );
		$ret = $_CB_database->query();
		if ( !$ret ) {
			$this->_error .= get_class( $this )."::changeColumn failed <br />" . $this->_db->getErrorMsg();
			return false;
		} else {
			return true;
		}
	}
	/**
	 * OBSOLETE DO NOT USE: kept in 1.2 for compatibility reasons only
	 * @access private
	 */
	function deleteColumn( $table, $column) {
			global $_CB_database;
		$sql = "ALTER TABLE " . $_CB_database->NameQuote( $table)
				. "\n DROP " .  $_CB_database->NameQuote( $column)
				;
		$_CB_database->SetQuery($sql);
		$ret = $_CB_database->query();
		if ( !$ret ) {
			$this->_error .= get_class( $this )."::deleteColumn failed <br />" . $this->_db->getErrorMsg();
			return false;
		} else {
			return true;
		}
	}
} //end class

class moscomprofilerTabs extends comprofilerDBTable {

   var $tabid				=	null;
   var $title				=	null;
   var $description			=	null;
   var $ordering			=	null;
   var $ordering_register	=	null;
   var $width				=	null;
   var $enabled				=	null;
   var $pluginclass			=	null;
   var $pluginid			=	null;
   var $fields				=	null;
   var $params				=	null;
   /**	@var int  system tab: >=1: from comprofiler core: can't be deleted. ==2: always enabled. ==3: collecting element (menu+status): rendered at end. */
   var $sys					=	null;
   var $displaytype			=	null;
   var $position			=	null;
   var $viewaccesslevel		=	null;
   var $useraccessgroupid	=	null;

    /**
    * Constructor
    * @param  CBdatabase  $db   A database connector object
    */
	function moscomprofilerTabs( &$db ) {

		$this->comprofilerDBTable( '#__comprofiler_tabs', 'tabid', $db );

	} //end func

	function store( $updateNulls=false) {
		global $_CB_database, $_POST;

		$sql = "SELECT COUNT(*) FROM #__comprofiler_tabs WHERE tabid = ". (int) $this->tabid;
		$_CB_database->SetQuery($sql);
		$total = $_CB_database->LoadResult();
		if ( $total > 0 ) {
			// existing record
			$ret = $this->_db->updateObject( $this->_tbl, $this, $this->_tbl_key, $updateNulls );	// escapes values!

		} else {
			$sql = "SELECT MAX(ordering) FROM #__comprofiler_tabs";
			$_CB_database->SetQuery($sql);
			$max = $_CB_database->LoadResult();
			$this->ordering = $max + 1;
			// new record
			$this->tabid = null;
			$ret = $this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key );

		}
		if ( !$ret ) {
			$this->_error = get_class( $this )."::store failed <br />" . $this->_db->getErrorMsg();
			return false;
		} else {
			return true;
		}
	}
} //end class
class moscomprofilerFieldValues extends comprofilerDBTable {
   var $fieldvalueid	=	null;
   var $fieldid			=	null;
   var $fieldtitle		=	null;
   var $ordering		=	null;
   var $sys				=	null;

    /**
    * Constructor
    *
    * @param  CBdatabase  $db   A database connector object
    */

	function moscomprofilerFieldValues( &$db ) {

		$this->comprofilerDBTable( '#__comprofiler_field_values', 'fieldvalueid', $db );

	} //end func

	function store( $fieldvalueid=0, $updateNulls=false) {
			global $_CB_database, $_POST;

		if ( ( ! isset( $_POST['fieldvalueid'] ) ) || $_POST['fieldvalueid'] == null || $_POST['fieldvalueid'] == '' ) {
			$this->fieldvalueid = (int) $fieldvalueid;
		} else {
			$this->fieldvalueid = (int) cbGetParam( $_POST, 'fieldvalueid', 0 );
		}
		$sql = "SELECT COUNT(*) FROM #__comprofiler_field_values WHERE fieldvalueid = " . (int) $this->fieldvalueid;
		$_CB_database->SetQuery($sql);
		$total = $_CB_database->LoadResult();
		if ( $total > 0 ) {
			// existing record
			$ret = $this->_db->updateObject( $this->_tbl, $this, $this->_tbl_key, $updateNulls );

		} else {
			// new record
			$this->fieldvalueid = null;
			$ret = $this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key );
		}
		if ( !$ret) {
			$this->_error = get_class( $this )."::store failed <br />" . $this->_db->getErrorMsg();
			return false;
		} else {

			return true;
		}
	}


} //end class
class moscomprofiler extends comprofilerDBTable {

	// IMPORTANT: ALL VARIABLES HERE MUST BE NULL in order to not be updated if not set.
	var $id						=	null;
	var $user_id				=	null;
	var $firstname				=	null;
	var $middlename				=	null;
	var $lastname				=	null;
	var $hits					=	null;
	var $message_last_sent		=	null;
	var $message_number_sent	=	null;
	var $avatar					=	null;
	var $avatarapproved			=	null;
	var $approved				=	null;
	var $confirmed				=	null;
	var $lastupdate				=	null;
	var $registeripaddr			=	null;
	var $cbactivation			=	null;
	var $banned					=	null;
	var $banneddate				=	null;
	var $unbanneddate			=	null;
	var $bannedby				=	null;
	var $unbannedby				=	null;
	var $bannedreason			=	null;
	var $acceptedterms			=	null;

    /**
    * Constructor
    *
    * @param  CBdatabase  $db   A database connector object
    */
	function moscomprofiler( &$db ) {
		$this->comprofilerDBTable( '#__comprofiler', 'id', $db );
	}
	/**
	* Inserts a new row in the database table
	*
	* @param  boolean  $updateNulls  TRUE: null object variables are also updated, FALSE: not.
	* @return boolean                TRUE if successful otherwise FALSE
	*/
	function storeNew( $updateNulls = false ) {
		$ok					=	$this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key );
		if ( ! $ok ) {
			$this->_error	=	strtolower(get_class($this))."::storeNew failed: " . $this->_db->getErrorMsg();
		}
		return $ok;
	}
	/**
	 * OBSOLETE AND BUGGY: DO NOT USE
	 * KEPT FOR 3PD COMPATIBILITY ONLY
	 */
	function storeExtras( $id=0, $updateNulls=false) {
		global $_CB_database, $_POST;

		if ( ( ! isset( $_POST['id'] ) ) || $_POST['id'] == null || $_POST['id'] == '' ) {
			$this->id = (int) $id;
		} else {
			$this->id = (int) cbGetParam( $_POST, 'id', 0 );
		}
		$sql = "SELECT count(*) FROM #__comprofiler WHERE id = ". (int) $this->id;
		$_CB_database->SetQuery($sql);
		$total = $_CB_database->LoadResult();
		if ( $total > 0 ) {
			// existing record
			$ret = $this->_db->updateObject( $this->_tbl, $this, $this->_tbl_key, $updateNulls );	// escapes values

		} else {
			// new record
			$sql = "SELECT MAX(id) FROM #__users";
			$_CB_database->SetQuery($sql);
			$last_id		= $_CB_database->LoadResult();
			$this->id		= $last_id;
			$this->user_id	= $last_id;
			$ret = $this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key );					// escapes values

		}
		if ( !$ret ) {
			$this->_error = get_class( $this )."::store failed <br />" . $this->_db->getErrorMsg();
			return false;
		} else {
			return true;
		}
	}
	/**
	*	Merges two object into one by reference ( avoids "_db", "_tbl", "_tbl_key", and $o2->($o2->_tbl_key) )
	*
	*	@deprecated CB 1.2.2
	*
	*   @static function:
	*	@param object $o1 first object
	*	@param object $o2 second object
	*	@return object
	*/
	function & dbObjectsMerge( &$o1, &$o2 ) {
		$r = new stdClass();

		$class_vars = get_object_vars($o1);
		foreach ($class_vars as $name => $value) {
			if (($name != "_db") and ($name != "_tbl") and ($name != "_tbl_key")) {
				$r->$name =& $o1->$name;
			}
		}
		$class_vars = get_object_vars($o2);
		$k = $o2->_tbl_key;
		foreach ($class_vars as $name => $value) {
			if (($name != $k) and ($name != "_db") and ($name != "_tbl") and ($name != "_tbl_key")) {
				$r->$name =& $o2->$name;
			}
		}
		return $r;
	}

} // class moscomprofiler
/**
 * WIP: EXPERIMENTAL: use at your own risk, no backwards compatibility guarrantee
 *
 * Class for single cb User tables object
 *
 */
class moscomprofilerUser extends moscomprofiler  {
	/** @var string */
	var $name					=	null;
	/** @var string */
	var $username				=	null;
	/** @var string */
	var $email					=	null;
	/** @var string */
	var $password				=	null;
	/** @var string */
	var $usertype				=	null;
	/** @var int */
	var $block					=	null;
	/** @var int */
	var $sendEmail				=	null;
	/** @var int */
	var $gid					=	null;
	/** @var array */
	var $gids					=	array();
	/** @var datetime */
	var $registerDate			=	null;
	/** @var datetime */
	var $lastvisitDate			=	null;
	/** @var string */
	var $activation				=	null;
	/** @var string */
	var $params					=	null;

	var $_cmsUserTable			=	'#__users';
	var $_cmsUserTableKey		=	'id';
	var $_cmsUserTableUsername	=	'username';
	var $_cmsUserTableEmail	=	'email';
	var $_cmsUserTableGid		=	'gid';

	/** CMS User object
	 *  @var JUser */
	var $_cmsUser				=	null;
	/** CB user table row
	 *  @var moscomprofiler */
	var $_comprofilerUser		=	null;
	/** CB Tabs
	 *  @var cbTabs */
	protected $_cbTabs			=	null;

	var $_nonComprofilerVars		 =	array( 'name', 'username', 'email', 'password', 'params'	, 	'usertype', 'block', 'sendEmail', 'gid', 'gids', 'registerDate', 'activation', 'lastvisitDate' );
	var $_frontendNonComprofilerVars =	array( 'name', 'username', 'email', 'password', 'params' );
	/**
	 * Constructor
	 *
	 * @param  CBdatabase $db
	 * @return moscomprofilerUser
	 */
	function moscomprofilerUser( &$db ) {
		parent::moscomprofiler( $db );
		if ( checkJversion() == 2 ) {
			$this->_cmsUserTableGid					=	'usertype';
		}
		$this->_reinitNonComprofileVars();
	}
	/**
	 * Resets public properties
	 *
	 * @param  mixed  $value  The value to set all properties to, default is null
	 */
	function reset( $value=null ) {
		parent::reset( $value );
		$this->_reinitNonComprofileVars();
	}
	/**
	 * Initializes non-comprofiler vars for CMS users table
	 *
	 * J2.5.5 introduced 2 new columns 'lastResetTime' and 'resetCount' to the CMS users table, but forgot to introduce it to JUser (Joomla bug #28703). JUser thus gets those only in J2.5.6.
	 * This function attempts to get the real database columns names that get loaded into JUser (and into $this moscomprofilerUser object) into $this->_nonComprofilerVars
	 *
	 * @since 1.8.1
	 *
	 * @return void
	 */
	protected function _reinitNonComprofileVars() {
		static $cache				=	array();

		if ( ! $cache ) {
			if ( $this->_cmsUser ) {
				$obj				=	$this->_cmsUser;
			} else {
				global $_CB_framework;
				$obj				=	$_CB_framework->_getCmsUserObject( $this->id );
			}

			$tableBased				=	false;

			// Try getting the users table column names:
			if ( is_callable( array( $obj, 'getTable' ) ) ) {
				/** @var $jUserTable JTableUser */
				$jUserTable			=	$obj->getTable();
				if ( is_callable( array( $jUserTable, 'getFields' ) ) ) {
					// Get the fields of the table instead of the variables of the user object itself:
					// (Joomla 2.5 does anyway call that function on reset() when it load()s the user table object, and then caches the result, so it is fast)
					$obj			=	$jUserTable->getFields();
					$tableBased		=	true;
				}
			}

			// Sets the keys for non-private variables based on:
			if ( $tableBased ) {
				// based on table:
				$cache				=	array_keys( $obj );
			} else {
				// based on object:
				foreach ( $obj as $k => $v ) {
					if ( $k[0] != '_' ) {
						$cache[] 	=	$k;
					}
				}
			}
			// Now also adds the private CMS/CB variables gid and gids:
			foreach ( array( 'gid', 'gids' ) as $k ) {
				if ( ! in_array( $k, $cache ) ) {
					$cache[]		=	$k;
				}
			}
		}
		// Reset the list of not comprofiler table columns completely:
		$this->_nonComprofilerVars	=	$cache;
	}
	/**
	*	Loads user from database
	*
	*	@param  int  $oid  [optional] User id
	*	@return boolean    TRUE: success, FALSE: error in database access
	*/
	function load( $oid = null ) {
		$k						=	$this->_tbl_key;

		if ($oid !== null) {
			$this->$k			=	(int) $oid;
		}

		$oid					=	$this->$k;

		if ( $oid === null ) {
			return false;
		}
		//BB fix : resets default values to all object variables, because NULL SQL fields do not overide existing variables !
		//Note: Prior to PHP 4.2.0, Uninitialized class variables will not be reported by get_class_vars().
		$class_vars				=	get_class_vars(get_class($this));
		foreach ( $class_vars as $name => $value ) {
			if ( ($name != $k) && ($name != "_db") && ($name != "_tbl") && ($name != "_tbl_key") && ! ( ( $name == '_cbTabs' ) && ( ( (int) $this->$k ) === (int) $oid ) ) ) {
				$this->$name	=	$value;
			}
		}
		$this->reset();
		//end of BB fix.
	/*
		$query = "SELECT *"
		. "\n FROM " . $this->_tbl . " c, " . $this->_cmsUserTable . " u"
		. "\n WHERE c." . $this->_tbl_key . " = u." . $this->_cmsUserTableKey
		. " AND c." . $this->_tbl_key . " = " . (int) $oid
		;
		$this->_db->setQuery( $query );

		// the following is needed for being able to edit a backend user in CB from CMS which is not yet synchronized with CB:
	*/
		$query					=	'SELECT c.*, u.*'			// don't use * as in case the left join is null, the second loaded id would overwrite the first id with null 
		. "\n FROM " . $this->_cmsUserTable . ' AS u'
		. "\n LEFT JOIN " . $this->_tbl . ' AS c ON c.' . $this->_tbl_key . ' = u.' . $this->_cmsUserTableKey
		. " WHERE u." . $this->_cmsUserTableKey . ' = ' . (int) $oid
		;
		$this->_db->setQuery( $query );

		$arr					=	$this->_db->loadAssoc( );

		if ( $arr === null ) {
			$query				=	'SELECT u.*, c.*'			// don't use * as in case the left join is null, the second loaded id would overwrite the first id with null
			. "\n FROM " . $this->_tbl . ' AS c'
			. "\n LEFT JOIN " . $this->_cmsUserTable . ' AS u ON c.' . $this->_tbl_key . ' = u.' . $this->_cmsUserTableKey
			. " WHERE c." . $this->_tbl_key . ' = ' . (int) $oid
			;
			$this->_db->setQuery( $query );

			$arr				=	$this->_db->loadAssoc( );
		}
		if ( $arr !== null ) {
			$this->bindThisUserFromDbArray( $arr, $oid );
			return true;
		} else {
			return false;
		}
	}
	/**
	* Copy the named array or object content into this object as vars
	* All $arr values are filled in vars of object
	* @access private
	*
	* @param  array               $arr    The input array
	* @param  moscomprofilerUser  $obj    The object to fill
	* @param  int                 $oid    id
	*/
	function bindThisUserFromDbArray( $arr, $oid = null  ) {
		foreach ( $arr as $kk => $v ) {
			$this->$kk		=	$v;
		}
		if ( $oid ) {
			// in case the left join is null, the second loaded id will be NULL and override id:
			$k					=	$this->_tbl_key;
			$this->$k			=	(int) $oid;
		}
		$this->afterBindFromDatabase();
	}
	/**
	 * This function should be called just after binding the moscomprofilerUser object from database
	 * to load the gids
	 * and to fix the CMS database storage bugs.
	 * It should be avoided externally, but is used by cb.lists.php
	 */
	function afterBindFromDatabase( ) {
		if ( checkJversion() == 2 ) {
			global $_CB_framework;

			$gids			=	array_values( (array) JFactory::getAcl()->getGroupsByUser( $this->id, false ) );

			foreach ( $gids as $k => $v ) {
				$gids[$k]	=	(string) $v;
			}

			$this->gids		=	$gids;
			$this->gid		=	(int) $_CB_framework->acl->getBackwardsCompatibleGid( $this->gids );
		} else {
			$this->gids		=	array( $this->gid );
			if ( ( checkJversion() == 0 ) && ( checkJversion( 'dev_level' ) < 11 ) ) {
				// revert effect of _cbMakeHtmlSafe on user save in older joomla/mambo versions:
				$this->name	=	cbUnHtmlspecialchars( $this->name );
			}
		}
	}
	/**
	 * Loads a list of moscomprofilerUser into an existing array if they are not already in it
	 * (indexed by key of this table)
	 * @since 1.4 (experimental)
	 *
	 * @param  array    $usersIds      array of id to load
	 * @param  array    $objectsArray  IN/OUT   (int) id => $class  (e.g. moscomprofilerUser) with method bindThisUserFromDbArray
	 * @param  string   $class
	 */
	function loadUsersMatchingIdIntoList( $usersIds, &$objectsArray, $class ) {
		// avoids re-loading already loaded ids:
		$usersIds			=	array_diff( $usersIds, array_keys( $objectsArray ) );

		$idsCount			=	count( $usersIds );
		if ( $idsCount > 0 ) {

			// in case the left join is null, the second loaded u.id will be NULL and override id:
			$query			=	'SELECT *, u.' . $this->_cmsUserTableKey
			. "\n FROM " . $this->_cmsUserTable . ' AS u'
			. "\n LEFT JOIN " . $this->_tbl . ' AS c ON c.' . $this->_tbl_key . ' = u.' . $this->_cmsUserTableKey
			. " WHERE u." . $this->_cmsUserTableKey . ( $idsCount == 1 ? ' = ' . (int) end( $usersIds ) : ' IN (' . implode( ',', cbArrayToInts( $usersIds ) ) . ')' );
			$this->_db->setQuery( $query );
			$resultsArray = $this->_db->loadAssocList( $this->_cmsUserTableKey );

			if ( is_array($resultsArray) ) {
				foreach ( $resultsArray as $k => $value ) {
					$objectsArray[(int) $k]	=	new $class( $this->_db );			// self (CBUser has method below too)
					$objectsArray[(int) $k]->bindThisUserFromDbArray( $value );
				}
			}
			unset( $resultsArray );
		}
	}
	/**
	*	Loads user username from database
	*
	*	@param  string   $username
	*	@return boolean    TRUE: success, FALSE: error in database access
	*/
	function loadByUsername( $username ) {
		return $this->_loadBy_field( $username, $this->_cmsUserTableUsername );
	}
	/**
	*	Loads user username from database
	*
	*	@param  string   $username
	*	@return boolean    TRUE: success, FALSE: error in database access
	*/
	function loadByEmail( $username ) {
		return $this->_loadBy_field( $username, $this->_cmsUserTableEmail );
	}
	/**
	*	Loads first user from database according to a given field
	*	@access private
	*
	*	@param  string   $fieldValue
	*	@param  string   $fieldName   Name of database field
	*	@return boolean    TRUE: success, FALSE: error in database access
	*/
	function _loadBy_field( $fieldValue, $fieldName ) {
		if ( $fieldValue == null ) {
			return false;
		}
		//BB fix : resets default values to all object variables, because NULL SQL fields do not overide existing variables !
		//Note: Prior to PHP 4.2.0, Uninitialized class variables will not be reported by get_class_vars().
		$class_vars				=	get_class_vars(get_class($this));
		foreach ($class_vars as $name => $value) {
			if ( ($name != $this->_tbl_key) and ($name != "_db") and ($name != "_tbl") and ($name != "_tbl_key") ) {
				$this->$name	=	$value;
			}
		}
		$this->reset();
		//end of BB fix.
		$query					=	'SELECT c.*, u.*'			// let u.id override c.id in case comprofiler entry is missing
		. "\n FROM " . $this->_cmsUserTable . ' AS u'
		. "\n LEFT JOIN " . $this->_tbl . ' AS c ON c.' . $this->_tbl_key . ' = u.' . $this->_cmsUserTableKey
		. " WHERE u." . $this->_db->NameQuote( $fieldName ) . ' = ' . $this->_db->Quote( $fieldValue )
		;
		$this->_db->setQuery( $query, 0, 1 );

		$arr					=	$this->_db->loadAssoc( );

		if ( $arr ) {
			foreach ( $arr as $k => $v ) {
				$this->$k		=	$v;
			}
			if ( checkJversion() == 2 ) {
				global $_CB_framework;

				$gids			=	array_values( (array) JFactory::getAcl()->getGroupsByUser( $this->id, false ) );

				foreach ( $gids as $k => $v ) {
					$gids[$k]	=	(string) $v;
				}

				$this->gids		=	$gids;
				$this->gid		=	(int) $_CB_framework->acl->getBackwardsCompatibleGid( $this->gids );
			} else {
				$this->gids		=	array( $this->gid );
			}
			return true;
		} else {
			return false;
		}
	}
	function bindSafely( &$array, $ui, $reason, &$oldUserComplete ) {
		global $_CB_framework, $ueConfig, $_PLUGINS;

		// Some basic sanitizations and securitizations: usertype will be re-computed based on gid in store()

		$this->id						=	(int) $this->id;

		if ( checkJversion() == 2 ) {
			$this->gids					=	( is_array( $this->gids ) ? $this->gids : array( $this->gid ) );
			$this->gid					=	(int) $_CB_framework->acl->getBackwardsCompatibleGid( $this->gids );
		} else {
			$this->gid					=	(int) $this->gid;
			$this->gids					=	array( $this->gid );
		}

		if ( ! $this->gid ) {
			$this->gid					=	null;
		}
		if ( $ui == 1 ) {
			if ( $this->id ) {
				// Front-end edit user: no changes in gid/usertype and confirmed/approved states
				$this->gid				=	(int) $oldUserComplete->gid;
				$this->gids				=	$oldUserComplete->gids;
				$this->usertype			=	$oldUserComplete->usertype;
				$this->block			=	(int) $oldUserComplete->block;
				$this->sendEmail		=	(int) $oldUserComplete->sendEmail;
				$this->confirmed		=	(int) $oldUserComplete->confirmed;
				$this->approved			=	(int) $oldUserComplete->approved;
			} else {
				// Front-end user registration: handle this here, so it is available to all plugins:
				$this->usertype			=	$_CB_framework->getCfg( 'new_usertype' );
				$this->gid				=	(int) $_CB_framework->acl->get_group_id( $this->usertype, 'ARO' );
				$this->gids				=	array( $this->gid );

				if ( $ueConfig['reg_admin_approval'] == 0) {
					$this->approved		=	1;
				} else {
					$this->approved		=	0;
					$this->block		=	1;
				}
				if ( $ueConfig['reg_confirmation'] == 0 ) {
					$this->confirmed	=	1;
				} else {
					$this->confirmed	=	0;
					$this->block		=	1;
				}
				if ( ( $this->confirmed == 1 ) && ( $this->approved == 1 ) ) {
					$this->block		=	0;
				} else {
					$this->block		=	1;
				}
				$this->sendEmail		=	0;

			}
			// Nb.: Backend user edit and new user are handled in core plugin CBfield_userparams field handler class
		}

		// By default, don't touch the hashed password, unless a new password is set by the saveTabsContents binding:
		$this->password					=	null;

		$this->_original_email			=	$this->email;						// needed for checkSafely()

		// Process the fields in form by CB field plugins:

		$_PLUGINS->loadPluginGroup('user');

		$this->_cbTabs					=	new cbTabs( 0, $ui, null, false );
		$this->_cbTabs->saveTabsContents( $this, $array, $reason );
		$errors							=	$_PLUGINS->getErrorMSG( false );
		if ( count( $errors ) > 0 ) {
			$this->_error				=	$errors;
			return false;
		}

		// Now do CMS-specific stuff, specially bugs-workarounds:

		$postCopy						=	array();
		if ( $ui == 1 ) {
			$vars						=	$this->_frontendNonComprofilerVars;
		} else {
			$vars						=	$this->_nonComprofilerVars;
		}
		foreach ( $vars as $k ) {
			if ( isset( $this->$k ) ) {
				$postCopy[$k]			=	$this->$k;
			}
		}
		if ( isset( $postCopy['password'] ) ) {
			$postCopy['verifyPass']		=	$postCopy['password'];			// Mambo and Joomla 1.0 has it in password2 and checks it in bind() !
			$postCopy['password2']		=	$postCopy['password'];			// Joomla 1.5 has it in password2 and checks it in bind() !
		}

		$this->_mapUsers();
		$row							=&	$this->_cmsUser;

		$pwd							=	$this->password;						// maybe cleartext at that stage.
		if ( $pwd == '' ) {
			$pwd						=	null;									// empty: don't update/change
			$this->password				=	null;
		}

		$rowBindResult					=	$row->bind( $postCopy );				// in Joomla 1.5, this modifies $postCopy and hashes password !
		if ( ! $rowBindResult ) {
			if ( checkJversion() == 1 ) {
				$this->_error			=	$row->getErrors();
				foreach ( array_keys( $this->_error ) as $ek ) {
					$this->_error[$ek]	=	stripslashes( $this->_error[$ek] );
				}
			} else {
				$this->_error			=	array( stripslashes( $row->getError() ) );
			}
			return false;
		}


		// Finally, emulate a pre-joomla 1.0.11 bug where jos_users was wtih htmlspecialchars ! :
		if ( checkJversion() == 0 ) {
			if ( checkJversion( 'dev_level' ) < 11 ) {
				_cbMakeHtmlSafe($row);
			}
		}
		$row->password					=	$pwd;		// J1.0: no htmlspecialchars on password, J1.5: restore cleartext password at this stage.
		return true;
	}

	function checkSafely() {
		global $_CB_framework;

		if ( $this->_cmsUser === null ) {
			$this->_mapUsers();
		}
		$row							=&	$this->_cmsUser;

		if ( is_callable( array( $row, 'check' ) ) ) {

			// fix a joomla 1.0 bug preventing from saving profile without changing email if site switched from uniqueemails = 0 to = 1 and duplicates existed
			$original_uniqueemail		=	$_CB_framework->getCfg( 'uniquemail' );
			if ( $_CB_framework->getCfg( 'uniquemail' ) && ( $row->email == $this->_original_email ) ) {
				global $mosConfig_uniquemail;	// this is voluntarily a MAMBO/JOOMLA 1.0 GLOBAL TO FIX A BUG
				$mosConfig_uniquemail	=	0;	// this is voluntarily a MAMBO/JOOMLA 1.0 GLOBAL TO FIX A BUG
			}

			$rowCheckResult				=	$row->check();

			if ( $original_uniqueemail && ( $row->email == $this->_original_email ) ) {
				$mosConfig_uniquemail	=	$original_uniqueemail;	// this is voluntarily a MAMBO/JOOMLA 1.0 GLOBAL TO FIX A BUG
			}

			if ( ! $rowCheckResult ) {
				$this->_error			=	( checkJversion() == 1 ? stripslashes( implode( '<br />', $row->getErrors() ) ) : stripslashes( $row->getError() ) );
				return false;
			}
		}
		return true;
	}
	/**
	* If table key (id) is NULL : inserts new rows
	* otherwise updates existing row in the database tables
	*
	* Can be overridden or overloaded by the child classes
	*
	* @param  boolean  $updateNulls  TRUE: null object variables are also updated, FALSE: not.
	* @return boolean                TRUE if successful otherwise FALSE
	*/
	function store( $updateNulls = false ) {
		global $_CB_framework, $_CB_database, $ueConfig;

		$this->id									=	(int) $this->id;

		if ( checkJversion() == 2 ) {
			$this->gids								=	( is_array( $this->gids ) ? $this->gids : array( $this->gid ) );
			$this->gid								=	(int) $_CB_framework->acl->getBackwardsCompatibleGid( $this->gids );
		} else {
			$this->gid								=	(int) $this->gid;
			$this->gids								=	array( $this->gid );
		}

		$isNew										=	( $this->id == 0 );

		$oldUsername								=	null;
		$oldGid										=	null;
		$oldBlock									=	null;

		//TOOD	//FIXME	Somehow the constructor does not get called in j1.6, so need to redo this here:
		if ( checkJversion() == 2 ) {
			$this->_cmsUserTableGid					=	'usertype';
		}

		if ( ! $isNew ) {
			// get actual username to update sessions in case:
			$sql			=	'SELECT ' . $_CB_database->NameQuote( $this->_cmsUserTableUsername )
							.	', '	. $_CB_database->NameQuote( $this->_cmsUserTableGid )
							.	', '	. $_CB_database->NameQuote( 'block' )
							.	' FROM ' . $_CB_database->NameQuote( $this->_cmsUserTable ) . ' WHERE ' . $_CB_database->NameQuote( $this->_cmsUserTableKey ) . ' = ' . (int) $this->user_id;
			$_CB_database->setQuery( $sql );
			$oldEntry								=	null;
			if ( $_CB_database->loadObject( $oldEntry ) ) {
				$oldUsername						=	$oldEntry->username;
				if ( checkJversion() == 2 ) {
					$gids							=	array_values( (array) JFactory::getAcl()->getGroupsByUser( $this->id, false ) );

					foreach ( $gids as $k => $v ) {
						$gids[$k]					=	(string) $v;
					}

					$oldGids						=	$gids;
					$oldGid							=	(int) $_CB_framework->acl->getBackwardsCompatibleGid( $oldGids );
				} else {
					$oldGid							=	(int) $oldEntry->gid;
					$oldGids						=	array( $oldEntry->gid );
				}
				$oldBlock							=	$oldEntry->block;
			}
		}

		// insure usertype is in sync with gid:
/*
 * This could be a better method:
		if ( checkJversion() == 1 ) {
			$gdataArray								=	$_CB_framework->acl->get_group_data( (int) $this->gid, 'ARO' );
			if ( $gdataArray ) {
				$this->usertype						=	$gdataArray[3];
			} else {
				user_error( sprintf( 'comprofilerUser::store: gacl:get_group_data: for user_id %d, name of group_id %d not found in acl groups table.', $this->id, $this->gid ), E_USER_WARNING );
				$this->usertype						=	'Registered';
			}
		} else {
			$this->usertype							=	$_CB_framework->acl->get_group_name( (int) $gid, 'ARO' );
		}
*/
		if ( checkJversion() == 2 ) {
			$query									= 'SELECT title AS name'
													. "\n FROM #__usergroups"
													. "\n WHERE id = " . (int) $this->gid
													;
		} elseif ( checkJversion() == 1 ) {
			$query									= 'SELECT name'
													. "\n FROM #__core_acl_aro_groups"
													. "\n WHERE id = " . (int) $this->gid
													;
		} else {
			$query									= 'SELECT name'
													. "\n FROM #__core_acl_aro_groups"
													. "\n WHERE group_id = " . (int) $this->gid
													;
		}
		$_CB_database->setQuery( $query );
		$this->usertype								=	$_CB_database->loadResult();

		if ( ( ! $isNew ) && ( $this->confirmed == 0 ) && ( $this->cbactivation == '' ) && ( $ueConfig['reg_confirmation'] != 0 ) ) {
			$this->_setActivationCode();
		}

		// creates CMS and CB objects:
		$this->_mapUsers();

		// remove the previous email set in bindSafely() and needed for checkSafely():
		unset( $this->_original_email );

		// stores first into CMS to get id of user if new:
		if ( is_callable( array( $this->_cmsUser, 'store' ) ) ) {
			$result									=	$this->_cmsUser->store( $updateNulls );
			if ( ! $result ) {
				$this->_error						=	$this->_cmsUser->getError();
			}
		} else {
			if ( checkJversion() == 2 ) {
				$this->_cmsUser->groups				=	$this->gids;
				}
			$result									=	$this->_cmsUser->save();	// Joomla 1.5 native
			if ( ! $result ) {
				$this->_error						=	$this->_cmsUser->getError();
				if ( class_exists( 'JText' ) ) {
					$this->_error					=	JText::_( $this->_error );
				}
			}
		}
		if ( $result ) {
			// synchronize id and user_id:
			if ( $isNew ) {
				if ( $this->_cmsUser->id == 0 ) {
					// this is only for mambo 4.5.0 backwards compatibility. 4.5.2.3 $row->store() updates id on insert
					$sql			=	'SELECT ' . $_CB_database->NameQuote( $this->_cmsUserTableKey ) . ' FROM ' . $_CB_database->NameQuote( $this->_cmsUserTable ) . ' WHERE ' . $_CB_database->NameQuote( $this->_cmsUserTableUsername ) . ' = ' . $_CB_database->Quote( $this->username);
					$_CB_database->setQuery( $sql );
					$this->_cmsUser->id				=	(int) $_CB_database->loadResult();
				}
				$this->id							=	$this->_cmsUser->id;
				$this->_comprofilerUser->id		=	$this->_cmsUser->id;

				if ( ( $this->confirmed == 0 ) && ( $this->cbactivation == '' ) && ( $ueConfig['reg_confirmation'] != 0 ) ) {
					$this->_setActivationCode();
				}
			}

			// stores CB user into comprofiler: if new, inserts, otherwise updates:
			if ( $this->user_id == 0 ) {
				$this->user_id						=	$this->_cmsUser->id;
				$this->_comprofilerUser->user_id	=	$this->user_id;
				$result								=	$this->_comprofilerUser->storeNew( $updateNulls );
			} else {
				$result								=	$this->_comprofilerUser->store( $updateNulls );
			}
			if ( ! $result ) {
				$this->_error						=	$this->_comprofilerUser->getError();
			}
		}
		if ( $result ) {
			// update the ACL:
			if ( checkJversion() == 2 ) {
				$query							=	'SELECT m.id AS aro_id, a.group_id FROM #__user_usergroup_map AS a'
												.	"\n INNER JOIN #__usergroups AS m ON m.id= a.group_id"
												.	"\n WHERE a.user_id = " . (int) $this->id
												;
			} elseif ( checkJversion() == 1 ) {
				$query							=	'SELECT a.id AS aro_id, m.group_id FROM #__core_acl_aro AS a'
												.	"\n INNER JOIN #__core_acl_groups_aro_map AS m ON m.aro_id = a.id"
												.	"\n WHERE a.value = " . $_CB_database->Quote( (int) $this->id )
												;
			} else {
				$query							=	'SELECT a.aro_id, m.group_id FROM #__core_acl_aro AS a'
												.	"\n INNER JOIN #__core_acl_groups_aro_map AS m ON m.aro_id = a.aro_id"
												.	"\n WHERE a.value = " . $_CB_database->Quote( (int) $this->id )
												;
			}
			$_CB_database->setQuery( $query );
			$aro_group							=	null;
			$result								=	$_CB_database->loadObject( $aro_group );

			if ( $result && ( $aro_group->group_id != $this->gid ) ) {
				if ( checkJversion() == 2 ) {
//					$query							=	'UPDATE #__user_usergroup_map'
//													.	"\n SET group_id = " . (int) $this->gid
//													.	"\n WHERE user_id = " . (int) $this->id
//													.	( $oldGid ? "\n AND group_id = " . (int) $oldGid : null )
//													;
//					$_CB_database->setQuery( $query );
//					$result							=	$_CB_database->query();
				} else {
					$query							=	'UPDATE #__core_acl_groups_aro_map'
													.	"\n SET group_id = " . (int) $this->gid
													.	"\n WHERE aro_id = " . (int) $aro_group->aro_id
													;
					$_CB_database->setQuery( $query );
					$result							=	$_CB_database->query();
				}
			}
			if ( $result && ( ! $isNew ) && ( ( $oldUsername != $this->username ) || ( $aro_group->group_id != $this->gid ) || ( $oldGid != $this->gid ) || ( ( $oldBlock == 0 ) && ( $this->block == 1 ) ) ) ) {
				// Update current sessions state if there is a change in gid or in username:
				if ( $this->block == 0 ) {
					$sessionGid			=	1;
					if ( $_CB_framework->acl->is_group_child_of( $this->usertype, 'Registered', 'ARO' ) || $_CB_framework->acl->is_group_child_of( $this->usertype, 'Public Backend', 'ARO' ) ) {
						// Authors, Editors, Publishers and Super Administrators are part of the Special Group:
						$sessionGid		=	2;
					}
					$query				=	'UPDATE #__session '
										.	"\n SET usertype = " . $_CB_database->Quote( $this->usertype );

					if ( checkJversion() <= 1 ) {
						$query			.=	', gid = ' . (int) $sessionGid;
					}

					$query				.=	', username = ' . $_CB_database->Quote( $this->username )
										.	"\n WHERE userid = " . (int) $this->id
										;
					//TBD: here maybe jaclplus fields update if JACLplus installed....
					$_CB_database->setQuery( $query );
					$result				=	$_CB_database->query();
				} else {
					// logout user now that user login has been blocked:
					if ( $_CB_framework->myId() == $this->id ) {
						$_CB_framework->logout();
					}
					$_CB_database->setQuery( "DELETE FROM #__session WHERE userid = " . (int) $this->id );			//TBD: check if this is enough for J 1.5
					$result				=	$_CB_database->query();
				}
			}
			if ( ! $result ) {
				$this->_error					=	$_CB_database->stderr();
				return false;
			}
		}
		return $result;
	}
	function storeDatabaseValue( $name, $value, $triggers = true ) {
		global $_CB_framework, $_PLUGINS;

		if ( $this->id && ( isset( $this->$name ) ) ) {
			$ui								=	$_CB_framework->getUi();

			$user							=	new moscomprofilerUser( $this->_db );
			$oldUserComplete				=	new moscomprofilerUser( $this->_db );
			foreach ( array_keys( get_object_vars( $this ) ) as $k ) {
				if ( substr( $k, 0, 1 ) != '_' ) {
					$user->$k				=	$this->$k;
					$oldUserComplete->$k	=	$this->$k;
				}
			}

			if ( $name != 'password' ) {
				$user->password				=	null;
			}

			// In case of Password, save cleartext value for the onAfter event:
			$currentvalue					=	$user->$name;

			if ( $triggers ) {
				if ( $ui == 1 ) {
					$_PLUGINS->trigger( 'onBeforeUserUpdate', array( &$user, &$user, &$oldUserComplete, &$oldUserComplete ) );
				} elseif ( $ui == 2 ) {
					$_PLUGINS->trigger( 'onBeforeUpdateUser', array( &$user, &$user, &$oldUserComplete ) );
				}
			}

			// In case of Password, hashed value:
			$user->$name					=	$value;

			$return							=	$user->store();

			if ( $name == 'password' ) {
				// In case of Password, cleartext value for the onAfter event:
				$user->$name				=	$currentvalue;
			}

			if ( $triggers ) {
				if ( $return ) {
					if ( $ui == 1 ) {
						$_PLUGINS->trigger( 'onAfterUserUpdate', array( &$user, &$user, $oldUserComplete ) );
					} elseif ( $ui == 2 ) {
						$_PLUGINS->trigger( 'onAfterUpdateUser', array( &$user, &$user, $oldUserComplete ) );
					}
				}
			}

			// Check if error is present in temporary user object:
			$error							=	$user->getError();
			if ( $error ) {
				// Pass error to current user object so can be output properly:
				$this->_error				=	$error;
			}

			unset( $user, $oldUserComplete );
			return $return;
		}

		return false;
	}
	/**
	 * Updates only in database $this->block
	 *
	 * @return boolean   Store query error
	 */
	function storeBlock( $triggers = true ) {
		if ( $this->id ) {
			return $this->storeDatabaseValue( 'block', (int) $this->block, $triggers );
		}
		return false;
	}
	/**
	 * Updates only in database the cleartext $this->password
	 *
	 * @return boolean   Store query error
	 */
	function storePassword( $triggers = true ) {
		if ( $this->id ) {
			return $this->storeDatabaseValue( 'password', $this->hashAndSaltPassword( $this->password ), $triggers );
		}
		return false;
	}
	/**
	 * Updates only in database $this->approved
	 *
	 * @return boolean   Store query error
	 */
	function storeApproved( $triggers = true ) {
		if ( $this->id ) {
			return $this->storeDatabaseValue( 'approved', (int) $this->approved, $triggers );
		}
		return false;
	}
	/**
	 * Updates only in database $this->approved
	 *
	 * @return boolean   Store query error
	 */
	function storeConfirmed( $triggers = true ) {
		if ( $this->id ) {
			return $this->storeDatabaseValue( 'confirmed', (int) $this->confirmed, $triggers );
		}
		return false;
	}
	/**
	 * Saves a new or existing CB+CMS user
	 * WARNINGS:
	 * - You must verify authorization of user to perform this (user checkCBpermissions() )
	 * - You must $this->load() existing user first
	 *
	 * @param  array   $array   Raw unfiltered input, typically $_POST
	 * @param  int     $ui      1 = Front-end (limitted rights), 2 = Backend (almost unlimitted), 0 = automated (full)
	 * @param  string  $reason  'edit' or 'register'
	 * @return boolean
	 */
	function saveSafely( &$array, $ui, $reason ) {
		global $_CB_framework, $_CB_database, $ueConfig, $_PLUGINS;

		// Get current user state and store it into $oldUserComplete:

		$oldUserComplete						=	new moscomprofilerUser( $this->_db );
		foreach ( array_keys( get_object_vars( $this ) ) as $k ) {
			if( substr( $k, 0, 1 ) != '_' ) {		// ignore internal vars
				$oldUserComplete->$k			=	$this->$k;
			}
		}
		if ( $oldUserComplete->gids === null ) {
			$oldUserComplete->gids				=	array();
		}


		// 1) Process and validate the fields in form by CB field plugins:
		// 2) Bind the fields to CMS User:
		$bindResults							=	$this->bindSafely( $array, $ui, $reason, $oldUserComplete );

		if ( $bindResults ) {
			// During bindSafely, in saveTabContents, the validations have already taken place, for mandatory fields.
			if ( ( $this->name == '' ) && ( $this->username == '' ) && ( $this->email != '' ) ) {
				$this->username						=	$this->email;
				$this->_cmsUser->username			=	$this->username;
			}
			// Checks that name is set. If not, uses the username as name, as Mambo/Joola mosUser::store() uses name for ACL
			// and ACL bugs with no name.
			if ( $this->name == '' ) {
				$this->name							=	$this->username;
				$this->_cmsUser->name				=	$this->name;
			} elseif ( $this->username == '' ) {
				$this->username						=	$this->name;
				$this->_cmsUser->username			=	$this->username;
			}

			if ( ! $this->checkSafely() ) {
				$bindResults					=	false;
			}
		}

		// For new registrations or backend user creations, set registration date and password if neeeded:
		$isNew									=	( ! $this->id );
		$newCBuser								=	( $oldUserComplete->user_id == null );

		if ( $isNew ) {
			if ( checkJversion() != 1 ) {
				// J1.5 works better with null here... has bug that it offsets the time by server date, others need this:
				$this->registerDate				=	date('Y-m-d H:i:s', $_CB_framework->now() );
			}
		}

		if ( $bindResults ) {
			if ( $isNew ) {
				if ( $this->password == null ) {
					$this->setRandomPassword();
					$ueConfig['emailpass']		=	1;		// set this global to 1 to force password to be sent to new users.
				}
			}

			// In backend only: if group has been changed and where original group was a Super Admin: check if there is at least a super-admin left:
			if ( $ui == 2 ) {
				$myGids							=	$_CB_framework->acl->get_groups_below_me( null, true );
				$cms_admin						=	$_CB_framework->acl->mapGroupNamesToValues( 'Administrator' );
				$cms_super_admin				=	$_CB_framework->acl->mapGroupNamesToValues( 'Superadministrator' );
				$i_am_super_admin				=	$_CB_framework->acl->amIaSuperAdmin();
				$i_am_admin						=	in_array( $cms_admin, $myGids );

				if ( ! $isNew ) {
					if ( checkJversion() == 2 ) {

						if ( $i_am_super_admin && ( $_CB_framework->myId() == $this->id ) ) {
							// Check that a fool Super User does not block himself:
							if ( $this->block && ! $oldUserComplete->block ) {
								$this->_error	=	'Super Users can not block themselves';
								return false;
							}
							// Check that a fool Super User does not demote himself from Super-User rights:
							if ( $this->gids != $oldUserComplete->gids ) {
								$staysSuperUser		=	$_CB_framework->acl->authorizeGroupsForAction( $this->gids,'core.admin', null );
								if ( ! $staysSuperUser ) {
									$this->_error	=	'You cannot demote yourself from your Super User permission';
									return false;
								}
							}
						}
						// Check that a non-Super User/non-admin does not demote an admin or a Super user:
						if ( $this->gids != $oldUserComplete->gids ) {
							if ( ( ! $i_am_super_admin ) && ! ( CBuser::getMyInstance()->authoriseAction( 'core.admin' ) || ( CBuser::getMyInstance()->authoriseAction( 'core.manage', 'com_users' ) && CBuser::getMyInstance()->authoriseAction( 'core.edit', 'com_users' )  && CBuser::getMyInstance()->authoriseAction( 'core.edit.state', 'com_users' ) ) ) ) {
								// I am not a Super User and not an Users administrator:
								$userIsSuperUser	=	JUser::getInstance( $this->id )->authorise( 'core.admin' );
								// User is super-user: Check if he stays so:
								if ( $userIsSuperUser ) {
									$staysSuperUser		=	$_CB_framework->acl->authorizeGroupsForAction( $this->gids, 'core.admin', null );
									if ( ! $staysSuperUser ) {
										$this->_error	=	'You cannot remove a Super User permission. Only Super Users can do that.';
										return false;
									}
								}
								$userCanAdminUsers	=	( CBuser::getInstance( $this->id )->authoriseAction( 'core.manage', 'com_users' ) || CBuser::getInstance( $this->id )->authoriseAction( 'core.manage' ) )
														&& CBuser::getInstance( $this->id )->authoriseAction( 'core.edit', 'com_users' )
														&& CBuser::getInstance( $this->id )->authoriseAction( 'core.edit.state', 'com_users' );
								// User is users-administrator: check if he can stay so:
								if ( $userCanAdminUsers ) {
									$staysUserAdmin	=	( $_CB_framework->acl->authorizeGroupsForAction( $this->gids, 'core.manage', 'com_users' ) || $_CB_framework->acl->authorizeGroupsForAction( $this->gids, 'core.manage' ) ) 
														&& $_CB_framework->acl->authorizeGroupsForAction( $this->gids, 'core.edit', 'com_users' )
														&& $_CB_framework->acl->authorizeGroupsForAction( $this->gids, 'core.edit.state', 'com_users' );
									if ( ! $staysUserAdmin ) {
										$this->_error	=	'An users manager cannot be demoted by a non-administrator';
										return false;
									}
								}
							}
						}

					} else {

						if ( $this->gid != $oldUserComplete->gid ) {
							if ( $oldUserComplete->gid == $cms_super_admin ) {
								// count number of active super admins
								$query				=	'SELECT COUNT( id )'
													.	"\n FROM #__users"
													.	"\n WHERE gid = " . (int) $cms_super_admin
													.	"\n AND block = 0"
													;
								$_CB_database->setQuery( $query );
								$count				=	$_CB_database->loadResult();
	
								if ( $count <= 1 ) {
									// disallow change if only one Super Admin exists
									$this->_error	=	'You cannot change this users Group as it is the only active Super Administrator for your site';
									return false;
								}
							}
	
							$user_group				=	strtolower( $_CB_framework->acl->get_group_name( $oldUserComplete->gid, 'ARO' ) );
	
							if ( ( $user_group == 'super administrator' && ! $i_am_super_admin ) ) {
								// disallow change of super-Admin by non-super admin
								$this->_error		=	'You cannot change this users Group as you are not a Super Administrator for your site';
								return false;
							} elseif ( $this->id == $_CB_framework->myId() && $i_am_super_admin ) {
								// CB-specific: disallow change of own Super Admin group:
								$this->_error		=	'You cannot change your own Super Administrator status for your site';
								return false;
							} else if ( ( ! $i_am_super_admin ) && $i_am_admin && ( $oldUserComplete->gid == $cms_admin ) ) {
								// disallow change of super-Admin by non-super admin
								$this->_error		=	'You cannot change the Group of another Administrator as you are not a Super Administrator for your site';
								return false;
							} elseif ( in_array( $oldUserComplete->gid, $myGids ) && ! in_array( $this->gid, $myGids ) ) {
								// disallow change of group of user into a group that is not child of admin/superadmin:
								$this->_error		=	'You cannot change the Group of this user to a group that is not child of Registered or Manager as otherwise that user cannot login. If you really need to do that, you can do it in Joomla User Manager.';
								return false;
							}
						}
						// ensure user can't add group higher than themselves done below
					}

				}
				// Security check to avoid creating/editing user to higher level than himself: CB response to artf4529.
				if ( ( ! $i_am_super_admin ) && ( $this->gids != $oldUserComplete->gids ) ) {
					// Does user try to edit a user that has higher groups ?
					if ( count( array_diff( $this->gids, $myGids ) ) != 0 ) {
						$this->_error				=	'Unauthorized attempt to change an user at higher level than allowed !';
						return false;
					}
					// Does the user try to demote higher levels ?
					if ( array_diff( $this->gids, $myGids ) != array_diff( $oldUserComplete->gids, $myGids ) ) {
						$this->_error				=	'Unauthorized attempt to change higher groups of an user than allowed !';
						return false;
					}
				}
			}

		}

		if ( $reason == 'edit' ) {
			if ( $ui == 1 ) {
				$_PLUGINS->trigger( 'onBeforeUserUpdate', array( &$this, &$this, &$oldUserComplete, &$oldUserComplete ) );
			} elseif ( $ui == 2 ) {
				if ( $isNew || $newCBuser ) {
					$_PLUGINS->trigger( 'onBeforeNewUser', array( &$this, &$this, false ) );
				} else {
					$_PLUGINS->trigger( 'onBeforeUpdateUser', array( &$this, &$this, &$oldUserComplete ) );
				}
			}
		} elseif ( $reason == 'register' ) {
			$_PLUGINS->trigger( 'onBeforeUserRegistration', array( &$this, &$this ) );
		}
		$beforeResult							=	! $_PLUGINS->is_errors();
		if ( ! $beforeResult ) {
			$this->_error						=	$_PLUGINS->getErrorMSG( false );			// $_PLUGIN collects all error messages, incl. previous ones.
		}

		// Saves tab plugins:

		// on edits, user params and block/email/approved/confirmed are done in cb.core predefined fields.
		// So now calls this and more (CBtabs are already created in $this->bindSafely() ).
		$pluginTabsResult						=	true;
		if ( $reason == 'edit' ) {
			$this->_cbTabs->savePluginTabs( $this, $array );
			$pluginTabsResult					=	! $_PLUGINS->is_errors();
			if ( ! $pluginTabsResult ) {
				$this->_error					=	$_PLUGINS->getErrorMSG( false );			// $_PLUGIN collects all error messages, incl. previous ones.
			}
		}

		if ( $bindResults && $beforeResult && $pluginTabsResult ) {
			// Hashes password for CMS storage:

			$clearTextPassword					=	$this->password;
			if ( $clearTextPassword ) {
				$hashedPassword					=	$this->hashAndSaltPassword( $clearTextPassword );
				$this->password					=	$hashedPassword;
			}

			// Stores user if it's a new user:

			if ( $isNew ) {
				if ( ! $this->store() ) {
					return false;
				}
			}

			// Restores cleartext password for the saveRegistrationPluginTabs:

			$this->password						=	$clearTextPassword;

			if ( $isNew ) {
				// Sets the instance of user, to avoid reload from database, and loss of the cleartext password.
				CBuser::setUserGetCBUserInstance( $this );
			}
		}

		if ( $reason == 'register' ) {
			// call here since we got to have a user id:
			$registerResults					=	array();
			$registerResults['tabs']			=	$this->_cbTabs->saveRegistrationPluginTabs( $this, $array );
			if ( $_PLUGINS->is_errors() ) {

				if ( $bindResults && $beforeResult && $pluginTabsResult ) {
					$plugins_error				=	$_PLUGINS->getErrorMSG( false );			// $_PLUGIN collects all error messages, incl. previous ones.
					if ( $isNew ) {
						// if it was a new user, and plugin gave error, revert the creation:
						$this->delete();
					}
					$this->_error				=	$plugins_error;
				} else {
					$this->_error				=	$_PLUGINS->getErrorMSG( false );			// $_PLUGIN collects all error messages, incl. previous ones.
				}
				$pluginTabsResult				=	false;
			}
		}

		if ( $bindResults && $beforeResult && $pluginTabsResult ) {
			$this->_cbTabs->commitTabsContents( $this, $array, $reason );
			$commit_errors						=	$_PLUGINS->getErrorMSG( false );

			if ( count( $commit_errors ) > 0 ) {
				$this->_error					=	$commit_errors;
				$bindResults					=	false;
			}
		}

		if ( ! ( $bindResults && $beforeResult && $pluginTabsResult ) ) {
			$this->_cbTabs->rollbackTabsContents( $this, $array, $reason );
			// Normal error exit point:
			$_PLUGINS->trigger( 'onSaveUserError', array( &$this, $this->_error, $reason ) );
			if ( is_array( $this->_error ) ) {
				$this->_error						=	implode( '<br />', $this->_error );
			}
			return false;
		}

		// Stores the user (again if it's a new as the plugins might have changed the user record):
		if ( $clearTextPassword ) {
			$this->password						=	$hashedPassword;
		}
		if ( ! $this->store() ) {
			return false;
		}

		// Restores cleartext password for the onAfter and activation events:

		$this->password							=	$clearTextPassword;

		// Triggers onAfter and activateUser events:

		if ( $reason == 'edit' ) {
			if ( $ui == 1 ) {
				$_PLUGINS->trigger( 'onAfterUserUpdate', array( &$this, &$this, $oldUserComplete ) );
			} elseif ( $ui == 2 ) {
				if ( $isNew || $newCBuser ) {
					if ( $isNew ) {
						$ueConfig['emailpass']	=	1;		// set this global to 1 to force password to be sent to new users.
					}
					$_PLUGINS->trigger( 'onAfterNewUser', array( &$this, &$this, false, true ) );
					if ( $this->block == 0 && $this->approved == 1 && $this->confirmed ) {
						activateUser( $this, 2, 'NewUser', false, $isNew );
					}
				} else {
					if ( ( ! ( ( $oldUserComplete->approved == 1 || $oldUserComplete->approved == 2 ) && $oldUserComplete->confirmed ) )
						 && ($this->approved == 1 && $this->confirmed ) )
					{
						// first time a just registered and confirmed user got approved in backend through save user:
						if( isset( $ueConfig['emailpass'] ) && ( $ueConfig['emailpass'] == "1" ) && ( $this->password == '' ) ) {
							// generate the password is auto-generated and not set by the admin at this occasion:
							$this->setRandomPassword();
							$pwd			=	$this->hashAndSaltPassword( $this->password );
							$_CB_database->setQuery( "UPDATE #__users SET password=" . $_CB_database->Quote($pwd) . " WHERE id = " . (int) $this->id );
			    			$_CB_database->query();
						}
					}
					$_PLUGINS->trigger( 'onAfterUpdateUser', array( &$this, &$this, $oldUserComplete ) );
					if ( ( ! ( ( $oldUserComplete->approved == 1 || $oldUserComplete->approved == 2 ) && $oldUserComplete->confirmed ) )
						 && ($this->approved == 1 && $this->confirmed ) )
					{
						// first time a just registered and confirmed user got approved in backend through save user:
						activateUser( $this, 2, 'UpdateUser', false );
					}

				}
			}
		} elseif ( $reason == 'register' ) {
			$registerResults['after']			=	$_PLUGINS->trigger( 'onAfterUserRegistration', array( &$this, &$this, true ) );
			$registerResults['ok']				=	true;
			return $registerResults;
		}
		return true;
	}
	/**
	* Deletes this record (no checks)
	*
	* @param  int      $oid   Key id of row to delete (otherwise it's the one of $this)
	* @return boolean         TRUE if OK, FALSE if error
	*/
	function delete( $oid = null ) {
		$k								=	$this->_tbl_key;
		if ( $oid ) {
			$this->$k					=	(int) $oid;
		}
		$result							=	cbDeleteUser( $this->$k );
		if ( ! is_bool( result ) ) {
			$this->_error				=	$result;
			$result						=	false;
		}
		return $result;
	}

	function checkin( $oid = null ) {
		$this->_mapUsers();
		// Checks-in the row (on the CMSes where applicable):
		if ( is_callable( array( $this->_cmsUser, 'checkin' ) ) ) {
			return $this->_cmsUser->checkin();
		} else {
			return true;
		}

	}
	function _mapUsers() {
		global $_CB_framework;

		if ( $this->_cmsUser === null ) {
			$this->_cmsUser							=	$_CB_framework->_getCmsUserObject();
		}
		if ( $this->_comprofilerUser === null ) {
			$this->_comprofilerUser				=	new moscomprofiler( $this->_db );
		}

		//Note: Prior to PHP 4.2.0, Uninitialized class variables will not be reported by get_object_vars(), which is ok here
		foreach ( get_object_vars( $this ) as $name => $value ) {
			if ( $name[0] != '_' ) {
				if ( in_array( $name, $this->_nonComprofilerVars ) ) {
					$this->_cmsUser->$name			=	$value;
				} else {
					$this->_comprofilerUser->$name	=	$value;
				}
			}
		}

		$this->_cmsUser->id							=	$this->id;
		$this->_comprofilerUser->id				=	$this->id;
		$this->_comprofilerUser->user_id			=	$this->id;
	}
	/**
	 * Sets a random password in clear-text into $this->password
	 *
	 */
	function setRandomPassword( ) {
		$this->password			=	cbMakeRandomString( 8, true );
	}
	/**
	* Generate the hashed/salted/encoded password for the database
	* and to check the password at login:
	* if $row provided, it is checking the existing password (and update if needed)
	* if not provided, it will generate a new hashed password
	*
	* @param  string  $passwd  cleartext
	* @return string           salted/hashed password
	*/
	function hashAndSaltPassword( $passwd ) {
		return $this->_cbHashPassword( $passwd, false );
	}
	/**
	* Generate the hashed/salted/encoded password for the database
	* and to check the password at login:
	* if $row provided, it is checking the existing password (and update if needed)
	* if not provided, it will generate a new hashed password
	*
	* @param  string   $passwd  cleartext
	* @return boolean           TRUE/FALSE on password check
	*/
	function verifyPassword( $passwd ) {
		return $this->_cbHashPassword( $passwd, true );
	}
	/**
	* Generate the hashed/salted/encoded password for the database
	* and to check the password at login:
	* if $row provided, it is checking the existing password (and update if needed)
	* if not provided, it will generate a new hashed password
	*
	* @param  string              $passwd  cleartext
	* @return string|boolean      salted/hashed password if $row not provided, otherwise TRUE/FALSE on password check
	*/
	function _cbHashPassword( $passwd, $check ) {
		global $_CB_database;

		$version					=	checkJversion();
		$method						=	'md5';
		if ( $version == 0 ) {
			if ( function_exists( 'josHashPassword' ) ) {	// more reliable version-checking than the often hacked version.php file!
				// 1.0.13+ (in fact RC3+):
				$method				=	'md5salt';
				$saltLength			=	16;
			}
		} elseif ( $version >= 1 ) {
			// 1.5 (in fact RC1+):
			$method					=	'md5salt';
			$saltLength				=	32;
		}
		switch ( $method ) {
			case 'md5salt':
				if ( $check ) {
					$parts			=	explode( ':', $this->password );
					if ( count( $parts ) > 1 ) {
						$salt		=	$parts[1];
					} else {
						// check password, if ok, auto-upgrade database:
						$salt		=	cbMakeRandomString( $saltLength );
						$crypt		=	md5( $passwd . $salt );
						$hashedPwd	=	$crypt. ':' . $salt;
						if ( md5( $passwd ) === $this->password ) {
							$query	= "UPDATE #__users SET password = '"
									. $_CB_database->getEscaped( $hashedPwd ) . "'"
									. " WHERE id = " . (int) $this->id;
							$_CB_database->setQuery( $query );
							$_CB_database->query();
							$this->password	=	$hashedPwd;
						}
					}
				} else {
					$salt			=	cbMakeRandomString( $saltLength );
				}
				$crypt				=	md5( $passwd . $salt );
				$hashedPwd			=	$crypt. ':' . $salt;
				break;

			case 'md5':
			default:
				if ( $check ) {
					$parts			=	explode( ':', $this->password );
					if ( count( $parts ) > 1 ) {
						// check password, if ok, auto-downgrade database:
						$salt		=	$parts[2];
						$crypt		=	md5( $passwd . $salt );
						$hashedPwd	=	$crypt. ':' . $salt;
						if ( $hashedPwd === $this->password ) {
							$hashedPwd	=	md5( $passwd );
							$query	= "UPDATE #__users SET password = '"
									. $_CB_database->getEscaped( $hashedPwd ) . "'"
									. " WHERE id = " . (int) $this->id;
							$_CB_database->setQuery( $query );
							$_CB_database->query();
							$this->password	=	$hashedPwd;
						}
					}
				}
				$hashedPwd			=	md5( $passwd );
				break;
		}
		if ( $check ) {
			if ( $this->password ) {
				return ( $hashedPwd === $this->password );
			} else {
				return true;	// this allows cms authentication to do its job without interfering or lowering security
			}
		} else {
			return $hashedPwd;
		}
	}
	function _setActivationCode( ) {
		global $_CB_framework;

		$randomHash						=	md5( cbMakeRandomString() );
		$scrambleSeed					=	(int) hexdec(substr( md5 ( $_CB_framework->getCfg( 'secret' ) . $_CB_framework->getCfg( 'db' ) ), 0, 7));
		$scrambledId					=	$scrambleSeed ^ ( (int) $this->id );
		$this->cbactivation				=	'reg' . $randomHash . sprintf( '%08x', $scrambledId );
		// for CMS compatibility (and JFusion compatibility):
		$this->activation				=	$randomHash;
	}
	function checkActivationCode( $confirmcode ) {
		return ( $this->cbactivation === $confirmcode );
	}
	function removeActivationCode( ) {
		$query	=	'UPDATE '	. $this->_db->NameQuote( '#__comprofiler' )
				.	"\n SET "	. $this->_db->NameQuote( 'cbactivation' ) . ' = ' . $this->_db->Quote( '' )
				.	"\n WHERE "	. $this->_db->NameQuote( 'id' ) . ' = ' . (int) $this->id;
		$this->_db->setQuery( $query );
		if ( $this->_db->query() ) {
			$this->cbactivation			=	'';

			$query	=	'UPDATE '	. $this->_db->NameQuote( $this->_cmsUserTable )
					.	"\n SET "	. $this->_db->NameQuote( 'activation' ) . ' = ' . $this->_db->Quote( '' )
					.	"\n WHERE "	. $this->_db->NameQuote( 'id' ) . ' = ' . (int) $this->id;
			$this->_db->setQuery( $query );
			if ( $this->_db->query() ) {
				$this->activation		=	'';
			}
		} else {
			global $_CB_framework;
			if ( $_CB_framework->getUi() != 0 ) {
				trigger_error( 'SQL-unblock2 error: ' . $this->_db->stderr(true), E_USER_WARNING );
			}
		}
	}
	/**
	 * Gets user_id out of the activation code. WARNING: do not trust the user id until full activation code is checked.
	 *
	 * @static
	 * @param  string    $confirmcode
	 * @return int|null
	 */
	function getUserIdFromActivationCode( $confirmcode ) {
		global $_CB_framework;

		$lengthConfirmcode	=	strlen( $confirmcode );
		if ($lengthConfirmcode == ( 3+32+8 ) ) {
			$scrambleSeed	=	(int) hexdec(substr( md5 ( $_CB_framework->getCfg( 'secret' ) . $_CB_framework->getCfg( 'db' ) ), 0, 7));
			$unscrambledId	=	$scrambleSeed ^ ( (int) hexdec(substr( $confirmcode, 3+32 ) ) );
			return $unscrambledId;
		}
		return null;
	}
	/**
	 * confirms user to make $this->confirmed = 1 and stored in database.
	 *
	 * @param  array    $messagesToUser  RETURNS: array of messages to user.
	 * @return boolean                   TRUE: the user has been (or is already) confirmed, FALSE: wrong confirmation code or integrations do not agree
	 */
	function confirmUser( &$messagesToUser ) {
		global $ueConfig, $_PLUGINS;

		if ( $this->confirmed == 0 ) {
			if ( ( $ueConfig['emailpass'] == '1' ) && ( $this->approved == 1 ) ) {
				$this->setRandomPassword();
			}

			$_PLUGINS->loadPluginGroup('user');
			$_PLUGINS->trigger( 'onBeforeUserConfirm', array( $this ) );
			if($_PLUGINS->is_errors()) {
				$messagesToUser	=	$_PLUGINS->getErrorMSG( false );
				return false;
			}

			$this->confirmed	=	1;
			$this->storeConfirmed( false );

			if ( ( $ueConfig['emailpass'] == '1' ) && ( $this->approved == 1 ) ) {
				$this->storePassword( false );
			}

			$messagesToUser		=	activateUser( $this, 1, 'UserConfirmation' );

			$_PLUGINS->trigger( 'onAfterUserConfirm', array( $this, true ) );
		}
		return true;
	}
}
class moscomprofilerUserReport extends comprofilerDBTable {

   var $reportid			=	null;
   var $reporteduser		=	null;
   var $reportedbyuser		=	null;
   var $reportedondate		=	null;
   var $reportexplaination	=	null;
   var $reportedstatus		=	null;

	/**
	 * Constructor
	 *
	 * @param  CBdatabase  $db   A database connector object
	 */
   function moscomprofilerUserReport( &$db ) {

		$this->comprofilerDBTable( '#__comprofiler_userreports', 'reportid', $db );

	}
	/**
	 * Deletes all user reports from that user and for that user (called on user delete)
	 *
	 * @param int $userId
	 * @return boolean true if ok, false with warning on sql error
	 */
	function deleteUserReports( $userId ) {
		global $_CB_database;
		$sql='DELETE FROM #__comprofiler_userreports WHERE reporteduser = '.(int) $userId.' OR reportedbyuser = '.(int) $userId;
		$_CB_database->SetQuery($sql);
		if (!$_CB_database->query()) {
			echo 'SQL error' . $_CB_database->stderr(true);
			return false;
		}
		return true;
	}
} //end class
class moscomprofilerMember extends comprofilerDBTable {

   var $referenceid			=	null;
   var $memberid			=	null;
   var $accepted			=	null;
   var $pending				=	null;
   var $membersince			=	null;
   var $reason				=	null;
   var $description			=	null;
   var $type				=	null;

	/**
	 * Constructor
	 *
	 * @param  CBdatabase  $db   A database connector object
	 */
   function moscomprofilerMember( &$db ) {
		$this->comprofilerDBTable( '#__comprofiler_members', array( 'referenceid', 'memberid' ), $db );			//TBD: implement arrays for tablekeys.
	}
} //end class

?>
