<?php
namespace OCA\Grauphel\AppInfo;
use \OCP\AppFramework\App;
+use \OCA\Grauphel\Lib\Dependencies;
class Application extends App
{
$container = $this->getContainer();
+ $container->registerService(
+ 'Session',
+ function($c) {
+ return $c->query('ServerContainer')->getUserSession();
+ }
+ );
+
/**
* Controllers
*/
$container->registerService(
- 'ApiController',
+ 'ApiController',
function($c) {
+ Dependencies::get()->urlGen
+ = $c->query('ServerContainer')->getURLGenerator();
return new \OCA\Grauphel\Controller\ApiController(
$c->query('AppName'),
$c->query('Request')
}
);
$container->registerService(
- 'AccessController',
+ 'AccessController',
function($c) {
+ Dependencies::get()->urlGen
+ = $c->query('ServerContainer')->getURLGenerator();
return new \OCA\Grauphel\Controller\AccessController(
$c->query('AppName'),
$c->query('Request')
}
);
$container->registerService(
- 'OAuthController',
+ 'OauthController',
function($c) {
- return new \OCA\Grauphel\Controller\OAuthController(
+ Dependencies::get()->urlGen
+ = $c->query('ServerContainer')->getURLGenerator();
+ return new \OCA\Grauphel\Controller\OauthController(
$c->query('AppName'),
- $c->query('Request')
+ $c->query('Request'),
+ $c->query('Session')->getUser()
);
}
);
'name' => 'access#test',
),
- array(
- 'url' => '/authorize',
- 'name' => 'access#authorize',
- 'verb' => 'GET',
- ),/*
array(
'url' => '/authorize',
'name' => 'access#authorize',
'verb' => 'POST',
- ),*/
+ ),
array(
'url' => '/login',
'name' => 'access#login',
'name' => 'oauth#authorize',
'verb' => 'GET',
),
+ array(
+ 'url' => '/oauth/confirm',
+ 'name' => 'oauth#confirm',
+ 'verb' => 'POST',
+ ),
array(
'url' => '/oauth/request_token',
'name' => 'oauth#requestToken',
+++ /dev/null
-<?php
-/**
- * Part of grauphel
- *
- * PHP version 5
- *
- * @category Tools
- * @package Grauphel
- * @author Christian Weiske <cweiske@cweiske.de>
- * @copyright 2014 Christian Weiske
- * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
- * @link http://cweiske.de/grauphel.htm
- */
-namespace OCA\Grauphel\Controller;
-use \OCP\AppFramework\Controller;
-
-/**
- * Login and authorization handling
- *
- * @category Tools
- * @package Grauphel
- * @author Christian Weiske <cweiske@cweiske.de>
- * @copyright 2014 Christian Weiske
- * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
- * @version Release: @package_version@
- * @link http://cweiske.de/grauphel.htm
- */
-class AccessController extends Controller
-{
- public function login($returnUrl = null)
- {
- $returnUrl = $this->loadReturnUrl($returnUrl);
-
- if (isset($_POST['user']) && trim($_POST['user']) != '') {
- $this->deps->frontend->setUser(trim($_POST['user']));
- header('Location: ' . $returnUrl);
- exit(0);
- }
-
- $hFormUrl = htmlspecialchars(
- $this->deps->urlGen->addParams(
- $this->deps->urlGen->accessLogin(),
- array('returnurl' => $returnUrl)
- )
- );
- //FIXME: do some real login
- header('HTTP/1.0 200 OK');
-
- echo <<<HTM
-<html>
- <head>
- <title>grauphel login</title>
- </head>
- <body>
- <form method="post" action="$hFormUrl">
- <p>
- Log into <em>grauphel</em>:
- </p>
- <label>
- User name:
- <input id="user" type="text" name="user" size="20" value=""/>
- </label>
- <input type="submit" value="Login" />
- </form>
- <script type="text/javascript">
-//FIXME
-/*
-document.getElementById('user').value = 'cweiske';
-document.forms[0].submit();
-/**/
- </script>
- </body>
-</html>
-HTM;
- exit(0);
- }
-
- public function authorize($returnUrl = null)
- {
- var_dump('asd');die();
- $returnUrl = $this->loadReturnUrl($returnUrl);
-
- if (isset($_POST['auth'])) {
- if ($_POST['auth'] == 'ok') {
- $this->deps->frontend->setAuth(true);
- } else if ($_POST['auth'] == 'cancel') {
- $this->deps->frontend->setAuth(false);
- }
- header('Location: ' . $returnUrl);
- exit(0);
- }
-
- header('HTTP/1.0 200 OK');
- $hFormUrl = htmlspecialchars(
- $this->deps->urlGen->addParams(
- $this->deps->urlGen->accessAuthorize(),
- array('returnurl' => $returnUrl)
- )
- );
-
- echo <<<HTM
-<html>
- <head>
- <title>grauphel authorization</title>
- </head>
- <body>
- <form method="post" action="$hFormUrl">
- <p>
- Shall application FIXME get full access to the notes?
- </p>
- <button type="submit" name="auth" value="ok">Yes, authorize</button>
- <button type="submit" name="auth" value="cancel">No, decline</button>
- </body>
-</html>
-HTM;
- exit(0);
- }
-
- protected function loadReturnUrl($returnUrl = null)
- {
- if ($returnUrl === null) {
- if (isset($_GET['returnurl'])) {
- $returnUrl = $_GET['returnurl'];
- } else {
- $returnUrl = $this->deps->urlGen->index();
- }
- }
- return $returnUrl;
- }
-
- /**
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- */
- public function test()
- {
- var_dump('asd');die();
- $this->registerResponder('xml', function($value) {
- return new XMLResponse($value);
- });
- return array('foo' => 'bar');
- }
-}
-?>
* @link http://cweiske.de/grauphel.htm
*/
namespace OCA\Grauphel\Controller;
+
use \OCP\AppFramework\Controller;
+use \OCP\AppFramework\Http\JSONResponse;
+
+use \OCA\Grauphel\Lib\OAuth;
+use \OCA\Grauphel\Lib\Dependencies;
/**
* Tomboy's REST API
{
/**
* /api/1.0
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
*/
public function index()
{
- var_dump('asd');die();
+ $deps = Dependencies::get();
$authenticated = false;
$oauth = new OAuth();
- $oauth->setDeps($this->deps);
- $urlGen = $this->deps->urlGen;
+ $oauth->setDeps($deps);
+ $urlGen = $deps->urlGen;
try {
$provider = new \OAuthProvider();
$oauth->registerHandler($provider)
->registerAccessTokenHandler($provider);
- $provider->checkOAuthRequest($urlGen->fullPath());
+ $provider->checkOAuthRequest(
+ $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute('grauphel.api.index')
+ )
+ );
$authenticated = true;
- $token = $this->deps->tokens->load('access', $provider->token);
+ $token = $deps->tokens->load('access', $provider->token);
$username = $token->user;
- } catch (OAuth_Exception $e) {
- $this->deps->renderer->errorOut($e->getMessage());
+ } catch (\OAuth_Exception $e) {
+ $deps->renderer->errorOut($e->getMessage());
} catch (\OAuthException $e) {
if ($e->getCode() != OAUTH_PARAMETER_ABSENT) {
$oauth->error($e);
}
$data = array(
- 'oauth_request_token_url' => $urlGen->oauthRequestToken(),
- 'oauth_authorize_url' => $urlGen->oauthAuthorize(),
- 'oauth_access_token_url' => $urlGen->oauthAccessToken(),
+ 'oauth_request_token_url' => $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute('grauphel.oauth.requestToken')
+ ),
+ 'oauth_authorize_url' => $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute('grauphel.oauth.authorize')
+ ),
+ 'oauth_access_token_url' => $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute('grauphel.oauth.accessToken')
+ ),
'api-version' => '1.0',
);
if ($authenticated) {
$data['user-ref'] = array(
- 'api-ref' => $urlGen->user($username),
- 'href' => $urlGen->userHtml($username),
+ 'api-ref' => $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute(
+ 'grauphel.api.user', array('user' => $username)
+ )
+ ),
+ 'href' => null,//FIXME
);
}
- $this->deps->renderer->sendJson($data);
+ return new JSONResponse($data);
+ $deps->renderer->sendJson($data);
}
/**
* GET /api/1.0/$user/notes/$noteguid
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
*/
public function note()
{
- $username = $this->deps->urlGen->loadUsername();
- $guid = $this->deps->urlGen->loadGuid();
- $oauth = new OAuth();
- $oauth->setDeps($this->deps);
- $oauth->verifyOAuthUser($username, $this->deps->urlGen->note($username, $guid));
-
- $note = $this->deps->notes->load($username, $guid, false);
+ $deps = Dependencies::get();
+ $username = $deps->urlGen->loadUsername();
+ $guid = $deps->urlGen->loadGuid();
+ $oauth = new \OAuth();
+ $oauth->setDeps($deps);
+ $oauth->verifyOAuthUser($username, $deps->urlGen->note($username, $guid));
+
+ $note = $deps->notes->load($username, $guid, false);
if ($note === null) {
header('HTTP/1.0 404 Not Found');
header('Content-type: text/plain');
}
$data = array('note' => array($note));
- $this->deps->renderer->sendJson($data);
+ $deps->renderer->sendJson($data);
}
/**
* GET|PUT /api/1.0/$user/notes
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
*/
public function notes()
{
- $username = $this->deps->urlGen->loadUsername();
- $oauth = new OAuth();
- $oauth->setDeps($this->deps);
- $oauth->verifyOAuthUser($username, $this->deps->urlGen->notes($username));
+ $deps = Dependencies::get();
+ $username = $deps->urlGen->loadUsername();
+ $oauth = new \OAuth();
+ $oauth->setDeps($deps);
+ $oauth->verifyOAuthUser($username, $deps->urlGen->notes($username));
- $syncdata = $this->deps->notes->loadSyncData($username);
+ $syncdata = $deps->notes->loadSyncData($username);
$this->handleNoteSave($username, $syncdata);
}
if (isset($_GET['include_notes']) && $_GET['include_notes']) {
- $notes = $this->deps->notes->loadNotesFull($username, $since);
+ $notes = $deps->notes->loadNotesFull($username, $since);
} else {
- $notes = $this->deps->notes->loadNotesOverview($username, $since);
+ $notes = $deps->notes->loadNotesOverview($username, $since);
}
//work around bug https://bugzilla.gnome.org/show_bug.cgi?id=734313
'latest-sync-revision' => $syncdata->latestSyncRevision,
'notes' => $notes,
);
- $this->deps->renderer->sendJson($data);
+ $deps->renderer->sendJson($data);
}
protected function handleNoteSave($username, $syncdata)
}
//update
+ $deps = Dependencies::get();
++$syncdata->latestSyncRevision;
foreach ($putObj->{'note-changes'} as $noteUpdate) {
- $note = $this->deps->notes->load($username, $noteUpdate->guid);
+ $note = $deps->notes->load($username, $noteUpdate->guid);
if (isset($noteUpdate->command) && $noteUpdate->command == 'delete') {
- $this->deps->notes->delete($username, $noteUpdate->guid);
+ $deps->notes->delete($username, $noteUpdate->guid);
} else {
- $this->deps->notes->update(
+ $deps->notes->update(
$note, $noteUpdate, $syncdata->latestSyncRevision
);
- $this->deps->notes->save($username, $note);
+ $deps->notes->save($username, $note);
}
}
- $this->deps->notes->saveSyncData($username, $syncdata);
+ $deps->notes->saveSyncData($username, $syncdata);
}
/**
* GET /api/1.0/$user
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
*/
public function user()
{
- $username = $this->deps->urlGen->loadUsername();
+ $deps = Dependencies::get();
+ $username = $deps->urlGen->loadUsername();
- $oauth = new OAuth();
- $oauth->setDeps($this->deps);
- $oauth->verifyOAuthUser($username, $this->deps->urlGen->user($username));
+ $oauth = new \OAuth();
+ $oauth->setDeps($deps);
+ $oauth->verifyOAuthUser($username, $deps->urlGen->user($username));
- $syncdata = $this->deps->notes->loadSyncData($username);
+ $syncdata = $deps->notes->loadSyncData($username);
$data = array(
'user-name' => $username,
'first-name' => null,
'last-name' => null,
'notes-ref' => array(
- 'api-ref' => $this->deps->urlGen->notes($username),
+ 'api-ref' => $deps->urlGen->notes($username),
'href' => null,
),
'latest-sync-revision' => $syncdata->latestSyncRevision,
'current-sync-guid' => $syncdata->currentSyncGuid,
);
- $this->deps->renderer->sendJson($data);
+ $deps->renderer->sendJson($data);
}
}
?>
* @link http://cweiske.de/grauphel.htm
*/
namespace OCA\Grauphel\Controller;
+
use \OCP\AppFramework\Controller;
+use \OCP\AppFramework\Http;
+use \OCP\AppFramework\Http\JSONResponse;
+use \OCP\AppFramework\Http\RedirectResponse;
+use \OCP\AppFramework\Http\TemplateResponse;
+
+use \OCA\Grauphel\Lib\Token;
+use \OCA\Grauphel\Lib\OAuth;
+use \OCA\Grauphel\Lib\Dependencies;
+use \OCA\Grauphel\Lib\Response\ErrorResponse;
+use \OCA\Grauphel\Lib\Response\FormResponse;
+use \OCA\Grauphel\Lib\OAuthException;
+use \OCA\Grauphel\Lib\UrlHelper;
/**
* OAuth handling
* @version Release: @package_version@
* @link http://cweiske.de/grauphel.htm
*/
-class OAuthController extends Controller
+class OauthController extends Controller
{
+ protected $user;
+
+ /**
+ * constructor of the controller
+ *
+ * @param string $appName Name of the app
+ * @param IRequest $request Instance of the request
+ */
+ public function __construct($appName, \OCP\IRequest $request, $user)
+ {
+ parent::__construct($appName, $request);
+ $this->user = $user;
+ $this->deps = Dependencies::get();
+
+ //default http header: we assume something is broken
+ header('HTTP/1.0 500 Internal Server Error');
+ }
+
/**
* Handle out an access token after verifying the verification token
* OAuth step 3 of 3
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
*/
- public function accessTokenAction()
+ public function accessToken()
{
$oauth = new OAuth();
$oauth->setDeps($this->deps);
+ $urlGen = $this->deps->urlGen;
try {
$provider = new \OAuthProvider();
$oauth->registerHandler($provider)
->registerVerificationTokenHandler($provider);
- $provider->checkOAuthRequest($this->deps->urlGen->oauthAccessToken());
+ $provider->checkOAuthRequest(
+ $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute('grauphel.oauth.accessToken')
+ )
+ );
$token = $this->deps->tokens->loadAndDelete('verify', $provider->token);
- $newToken = new OAuth_Token('access');
+ $newToken = new Token('access');
$newToken->tokenKey = 'a' . bin2hex($provider->generateToken(8));
$newToken->secret = 's' . bin2hex($provider->generateToken(8));
$newToken->user = $token->user;
$this->deps->tokens->store($newToken);
- $this->deps->renderer->sendFormData(
+ return new FormResponse(
array(
'oauth_token' => $newToken->tokenKey,
'oauth_token_secret' => $newToken->secret,
)
);
- exit(0);
+ } catch (OAuthException $e) {
+ return new ErrorResponse($e->getMessage());
} catch (\OAuthException $e) {
$oauth->error($e);
}
/**
* Log the user in and let him authorize that the app may access notes
* OAuth step 2 of 3
+ *
+ * Page is not public and thus requires owncloud login
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
*/
- public function authorizeAction()
+ public function authorize()
{
- $oauth = new OAuth();
- $oauth->setDeps($this->deps);
-
- if (!isset($_REQUEST['oauth_token'])) {
- $this->deps->renderer->errorOut('oauth_token missing');
- }
- if (!$oauth->validateToken($_REQUEST['oauth_token'])) {
- $this->deps->renderer->errorOut('Invalid token string');
- }
-
- $reqToken = $_REQUEST['oauth_token'];
-
- try {
- $token = $this->deps->tokens->load('temp', $reqToken);
- } catch (OAuth_Exception $e) {
- $this->deps->renderer->errorOut($e->getMessage());
+ $token = $this->verifyRequestToken();
+ if (!$token instanceof Token) {
+ return $token;
}
- $authState = $this->deps->frontend->doAuthorize(
- $this->deps->urlGen->current()
+ $res = new TemplateResponse('grauphel', 'oauthAuthorize');
+ $res->setParams(
+ array(
+ 'oauth_token' => $token->tokenKey,
+ 'formaction' => $this->deps->urlGen->linkToRoute(
+ 'grauphel.oauth.confirm'
+ ),
+ )
);
- if ($authState === null) {
- //this should not happen; doAuthorize() must block
- exit(1);
- }
+ return $res;
+ }
+
+ /**
+ * User confirms or declines the authorization request
+ * OAuth step 2.5 of 3
+ *
+ * @NoAdminRequired
+ */
+ public function confirm()
+ {
+ $token = $this->verifyRequestToken();
+ $oauth = new OAuth();
+ $oauth->setDeps($this->deps);
try {
- $token = $this->deps->tokens->loadAndDelete('temp', $reqToken);
- } catch (OAuth_Exception $e) {
- $this->deps->renderer->errorOut($e->getMessage());
+ $token = $this->deps->tokens->loadAndDelete('temp', $token->tokenKey);
+ } catch (OAuthException $e) {
+ return new ErrorResponse($e->getMessage());
}
+ $authState = isset($_POST['auth']) && $_POST['auth'] == 'ok';
if ($authState === false) {
//user declined
//http://wiki.oauth.net/w/page/12238543/ProblemReporting
- $callback = $this->deps->urlGen->addParams(
- $token->callback,
- array(
- 'oauth_token' => $token->tokenKey,
- 'oauth_problem' => 'permission_denied',
+ $res = new RedirectResponse(
+ UrlHelper::addParams(
+ $token->callback,
+ array(
+ 'oauth_token' => $token->tokenKey,
+ 'oauth_problem' => 'permission_denied',
+ )
)
);
- header('Location: ' . $callback, true, 302);
- exit(0);
+ $res->setStatus(Http::STATUS_SEE_OTHER);
+ return $res;
}
//the user is logged in and authorized
$provider = new \OAuthProvider();
- $newToken = new OAuth_Token('verify');
+ $newToken = new Token('verify');
$newToken->tokenKey = $token->tokenKey;
$newToken->secret = $token->secret;
$newToken->verifier = 'v' . bin2hex($provider->generateToken(8));
- $newToken->user = $this->deps->frontend->getUser();
+ $newToken->user = $this->user->getUID();
$this->deps->tokens->store($newToken);
//redirect
//FIXME: if no callback is given, show the token to the user
- $callback = $this->deps->urlGen->addParams(
- $token->callback,
- array(
- 'oauth_token' => $newToken->tokenKey,
- 'oauth_verifier' => $newToken->verifier
+ $res = new RedirectResponse(
+ UrlHelper::addParams(
+ $token->callback,
+ array(
+ 'oauth_token' => $newToken->tokenKey,
+ 'oauth_verifier' => $newToken->verifier
+ )
)
);
+ $res->setStatus(Http::STATUS_SEE_OTHER);
+ return $res;
+ }
+
+ protected function verifyRequestToken()
+ {
+ if (!isset($_REQUEST['oauth_token'])) {
+ return new ErrorResponse('oauth_token missing');
+ }
- header('Location: ' . $callback, true, 302);
- exit();
+ $oauth = new OAuth();
+ $oauth->setDeps($this->deps);
+ if (!$oauth->validateToken($_REQUEST['oauth_token'])) {
+ return new ErrorResponse('Invalid token string');
+ }
+
+ $reqToken = $_REQUEST['oauth_token'];
+
+ try {
+ $token = $this->deps->tokens->load('temp', $reqToken);
+ } catch (OAuthException $e) {
+ return new ErrorResponse($e->getMessage());
+ }
+
+ return $token;
}
/**
* Create and return a request token.
* OAuth step 1 of 3
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
*/
- public function requestTokenAction()
+ public function requestToken()
{
$oauth = new OAuth();
$oauth->setDeps($this->deps);
+ $urlGen = $this->deps->urlGen;
try {
$provider = new \OAuthProvider();
$oauth->registerHandler($provider);
$provider->isRequestTokenEndpoint(true);
- $provider->checkOAuthRequest($this->deps->urlGen->oauthRequestToken());
+ $provider->checkOAuthRequest(
+ $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute('grauphel.oauth.requestToken')
+ )
+ );
//store token + callback URI for later
- $token = new OAuth_Token('temp');
+ $token = new Token('temp');
$token->tokenKey = 'r' . bin2hex($provider->generateToken(8));
$token->secret = 's' . bin2hex($provider->generateToken(8));
$token->callback = $provider->callback;
$this->deps->tokens->store($token);
- $this->deps->renderer->sendFormData(
+ return new FormResponse(
array(
'oauth_token' => $token->tokenKey,
'oauth_token_secret' => $token->secret,
'oauth_callback_confirmed' => 'TRUE'
)
);
+ } catch (OAuthException $e) {
+ return new ErrorResponse($e->getMessage());
} catch (\OAuthException $e) {
$oauth->error($e);
}
--- /dev/null
+<?php
+/**
+ * Part of grauphel
+ *
+ * PHP version 5
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @link http://cweiske.de/grauphel.htm
+ */
+namespace OCA\Grauphel\Lib;
+
+/**
+ * Object container
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @version Release: @package_version@
+ * @link http://cweiske.de/grauphel.htm
+ */
+class Dependencies
+{
+ /**
+ * @var Frontend\Default
+ */
+ public $frontend;
+
+ /**
+ * @var Note\Storage
+ */
+ public $noteStorage;
+
+ /**
+ * @var OAuth\Storage
+ */
+ public $oauthStorage;
+
+ /**
+ * @var IURLGenerator
+ */
+ public $urlGen;
+
+ protected static $instance;
+
+ public static function get()
+ {
+ if (self::$instance !== null) {
+ return self::$instance;
+ }
+ $deps = new self();
+ /*
+ $deps->notes = new Note_Storage_Flatfile();
+ $deps->notes->setDataDir($dataDir);
+ $deps->notes->setDeps($deps);
+
+ $deps->urlGen = new UrlGen_Pretty();
+ $deps->urlGen->setDeps($deps);
+ /*
+ $deps->frontend = new Frontend_Default();
+ $deps->frontend->setDeps($deps);
+ */
+
+ $deps->tokens = new TokenStorage();
+
+ self::$instance = $deps;
+ return self::$instance;
+ }
+}
+?>
--- /dev/null
+<?php
+/**
+ * Part of grauphel
+ *
+ * PHP version 5
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @link http://cweiske.de/grauphel.htm
+ */
+namespace OCA\Grauphel\Lib;
+
+/**
+ * Storage base class that implements note updating
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @version Release: @package_version@
+ * @link http://cweiske.de/grauphel.htm
+ */
+class OAuth
+{
+ /**
+ * Token data store
+ *
+ * @var Token_Storage
+ */
+ protected $tokens;
+
+ public function setDeps(Dependencies $deps)
+ {
+ $this->tokens = $deps->tokens;
+ }
+
+ /**
+ * Register callbacks for the oauth dance.
+ */
+ public function registerHandler(\OAuthProvider $provider)
+ {
+ $provider->consumerHandler(array($this, 'lookupConsumer'));
+ $provider->timestampNonceHandler(array($this, 'timestampNonceChecker'));
+ return $this;
+ }
+
+ public function registerVerificationTokenHandler(\OAuthProvider $provider)
+ {
+ $provider->tokenHandler(array($this, 'verifyTokenHandler'));
+ return $this;
+ }
+
+ public function registerAccessTokenHandler(\OAuthProvider $provider)
+ {
+ $provider->tokenHandler(array($this, 'accessTokenHandler'));
+ return $this;
+ }
+
+ public function validateToken($tokenKey)
+ {
+ return (bool) preg_match('#^[a-z0-9]+$#', $tokenKey);
+ }
+
+ public function lookupConsumer(\OAuthProvider $provider)
+ {
+ //tomboy assumes secret==key=="anyone"
+ $provider->consumer_secret = $provider->consumer_key;//'anyone';
+ $provider->addRequiredParameter('oauth_callback');
+
+ return OAUTH_OK;
+ }
+
+ public function timestampNonceChecker(\OAuthProvider $provider)
+ {
+ //var_dump($provider->nonce, $provider->timestamp);
+ //OAUTH_BAD_NONCE
+ //OAUTH_BAD_TIMESTAMP
+ return OAUTH_OK;
+ }
+
+ public function verifyTokenHandler(\OAuthProvider $provider)
+ {
+ $token = $this->tokens->load('verify', $provider->token);
+ if ($provider->verifier == '') {
+ return OAUTH_VERIFIER_INVALID;
+ }
+ if ($provider->verifier != $token->verifier) {
+ return OAUTH_VERIFIER_INVALID;
+ }
+
+ $provider->token_secret = $token->secret;
+ return OAUTH_OK;
+ }
+
+ public function accessTokenHandler(\OAuthProvider $provider)
+ {
+ $token = $this->tokens->load('access', $provider->token);
+ $provider->token_secret = $token->secret;
+ return OAUTH_OK;
+ }
+
+ public function verifyOAuthUser($username, $url)
+ {
+ try {
+ $provider = new \OAuthProvider();
+ $this->registerHandler($provider);
+ $this->registerAccessTokenHandler($provider);
+ //do not use "user" in signature
+ $provider->setParam('user', null);
+
+ $provider->checkOAuthRequest($url);
+
+ $token = $this->tokens->load('access', $provider->token);
+ if ($token->user != $username) {
+ errorOut('Invalid user');
+ }
+ } catch (\OAuthException $e) {
+ $this->error($e);
+ }
+ }
+
+ public function error(\OAuthException $e)
+ {
+ header('HTTP/1.0 400 Bad Request');
+ //header('Content-type: application/x-www-form-urlencoded');
+ echo \OAuthProvider::reportProblem($e);
+ //var_dump($e);
+ exit(1);
+ }
+}
+?>
--- /dev/null
+<?php
+/**
+ * Part of grauphel
+ *
+ * PHP version 5
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @link http://cweiske.de/grauphel.htm
+ */
+namespace OCA\Grauphel\Lib;
+
+/**
+ * OAuth error
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @version Release: @package_version@
+ * @link http://cweiske.de/grauphel.htm
+ */
+class OAuthException extends \Exception
+{
+}
+?>
--- /dev/null
+<?php
+namespace OCA\Grauphel\Lib\Response;
+
+class ErrorResponse extends \OCP\AppFramework\Http\Response
+{
+ protected $error;
+
+ public function __construct($error)
+ {
+ $this->setStatus(\OCP\AppFramework\Http::STATUS_BAD_REQUEST);
+ $this->addHeader('Content-Type', 'text/plain; charset=utf-8');
+ $this->error = $error;
+ }
+
+ public function render()
+ {
+ return $this->error . "\n";
+ }
+}
+?>
--- /dev/null
+<?php
+namespace OCA\Grauphel\Lib\Response;
+
+class FormResponse extends \OCP\AppFramework\Http\Response
+{
+ protected $data;
+
+ public function __construct($data)
+ {
+ $this->setStatus(\OCP\AppFramework\Http::STATUS_OK);
+ $this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
+ $this->data = $data;
+ }
+
+ public function render()
+ {
+ return http_build_query($this->data, null, '&');
+ }
+}
+?>
--- /dev/null
+<?php
+/**
+ * Part of grauphel
+ *
+ * PHP version 5
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @link http://cweiske.de/grauphel.htm
+ */
+namespace OCA\Grauphel\Lib;
+
+/**
+ * Synchronization data model
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @version Release: @package_version@
+ * @link http://cweiske.de/grauphel.htm
+ */
+class SyncData
+{
+ /**
+ * The latest sync revision from Tomboy, given from last PUT
+ * of a note from Tomboy.
+ * Give a -1 here if you have not synced with Tomboy yet.,
+ *
+ * @var integer
+ */
+ public $latestSyncRevision;
+
+ /**
+ * A uuid generated by the sync application.
+ * It should change only if the user decides to clear their
+ * sync history from the server and start over
+ * with an empty note set.
+ *
+ * @var string
+ */
+ public $currentSyncGuid;
+
+ /**
+ * Initialize the variables to represent the data of a user
+ * that never synced
+ *
+ * @param string $username Name of user
+ *
+ * @return void
+ */
+ public function initNew($username)
+ {
+ $this->latestSyncRevision = -1;
+ $this->currentSyncGuid = uniqid($username . '-', true);
+ }
+}
+?>
--- /dev/null
+<?php
+/**
+ * Part of grauphel
+ *
+ * PHP version 5
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @link http://cweiske.de/grauphel.htm
+ */
+namespace OCA\Grauphel\Lib;
+
+/**
+ * OAuth token with some additional data
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @version Release: @package_version@
+ * @link http://cweiske.de/grauphel.htm
+ */
+class Token
+{
+ /**
+ * One of: temp, access, verify
+ *
+ * @var string
+ */
+ public $type;
+
+ /**
+ * Actual random token string
+ *
+ * @var string
+ */
+ public $tokenKey;
+
+ /**
+ * Matching secret for the token string
+ *
+ * @var string
+ */
+ public $secret;
+
+ /**
+ * User name for which the token is valid
+ *
+ * @var string
+ */
+ public $user;
+
+ /**
+ * Verification string.
+ * Only used when $type == 'verify'
+ *
+ * @var string
+ */
+ public $verifier;
+
+ /**
+ * Callback URL for temp tokens
+ *
+ * @var string
+ */
+ public $callback;
+
+ public function __construct($type = null)
+ {
+ $this->type = $type;
+ }
+}
+?>
--- /dev/null
+<?php
+/**
+ * Part of grauphel
+ *
+ * PHP version 5
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @link http://cweiske.de/grauphel.htm
+ */
+namespace OCA\Grauphel\Lib;
+
+/**
+ * Token store
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @version Release: @package_version@
+ * @link http://cweiske.de/grauphel.htm
+ */
+class TokenStorage
+{
+ /**
+ * Store the given token
+ *
+ * @param OAuth_Token $token Token object to store
+ *
+ * @return void
+ */
+ public function store(OAuth_Token $token)
+ {
+ \OC_DB::executeAudited(
+ 'INSERT INTO `*PREFIX*grauphel_oauth_tokens`'
+ . '(`token_user`, `token_type`, `token_key`, `token_secret`, `token_verifier`, `token_callback`)'
+ . ' VALUES(?, ?, ?, ?, ?, ?)',
+ array(
+ $token->user,
+ $token->type,
+ $token->tokenKey,
+ (string) $token->secret,
+ (string) $token->verifier,
+ (string) $token->callback
+ )
+ );
+ }
+
+ /**
+ * Load the token and destroy it.
+ *
+ * @param string $type Token type: temp, access, verify
+ * @param string $tokenKey Random token string to load
+ *
+ * @return OAuth_Token Stored token
+ *
+ * @throws OAuth_Exception When token does not exist
+ */
+ public function loadAndDelete($type, $tokenKey)
+ {
+ try {
+ $token = $this->load($type, $tokenKey);
+ \OC_DB::executeAudited(
+ 'DELETE FROM `*PREFIX*grauphel_oauth_tokens`'
+ . ' WHERE `token_key` = ? AND `token_type` = ?',
+ array($tokenKey, $type)
+ );
+ return $token;
+ } catch (OAuthException $e) {
+ throw $e;
+ }
+ }
+
+
+ /**
+ * Load the token.
+ *
+ * @param string $type Token type: temp, access, verify
+ * @param string $tokenKey Random token string to load
+ *
+ * @return OAuth_Token Stored token
+ *
+ * @throws OAuth_Exception When token does not exist or
+ */
+ public function load($type, $tokenKey)
+ {
+ $tokenRow = \OC_DB::executeAudited(
+ 'SELECT * FROM `*PREFIX*grauphel_oauth_tokens`'
+ . ' WHERE `token_key` = ? AND `token_type` = ?',
+ array($tokenKey, $type)
+ )->fetchRow();
+
+ if ($tokenRow === false) {
+ throw new OAuthException('Unknown token: ' . $type . ' / ' . $tokenKey);
+ }
+
+ $token = $this->fromDb($tokenRow);
+ if ($token->tokenKey != $tokenKey) {
+ throw new OAuthException('Invalid token');
+ }
+
+ return $token;
+ }
+
+ protected function fromDb($tokenRow)
+ {
+ $token = new Token();
+ $token->type = $tokenRow['token_user'];
+ $token->tokenKey = $tokenRow['token_key'];
+ $token->secret = $tokenRow['token_secret'];
+ $token->user = $tokenRow['token_user'];
+ $token->verifier = $tokenRow['token_verifier'];
+ $token->callback = $tokenRow['token_callback'];
+ return $token;
+ }
+}
+?>
--- /dev/null
+<?php
+/**
+ * Part of grauphel
+ *
+ * PHP version 5
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @link http://cweiske.de/grauphel.htm
+ */
+namespace OCA\Grauphel\Lib;
+
+/**
+ * URL helper methods
+ *
+ * @category Tools
+ * @package Grauphel
+ * @author Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @version Release: @package_version@
+ * @link http://cweiske.de/grauphel.htm
+ */
+class UrlHelper
+{
+ public static function addParams($url, $arParams)
+ {
+ $parts = array();
+ foreach($arParams as $key => $val) {
+ if ($val != '') {
+ $parts[] = urlencode($key) . '=' . urlencode($val);
+ }
+ }
+ $sep = (strpos($url, '?') !== false) ? '&' : '?';
+ return $url . $sep . implode('&', $parts);
+ }
+}
+?>
--- /dev/null
+<form method="post" action="<?php p($_['formaction']); ?>">
+ <input type="hidden" value="<?php p($_['requesttoken']); ?>" name="requesttoken" />
+ <input type="hidden" value="<?php p($_['oauth_token']); ?>" name="oauth_token" />
+ <p>
+ Shall application FIXME get full access to the notes?
+ </p>
+ <button type="submit" name="auth" value="ok">Yes, authorize</button>
+ <button type="submit" name="auth" value="cancel">No, decline</button>
+</form>