commit
eeec29c6be
28 changed files with 3198 additions and 11 deletions
5
boot.php
5
boot.php
|
@ -11,7 +11,7 @@ require_once('include/cache.php');
|
||||||
define ( 'FRIENDIKA_PLATFORM', 'Friendica');
|
define ( 'FRIENDIKA_PLATFORM', 'Friendica');
|
||||||
define ( 'FRIENDIKA_VERSION', '2.3.1158' );
|
define ( 'FRIENDIKA_VERSION', '2.3.1158' );
|
||||||
define ( 'DFRN_PROTOCOL_VERSION', '2.22' );
|
define ( 'DFRN_PROTOCOL_VERSION', '2.22' );
|
||||||
define ( 'DB_UPDATE_VERSION', 1102 );
|
define ( 'DB_UPDATE_VERSION', 1103 );
|
||||||
|
|
||||||
define ( 'EOL', "<br />\r\n" );
|
define ( 'EOL', "<br />\r\n" );
|
||||||
define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
|
define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
|
||||||
|
@ -654,7 +654,7 @@ function get_guid($size=16) {
|
||||||
// returns the complete html for inserting into the page
|
// returns the complete html for inserting into the page
|
||||||
|
|
||||||
if(! function_exists('login')) {
|
if(! function_exists('login')) {
|
||||||
function login($register = false) {
|
function login($register = false, $hiddens=false) {
|
||||||
$o = "";
|
$o = "";
|
||||||
$reg = false;
|
$reg = false;
|
||||||
if ($register) {
|
if ($register) {
|
||||||
|
@ -685,6 +685,7 @@ function login($register = false) {
|
||||||
'$openid' => !$noid,
|
'$openid' => !$noid,
|
||||||
'$lopenid' => array('openid_url', t('OpenID: '),'',''),
|
'$lopenid' => array('openid_url', t('OpenID: '),'',''),
|
||||||
|
|
||||||
|
'$hiddens' => $hiddens,
|
||||||
|
|
||||||
'$register' => $reg,
|
'$register' => $reg,
|
||||||
|
|
||||||
|
|
|
@ -460,14 +460,19 @@ CREATE TABLE IF NOT EXISTS `clients` (
|
||||||
`client_id` VARCHAR( 20 ) NOT NULL ,
|
`client_id` VARCHAR( 20 ) NOT NULL ,
|
||||||
`pw` VARCHAR( 20 ) NOT NULL ,
|
`pw` VARCHAR( 20 ) NOT NULL ,
|
||||||
`redirect_uri` VARCHAR( 200 ) NOT NULL ,
|
`redirect_uri` VARCHAR( 200 ) NOT NULL ,
|
||||||
|
`name` VARCHAR( 128 ) NULL DEFAULT NULL,
|
||||||
|
`icon` VARCHAR( 255 ) NULL DEFAULT NULL,
|
||||||
|
`uid` INT NOT NULL DEFAULT 0,
|
||||||
PRIMARY KEY ( `client_id` )
|
PRIMARY KEY ( `client_id` )
|
||||||
) ENGINE = MyISAM DEFAULT CHARSET=utf8;
|
) ENGINE = MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `tokens` (
|
CREATE TABLE IF NOT EXISTS `tokens` (
|
||||||
`id` VARCHAR( 40 ) NOT NULL ,
|
`id` VARCHAR( 40 ) NOT NULL ,
|
||||||
|
`secret` VARCHAR( 40 ) NOT NULL ,
|
||||||
`client_id` VARCHAR( 20 ) NOT NULL ,
|
`client_id` VARCHAR( 20 ) NOT NULL ,
|
||||||
`expires` INT NOT NULL ,
|
`expires` INT NOT NULL ,
|
||||||
`scope` VARCHAR( 200 ) NOT NULL ,
|
`scope` VARCHAR( 200 ) NOT NULL ,
|
||||||
|
`uid` INT NOT NULL ,
|
||||||
PRIMARY KEY ( `id` )
|
PRIMARY KEY ( `id` )
|
||||||
) ENGINE = MyISAM DEFAULT CHARSET=utf8;
|
) ENGINE = MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
BIN
images/icons/10/plugin.png
Normal file
BIN
images/icons/10/plugin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 471 B |
BIN
images/icons/16/plugin.png
Normal file
BIN
images/icons/16/plugin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 649 B |
BIN
images/icons/22/plugin.png
Normal file
BIN
images/icons/22/plugin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 844 B |
BIN
images/icons/48/plugin.png
Normal file
BIN
images/icons/48/plugin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -2,7 +2,7 @@
|
||||||
IMAGES=add.png edit.png gear.png info.png menu.png \
|
IMAGES=add.png edit.png gear.png info.png menu.png \
|
||||||
notify_off.png star.png delete.png feed.png group.png \
|
notify_off.png star.png delete.png feed.png group.png \
|
||||||
lock.png notice.png notify_on.png user.png link.png \
|
lock.png notice.png notify_on.png user.png link.png \
|
||||||
play.png
|
play.png plugin.png
|
||||||
|
|
||||||
DESTS=10/ 16/ 22/ 48/ \
|
DESTS=10/ 16/ 22/ 48/ \
|
||||||
$(addprefix 10/, $(IMAGES)) \
|
$(addprefix 10/, $(IMAGES)) \
|
||||||
|
|
BIN
images/icons/plugin.png
Normal file
BIN
images/icons/plugin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
|
@ -2,7 +2,7 @@
|
||||||
require_once("bbcode.php");
|
require_once("bbcode.php");
|
||||||
require_once("datetime.php");
|
require_once("datetime.php");
|
||||||
require_once("conversation.php");
|
require_once("conversation.php");
|
||||||
|
require_once("oauth.php");
|
||||||
/*
|
/*
|
||||||
* Twitter-Like API
|
* Twitter-Like API
|
||||||
*
|
*
|
||||||
|
@ -27,6 +27,23 @@
|
||||||
* Simple HTTP Login
|
* Simple HTTP Login
|
||||||
*/
|
*/
|
||||||
function api_login(&$a){
|
function api_login(&$a){
|
||||||
|
// login with oauth
|
||||||
|
try{
|
||||||
|
$oauth = new FKOAuth1();
|
||||||
|
list($consumer,$token) = $oauth->verify_request(OAuthRequest::from_request());
|
||||||
|
if (!is_null($token)){
|
||||||
|
$oauth->loginUser($token->uid);
|
||||||
|
call_hooks('logged_in', $a->user);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
echo __file__.__line__.__function__."<pre>"; var_dump($consumer, $token); die();
|
||||||
|
}catch(Exception $e){
|
||||||
|
logger(__file__.__line__.__function__."\n".$e);
|
||||||
|
//die(__file__.__line__.__function__."<pre>".$e); die();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// workaround for HTTP-auth in CGI mode
|
// workaround for HTTP-auth in CGI mode
|
||||||
if(x($_SERVER,'REDIRECT_REMOTE_USER')) {
|
if(x($_SERVER,'REDIRECT_REMOTE_USER')) {
|
||||||
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"],6)) ;
|
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"],6)) ;
|
||||||
|
@ -1127,3 +1144,31 @@
|
||||||
}
|
}
|
||||||
api_register_func('api/direct_messages/sent','api_direct_messages_sentbox',true);
|
api_register_func('api/direct_messages/sent','api_direct_messages_sentbox',true);
|
||||||
api_register_func('api/direct_messages','api_direct_messages_inbox',true);
|
api_register_func('api/direct_messages','api_direct_messages_inbox',true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function api_oauth_request_token(&$a, $type){
|
||||||
|
try{
|
||||||
|
$oauth = new FKOAuth1();
|
||||||
|
$r = $oauth->fetch_request_token(OAuthRequest::from_request());
|
||||||
|
}catch(Exception $e){
|
||||||
|
echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); killme();
|
||||||
|
}
|
||||||
|
echo $r;
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
function api_oauth_access_token(&$a, $type){
|
||||||
|
try{
|
||||||
|
$oauth = new FKOAuth1();
|
||||||
|
$r = $oauth->fetch_access_token(OAuthRequest::from_request());
|
||||||
|
}catch(Exception $e){
|
||||||
|
echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); killme();
|
||||||
|
}
|
||||||
|
echo $r;
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
api_register_func('api/oauth/request_token', 'api_oauth_request_token', false);
|
||||||
|
api_register_func('api/oauth/access_token', 'api_oauth_access_token', false);
|
||||||
|
|
||||||
|
|
||||||
|
|
266
include/oauth.php
Normal file
266
include/oauth.php
Normal file
|
@ -0,0 +1,266 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* OAuth server
|
||||||
|
* Based on oauth2-php <http://code.google.com/p/oauth2-php/>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
define('REQUEST_TOKEN_DURATION', 300);
|
||||||
|
define('ACCESS_TOKEN_DURATION', 31536000);
|
||||||
|
|
||||||
|
require_once("library/OAuth1.php");
|
||||||
|
require_once("library/oauth2-php/lib/OAuth2.inc");
|
||||||
|
|
||||||
|
class FKOAuthDataStore extends OAuthDataStore {
|
||||||
|
function gen_token(){
|
||||||
|
return md5(base64_encode(pack('N6', mt_rand(), mt_rand(), mt_rand(), mt_rand(), mt_rand(), uniqid())));
|
||||||
|
}
|
||||||
|
|
||||||
|
function lookup_consumer($consumer_key) {
|
||||||
|
logger(__function__.":".$consumer_key);
|
||||||
|
//echo "<pre>"; var_dump($consumer_key); killme();
|
||||||
|
|
||||||
|
$r = q("SELECT client_id, pw, redirect_uri FROM clients WHERE client_id='%s'",
|
||||||
|
dbesc($consumer_key)
|
||||||
|
);
|
||||||
|
if (count($r))
|
||||||
|
return new OAuthConsumer($r[0]['client_id'],$r[0]['pw'],$r[0]['redirect_uri']);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lookup_token($consumer, $token_type, $token) {
|
||||||
|
logger(__function__.":".$consumer.", ". $token_type.", ".$token);
|
||||||
|
$r = q("SELECT id, secret,scope, expires, uid FROM tokens WHERE client_id='%s' AND scope='%s' AND id='%s'",
|
||||||
|
dbesc($consumer->key),
|
||||||
|
dbesc($token_type),
|
||||||
|
dbesc($token)
|
||||||
|
);
|
||||||
|
if (count($r)){
|
||||||
|
$ot=new OAuthToken($r[0]['id'],$r[0]['secret']);
|
||||||
|
$ot->scope=$r[0]['scope'];
|
||||||
|
$ot->expires = $r[0]['expires'];
|
||||||
|
$ot->uid = $r[0]['uid'];
|
||||||
|
return $ot;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lookup_nonce($consumer, $token, $nonce, $timestamp) {
|
||||||
|
//echo __file__.":".__line__."<pre>"; var_dump($consumer,$key); killme();
|
||||||
|
$r = q("SELECT id, secret FROM tokens WHERE client_id='%s' AND id='%s' AND expires=%d",
|
||||||
|
dbesc($consumer->key),
|
||||||
|
dbesc($nonce),
|
||||||
|
intval($timestamp)
|
||||||
|
);
|
||||||
|
if (count($r))
|
||||||
|
return new OAuthToken($r[0]['id'],$r[0]['secret']);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function new_request_token($consumer, $callback = null) {
|
||||||
|
logger(__function__.":".$consumer.", ". $callback);
|
||||||
|
$key = $this->gen_token();
|
||||||
|
$sec = $this->gen_token();
|
||||||
|
|
||||||
|
if ($consumer->key){
|
||||||
|
$k = $consumer->key;
|
||||||
|
} else {
|
||||||
|
$k = $consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = q("INSERT INTO tokens (id, secret, client_id, scope, expires) VALUES ('%s','%s','%s','%s', UNIX_TIMESTAMP()+%d)",
|
||||||
|
dbesc($key),
|
||||||
|
dbesc($sec),
|
||||||
|
dbesc($k),
|
||||||
|
'request',
|
||||||
|
intval(REQUEST_TOKEN_DURATION));
|
||||||
|
if (!$r) return null;
|
||||||
|
return new OAuthToken($key,$sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
function new_access_token($token, $consumer, $verifier = null) {
|
||||||
|
logger(__function__.":".$token.", ". $consumer.", ". $verifier);
|
||||||
|
|
||||||
|
// return a new access token attached to this consumer
|
||||||
|
// for the user associated with this token if the request token
|
||||||
|
// is authorized
|
||||||
|
// should also invalidate the request token
|
||||||
|
|
||||||
|
$ret=Null;
|
||||||
|
|
||||||
|
// get user for this verifier
|
||||||
|
$uverifier = get_config("oauth", $verifier);
|
||||||
|
logger(__function__.":".$verifier.",".$uverifier);
|
||||||
|
if (is_null($verifier) || ($uverifier!==false)){
|
||||||
|
|
||||||
|
$key = $this->gen_token();
|
||||||
|
$sec = $this->gen_token();
|
||||||
|
$r = q("INSERT INTO tokens (id, secret, client_id, scope, expires, uid) VALUES ('%s','%s','%s','%s', UNIX_TIMESTAMP()+%d, %d)",
|
||||||
|
dbesc($key),
|
||||||
|
dbesc($sec),
|
||||||
|
dbesc($consumer->key),
|
||||||
|
'access',
|
||||||
|
intval(ACCESS_TOKEN_DURATION),
|
||||||
|
intval($uverifier));
|
||||||
|
if ($r)
|
||||||
|
$ret = new OAuthToken($key,$sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
q("DELETE FROM tokens WHERE id='%s'", $token->key);
|
||||||
|
|
||||||
|
|
||||||
|
if (!is_null($ret) && $uverifier!==false){
|
||||||
|
del_config("oauth", $verifier);
|
||||||
|
/* $apps = get_pconfig($uverifier, "oauth", "apps");
|
||||||
|
if ($apps===false) $apps=array();
|
||||||
|
$apps[] = $consumer->key;
|
||||||
|
set_pconfig($uverifier, "oauth", "apps", $apps);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FKOAuth1 extends OAuthServer {
|
||||||
|
function __construct() {
|
||||||
|
parent::__construct(new FKOAuthDataStore());
|
||||||
|
$this->add_signature_method(new OAuthSignatureMethod_PLAINTEXT());
|
||||||
|
$this->add_signature_method(new OAuthSignatureMethod_HMAC_SHA1());
|
||||||
|
}
|
||||||
|
|
||||||
|
function loginUser($uid){
|
||||||
|
logger("FKOAuth1::loginUser $uid");
|
||||||
|
$a = get_app();
|
||||||
|
$r = q("SELECT * FROM `user` WHERE uid=%d AND `blocked` = 0 AND `account_expired` = 0 AND `verified` = 1 LIMIT 1",
|
||||||
|
intval($uid)
|
||||||
|
);
|
||||||
|
if(count($r)){
|
||||||
|
$record = $r[0];
|
||||||
|
} else {
|
||||||
|
logger('FKOAuth1::loginUser failure: ' . print_r($_SERVER,true), LOGGER_DEBUG);
|
||||||
|
header('HTTP/1.0 401 Unauthorized');
|
||||||
|
die('This api requires login');
|
||||||
|
}
|
||||||
|
$_SESSION['uid'] = $record['uid'];
|
||||||
|
$_SESSION['theme'] = $record['theme'];
|
||||||
|
$_SESSION['authenticated'] = 1;
|
||||||
|
$_SESSION['page_flags'] = $record['page-flags'];
|
||||||
|
$_SESSION['my_url'] = $a->get_baseurl() . '/profile/' . $record['nickname'];
|
||||||
|
$_SESSION['addr'] = $_SERVER['REMOTE_ADDR'];
|
||||||
|
|
||||||
|
//notice( t("Welcome back ") . $record['username'] . EOL);
|
||||||
|
$a->user = $record;
|
||||||
|
|
||||||
|
if(strlen($a->user['timezone'])) {
|
||||||
|
date_default_timezone_set($a->user['timezone']);
|
||||||
|
$a->timezone = $a->user['timezone'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1",
|
||||||
|
intval($_SESSION['uid']));
|
||||||
|
if(count($r)) {
|
||||||
|
$a->contact = $r[0];
|
||||||
|
$a->cid = $r[0]['id'];
|
||||||
|
$_SESSION['cid'] = $a->cid;
|
||||||
|
}
|
||||||
|
q("UPDATE `user` SET `login_date` = '%s' WHERE `uid` = %d LIMIT 1",
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
intval($_SESSION['uid'])
|
||||||
|
);
|
||||||
|
|
||||||
|
call_hooks('logged_in', $a->user);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
class FKOAuth2 extends OAuth2 {
|
||||||
|
|
||||||
|
private function db_secret($client_secret){
|
||||||
|
return hash('whirlpool',$client_secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addClient($client_id, $client_secret, $redirect_uri) {
|
||||||
|
$client_secret = $this->db_secret($client_secret);
|
||||||
|
$r = q("INSERT INTO clients (client_id, pw, redirect_uri) VALUES ('%s', '%s', '%s')",
|
||||||
|
dbesc($client_id),
|
||||||
|
dbesc($client_secret),
|
||||||
|
dbesc($redirect_uri)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkClientCredentials($client_id, $client_secret = NULL) {
|
||||||
|
$client_secret = $this->db_secret($client_secret);
|
||||||
|
|
||||||
|
$r = q("SELECT pw FROM clients WHERE client_id = '%s'",
|
||||||
|
dbesc($client_id));
|
||||||
|
|
||||||
|
if ($client_secret === NULL)
|
||||||
|
return $result !== FALSE;
|
||||||
|
|
||||||
|
return $result["client_secret"] == $client_secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRedirectUri($client_id) {
|
||||||
|
$r = q("SELECT redirect_uri FROM clients WHERE client_id = '%s'",
|
||||||
|
dbesc($client_id));
|
||||||
|
if ($r === FALSE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return isset($r[0]["redirect_uri"]) && $r[0]["redirect_uri"] ? $r[0]["redirect_uri"] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAccessToken($oauth_token) {
|
||||||
|
$r = q("SELECT client_id, expires, scope FROM tokens WHERE id = '%s'",
|
||||||
|
dbesc($oauth_token));
|
||||||
|
|
||||||
|
if (count($r))
|
||||||
|
return $r[0];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected function setAccessToken($oauth_token, $client_id, $expires, $scope = NULL) {
|
||||||
|
$r = q("INSERT INTO tokens (id, client_id, expires, scope) VALUES ('%s', '%s', %d, '%s')",
|
||||||
|
dbesc($oauth_token),
|
||||||
|
dbesc($client_id),
|
||||||
|
intval($expires),
|
||||||
|
dbesc($scope));
|
||||||
|
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getSupportedGrantTypes() {
|
||||||
|
return array(
|
||||||
|
OAUTH2_GRANT_TYPE_AUTH_CODE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function getAuthCode($code) {
|
||||||
|
$r = q("SELECT id, client_id, redirect_uri, expires, scope FROM auth_codes WHERE id = '%s'",
|
||||||
|
dbesc($code));
|
||||||
|
|
||||||
|
if (count($r))
|
||||||
|
return $r[0];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setAuthCode($code, $client_id, $redirect_uri, $expires, $scope = NULL) {
|
||||||
|
$r = q("INSERT INTO auth_codes
|
||||||
|
(id, client_id, redirect_uri, expires, scope) VALUES
|
||||||
|
('%s', '%s', '%s', %d, '%s')",
|
||||||
|
dbesc($code),
|
||||||
|
dbesc($client_id),
|
||||||
|
dbesc($redirect_uri),
|
||||||
|
intval($expires),
|
||||||
|
dbesc($scope));
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
|
@ -27,6 +27,10 @@ class OAuthToken {
|
||||||
public $key;
|
public $key;
|
||||||
public $secret;
|
public $secret;
|
||||||
|
|
||||||
|
public $expires;
|
||||||
|
public $scope;
|
||||||
|
public $uid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key = the token
|
* key = the token
|
||||||
* secret = the token secret
|
* secret = the token secret
|
||||||
|
@ -85,7 +89,8 @@ abstract class OAuthSignatureMethod {
|
||||||
*/
|
*/
|
||||||
public function check_signature($request, $consumer, $token, $signature) {
|
public function check_signature($request, $consumer, $token, $signature) {
|
||||||
$built = $this->build_signature($request, $consumer, $token);
|
$built = $this->build_signature($request, $consumer, $token);
|
||||||
return $built == $signature;
|
//echo "<pre>"; var_dump($signature, $built, ($built == $signature)); killme();
|
||||||
|
return ($built == $signature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +118,9 @@ class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {
|
||||||
$key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
|
$key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
|
||||||
$key = implode('&', $key_parts);
|
$key = implode('&', $key_parts);
|
||||||
|
|
||||||
return base64_encode(hash_hmac('sha1', $base_string, $key, true));
|
|
||||||
|
$r = base64_encode(hash_hmac('sha1', $base_string, $key, true));
|
||||||
|
return $r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +289,12 @@ class OAuthRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// fix for friendika redirect system
|
||||||
|
|
||||||
|
$http_url = substr($http_url, 0, strpos($http_url,$parameters['q'])+strlen($parameters['q']));
|
||||||
|
unset( $parameters['q'] );
|
||||||
|
|
||||||
|
//echo "<pre>".__function__."\n"; var_dump($http_method, $http_url, $parameters, $_SERVER['REQUEST_URI']); killme();
|
||||||
return new OAuthRequest($http_method, $http_url, $parameters);
|
return new OAuthRequest($http_method, $http_url, $parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,6 +556,7 @@ class OAuthServer {
|
||||||
public function verify_request(&$request) {
|
public function verify_request(&$request) {
|
||||||
$this->get_version($request);
|
$this->get_version($request);
|
||||||
$consumer = $this->get_consumer($request);
|
$consumer = $this->get_consumer($request);
|
||||||
|
//echo __file__.__line__.__function__."<pre>"; var_dump($consumer); die();
|
||||||
$token = $this->get_token($request, $consumer, "access");
|
$token = $this->get_token($request, $consumer, "access");
|
||||||
$this->check_signature($request, $consumer, $token);
|
$this->check_signature($request, $consumer, $token);
|
||||||
return array($consumer, $token);
|
return array($consumer, $token);
|
||||||
|
@ -643,6 +656,7 @@ class OAuthServer {
|
||||||
$signature
|
$signature
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
if (!$valid_sig) {
|
if (!$valid_sig) {
|
||||||
throw new OAuthException("Invalid signature");
|
throw new OAuthException("Invalid signature");
|
||||||
}
|
}
|
||||||
|
|
98
library/oauth2-php/CHANGELOG.txt
Normal file
98
library/oauth2-php/CHANGELOG.txt
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
oauth2-php revision xxx, xxxx-xx-xx (development version)
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
oauth2-php revision 23, 2011-01-25
|
||||||
|
----------------------
|
||||||
|
* introduce Drupal style getVariable() and setVariable, replace legacy
|
||||||
|
variable get/set functions.
|
||||||
|
* remove hardcode PHP display_error and errror_reporting, as this should
|
||||||
|
be manually implement within 3rd party integration.
|
||||||
|
* make verbose error as configurable and default disable, as this should
|
||||||
|
be manually enable within 3rd party integration.
|
||||||
|
* add lib/OAuth2Client.inc and lib/OAuth2Exception.inc for client-side
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
oauth2-php revision 21, 2010-12-18
|
||||||
|
----------------------
|
||||||
|
* cleanup tabs and trailing whitespace at the end.
|
||||||
|
* remove server/examples/mongo/lib/oauth.php and
|
||||||
|
server/examples/pdo/lib/oauth.php, so only keep single copy as
|
||||||
|
lib /oauth.php.
|
||||||
|
* issue #5: Wrong variable name in get_access_token() in pdo_oatuh.php.
|
||||||
|
* issue #6: mysql_create_tables.sql should allow scope to be NULL.
|
||||||
|
* issue #7: authorize_client_response_type() is never used.
|
||||||
|
* issue #9: Change "redirect_uri" filtering from FILTER_VALIDATE_URL to
|
||||||
|
FILTER_SANITIZE_URL.
|
||||||
|
* better coding syntax for error() and callback_error().
|
||||||
|
* better pdo_oauth2.php variable naming with change to
|
||||||
|
mysql_create_tables.sql.
|
||||||
|
* change REGEX_CLIENT_ID as 3-32 characters long, so will work with md5()
|
||||||
|
result directly.
|
||||||
|
* debug linkage to oauth2.php during previous commit.
|
||||||
|
* debug redirect_uri check for AUTH_CODE_GRANT_TYPE, clone from
|
||||||
|
get_authorize_params().
|
||||||
|
* update mysql_create_tables.sql with phpmyadmin export format.
|
||||||
|
* rename library files, prepare for adding client-side implementation.
|
||||||
|
* code cleanup with indent and spacing.
|
||||||
|
* code cleanup true/false/null with TRUE/FALSE/NULL.
|
||||||
|
* rename constants with OAUTH2_ prefix, prevent 3rd party integration
|
||||||
|
conflict.
|
||||||
|
* remove HTTP 400 response constant, as useless refer to draft v10.
|
||||||
|
* merge ERROR_INVALID_CLIENT_ID and ERROR_UNAUTHORIZED_CLIENT as
|
||||||
|
OAUTH2_ERROR_INVALID_CLIENT, as refer to that of draft v9 to v10 changes.
|
||||||
|
* improve constants comment with doxygen syntax.
|
||||||
|
* update class function call naming.
|
||||||
|
* coding style clean up.
|
||||||
|
* update part of documents.
|
||||||
|
* change expirseRefreshToken() as unsetRefreshToken().
|
||||||
|
* update token and auth code generation as md5() result, simpler for manual
|
||||||
|
debug with web browser.
|
||||||
|
* update all documents.
|
||||||
|
* restructure @ingroup.
|
||||||
|
* rename checkRestrictedClientResponseTypes() as
|
||||||
|
checkRestrictedAuthResponseType().
|
||||||
|
* rename checkRestrictedClientGrantTypes() as checkRestrictedGrantType().
|
||||||
|
* rename error() as errorJsonResponse().
|
||||||
|
* rename errorCallback() as errorDoRedirectUriCallback().
|
||||||
|
* rename send401Unauthorized() as errorWWWAuthenticateResponseHeader(),
|
||||||
|
update support with different HTTP status code.
|
||||||
|
* update __construct() with array input.
|
||||||
|
* update finishClientAuthorization() with array input.
|
||||||
|
* add get/set functions for $access_token_lifetime, $auth_code_lifetime and
|
||||||
|
$refresh_token_lifetime.
|
||||||
|
* fix a lots of typos.
|
||||||
|
* document all sample server implementation.
|
||||||
|
* more documents.
|
||||||
|
* add config.doxy for doxygen default setup.
|
||||||
|
* add MIT LICENSE.txt.
|
||||||
|
* add CHANGELOG.txt.
|
||||||
|
|
||||||
|
oauth2-php revision 9, 2010-09-04
|
||||||
|
----------------------
|
||||||
|
- fixes for issues #2 and #4, updates oauth lib in the example folders to
|
||||||
|
the latest version in the 'lib' folder.
|
||||||
|
- updates server library to revision 10 of the OAuth 2.0 spec.
|
||||||
|
- adds an option for more verbose error messages to be returned in the JSON
|
||||||
|
response.
|
||||||
|
- adds method to be overridden for expiring used refresh tokens.
|
||||||
|
- fixes bug checking token expiration.
|
||||||
|
- makes some more methods protected instead of private so they can be
|
||||||
|
overridden.
|
||||||
|
- fixes issue #1 http://code.google.com/p/oauth2-php/issues/detail?id=1
|
||||||
|
|
||||||
|
oauth2-php revision 7, 2010-06-29
|
||||||
|
----------------------
|
||||||
|
- fixed mongo connection constants.
|
||||||
|
- updated store_refresh_token to include expires time.
|
||||||
|
- changed example server directory structure
|
||||||
|
- corrected "false" return result on get_stored_auth_code.
|
||||||
|
- implemented PDO example adapter.
|
||||||
|
- corrected an error in assertion grant type.
|
||||||
|
- updated for ietf draft v9:
|
||||||
|
http://tools.ietf.org/html/draft-ietf-oauth-v2-09.
|
||||||
|
- updated updated to support v9 lib.
|
||||||
|
- added mysql table creation script.
|
||||||
|
|
||||||
|
oauth2-php revision 0, 2010-06-27
|
||||||
|
----------------------
|
||||||
|
- initial commit.
|
21
library/oauth2-php/LICENSE.txt
Normal file
21
library/oauth2-php/LICENSE.txt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2010 Tim Ridgely <tim@opendining.net>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
1560
library/oauth2-php/lib/OAuth2.inc
Normal file
1560
library/oauth2-php/lib/OAuth2.inc
Normal file
File diff suppressed because it is too large
Load diff
721
library/oauth2-php/lib/OAuth2Client.inc
Normal file
721
library/oauth2-php/lib/OAuth2Client.inc
Normal file
|
@ -0,0 +1,721 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default Cache Lifetime (in seconds).
|
||||||
|
*/
|
||||||
|
define("OAUTH2_DEFAULT_EXPIRES_IN", 3600);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default Base domain for the Cookie.
|
||||||
|
*/
|
||||||
|
define("OAUTH2_DEFAULT_BASE_DOMAIN", '');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth2.0 draft v10 client-side implementation.
|
||||||
|
*
|
||||||
|
* @author Originally written by Naitik Shah <naitik@facebook.com>.
|
||||||
|
* @author Update to draft v10 by Edison Wong <hswong3i@pantarei-design.com>.
|
||||||
|
*
|
||||||
|
* @sa <a href="https://github.com/facebook/php-sdk">Facebook PHP SDK</a>.
|
||||||
|
*/
|
||||||
|
abstract class OAuth2Client {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of persistent variables stored.
|
||||||
|
*/
|
||||||
|
protected $conf = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a persistent variable.
|
||||||
|
*
|
||||||
|
* To avoid problems, always use lower case for persistent variable names.
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
* The name of the variable to return.
|
||||||
|
* @param $default
|
||||||
|
* The default value to use if this variable has never been set.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The value of the variable.
|
||||||
|
*/
|
||||||
|
public function getVariable($name, $default = NULL) {
|
||||||
|
return isset($this->conf[$name]) ? $this->conf[$name] : $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a persistent variable.
|
||||||
|
*
|
||||||
|
* To avoid problems, always use lower case for persistent variable names.
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
* The name of the variable to set.
|
||||||
|
* @param $value
|
||||||
|
* The value to set.
|
||||||
|
*/
|
||||||
|
public function setVariable($name, $value) {
|
||||||
|
$this->conf[$name] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stuff that should get overridden by subclasses.
|
||||||
|
//
|
||||||
|
// I don't want to make these abstract, because then subclasses would have
|
||||||
|
// to implement all of them, which is too much work.
|
||||||
|
//
|
||||||
|
// So they're just stubs. Override the ones you need.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a Drupal OAuth2.0 Application.
|
||||||
|
*
|
||||||
|
* @param $config
|
||||||
|
* An associative array as below:
|
||||||
|
* - base_uri: The base URI for the OAuth2.0 endpoints.
|
||||||
|
* - code: (optional) The authorization code.
|
||||||
|
* - username: (optional) The username.
|
||||||
|
* - password: (optional) The password.
|
||||||
|
* - client_id: (optional) The application ID.
|
||||||
|
* - client_secret: (optional) The application secret.
|
||||||
|
* - authorize_uri: (optional) The end-user authorization endpoint URI.
|
||||||
|
* - access_token_uri: (optional) The token endpoint URI.
|
||||||
|
* - services_uri: (optional) The services endpoint URI.
|
||||||
|
* - cookie_support: (optional) TRUE to enable cookie support.
|
||||||
|
* - base_domain: (optional) The domain for the cookie.
|
||||||
|
* - file_upload_support: (optional) TRUE if file uploads are enabled.
|
||||||
|
*/
|
||||||
|
public function __construct($config = array()) {
|
||||||
|
// We must set base_uri first.
|
||||||
|
$this->setVariable('base_uri', $config['base_uri']);
|
||||||
|
unset($config['base_uri']);
|
||||||
|
|
||||||
|
// Use predefined OAuth2.0 params, or get it from $_REQUEST.
|
||||||
|
foreach (array('code', 'username', 'password') as $name) {
|
||||||
|
if (isset($config[$name]))
|
||||||
|
$this->setVariable($name, $config[$name]);
|
||||||
|
else if (isset($_REQUEST[$name]) && !empty($_REQUEST[$name]))
|
||||||
|
$this->setVariable($name, $_REQUEST[$name]);
|
||||||
|
unset($config[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoint URIs.
|
||||||
|
foreach (array('authorize_uri', 'access_token_uri', 'services_uri') as $name) {
|
||||||
|
if (isset($config[$name]))
|
||||||
|
if (substr($config[$name], 0, 4) == "http")
|
||||||
|
$this->setVariable($name, $config[$name]);
|
||||||
|
else
|
||||||
|
$this->setVariable($name, $this->getVariable('base_uri') . $config[$name]);
|
||||||
|
unset($config[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other else configurations.
|
||||||
|
foreach ($config as $name => $value) {
|
||||||
|
$this->setVariable($name, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to get session object from custom method.
|
||||||
|
*
|
||||||
|
* By default we generate session object based on access_token response, or
|
||||||
|
* if it is provided from server with $_REQUEST. For sure, if it is provided
|
||||||
|
* by server it should follow our session object format.
|
||||||
|
*
|
||||||
|
* Session object provided by server can ensure the correct expirse and
|
||||||
|
* base_domain setup as predefined in server, also you may get more useful
|
||||||
|
* information for custom functionality, too. BTW, this may require for
|
||||||
|
* additional remote call overhead.
|
||||||
|
*
|
||||||
|
* You may wish to override this function with your custom version due to
|
||||||
|
* your own server-side implementation.
|
||||||
|
*
|
||||||
|
* @param $access_token
|
||||||
|
* (optional) A valid access token in associative array as below:
|
||||||
|
* - access_token: A valid access_token generated by OAuth2.0
|
||||||
|
* authorization endpoint.
|
||||||
|
* - expires_in: (optional) A valid expires_in generated by OAuth2.0
|
||||||
|
* authorization endpoint.
|
||||||
|
* - refresh_token: (optional) A valid refresh_token generated by OAuth2.0
|
||||||
|
* authorization endpoint.
|
||||||
|
* - scope: (optional) A valid scope generated by OAuth2.0
|
||||||
|
* authorization endpoint.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A valid session object in associative array for setup cookie, and
|
||||||
|
* NULL if not able to generate it with custom method.
|
||||||
|
*/
|
||||||
|
protected function getSessionObject($access_token = NULL) {
|
||||||
|
$session = NULL;
|
||||||
|
|
||||||
|
// Try generate local version of session cookie.
|
||||||
|
if (!empty($access_token) && isset($access_token['access_token'])) {
|
||||||
|
$session['access_token'] = $access_token['access_token'];
|
||||||
|
$session['base_domain'] = $this->getVariable('base_domain', OAUTH2_DEFAULT_BASE_DOMAIN);
|
||||||
|
$session['expirse'] = isset($access_token['expires_in']) ? time() + $access_token['expires_in'] : time() + $this->getVariable('expires_in', OAUTH2_DEFAULT_EXPIRES_IN);
|
||||||
|
$session['refresh_token'] = isset($access_token['refresh_token']) ? $access_token['refresh_token'] : '';
|
||||||
|
$session['scope'] = isset($access_token['scope']) ? $access_token['scope'] : '';
|
||||||
|
$session['secret'] = md5(base64_encode(pack('N6', mt_rand(), mt_rand(), mt_rand(), mt_rand(), mt_rand(), uniqid())));
|
||||||
|
|
||||||
|
// Provide our own signature.
|
||||||
|
$sig = self::generateSignature(
|
||||||
|
$session,
|
||||||
|
$this->getVariable('client_secret')
|
||||||
|
);
|
||||||
|
$session['sig'] = $sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try loading session from $_REQUEST.
|
||||||
|
if (!$session && isset($_REQUEST['session'])) {
|
||||||
|
$session = json_decode(
|
||||||
|
get_magic_quotes_gpc()
|
||||||
|
? stripslashes($_REQUEST['session'])
|
||||||
|
: $_REQUEST['session'],
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an API call.
|
||||||
|
*
|
||||||
|
* Support both OAuth2.0 or normal GET/POST API call, with relative
|
||||||
|
* or absolute URI.
|
||||||
|
*
|
||||||
|
* If no valid OAuth2.0 access token found in session object, this function
|
||||||
|
* will automatically switch as normal remote API call without "oauth_token"
|
||||||
|
* parameter.
|
||||||
|
*
|
||||||
|
* Assume server reply in JSON object and always decode during return. If
|
||||||
|
* you hope to issue a raw query, please use makeRequest().
|
||||||
|
*
|
||||||
|
* @param $path
|
||||||
|
* The target path, relative to base_path/service_uri or an absolute URI.
|
||||||
|
* @param $method
|
||||||
|
* (optional) The HTTP method (default 'GET').
|
||||||
|
* @param $params
|
||||||
|
* (optional The GET/POST parameters.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The JSON decoded response object.
|
||||||
|
*
|
||||||
|
* @throws OAuth2Exception
|
||||||
|
*/
|
||||||
|
public function api($path, $method = 'GET', $params = array()) {
|
||||||
|
if (is_array($method) && empty($params)) {
|
||||||
|
$params = $method;
|
||||||
|
$method = 'GET';
|
||||||
|
}
|
||||||
|
|
||||||
|
// json_encode all params values that are not strings.
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
if (!is_string($value)) {
|
||||||
|
$params[$key] = json_encode($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = json_decode($this->makeOAuth2Request(
|
||||||
|
$this->getUri($path),
|
||||||
|
$method,
|
||||||
|
$params
|
||||||
|
), TRUE);
|
||||||
|
|
||||||
|
// Results are returned, errors are thrown.
|
||||||
|
if (is_array($result) && isset($result['error'])) {
|
||||||
|
$e = new OAuth2Exception($result);
|
||||||
|
switch ($e->getType()) {
|
||||||
|
// OAuth 2.0 Draft 10 style.
|
||||||
|
case 'invalid_token':
|
||||||
|
$this->setSession(NULL);
|
||||||
|
default:
|
||||||
|
$this->setSession(NULL);
|
||||||
|
}
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End stuff that should get overridden.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default options for cURL.
|
||||||
|
*/
|
||||||
|
public static $CURL_OPTS = array(
|
||||||
|
CURLOPT_CONNECTTIMEOUT => 10,
|
||||||
|
CURLOPT_RETURNTRANSFER => TRUE,
|
||||||
|
CURLOPT_HEADER => TRUE,
|
||||||
|
CURLOPT_TIMEOUT => 60,
|
||||||
|
CURLOPT_USERAGENT => 'oauth2-draft-v10',
|
||||||
|
CURLOPT_HTTPHEADER => array("Accept: application/json"),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the Session.
|
||||||
|
*
|
||||||
|
* @param $session
|
||||||
|
* (optional) The session object to be set. NULL if hope to frush existing
|
||||||
|
* session object.
|
||||||
|
* @param $write_cookie
|
||||||
|
* (optional) TRUE if a cookie should be written. This value is ignored
|
||||||
|
* if cookie support has been disabled.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The current OAuth2.0 client-side instance.
|
||||||
|
*/
|
||||||
|
public function setSession($session = NULL, $write_cookie = TRUE) {
|
||||||
|
$this->setVariable('_session', $this->validateSessionObject($session));
|
||||||
|
$this->setVariable('_session_loaded', TRUE);
|
||||||
|
if ($write_cookie) {
|
||||||
|
$this->setCookieFromSession($this->getVariable('_session'));
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the session object.
|
||||||
|
*
|
||||||
|
* This will automatically look for a signed session via custom method,
|
||||||
|
* OAuth2.0 grant type with authorization_code, OAuth2.0 grant type with
|
||||||
|
* password, or cookie that we had already setup.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The valid session object with OAuth2.0 infomration, and NULL if not
|
||||||
|
* able to discover any cases.
|
||||||
|
*/
|
||||||
|
public function getSession() {
|
||||||
|
if (!$this->getVariable('_session_loaded')) {
|
||||||
|
$session = NULL;
|
||||||
|
$write_cookie = TRUE;
|
||||||
|
|
||||||
|
// Try obtain login session by custom method.
|
||||||
|
$session = $this->getSessionObject(NULL);
|
||||||
|
$session = $this->validateSessionObject($session);
|
||||||
|
|
||||||
|
// grant_type == authorization_code.
|
||||||
|
if (!$session && $this->getVariable('code')) {
|
||||||
|
$access_token = $this->getAccessTokenFromAuthorizationCode($this->getVariable('code'));
|
||||||
|
$session = $this->getSessionObject($access_token);
|
||||||
|
$session = $this->validateSessionObject($session);
|
||||||
|
}
|
||||||
|
|
||||||
|
// grant_type == password.
|
||||||
|
if (!$session && $this->getVariable('username') && $this->getVariable('password')) {
|
||||||
|
$access_token = $this->getAccessTokenFromPassword($this->getVariable('username'), $this->getVariable('password'));
|
||||||
|
$session = $this->getSessionObject($access_token);
|
||||||
|
$session = $this->validateSessionObject($session);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try loading session from cookie if necessary.
|
||||||
|
if (!$session && $this->getVariable('cookie_support')) {
|
||||||
|
$cookie_name = $this->getSessionCookieName();
|
||||||
|
if (isset($_COOKIE[$cookie_name])) {
|
||||||
|
$session = array();
|
||||||
|
parse_str(trim(
|
||||||
|
get_magic_quotes_gpc()
|
||||||
|
? stripslashes($_COOKIE[$cookie_name])
|
||||||
|
: $_COOKIE[$cookie_name],
|
||||||
|
'"'
|
||||||
|
), $session);
|
||||||
|
$session = $this->validateSessionObject($session);
|
||||||
|
// Write only if we need to delete a invalid session cookie.
|
||||||
|
$write_cookie = empty($session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setSession($session, $write_cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getVariable('_session');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an OAuth2.0 access token from session.
|
||||||
|
*
|
||||||
|
* This will trigger getSession() and so we MUST initialize with required
|
||||||
|
* configuration.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The valid OAuth2.0 access token, and NULL if not exists in session.
|
||||||
|
*/
|
||||||
|
public function getAccessToken() {
|
||||||
|
$session = $this->getSession();
|
||||||
|
return isset($session['access_token']) ? $session['access_token'] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get access token from OAuth2.0 token endpoint with authorization code.
|
||||||
|
*
|
||||||
|
* This function will only be activated if both access token URI, client
|
||||||
|
* identifier and client secret are setup correctly.
|
||||||
|
*
|
||||||
|
* @param $code
|
||||||
|
* Authorization code issued by authorization server's authorization
|
||||||
|
* endpoint.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A valid OAuth2.0 JSON decoded access token in associative array, and
|
||||||
|
* NULL if not enough parameters or JSON decode failed.
|
||||||
|
*/
|
||||||
|
private function getAccessTokenFromAuthorizationCode($code) {
|
||||||
|
if ($this->getVariable('access_token_uri') && $this->getVariable('client_id') && $this->getVariable('client_secret')) {
|
||||||
|
return json_decode($this->makeRequest(
|
||||||
|
$this->getVariable('access_token_uri'),
|
||||||
|
'POST',
|
||||||
|
array(
|
||||||
|
'grant_type' => 'authorization_code',
|
||||||
|
'client_id' => $this->getVariable('client_id'),
|
||||||
|
'client_secret' => $this->getVariable('client_secret'),
|
||||||
|
'code' => $code,
|
||||||
|
'redirect_uri' => $this->getCurrentUri(),
|
||||||
|
)
|
||||||
|
), TRUE);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get access token from OAuth2.0 token endpoint with basic user
|
||||||
|
* credentials.
|
||||||
|
*
|
||||||
|
* This function will only be activated if both username and password
|
||||||
|
* are setup correctly.
|
||||||
|
*
|
||||||
|
* @param $username
|
||||||
|
* Username to be check with.
|
||||||
|
* @param $password
|
||||||
|
* Password to be check with.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A valid OAuth2.0 JSON decoded access token in associative array, and
|
||||||
|
* NULL if not enough parameters or JSON decode failed.
|
||||||
|
*/
|
||||||
|
private function getAccessTokenFromPassword($username, $password) {
|
||||||
|
if ($this->getVariable('access_token_uri') && $this->getVariable('client_id') && $this->getVariable('client_secret')) {
|
||||||
|
return json_decode($this->makeRequest(
|
||||||
|
$this->getVariable('access_token_uri'),
|
||||||
|
'POST',
|
||||||
|
array(
|
||||||
|
'grant_type' => 'password',
|
||||||
|
'client_id' => $this->getVariable('client_id'),
|
||||||
|
'client_secret' => $this->getVariable('client_secret'),
|
||||||
|
'username' => $username,
|
||||||
|
'password' => $password,
|
||||||
|
)
|
||||||
|
), TRUE);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an OAuth2.0 Request.
|
||||||
|
*
|
||||||
|
* Automatically append "oauth_token" in query parameters if not yet
|
||||||
|
* exists and able to discover a valid access token from session. Otherwise
|
||||||
|
* just ignore setup with "oauth_token" and handle the API call AS-IS, and
|
||||||
|
* so may issue a plain API call without OAuth2.0 protection.
|
||||||
|
*
|
||||||
|
* @param $path
|
||||||
|
* The target path, relative to base_path/service_uri or an absolute URI.
|
||||||
|
* @param $method
|
||||||
|
* (optional) The HTTP method (default 'GET').
|
||||||
|
* @param $params
|
||||||
|
* (optional The GET/POST parameters.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The JSON decoded response object.
|
||||||
|
*
|
||||||
|
* @throws OAuth2Exception
|
||||||
|
*/
|
||||||
|
protected function makeOAuth2Request($path, $method = 'GET', $params = array()) {
|
||||||
|
if ((!isset($params['oauth_token']) || empty($params['oauth_token'])) && $oauth_token = $this->getAccessToken()) {
|
||||||
|
$params['oauth_token'] = $oauth_token;
|
||||||
|
}
|
||||||
|
return $this->makeRequest($path, $method, $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an HTTP request.
|
||||||
|
*
|
||||||
|
* This method can be overriden by subclasses if developers want to do
|
||||||
|
* fancier things or use something other than cURL to make the request.
|
||||||
|
*
|
||||||
|
* @param $path
|
||||||
|
* The target path, relative to base_path/service_uri or an absolute URI.
|
||||||
|
* @param $method
|
||||||
|
* (optional) The HTTP method (default 'GET').
|
||||||
|
* @param $params
|
||||||
|
* (optional The GET/POST parameters.
|
||||||
|
* @param $ch
|
||||||
|
* (optional) An initialized curl handle
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The JSON decoded response object.
|
||||||
|
*/
|
||||||
|
protected function makeRequest($path, $method = 'GET', $params = array(), $ch = NULL) {
|
||||||
|
if (!$ch)
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
$opts = self::$CURL_OPTS;
|
||||||
|
if ($params) {
|
||||||
|
switch ($method) {
|
||||||
|
case 'GET':
|
||||||
|
$path .= '?' . http_build_query($params, NULL, '&');
|
||||||
|
break;
|
||||||
|
// Method override as we always do a POST.
|
||||||
|
default:
|
||||||
|
if ($this->getVariable('file_upload_support')) {
|
||||||
|
$opts[CURLOPT_POSTFIELDS] = $params;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$opts[CURLOPT_POSTFIELDS] = http_build_query($params, NULL, '&');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$opts[CURLOPT_URL] = $path;
|
||||||
|
|
||||||
|
// Disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
|
||||||
|
// for 2 seconds if the server does not support this header.
|
||||||
|
if (isset($opts[CURLOPT_HTTPHEADER])) {
|
||||||
|
$existing_headers = $opts[CURLOPT_HTTPHEADER];
|
||||||
|
$existing_headers[] = 'Expect:';
|
||||||
|
$opts[CURLOPT_HTTPHEADER] = $existing_headers;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$opts[CURLOPT_HTTPHEADER] = array('Expect:');
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt_array($ch, $opts);
|
||||||
|
$result = curl_exec($ch);
|
||||||
|
|
||||||
|
if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT
|
||||||
|
error_log('Invalid or no certificate authority found, using bundled information');
|
||||||
|
curl_setopt($ch, CURLOPT_CAINFO,
|
||||||
|
dirname(__FILE__) . '/fb_ca_chain_bundle.crt');
|
||||||
|
$result = curl_exec($ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result === FALSE) {
|
||||||
|
$e = new OAuth2Exception(array(
|
||||||
|
'code' => curl_errno($ch),
|
||||||
|
'message' => curl_error($ch),
|
||||||
|
));
|
||||||
|
curl_close($ch);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
// Split the HTTP response into header and body.
|
||||||
|
list($headers, $body) = explode("\r\n\r\n", $result);
|
||||||
|
$headers = explode("\r\n", $headers);
|
||||||
|
|
||||||
|
// We catch HTTP/1.1 4xx or HTTP/1.1 5xx error response.
|
||||||
|
if (strpos($headers[0], 'HTTP/1.1 4') !== FALSE || strpos($headers[0], 'HTTP/1.1 5') !== FALSE) {
|
||||||
|
$result = array(
|
||||||
|
'code' => 0,
|
||||||
|
'message' => '',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (preg_match('/^HTTP\/1.1 ([0-9]{3,3}) (.*)$/', $headers[0], $matches)) {
|
||||||
|
$result['code'] = $matches[1];
|
||||||
|
$result['message'] = $matches[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case retrun with WWW-Authenticate replace the description.
|
||||||
|
foreach ($headers as $header) {
|
||||||
|
if (preg_match("/^WWW-Authenticate:.*error='(.*)'/", $header, $matches)) {
|
||||||
|
$result['error'] = $matches[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_encode($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the cookie that contains the session object.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The cookie name.
|
||||||
|
*/
|
||||||
|
private function getSessionCookieName() {
|
||||||
|
return 'oauth2_' . $this->getVariable('client_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a JS Cookie based on the _passed in_ session.
|
||||||
|
*
|
||||||
|
* It does not use the currently stored session - you need to explicitly
|
||||||
|
* pass it in.
|
||||||
|
*
|
||||||
|
* @param $session
|
||||||
|
* The session to use for setting the cookie.
|
||||||
|
*/
|
||||||
|
protected function setCookieFromSession($session = NULL) {
|
||||||
|
if (!$this->getVariable('cookie_support'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
$cookie_name = $this->getSessionCookieName();
|
||||||
|
$value = 'deleted';
|
||||||
|
$expires = time() - 3600;
|
||||||
|
$base_domain = $this->getVariable('base_domain', OAUTH2_DEFAULT_BASE_DOMAIN);
|
||||||
|
if ($session) {
|
||||||
|
$value = '"' . http_build_query($session, NULL, '&') . '"';
|
||||||
|
$base_domain = isset($session['base_domain']) ? $session['base_domain'] : $base_domain;
|
||||||
|
$expires = isset($session['expires']) ? $session['expires'] : time() + $this->getVariable('expires_in', OAUTH2_DEFAULT_EXPIRES_IN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend dot if a domain is found.
|
||||||
|
if ($base_domain)
|
||||||
|
$base_domain = '.' . $base_domain;
|
||||||
|
|
||||||
|
// If an existing cookie is not set, we dont need to delete it.
|
||||||
|
if ($value == 'deleted' && empty($_COOKIE[$cookie_name]))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (headers_sent())
|
||||||
|
error_log('Could not set cookie. Headers already sent.');
|
||||||
|
else
|
||||||
|
setcookie($cookie_name, $value, $expires, '/', $base_domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a session_version = 3 style session object.
|
||||||
|
*
|
||||||
|
* @param $session
|
||||||
|
* The session object.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The session object if it validates, NULL otherwise.
|
||||||
|
*/
|
||||||
|
protected function validateSessionObject($session) {
|
||||||
|
// Make sure some essential fields exist.
|
||||||
|
if (is_array($session) && isset($session['access_token']) && isset($session['sig'])) {
|
||||||
|
// Validate the signature.
|
||||||
|
$session_without_sig = $session;
|
||||||
|
unset($session_without_sig['sig']);
|
||||||
|
|
||||||
|
$expected_sig = self::generateSignature(
|
||||||
|
$session_without_sig,
|
||||||
|
$this->getVariable('client_secret')
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($session['sig'] != $expected_sig) {
|
||||||
|
error_log('Got invalid session signature in cookie.');
|
||||||
|
$session = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$session = NULL;
|
||||||
|
}
|
||||||
|
return $session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since $_SERVER['REQUEST_URI'] is only available on Apache, we
|
||||||
|
* generate an equivalent using other environment variables.
|
||||||
|
*/
|
||||||
|
function getRequestUri() {
|
||||||
|
if (isset($_SERVER['REQUEST_URI'])) {
|
||||||
|
$uri = $_SERVER['REQUEST_URI'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (isset($_SERVER['argv'])) {
|
||||||
|
$uri = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['argv'][0];
|
||||||
|
}
|
||||||
|
elseif (isset($_SERVER['QUERY_STRING'])) {
|
||||||
|
$uri = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$uri = $_SERVER['SCRIPT_NAME'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Prevent multiple slashes to avoid cross site requests via the Form API.
|
||||||
|
$uri = '/' . ltrim($uri, '/');
|
||||||
|
|
||||||
|
return $uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Current URL.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The current URL.
|
||||||
|
*/
|
||||||
|
protected function getCurrentUri() {
|
||||||
|
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
|
||||||
|
? 'https://'
|
||||||
|
: 'http://';
|
||||||
|
$current_uri = $protocol . $_SERVER['HTTP_HOST'] . $this->getRequestUri();
|
||||||
|
$parts = parse_url($current_uri);
|
||||||
|
|
||||||
|
$query = '';
|
||||||
|
if (!empty($parts['query'])) {
|
||||||
|
$params = array();
|
||||||
|
parse_str($parts['query'], $params);
|
||||||
|
$params = array_filter($params);
|
||||||
|
if (!empty($params)) {
|
||||||
|
$query = '?' . http_build_query($params, NULL, '&');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use port if non default.
|
||||||
|
$port = isset($parts['port']) &&
|
||||||
|
(($protocol === 'http://' && $parts['port'] !== 80) || ($protocol === 'https://' && $parts['port'] !== 443))
|
||||||
|
? ':' . $parts['port'] : '';
|
||||||
|
|
||||||
|
// Rebuild.
|
||||||
|
return $protocol . $parts['host'] . $port . $parts['path'] . $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the URL for given path and parameters.
|
||||||
|
*
|
||||||
|
* @param $path
|
||||||
|
* (optional) The path.
|
||||||
|
* @param $params
|
||||||
|
* (optional) The query parameters in associative array.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The URL for the given parameters.
|
||||||
|
*/
|
||||||
|
protected function getUri($path = '', $params = array()) {
|
||||||
|
$url = $this->getVariable('services_uri') ? $this->getVariable('services_uri') : $this->getVariable('base_uri');
|
||||||
|
|
||||||
|
if (!empty($path))
|
||||||
|
if (substr($path, 0, 4) == "http")
|
||||||
|
$url = $path;
|
||||||
|
else
|
||||||
|
$url = rtrim($url, '/') . '/' . ltrim($path, '/');
|
||||||
|
|
||||||
|
if (!empty($params))
|
||||||
|
$url .= '?' . http_build_query($params, NULL, '&');
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a signature for the given params and secret.
|
||||||
|
*
|
||||||
|
* @param $params
|
||||||
|
* The parameters to sign.
|
||||||
|
* @param $secret
|
||||||
|
* The secret to sign with.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The generated signature
|
||||||
|
*/
|
||||||
|
protected function generateSignature($params, $secret) {
|
||||||
|
// Work with sorted data.
|
||||||
|
ksort($params);
|
||||||
|
|
||||||
|
// Generate the base string.
|
||||||
|
$base_string = '';
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
$base_string .= $key . '=' . $value;
|
||||||
|
}
|
||||||
|
$base_string .= $secret;
|
||||||
|
|
||||||
|
return md5($base_string);
|
||||||
|
}
|
||||||
|
}
|
85
library/oauth2-php/lib/OAuth2Exception.inc
Normal file
85
library/oauth2-php/lib/OAuth2Exception.inc
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth2.0 draft v10 exception handling.
|
||||||
|
*
|
||||||
|
* @author Originally written by Naitik Shah <naitik@facebook.com>.
|
||||||
|
* @author Update to draft v10 by Edison Wong <hswong3i@pantarei-design.com>.
|
||||||
|
*
|
||||||
|
* @sa <a href="https://github.com/facebook/php-sdk">Facebook PHP SDK</a>.
|
||||||
|
*/
|
||||||
|
class OAuth2Exception extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result from the API server that represents the exception information.
|
||||||
|
*/
|
||||||
|
protected $result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a new API Exception with the given result.
|
||||||
|
*
|
||||||
|
* @param $result
|
||||||
|
* The result from the API server.
|
||||||
|
*/
|
||||||
|
public function __construct($result) {
|
||||||
|
$this->result = $result;
|
||||||
|
|
||||||
|
$code = isset($result['code']) ? $result['code'] : 0;
|
||||||
|
|
||||||
|
if (isset($result['error'])) {
|
||||||
|
// OAuth 2.0 Draft 10 style
|
||||||
|
$message = $result['error'];
|
||||||
|
}
|
||||||
|
elseif (isset($result['message'])) {
|
||||||
|
// cURL style
|
||||||
|
$message = $result['message'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$message = 'Unknown Error. Check getResult()';
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::__construct($message, $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the associated result object returned by the API server.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The result from the API server.
|
||||||
|
*/
|
||||||
|
public function getResult() {
|
||||||
|
return $this->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the associated type for the error. This will default to
|
||||||
|
* 'Exception' when a type is not available.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The type for the error.
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
if (isset($this->result['error'])) {
|
||||||
|
$message = $this->result['error'];
|
||||||
|
if (is_string($message)) {
|
||||||
|
// OAuth 2.0 Draft 10 style
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'Exception';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To make debugging easier.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The string representation of the error.
|
||||||
|
*/
|
||||||
|
public function __toString() {
|
||||||
|
$str = $this->getType() . ': ';
|
||||||
|
if ($this->code != 0) {
|
||||||
|
$str .= $this->code . ': ';
|
||||||
|
}
|
||||||
|
return $str . $this->message;
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
108
mod/api.php
108
mod/api.php
|
@ -2,7 +2,115 @@
|
||||||
|
|
||||||
require_once('include/api.php');
|
require_once('include/api.php');
|
||||||
|
|
||||||
|
function oauth_get_client($request){
|
||||||
|
|
||||||
|
|
||||||
|
$params = $request->get_parameters();
|
||||||
|
$token = $params['oauth_token'];
|
||||||
|
|
||||||
|
$r = q("SELECT `clients`.*
|
||||||
|
FROM `clients`, `tokens`
|
||||||
|
WHERE `clients`.`client_id`=`tokens`.`client_id`
|
||||||
|
AND `tokens`.`id`='%s' AND `tokens`.`scope`='request'",
|
||||||
|
dbesc($token));
|
||||||
|
|
||||||
|
if (!count($r))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $r[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function api_post(&$a) {
|
||||||
|
|
||||||
|
if(! local_user()) {
|
||||||
|
notice( t('Permission denied.') . EOL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count($a->user) && x($a->user,'uid') && $a->user['uid'] != local_user()) {
|
||||||
|
notice( t('Permission denied.') . EOL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function api_content(&$a) {
|
function api_content(&$a) {
|
||||||
|
if ($a->cmd=='api/oauth/authorize'){
|
||||||
|
/*
|
||||||
|
* api/oauth/authorize interact with the user. return a standard page
|
||||||
|
*/
|
||||||
|
|
||||||
|
$a->page['template'] = "minimal";
|
||||||
|
|
||||||
|
|
||||||
|
// get consumer/client from request token
|
||||||
|
try {
|
||||||
|
$request = OAuthRequest::from_request();
|
||||||
|
} catch(Exception $e) {
|
||||||
|
echo "<pre>"; var_dump($e); killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (x($_POST,'oauth_yes')){
|
||||||
|
|
||||||
|
$app = oauth_get_client($request);
|
||||||
|
if (is_null($app)) return "Invalid request. Unknown token.";
|
||||||
|
$consumer = new OAuthConsumer($app['client_id'], $app['pw'], $app['redirect_uri']);
|
||||||
|
|
||||||
|
$verifier = md5($app['secret'].local_user());
|
||||||
|
set_config("oauth", $verifier, local_user());
|
||||||
|
|
||||||
|
|
||||||
|
if ($consumer->callback_url!=null) {
|
||||||
|
$params = $request->get_parameters();
|
||||||
|
$glue="?";
|
||||||
|
if (strstr($consumer->callback_url,$glue)) $glue="?";
|
||||||
|
goaway($consumer->callback_url.$glue."oauth_token=".OAuthUtil::urlencode_rfc3986($params['oauth_token'])."&oauth_verifier=".OAuthUtil::urlencode_rfc3986($verifier));
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$tpl = get_markup_template("oauth_authorize_done.tpl");
|
||||||
|
$o = replace_macros($tpl, array(
|
||||||
|
'$title' => t('Authorize application connection'),
|
||||||
|
'$info' => t('Return to your app and insert this Securty Code:'),
|
||||||
|
'$code' => $verifier,
|
||||||
|
));
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(! local_user()) {
|
||||||
|
//TODO: we need login form to redirect to this page
|
||||||
|
notice( t('Please login to continue.') . EOL );
|
||||||
|
return login(false,$request->get_parameters());
|
||||||
|
}
|
||||||
|
//FKOAuth1::loginUser(4);
|
||||||
|
|
||||||
|
$app = oauth_get_client($request);
|
||||||
|
if (is_null($app)) return "Invalid request. Unknown token.";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$tpl = get_markup_template('oauth_authorize.tpl');
|
||||||
|
$o = replace_macros($tpl, array(
|
||||||
|
'$title' => t('Authorize application connection'),
|
||||||
|
'$app' => $app,
|
||||||
|
'$authorize' => t('Do you want to authorize this application to access your posts and contacts, and/or create new posts for you?'),
|
||||||
|
'$yes' => t('Yes'),
|
||||||
|
'$no' => t('No'),
|
||||||
|
));
|
||||||
|
|
||||||
|
//echo "<pre>"; var_dump($app); killme();
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
echo api_call($a);
|
echo api_call($a);
|
||||||
killme();
|
killme();
|
||||||
}
|
}
|
||||||
|
|
20
mod/notice.php
Normal file
20
mod/notice.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
/* identi.ca -> friendika items permanent-url compatibility */
|
||||||
|
|
||||||
|
function notice_init(&$a){
|
||||||
|
$id = $a->argv[1];
|
||||||
|
$r = q("SELECT user.nickname FROM user LEFT JOIN item ON item.uid=user.uid WHERE item.id=%d",
|
||||||
|
intval($id)
|
||||||
|
);
|
||||||
|
if (count($r)){
|
||||||
|
$nick = $r[0]['nickname'];
|
||||||
|
$url = $a->get_baseurl()."/display/$nick/$id";
|
||||||
|
goaway($url);
|
||||||
|
} else {
|
||||||
|
$a->error = 404;
|
||||||
|
notice( t('Item not found.') . EOL);
|
||||||
|
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
132
mod/settings.php
132
mod/settings.php
|
@ -47,6 +47,58 @@ function settings_post(&$a) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(($a->argc > 1) && ($a->argv[1] === 'oauth') && x($_POST,'remove')){
|
||||||
|
$key = $_POST['remove'];
|
||||||
|
q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
|
||||||
|
dbesc($key),
|
||||||
|
local_user());
|
||||||
|
goaway($a->get_baseurl()."/settings/oauth/");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(($a->argc > 2) && ($a->argv[1] === 'oauth') && ($a->argv[2] === 'edit'||($a->argv[2] === 'add')) && x($_POST,'submit')) {
|
||||||
|
|
||||||
|
$name = ((x($_POST,'name')) ? $_POST['name'] : '');
|
||||||
|
$key = ((x($_POST,'key')) ? $_POST['key'] : '');
|
||||||
|
$secret = ((x($_POST,'secret')) ? $_POST['secret'] : '');
|
||||||
|
$redirect = ((x($_POST,'redirect')) ? $_POST['redirect'] : '');
|
||||||
|
$icon = ((x($_POST,'icon')) ? $_POST['icon'] : '');
|
||||||
|
if ($name=="" || $key=="" || $secret==""){
|
||||||
|
notice(t("Missing some important data!"));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if ($_POST['submit']==t("Update")){
|
||||||
|
$r = q("UPDATE clients SET
|
||||||
|
client_id='%s',
|
||||||
|
pw='%s',
|
||||||
|
name='%s',
|
||||||
|
redirect_uri='%s',
|
||||||
|
icon='%s',
|
||||||
|
uid=%d
|
||||||
|
WHERE client_id='%s'",
|
||||||
|
dbesc($key),
|
||||||
|
dbesc($secret),
|
||||||
|
dbesc($name),
|
||||||
|
dbesc($redirect),
|
||||||
|
dbesc($icon),
|
||||||
|
local_user(),
|
||||||
|
dbesc($key));
|
||||||
|
} else {
|
||||||
|
$r = q("INSERT INTO clients
|
||||||
|
(client_id, pw, name, redirect_uri, icon, uid)
|
||||||
|
VALUES ('%s','%s','%s','%s','%s',%d)",
|
||||||
|
dbesc($key),
|
||||||
|
dbesc($secret),
|
||||||
|
dbesc($name),
|
||||||
|
dbesc($redirect),
|
||||||
|
dbesc($icon),
|
||||||
|
local_user());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goaway($a->get_baseurl()."/settings/oauth/");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(($a->argc > 1) && ($a->argv[1] == 'addon')) {
|
if(($a->argc > 1) && ($a->argv[1] == 'addon')) {
|
||||||
call_hooks('plugin_settings_post', $_POST);
|
call_hooks('plugin_settings_post', $_POST);
|
||||||
return;
|
return;
|
||||||
|
@ -341,6 +393,11 @@ function settings_content(&$a) {
|
||||||
'url' => $a->get_baseurl().'/settings/addon',
|
'url' => $a->get_baseurl().'/settings/addon',
|
||||||
'sel' => (($a->argc > 1) && ($a->argv[1] === 'addon')?'active':''),
|
'sel' => (($a->argc > 1) && ($a->argv[1] === 'addon')?'active':''),
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'label' => t('Connections'),
|
||||||
|
'url' => $a->get_baseurl() . '/settings/oauth',
|
||||||
|
'sel' => (($a->argc > 1) && ($a->argv[1] === 'oauth')?'active':''),
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
'label' => t('Export personal data'),
|
'label' => t('Export personal data'),
|
||||||
'url' => $a->get_baseurl() . '/uexport',
|
'url' => $a->get_baseurl() . '/uexport',
|
||||||
|
@ -353,8 +410,83 @@ function settings_content(&$a) {
|
||||||
'$tabs' => $tabs,
|
'$tabs' => $tabs,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if(($a->argc > 1) && ($a->argv[1] === 'oauth')) {
|
||||||
|
|
||||||
|
if(($a->argc > 2) && ($a->argv[2] === 'add')) {
|
||||||
|
$tpl = get_markup_template("settings_oauth_edit.tpl");
|
||||||
|
$o .= replace_macros($tpl, array(
|
||||||
|
'$tabs' => $tabs,
|
||||||
|
'$title' => t('Add application'),
|
||||||
|
'$submit' => t('Submit'),
|
||||||
|
'$cancel' => t('Cancel'),
|
||||||
|
'$name' => array('name', t('Name'), '', ''),
|
||||||
|
'$key' => array('key', t('Consumer Key'), '', ''),
|
||||||
|
'$secret' => array('secret', t('Consumer Secret'), '', ''),
|
||||||
|
'$redirect' => array('redirect', t('Redirect'), '', ''),
|
||||||
|
'$icon' => array('icon', t('Icon url'), '', ''),
|
||||||
|
));
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(($a->argc > 3) && ($a->argv[2] === 'edit')) {
|
||||||
|
$r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d",
|
||||||
|
dbesc($a->argv[3]),
|
||||||
|
local_user());
|
||||||
|
|
||||||
|
if (!count($r)){
|
||||||
|
notice(t("You can't edit this application."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$app = $r[0];
|
||||||
|
|
||||||
|
$tpl = get_markup_template("settings_oauth_edit.tpl");
|
||||||
|
$o .= replace_macros($tpl, array(
|
||||||
|
'$tabs' => $tabs,
|
||||||
|
'$title' => t('Add application'),
|
||||||
|
'$submit' => t('Update'),
|
||||||
|
'$cancel' => t('Cancel'),
|
||||||
|
'$name' => array('name', t('Name'), $app['name'] , ''),
|
||||||
|
'$key' => array('key', t('Consumer Key'), $app['client_id'], ''),
|
||||||
|
'$secret' => array('secret', t('Consumer Secret'), $app['pw'], ''),
|
||||||
|
'$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], ''),
|
||||||
|
'$icon' => array('icon', t('Icon url'), $app['icon'], ''),
|
||||||
|
));
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(($a->argc > 3) && ($a->argv[2] === 'delete')) {
|
||||||
|
$r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d",
|
||||||
|
dbesc($a->argv[3]),
|
||||||
|
local_user());
|
||||||
|
goaway($a->get_baseurl()."/settings/oauth/");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my
|
||||||
|
FROM clients
|
||||||
|
LEFT JOIN tokens ON clients.client_id=tokens.client_id
|
||||||
|
WHERE clients.uid IN (%d,0)",
|
||||||
|
local_user(),
|
||||||
|
local_user());
|
||||||
|
|
||||||
|
|
||||||
|
$tpl = get_markup_template("settings_oauth.tpl");
|
||||||
|
$o .= replace_macros($tpl, array(
|
||||||
|
'$baseurl' => $a->get_baseurl(),
|
||||||
|
'$title' => t('Connected Apps'),
|
||||||
|
'$add' => t('Add application'),
|
||||||
|
'$edit' => t('Edit'),
|
||||||
|
'$delete' => t('Delete'),
|
||||||
|
'$consumerkey' => t('Client key starts with'),
|
||||||
|
'$noname' => t('No name'),
|
||||||
|
'$remove' => t('Remove authorization'),
|
||||||
|
'$tabs' => $tabs,
|
||||||
|
'$apps' => $r,
|
||||||
|
));
|
||||||
|
return $o;
|
||||||
|
|
||||||
|
}
|
||||||
if(($a->argc > 1) && ($a->argv[1] === 'addon')) {
|
if(($a->argc > 1) && ($a->argv[1] === 'addon')) {
|
||||||
$settings_addons = "";
|
$settings_addons = "";
|
||||||
|
|
||||||
|
|
11
update.php
11
update.php
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
define( 'UPDATE_VERSION' , 1102 );
|
define( 'UPDATE_VERSION' , 1103 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -874,7 +874,14 @@ function update_1101() {
|
||||||
q("ALTER TABLE `gcign` ADD INDEX (`uid`), ADD INDEX (`gcid`) ");
|
q("ALTER TABLE `gcign` ADD INDEX (`uid`), ADD INDEX (`gcid`) ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function update_1102() {
|
||||||
|
q("ALTER TABLE `clients` ADD `name` TEXT NULL DEFAULT NULL AFTER `redirect_uri` ");
|
||||||
|
q("ALTER TABLE `clients` ADD `icon` TEXT NULL DEFAULT NULL AFTER `name` ");
|
||||||
|
q("ALTER TABLE `clients` ADD `uid` INT NOT NULL DEFAULT 0 AFTER `icon` ");
|
||||||
|
|
||||||
|
q("ALTER TABLE `tokens` ADD `secret` TEXT NOT NULL AFTER `id` ");
|
||||||
|
q("ALTER TABLE `tokens` ADD `uid` INT NOT NULL AFTER `scope` ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
<input type="submit" name="submit" id="login-submit-button" value="$login" />
|
<input type="submit" name="submit" id="login-submit-button" value="$login" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{ for $hiddens as $k=>$v }}
|
||||||
|
<input type="hidden" name="$k" value="$v" />
|
||||||
|
{{ endfor }}
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
|
14
view/minimal.php
Normal file
14
view/minimal.php
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html >
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title><?php if(x($page,'title')) echo $page['title'] ?></title>
|
||||||
|
<script>var baseurl="<?php echo $a->get_baseurl() ?>";</script>
|
||||||
|
<?php if(x($page,'htmlhead')) echo $page['htmlhead'] ?>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<section style="margin:0px!important; padding:0px!important; float:none!important;display:block!important;"><?php if(x($page,'content')) echo $page['content']; ?>
|
||||||
|
<div id="page-footer"></div>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
10
view/oauth_authorize.tpl
Normal file
10
view/oauth_authorize.tpl
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<h1>$title</h1>
|
||||||
|
|
||||||
|
<div class='oauthapp'>
|
||||||
|
<img src='$app.icon'>
|
||||||
|
<h4>$app.name</h4>
|
||||||
|
</div>
|
||||||
|
<h3>$authorize</h3>
|
||||||
|
<form method="POST">
|
||||||
|
<div class="settings-submit-wrapper"><input class="settings-submit" type="submit" name="oauth_yes" value="$yes" /></div>
|
||||||
|
</form>
|
4
view/oauth_authorize_done.tpl
Normal file
4
view/oauth_authorize_done.tpl
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<h1>$title</h1>
|
||||||
|
|
||||||
|
<p>$info</p>
|
||||||
|
<code>$code</code>
|
32
view/settings_oauth.tpl
Normal file
32
view/settings_oauth.tpl
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
$tabs
|
||||||
|
|
||||||
|
<h1>$title</h1>
|
||||||
|
|
||||||
|
|
||||||
|
<form action="settings/oauth" method="post" autocomplete="off">
|
||||||
|
|
||||||
|
<div id="profile-edit-links">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a id="profile-edit-view-link" href="$baseurl/settings/oauth/add">$add</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ for $apps as $app }}
|
||||||
|
<div class='oauthapp'>
|
||||||
|
<img src='$app.icon' class="{{ if $app.icon }} {{ else }}noicon{{ endif }}">
|
||||||
|
{{ if $app.name }}<h4>$app.name</h4>{{ else }}<h4>$noname</h4>{{ endif }}
|
||||||
|
{{ if $app.my }}
|
||||||
|
{{ if $app.oauth_token }}
|
||||||
|
<div class="settings-submit-wrapper" ><button class="settings-submit" type="submit" name="remove" value="$app.oauth_token">$remove</button></div>
|
||||||
|
{{ endif }}
|
||||||
|
{{ endif }}
|
||||||
|
{{ if $app.my }}
|
||||||
|
<a href="$baseurl/settings/oauth/edit/$app.client_id" class="icon edit" title="$edit"> </a>
|
||||||
|
<a href="$baseurl/settings/oauth/delete/$app.client_id" class="icon drop" title="$delete"> </a>
|
||||||
|
{{ endif }}
|
||||||
|
</div>
|
||||||
|
{{ endfor }}
|
||||||
|
|
||||||
|
</form>
|
17
view/settings_oauth_edit.tpl
Normal file
17
view/settings_oauth_edit.tpl
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
$tabs
|
||||||
|
|
||||||
|
<h1>$title</h1>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
{{ inc field_input.tpl with $field=$name }}{{ endinc }}
|
||||||
|
{{ inc field_input.tpl with $field=$key }}{{ endinc }}
|
||||||
|
{{ inc field_input.tpl with $field=$secret }}{{ endinc }}
|
||||||
|
{{ inc field_input.tpl with $field=$redirect }}{{ endinc }}
|
||||||
|
{{ inc field_input.tpl with $field=$icon }}{{ endinc }}
|
||||||
|
|
||||||
|
<div class="settings-submit-wrapper" >
|
||||||
|
<input type="submit" name="submit" class="settings-submit" value="$submit" />
|
||||||
|
<input type="submit" name="cancel" class="settings-submit" value="$cancel" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
|
@ -2779,6 +2779,28 @@ a.mail-list-link {
|
||||||
.panel_text .progress { width: 50%; overflow: hidden; height: auto; border: 1px solid #cccccc; margin-bottom: 5px}
|
.panel_text .progress { width: 50%; overflow: hidden; height: auto; border: 1px solid #cccccc; margin-bottom: 5px}
|
||||||
.panel_text .progress span {float: right; display: block; width: 25%; background-color: #eeeeee; text-align: right;}
|
.panel_text .progress span {float: right; display: block; width: 25%; background-color: #eeeeee; text-align: right;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth
|
||||||
|
*/
|
||||||
|
.oauthapp {
|
||||||
|
height: auto; overflow: auto;
|
||||||
|
border-bottom: 2px solid #cccccc;
|
||||||
|
padding-bottom: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.oauthapp img {
|
||||||
|
float: left;
|
||||||
|
width: 48px; height: 48px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
.oauthapp img.noicon {
|
||||||
|
background-image: url("../../../images/icons/48/plugin.png");
|
||||||
|
background-position: center center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
.oauthapp a {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ICONS
|
* ICONS
|
||||||
|
|
Loading…
Reference in a new issue