456 lines
12 KiB
PHP
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§ion=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§ion=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;
|
|
}
|
|
} |