Files
IPB/upload/admin/sources/classes/vkontakte/connect.php
T
2025-12-19 00:32:22 -08:00

456 lines
12 KiB
PHP

<?php
/**
* <pre>
* Invision Power Services
* IP.Board v3.1.0
* Vkontakte Connect Library
* Created by Ivan Gavrikov
* </pre>
*
* @author $Author: giv $
* @copyright (c) 2010 IBResource, LTD.
* @license http://www.ibresource.ru/products/ipboard/
* @package IP.Board
* @link http://www.ibresource.ru
* @version $Rev: 6242 $
*
*/
class Vkontakte_Request_Validator
{
/**
* Vkontakte API key
*
* @var string
*/
protected $_api_key = '';
/**
* Vkontakte API Secret
*
* @var string
*/
protected $_secret = '';
/**
* VK data
*
* @var array
*/
private $_data = array();
/**
* Valid vk data names
*
* @var array
*/
private $_valid_params = array(
'expire', 'mid', 'secret', 'sid', 'sig'
);
/**
* Request validity flag
*
* @var boolean
*/
private $_valid = true;
/**
* undocumented function
*
* @param string $api_key
* @param string $secret
* @author GiV
*/
public function __construct( $api_key, $secret )
{
$this->_api_key = $api_key;
$this->_secret = $secret;
$this->_validate_params();
}
/**
* Get request validity status
*
* @return boolean
*/
public function isValid()
{
return $this->_valid;
}
/**
* Check vkontakte data parameters validity
* compare signature of recieved params and
* recieved signature
*
* @return void
*/
private function _validate_params()
{
if( isset($_COOKIE[ 'vk_app_' . $this->_api_key ]) )
{
$params = explode( '&', $_COOKIE[ 'vk_app_' . $this->_api_key ]);
foreach( $params as &$param )
{
$param_data = explode( '=', $param );
if( count( $param_data) > 1 )
{
if( in_array( $param_data[0], $this->_valid_params ) )
{
$this->_data[ $param_data[0] ] = $param_data[1];
if ( 'sig' == $param_data[0] )
{
$param = '';
}
}
}
}
if( time() > $this->expire )
{
$this->_valid = false;
}
if( $this->sig != $this->_getSignature( $params ) )
{
$this->_valid = false;
}
return;
}
$this->_valid = false;
return;
}
/**
* Make signature for data array
*
* @param string $data Array
* @return string
*/
private function _getSignature( $data )
{
return md5( implode('', $data) . $this->_secret );
}
/**
* Magic method for setting data value
* from request
*
* @param string $key
* @param string $value
* @return mixed
*/
public function __set( $key, $value )
{
$this->_data[ $key ] = $value;
}
/**
* Magic method for getting data value
* from request
*
* @param string $key
* @return mixed
*/
public function __get( $key )
{
if( isset( $this->_data[ $key ] ) && $this->_valid )
{
return $this->_data[ $key ];
}
return false;
}
}
/**
* Class for working with vkontakte users
*
* @author $Author: giv $
* @copyright (c) 2010 IBResource, LTD.
* @license http://www.ibresource.ru/products/ipboard/
* @package IP.Board
* @link http://www.ibresource.ru
* @version $Rev: 6242 $
*/
class vkontakte_connect
{
/**#@+
* Registry Object Shortcuts
*
* @access protected
* @var object
*/
protected $DB;
protected $settings;
protected $lang;
protected $member;
protected $memberData;
protected $cache;
protected $caches;
/**#@-*/
/**
* IPBs log in handler
*
* @access private
* @var object
*/
private $_login;
/**
* User: Token
*
* @access private
* @var string
*/
private $_token;
/**
* User: Data
*
* @access private
* @var array
*/
private $_userData = array();
/**
* Construct.
*
* @access public
* @return void
*/
public function __construct( $registry, $token='' )
{
/* Make object */
$this->registry = $registry;
$this->_token = $token;
$this->DB = $this->registry->DB();
$this->settings =& $this->registry->fetchSettings();
$this->request =& $this->registry->fetchRequest();
$this->lang = $this->registry->getClass('class_localization');
$this->member = $this->registry->member();
$this->memberData =& $this->registry->member()->fetchMemberData();
$this->cache = $this->registry->cache();
$this->caches =& $this->registry->cache()->fetchCaches();
}
/**
* Show the vkontakte connect page.
*
* @access public
* @return redirect
*/
public function redirectToConnectPage()
{
$template = $this->registry->getClass('output')->getTemplate('vkontakte')->showLogInVkFrame( $this->member->form_hash );
print $template;
}
/**
* Completes the connection
*
* @access public
* @return redirect
*/
public function finishLogin()
{
$vk = new Vkontakte_Request_Validator( $this->settings['vk_api_id'], $this->settings['vk_secret'] );
if ( $vk->mid )
{
/* Got a member linked already? */
$_member = IPSMember::load( $vk->mid, 'all', 'vk_uid' );
if ( $_member['member_id'] )
{
/* Check for partial member id */
$pmember = $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'members_partial', 'where' => "partial_member_id=" . $_member['member_id'] ) );
if ( $pmember['partial_member_id'] )
{
$this->_token = $_REQUEST['key'];
$this->DB->update( 'vkontakte_connect', array( 'v_key' => $pmember['partial_date']), "v_key='" . IPSText::md5Clean( $this->_token ) . "'" );
$this->registry->getClass('output')->silentRedirect( $this->settings['base_url'] . 'app=core&module=global&section=register&do=complete_login&mid='. $_member['member_id'].'&key='.$pmember['partial_date'] );
}
else
{
/* Here, so log us in!! */
$this->_login()->loginWithoutCheckingCredentials( $_member['member_id'], TRUE );
$this->registry->getClass('output')->silentRedirect( $this->settings['base_url'] );
}
}
else
{
$this->_token = $_REQUEST['key'];
$this->fetchUserData();
if ( $vk->mid !== $this->_userData['id'] )
{
throw new Exception( 'CREATION_FAIL' );
}
/* From reg, so create new account properly */
$toSave = array( 'core' => array( 'name' => IPSText::convertCharsets( $this->_userData['name'], 'utf-8', IPS_DOC_CHAR_SET ),
'members_display_name' => '',
'members_created_remote' => 1,
'member_group_id' => ( $this->settings['vk_mgid'] ) ? $this->settings['vk_mgid'] : $this->settings['member_group'],
'email' => '',
'vk_uid' => $this->_userData['id']),
'extendedProfile' => array(
'avatar_location' => $this->_userData['photo'],
'avatar_type' => 'vk' ) );
$memberData = IPSMember::create( $toSave, TRUE, FALSE, FALSE );
if ( ! $memberData['member_id'] )
{
throw new Exception( 'CREATION_FAIL' );
}
$pmember = $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'members_partial', 'where' => "partial_member_id=" . $memberData['member_id'] ) );
if ( $pmember['partial_member_id'] )
{
$this->DB->update( 'vkontakte_connect', array( 'v_key' => $pmember['partial_date']), "v_key='" . IPSText::md5Clean( $this->_token ) . "'" );
$this->registry->getClass('output')->silentRedirect( $this->settings['base_url'] . 'app=core&module=global&section=register&do=complete_login&mid='. $memberData['member_id'].'&key='.$pmember['partial_date'] );
}
else
{
throw new Exception( 'CREATION_FAIL' );
}
}
}
}
/**
* Return user data
*
* @access public
* @return array
*/
public function fetchUserData()
{
//echo $this->_token; exit;
$connectData = $this->DB->buildAndFetch( array( 'select' => '*',
'from' => 'vkontakte_connect',
'where' => "v_key='" . IPSText::md5Clean( $this->_token ) . "'" ) );
if ( !$connectData['v_key'] )
{
/* @todo something more useful here */
throw new Exception( "NO_KEY_FOUND" );
}
$this->_userData = array( 'name' => $connectData['v_user'],
'photo' => $connectData['v_data'],
'id' => $connectData['v_id'] );
return $this->_userData;
}
/**
* Finish a log-in connection
* WARNING: NO PERMISSION CHECKS ARE PERFORMED IN THIS FUNCTION.
*
* @access public
* @param int Forum ID of original member (member to keep)
* @param int Forum ID of linking member (member to remove)
* @return boolean
*/
public function finishNewConnection( $originalId, $newId )
{
$this->DB->delete( 'vkontakte_connect', "v_key='" . IPSText::md5Clean( $this->_token ) . "'" );
if ( $originalId AND $newId )
{
$original = IPSMember::load( $originalId, 'all' );
$new = IPSMember::load( $newId, 'all' );
if ( $original['member_id'] AND $new['vk_uid'] )
{
IPSMember::save( $original['member_id'], array( 'core' => array( 'vk_uid' => $new['vk_uid'] ) ) );
return true;
}
}
return false;
}
/**
* Check if vk user linked to forum account
*
* @return boolean|array
*/
public function isLinked()
{
$vk = new Vkontakte_Request_Validator( $this->settings['vk_api_id'], $this->settings['vk_secret'] );
if ( $vk->mid )
{
$_member = IPSMember::load( $vk->mid, 'all', 'vk_uid' );
return $_member['member_id'];
}
else
{
return false;
}
}
/**
* Make linking local account and current vk user
*
* @return boolean
*/
public function linkTo( $mid )
{
$vk = new Vkontakte_Request_Validator( $this->settings['vk_api_id'], $this->settings['vk_secret'] );
if ( $vk->mid )
{
$isLinked = $this->isLinked();
if( ! $isLinked OR $isLinked !== $mid )
{
if ( $isLinked ) IPSMember::remove( $isLinked );
IPSMember::save( $mid, array( 'core' => array( 'vk_uid' => intval($vk->mid) ) ) );
return true;
}
}
return false;
}
/**
* Accessor for the log in functions
*
* @access public
* @return object
*/
public function _login()
{
if ( ! is_object( $this->_login ) )
{
require_once( IPS_ROOT_PATH . 'sources/handlers/han_login.php' );
$this->_login = new han_login( $this->registry );
$this->_login->init();
}
return $this->_login;
}
}