<?php
/* --------------------------------------------------------------------
Chevereto
http://chevereto.com/
@version 3.3.0
@author Rodolfo Berrios A. <http://rodolfoberrios.com/>
<inbox@rodolfoberrios.com>
Copyright (C) 2014 Rodolfo Berrios A. All rights reserved.
BY USING THIS SOFTWARE YOU DECLARE TO ACCEPT THE CHEVERETO EULA
http://chevereto.com/license
--------------------------------------------------------------------- */
$route = function($handler) {
try {
$doing = $handler->request[0];
if(empty($doing)) {
return $handler->issue404();
}
$logged_user = CHV\Login::getUser();
// User status override redirect
CHV\User::statusRedirect($logged_user['status']);
$do_connect = false;
// Include the connect stuff
require_once(CHV_APP_PATH_LIB_VENDOR . $doing.'/'.$doing.'.php');
if($_REQUEST['return']) {
$_SESSION['connect_return'] = $_REQUEST['return'];
}
if($_SESSION['login']['type'] == $doing) {
G\redirect($logged_user['url']);
}
if(!CHV\get_chv_setting($doing)) {
return $handler->issue404();
}
switch($doing) {
case 'facebook':
$facebook = new Facebook([
'appId' => CHV\get_chv_setting('facebook_app_id'),
'secret' => CHV\get_chv_setting('facebook_app_secret')
]);
$get_user = $facebook->getUser();
if($get_user) {
$get_user = $facebook->api($get_user);
// Ugly profile url https://www.facebook.com/app_scoped_user_id/<ID>
$social_pictures = [
'avatar' => 'http://graph.facebook.com/'.$get_user['id'].'/picture',
'background' => NULL
];
$connect_user = [
'id' => $get_user['id'],
'username' => G\sanitize_string(G\unaccent_string($get_user['name']), true, true),
'name' => $get_user['name'],
'avatar' => $social_pictures['avatar'],
'url' => $get_user['link'],
'website' => NULL
];
$connect_tokens = [
'secret' => $facebook->getAccessToken(),
'token_hash'=> NULL
];
$do_connect = true;
} else {
G\redirect($facebook->getLoginUrl(['redirect_uri' => G\get_base_url('connect/facebook/?callback')]));
}
break;
case 'twitter':
$twitter = [
'key' => CHV\get_chv_setting('twitter_api_key'),
'secret' => CHV\get_chv_setting('twitter_api_secret')
];
if($_REQUEST['oauth_verifier'] and $_SESSION['twitter']['oauth_token'] and $_SESSION['twitter']['oauth_token_secret']){
// Handle the twitter callback
$twitteroauth = new TwitterOAuth($twitter['key'], $twitter['secret'], $_SESSION['twitter']['oauth_token'], $_SESSION['twitter']['oauth_token_secret']);
$access_token = $twitteroauth->getAccessToken($_REQUEST['oauth_verifier']);
if($access_token) {
$twitteroauth = new TwitterOAuth($twitter['key'], $twitter['secret'], $access_token['oauth_token'], $access_token['oauth_token_secret']);
$get_user = $twitteroauth->get('account/verify_credentials');
if($get_user->errors) {
G\redirect('connect/'.$doing);
} else {
$social_pictures = [
'avatar' => str_replace('_normal.', '.', $get_user->profile_image_url_https),
'background' => $get_user->profile_background_image_url
];
$connect_user = [
'id' => $get_user->id,
'username' => $get_user->screen_name,
'name' => $get_user->name,
'avatar' => $social_pictures['avatar'],
'url' => 'http://twitter.com/'.$get_user->screen_name,
'website' => $get_user->entities->url ? $get_user->entities->url->urls[0]->expanded_url : NULL
];
$connect_tokens = [
'secret' => $access_token['oauth_token_secret'],
'token_hash'=> $access_token['oauth_token']
];
$do_connect = true;
}
} else {
throw new Exception('Twitter connect error code:'.$twitteroauth->http_code, 400);
}
} else {
// Request the twitter login
$twitteroauth = new TwitterOAuth($twitter['key'], $twitter['secret']);
$request_token = $twitteroauth->getRequestToken(G\get_base_url('connect/twitter'));
if($twitteroauth->http_code == 200){
$_SESSION['twitter']['oauth_token'] = $request_token['oauth_token'];
$_SESSION['twitter']['oauth_token_secret'] = $request_token['oauth_token_secret'];
$url = $twitteroauth->getAuthorizeURL($request_token['oauth_token']);
G\redirect($url);
} else {
unset($_SESSION['twitter']);
throw new Exception('Twitter connect error code:'.$twitteroauth->http_code, 400);
}
}
break;
case 'google':
$google = [
'id' => CHV\get_chv_setting('google_client_id'),
'secret' => CHV\get_chv_setting('google_client_secret')
];
// Validate agains CSRF
if($_REQUEST['state'] and $_SESSION['google']['state'] !== $_REQUEST['state']) {
G\set_status_header(403);
$handler->template = "request-denied";
} else {
$_SESSION['google']['state'] = md5(uniqid(mt_rand(), true));
}
// User cancelled the login flow
if($_REQUEST['error'] == 'access_denied') {
G\redirect('login');
}
$client = new Google_Client();
$client->setApplicationName(CHV\get_chv_setting('website_name') . ' connect');
$client->setClientId($google['id']);
$client->setClientSecret($google['secret']);
$client->setRedirectUri(G\get_base_url('connect/google'));
$client->setState($_SESSION['google']['state']);
$client->setScopes(['https://www.googleapis.com/auth/plus.login']); // https://developers.google.com/+/api/oauth
require_once(CHV_APP_PATH_LIB_VENDOR . 'google/contrib/Google_PlusService.php');
$plus = new Google_PlusService($client);
if(isset($_GET['code'])) {
$client->authenticate();
$_SESSION['google']['token'] = $client->getAccessToken();
}
if($_SESSION['google']['token']) {
$client->setAccessToken($_SESSION['google']['token']);
}
if($client->getAccessToken()) {
$get_user = $plus->people->get('me');
if($get_user) {
$social_pictures = [
'avatar' => preg_replace('/\?.*/', '', $get_user['image']['url']),
'background' => NULL
];
$connect_user = [
'id' => $get_user['id'],
'username' => G\sanitize_string(G\unaccent_string($get_user['displayName']), true, true),
'name' => $get_user['displayName'],
'avatar' => $get_user['image']['url'],
'url' => $get_user['url'],
'website' => preg_match('#https?:\/\/profiles\.google\.com\/.*#', $get_user['urls'][0]['value']) ? NULL : $get_user['urls'][0]['value']
];
$google_token = json_decode($client->getAccessToken());
$connect_tokens = [
'secret' => $client->getAccessToken(),
'token_hash'=> $google_token->access_token
];
$do_connect = true;
}
} else {
G\redirect($client->createAuthUrl());
}
break;
}
if($do_connect) {
$login_array_db = ['type' => $doing, 'resource_id' => $connect_user['id']];
$login = CHV\Login::get($login_array_db, NULL, 1);
// Populate the token stuff
$login_array_db = array_merge($login_array_db, $connect_tokens);
// Pupulate the rest
$login_array_db = array_merge($login_array_db, [
'resource_name' => $connect_user['name'],
'resource_avatar' => $connect_user['avatar'],
'resource_url' => $connect_user['url'],
'date' => G\datetime(),
'date_gmt' => G\datetimegmt()
]);
// Login exists then update login
if($login) {
$updated_login = CHV\Login::update($login['login_id'], $login_array_db);
// Session user doesn't match. Stop bugging
if($_SESSION["login"] and $login['login_user_id'] !== $_SESSION["login"]['id']) {
$logout = CHV\Login::logout($_SESSION["login"]['id']);
}
$user_id = $login['login_user_id'];
} else { // Login needs to be inserted
if(!CHV\get_chv_setting('enable_signups')) {
return $handler->issue404();
}
// User already logged in?
if($_SESSION["login"]) {
$user_id = $_SESSION["login"]['id'];
$login_array_db['user_id'] = $_SESSION["login"]['id'];
}
$inserted_login = CHV\Login::insert($login_array_db);
}
// Get user candidate if any
$user = $user_id ? CHV\User::getSingle($user_id, 'id') : false;
// We need to create or update the user?
// Edit user
if($user) {
if(in_array($doing, ['twitter', 'facebook'])) {
$user_array[$doing.'_username'] = $connect_user['username'];
}
if(count($user_array) > 0) {
CHV\User::update($user_id, $user_array);
}
} else { // Create user
// Wait a second, username already exists?
$username = '';
preg_match_all('/[\w]/', $connect_user['username'], $user_matches);
foreach($user_matches[0] as $match) {
$username .= $match;
}
$username = substr(strtolower($username), 0, CHV\get_chv_setting('username_max_length'));
$i = 1;
while(CHV\User::getSingle($username, 'username', false)) {
$i++;
$username = $connect_user['username'] . G\random_values(2, $i, 1)[0];
}
$insert_user_values = [
'username' => $username,
'name' => $connect_user['name'],
'status' => 'awaiting-email',
'website' => $connect_user['website'],
'timezone' => CHV\get_chv_setting('default_timezone'),
'language' => CHV_LANGUAGE_CODE, // nota. fail
];
if(in_array($doing, ['twitter', 'facebook'])) {
$insert_user_values[$doing.'_username'] = $connect_user['username'];
}
$inserted_user = CHV\User::insert($insert_user_values);
$updated_login = CHV\Login::update($login ? $login['login_id'] : $inserted_login, ['user_id' => $inserted_user]);
}
$user_id = $inserted_user ? $inserted_user : $user_id;
$user = CHV\User::getSingle($user_id, 'id');
// Fetch the social network images
if(!$user or !$user['avatar']['filename'] or !$user['background']['filename']) {
$avatar_needed = !$user ? true : !$user['avatar']['filename'];
$background_needed = !$user ? true : !$user['background']['filename'];
try {
if($avatar_needed and $social_pictures['avatar']) {
CHV\User::uploadPicture($user, 'avatar', $social_pictures['avatar']);
}
if($background_needed and $social_pictures['background']) {
CHV\User::uploadPicture($user, 'background', $social_pictures['background']);
}
} catch(Exception $e) {} // Silence
}
$logged_user = CHV\Login::login($user_id, $doing);
$token = $connect_tokens['secret'].$connect_tokens['token_hash'];
$hash = password_hash($token, PASSWORD_BCRYPT);
$cookie = implode(':', [CHV\encodeID($user_id), $doing, $hash]) . ':' . strtotime($login_array_db['date_gmt']);
setcookie("KEEP_LOGIN_SOCIAL", $cookie, time()+(60*60*24*30), G_ROOT_PATH_RELATIVE);
$redirect_to = $_SESSION['connect_return'] ? urldecode($_SESSION['connect_return']) : $logged_user['url'];
unset($_SESSION['connect_return']);
G\redirect($redirect_to);
}
} catch(Exception $e) {
G\exception_to_error($e);
}
};