Compare commits

...

12 Commits

Author SHA1 Message Date
Christian Weiske
635be284de use autoloader 2014-03-26 22:49:40 +01:00
Christian Weiske
90ba326f85 show error when openid is already registered 2014-03-26 22:49:36 +01:00
Christian Weiske
09cf21aa7e use custom HTTP adapter to get rid of HTTP warnings thrown by XML_XRD's simplexml_load_file usage 2014-03-26 22:49:31 +01:00
Christian Weiske
3acd0e8db4 WebFinger support! 2014-03-26 22:49:27 +01:00
Christian Weiske
e1655f0e22 adding new openids in user profile works now 2014-03-26 22:49:23 +01:00
Christian Weiske
3afbf11087 restructure code a bit 2014-03-26 22:49:08 +01:00
Christian Weiske
8258c39e54 CS: tab2spaces 2014-03-26 22:46:59 +01:00
Christian Weiske
da38761814 begin describing OpenID login process 2014-03-26 22:45:39 +01:00
Christian Weiske
9ac32984eb catch openid errors 2014-03-26 22:45:36 +01:00
Christian Weiske
1ab3c45d71 Move OpenID login handling into separate class 2014-03-26 22:45:32 +01:00
Christian Weiske
14640ed8a5 openid identifier table 2014-03-26 22:45:27 +01:00
Christian Weiske
16c08eb3b6 first working openid login (very very rough, but works!) 2014-03-26 22:45:23 +01:00
16 changed files with 797 additions and 88 deletions

View File

@ -105,11 +105,15 @@
channel="pear.php.net" channel="pear.php.net"
minimum_version="0.4.0" minimum_version="0.4.0"
/> />
<!-- unit tests: -->
<package name="HTML_Request2" <package name="HTML_Request2"
channel="pear.php.net" channel="pear.php.net"
minimum_version="2.0.0" minimum_version="2.0.0"
/> />
<package name="Net_WebFinger"
channel="pear.php.net"
minimum_version="0.2.0"
/>
<!-- unit tests: -->
<package name="Stream_Var" <package name="Stream_Var"
channel="pear.php.net" channel="pear.php.net"
minimum_version="1.1.0" minimum_version="1.1.0"

View File

@ -79,6 +79,15 @@ CREATE TABLE `sc_users` (
-- -------------------------------------------------------- -- --------------------------------------------------------
CREATE TABLE `sc_users_openids` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uId` int(11) NOT NULL,
`url` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) CHARACTER SET utf8 COLLATE utf8_general_ci;
-- --------------------------------------------------------
CREATE TABLE `sc_users_sslclientcerts` ( CREATE TABLE `sc_users_sslclientcerts` (
`id` INT NOT NULL AUTO_INCREMENT , `id` INT NOT NULL AUTO_INCREMENT ,
`uId` INT NOT NULL , `uId` INT NOT NULL ,

View File

@ -0,0 +1,48 @@
<?php
/**
* User's own profile page: OpenID management
*
* @param array $openIds Array of OpenID association objects
* @param string $formaction URL where to send the forms to
* @param SemanticScuttle_Model_User_OpenId
* $currentOpenId Current OpenID object (may be null)
*/
?>
<h3><?php echo T_('OpenIDs'); ?></h3>
<?php if (count($openIds)) { ?>
<table>
<thead>
<tr>
<th>Options</th>
<th><?php echo T_('OpenID URL'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach($openIds as $openId) { ?>
<tr <?php if ($openId->isCurrent()) { echo 'class="openid-current"'; } ?>>
<td>
<form method="post" action="<?php echo $formaction; ?>">
<input type="hidden" name="openIdUrl" value="<?php echo htmlspecialchars($openId->url); ?>"/>
<button type="submit" name="action" value="deleteOpenId">
<?php echo T_('delete'); ?>
</button>
</form>
</td>
<td><?php echo htmlspecialchars($openId->url); ?></td>
</tr>
<?php } ?>
</tbody>
</table>
<?php } else { ?>
<p><?php echo T_('No OpenIDs registered'); ?></p>
<?php } ?>
<p>
<form method="post" action="<?php echo $formaction; ?>">
<label for="openid"><?php echo T_('New E-Mail or OpenID'); ?></label>
<input type="text" id="openid" name="openid_identifier" size="20" />
<button type="submit" name="action" value="registerOpenId">
<?php echo T_('Register'); ?>
</button>
</form>
</p>

View File

@ -59,6 +59,7 @@ $this->includeTemplate($GLOBALS['top_include']);
</tr> </tr>
</table> </table>
<?php include 'editprofile-openid.tpl.php'; ?>
<?php include 'editprofile-sslclientcerts.tpl.php'; ?> <?php include 'editprofile-sslclientcerts.tpl.php'; ?>
<h3><?php echo T_('Actions'); ?></h3> <h3><?php echo T_('Actions'); ?></h3>
<table class="profile"> <table class="profile">

View File

@ -17,6 +17,15 @@ if (!$userservice->isSessionStable()) {
<form action="<?php echo $formaction; ?>" method="post"> <form action="<?php echo $formaction; ?>" method="post">
<div><input type="hidden" name="query" value="<?php echo $querystring; ?>" /></div> <div><input type="hidden" name="query" value="<?php echo $querystring; ?>" /></div>
<table> <table>
<tr>
<th align="left"><label for="openid"><?php echo T_('E-Mail or OpenID'); ?></label></th>
<td><input type="text" id="openid" name="openid_identifier" size="20" /></td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="2" class="login-or">or</td>
</tr>
<tr> <tr>
<th align="left"><label for="username"><?php echo T_('Username'); ?></label></th> <th align="left"><label for="username"><?php echo T_('Username'); ?></label></th>
<td><input type="text" id="username" name="username" size="20" /></td> <td><input type="text" id="username" name="username" size="20" /></td>

View File

@ -8,7 +8,7 @@ Prerequisites
============= =============
To run SemanticScuttle, you need: To run SemanticScuttle, you need:
- PHP5 with filter functions enabled - PHP5
- A web server, for example Apache - A web server, for example Apache

Binary file not shown.

82
doc/developers/OpenID.rst Normal file
View File

@ -0,0 +1,82 @@
**************
OpenID support
**************
Since SemanticScuttle 0.99.0, users may log in via OpenID.
=============
Login Process
=============
::
.
+------------------+
/ OpenID URL entry /
+------------------+
|
v
+----------------------------+ Cancel +------------+
| Request to OpenID provider | ------------------------> | Login fail |
+----------------------------+ +------------+
| Success ^
_____ v ________________________ | No
/ \ No +----------------------------+
| OpenID associated with a user? | ----------> | User registration enabled? |
\________________________________/ +----------------------------+
| | Yes
| Yes v
| +-------------------------+
| / Registration form /
| / prefilled with data /
| / from OpenID provider /
| / /
| / Password not required /
| / Email not required /
| +-------------------------+
| |
v v
+-------+ +----------------+
| Login | <----------------------------------------- | Create account |
+-------+ +----------------+
|
_____v_______________
/ \ Yes +------------------+
| Data update active? |------------> | Update user data |
\_____________________/ | from OpenID |
| +------------------+
v |
+----------------+ |
| Login finished | <--------------------------+
+----------------+
Automatic registration?
=======================
No. We show the user the login form prefilled with data.
1. It prevents users from creating several accounts when they use multiple
OpenIDs and forgot which they used in this instance.
2. In case the user name is already taken, we need to ask for a new user name
anyway.
3. People may not want to use the data from their OpenID provider when
registering
Discussion on this topic happened in http://drupal.org/node/637850
=====
Links
=====
- http://stackoverflow.com/questions/4564337/guidance-on-flow-for-openid-registration-form
- http://stackoverflow.com/questions/1316983/to-openid-or-not-to-openid-is-it-worth-it
- http://wiki.openid.net/w/page/12995223/Relying%20Party%20Best%20Practices
====
TODO
====
Blog post:
- automatic registration
- openid login/registration process flow chart

View File

@ -0,0 +1,33 @@
<?php
require_once 'SemanticScuttle/Exception/User.php';
class SemanticScuttle_Exception extends Exception
{
/**
* Returns an error message that can be shown to the user.
*
* FIXME: maybe move that method to somewhere else
*
* @return string Error message to display to the user
*/
public static function getErrorMessage(Exception $e)
{
if ($e instanceof SemanticScuttle_Exception_User) {
if (isset($GLOBALS['debugMode']) && $GLOBALS['debugMode']) {
$prev = $e->getPrevious();
if ($prev) {
$msg = $prev->getMessage();
} else {
$msg = $e->getMessage();
}
} else {
$msg = $e->getMessage();
}
} else {
$msg = $e->getMessage();
}
return $msg;
}
}
?>

View File

@ -0,0 +1,10 @@
<?php
/**
* Exception class whose message may be displayed to users in the frontend.
*
* The detailled message is in the previous exception (getPrevious()).
*/
class SemanticScuttle_Exception_User extends Exception
{
}
?>

View File

@ -0,0 +1,60 @@
<?php
/**
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license AGPL http://www.gnu.org/licenses/agpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
/**
* OpenID model. Represents one single OpenID association to a user.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license AGPL http://www.gnu.org/licenses/agpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
class SemanticScuttle_Model_OpenId
{
public $id;
public $uId;
public $url;
/**
* Creates and returns a new object and fills it with
* the passed values from the database.
*
* @param array $arOpenIdRow Database row array
*
* @return SemanticScuttle_Model_OpenId
*/
public static function fromDb($arOpenIdRow)
{
$openId = new self();
foreach (get_object_vars($openId) as $variable => $dummy) {
if (isset($arOpenIdRow[$variable])) {
$openId->$variable = $arOpenIdRow[$variable];
}
}
return $openId;
}
/**
* Returns if this OpenID is the one the user is logged in with currently.
*
* @return boolean True if the User logged in with this OpenID
*/
public function isCurrent()
{
//FIXME
return false;
}
}

View File

@ -0,0 +1,378 @@
<?php
/**
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license AGPL http://www.gnu.org/licenses/agpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
require_once 'SemanticScuttle/Exception/User.php';
require_once 'SemanticScuttle/Model/OpenId.php';
require_once 'OpenID.php';
require_once 'OpenID/RelyingParty.php';
require_once 'OpenID/Extension/SREG11.php';
/**
* SemanticScuttle OpenID verification and management
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license AGPL http://www.gnu.org/licenses/agpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
class SemanticScuttle_Service_OpenId extends SemanticScuttle_DbService
{
/**
* Creates a new instance, sets database variable and table name.
*
* @param sql_db $db Database object
*/
protected function __construct($db)
{
$this->db = $db;
$this->tablename = $GLOBALS['tableprefix'] . 'users_openids';
}
/**
* Returns the single service instance
*
* @param sql_db $db Database object
*
* @return SemanticScuttle_Service_OpenId
*/
public static function getInstance($db)
{
static $instance;
if (!isset($instance)) {
$instance = new self($db);
}
return $instance;
}
/**
* When the user gives an e-mail address instead of an OpenID, we use
* WebFinger to find his OpenID.
*
* @param string $identifier OpenID URL OR e-mail address
*
* @return string Raw/unnormalized OpenID URL.
*
* @throws SemanticScuttle_Exception_User When the user's mail host does not
* support WebFinger
*/
protected function resolveEmailIdentifier($identifier)
{
if (filter_var($identifier, FILTER_VALIDATE_EMAIL) === false) {
//no valid email
return $identifier;
}
require_once 'Net/WebFinger.php';
require_once 'HTTP/Request2.php';
$req = new HTTP_Request2();
$req->setConfig('follow_redirects', true);
$req->setHeader('User-Agent', 'SemanticScuttle');
$wf = new Net_WebFinger();
$wf->setHttpClient($req);
$react = $wf->finger($identifier);
if ($react->openid === null) {
throw new SemanticScuttle_Exception_User(
'No OpenID found for the given email address ' . $identifier,
20
);
}
return $react->openid;
}
/**
* Part 1 of the OpenID login process: Send user to his identity provider.
*
* If an e-mail address is given, a WebFinger lookup is made to find out the
* user's OpenID.
*
* This method exits the PHP process.
*
* @param string $identifier OpenID URL OR e-mail address
* @param string $returnUrl URL the identity provider shall send the user
* back to
*
* @return void No return value needed since it exits.
*
* @throws SemanticScuttle_Exception_User When something goes wrong
*/
public function sendIdRequest($identifier, $returnUrl)
{
$identifier = $this->resolveEmailIdentifier($identifier);
//send request to ID provider
try {
$identifier = OpenID::normalizeIdentifier($identifier);
} catch (OpenID_Exception $e) {
throw new SemanticScuttle_Exception_User(
'Invalid OpenID identifier', 11, $e
);
}
try {
$rp = new OpenID_RelyingParty(
$returnUrl,
addProtocolToUrl(ROOT)/* realm */,
$identifier
);
$authRequest = $rp->prepare();
//FIXME: when user exists already, use immediate mode first and
// fall back to normal when it fails
//FIXME: (?) when user exists already, don't request details
$sreg = new OpenID_Extension_SREG11(OpenID_Extension::REQUEST);
//$sreg->set('required', 'email');
$sreg->set('optional', 'email,nickname,fullname');
$authRequest->addExtension($sreg);
//$auth->setMode(OpenID::MODE_CHECKID_IMMEDIATE);
header('Location: ' . $authRequest->getAuthorizeURL());
exit();
} catch (OpenID_Exception $e) {
throw new SemanticScuttle_Exception_User(
'Error communicating with OpenID identity server', 12, $e
);
}
}
/**
* Part 2 of the OpenID login process: Handle the IDP response
*
* @param string $returnUrl URL the identity provider shall send the user
* back to
*
* @return array Array with user data. Keys:
* - identifier - OpenID URL/identifier
* - userId - Local user ID from database
* - email - OpenID-submitted email
* - nickname - OpenID-submitted nickname
* - fullname - OpenID-submitted full name
*
* @throws SemanticScuttle_Exception_User When something goes wrong
*/
public function handleIdResponse($returnUrl)
{
$rp = new OpenID_RelyingParty(
$returnUrl,
addProtocolToUrl(ROOT)/* realm */
);
if (!count($_POST)) {
list(, $queryString) = explode('?', $_SERVER['REQUEST_URI']);
} else {
$queryString = file_get_contents('php://input');
}
try {
$request = new Net_URL2($returnUrl . '?' . $queryString);
$message = new OpenID_Message($queryString, OpenID_Message::FORMAT_HTTP);
$mode = $message->get('openid.mode');
if ($mode == 'cancel') {
throw new SemanticScuttle_Exception_User(
'OpenID login cancelled', 10
);
} else if ($mode == 'setup_needed') {
throw new SemanticScuttle_Exception_User(
'Immediate OpenID login not possible', 12
);
}
$result = $rp->verify($request, $message);
if (!$result->success()) {
throw new SemanticScuttle_Exception_User(
'OpenID verification failed', 13
);
}
$identifier = $message->get('openid.claimed_id');
} catch (OpenID_Exception $e) {
throw new SemanticScuttle_Exception_User(
'Unknown OpenID error', 14, $e
);
}
try {
$identifier = OpenID::normalizeIdentifier($identifier);
} catch (OpenID_Exception $e) {
throw new SemanticScuttle_Exception_User(
'Invalid OpenID identifier', 11, $e
);
}
return array(
'identifier' => $identifier,
'userId' => $this->getUserId($identifier),
'email' => $message->get('openid.sreg.email'),
'nickname' => $message->get('openid.sreg.nickname'),
'fullname' => $message->get('openid.sreg.fullname'),
);
}
/**
* Returns the user ID for the given OpenID identifier.
*
* @param string $identifier OpenID identifier (URL)
*
* @return integer User ID or NULL if not found
*
* @throws SemanticScuttle_Exception_User When the identifier is invalid
*/
public function getUserId($identifier)
{
$query = 'SELECT sc_users_openids.uId'
. ' FROM sc_users_openids JOIN sc_users USING (uId)'
. ' WHERE url = "' . $this->db->sql_escape($identifier) . '"';
if (!($dbresult = $this->db->sql_query($query))) {
message_die(
GENERAL_ERROR,
'Could not get user',
'', __LINE__, __FILE__, $query, $this->db
);
}
$row = $this->db->sql_fetchrow($dbresult);
$this->db->sql_freeresult($dbresult);
if (!$row) {
//OpenID not found in database.
return null;
}
return $row['uId'];
}
/**
* Add an OpenID to a given user
*
* @param integer $uId User ID to attach the OpenID to
* @param string $identifier OpenID identifier (URL)
* @param string $email OpenID-delivered e-mail address of the user
*
* @return void
*
* @throws SemanticScuttle_Exception When something goes wrong,
* e.g. the OpenID is already registered
*/
public function register($uId, $identifier, $email = null)
{
if ($this->getId($identifier) !== null) {
//already registered
throw new SemanticScuttle_Exception_User(
'OpenID already registered: ' . $identifier,
21
);
}
//FIXME: use email when google-openid
$query = 'INSERT INTO ' . $this->getTableName()
. ' ' . $this->db->sql_build_array(
'INSERT', array(
'uId' => $uId,
'url' => $identifier,
)
);
if (!($dbresult = $this->db->sql_query($query))) {
message_die(
GENERAL_ERROR, 'Could not register OpenID',
'', __LINE__, __FILE__, $query, $this->db
);
}
}
/**
* Deletes the OpenID with the given numeric database ID
*
* @param integer $id Numeric ID from database
*
* @return boolean True if it worked, false if not
*/
public function delete($id)
{
if ($id instanceof SemanticScuttle_Model_OpenId) {
$id = $id->id;
}
$id = (int)$id;
$query = 'DELETE FROM ' . $this->getTableName()
.' WHERE id = ' . $id;
if (!($dbresult = $this->db->sql_query($query))) {
message_die(
GENERAL_ERROR, 'Could not delete OpenID',
'', __LINE__, __FILE__, $query, $this->db
);
return false;
}
return true;
}
/**
* Loads an OpenID object from the given identifiert
*
* @param string $identifier OpenID identifier (URL)
*
* @return SemanticScuttle_Model_OpenId OpenID object or NULL if not found
*/
public function getId($identifier)
{
$query = 'SELECT * FROM ' . $this->getTableName()
. ' WHERE url = "' . $this->db->sql_escape($identifier) . '"';
if (!($dbresult = $this->db->sql_query($query))) {
message_die(
GENERAL_ERROR, 'Could not load OpenID',
'', __LINE__, __FILE__, $query, $this->db
);
return null;
}
if ($row = $this->db->sql_fetchrow($dbresult)) {
$cert = SemanticScuttle_Model_OpenId::fromDb($row);
} else {
$cert = null;
}
$this->db->sql_freeresult($dbresult);
return $cert;
}
/**
* Fetch all OpenIDs the given user has attached
*
* @param integer $uId User ID to fetch registered OpenIDs for
*
* @return array Array of SemanticScuttle_Model_OpenId objects
*/
public function getIds($uId)
{
$query = 'SELECT * FROM ' . $this->getTableName()
. ' WHERE uId = ' . (int)$uId
. ' ORDER BY url ASC';
if (!($dbresult = $this->db->sql_query($query))) {
message_die(
GENERAL_ERROR, 'Could not load OpenIDs',
'', __LINE__, __FILE__, $query, $this->db
);
return array();
}
$certs = array();
while ($row = $this->db->sql_fetchrow($dbresult)) {
$certs[] = SemanticScuttle_Model_OpenId::fromDb($row);
}
$this->db->sql_freeresult($dbresult);
return $certs;
}
}
?>

View File

@ -96,15 +96,12 @@ if (DEBUG_MODE) {
error_reporting(0); error_reporting(0);
} }
// 2 // Second requirements part which could display bugs require_once 'silex.phar';
// (must come after debug management) //modify silex/symfony autoloader
require_once 'SemanticScuttle/Service.php'; $loader->useIncludePath(true);
require_once 'SemanticScuttle/DbService.php';
require_once 'SemanticScuttle/Service/Factory.php';
require_once 'SemanticScuttle/functions.php'; require_once 'SemanticScuttle/functions.php';
require_once 'SemanticScuttle/Model/Bookmark.php';
require_once 'SemanticScuttle/Model/UserArray.php';
require_once 'SemanticScuttle/Model/User/SslClientCert.php';
if (count($GLOBALS['serviceoverrides']) > 0 if (count($GLOBALS['serviceoverrides']) > 0
&& !defined('UNIT_TEST_MODE') && !defined('UNIT_TEST_MODE')

BIN
src/silex.phar Normal file

Binary file not shown.

View File

@ -35,20 +35,50 @@ isset($_POST['query']) ? define('POST_QUERY', $_POST['query']): define('POST_QUE
$keeppass = (POST_KEEPPASS=='yes')?true:false; $keeppass = (POST_KEEPPASS=='yes')?true:false;
@list($url, $method) = isset($_SERVER['PATH_INFO']) ? explode('/', $_SERVER['PATH_INFO']) : NULL;
$login = false; $login = false;
if (POST_SUBMITTED!='' && POST_USERNAME!='' && POST_PASSWORD!='') { if ($method == 'openidreturn'
|| (POST_SUBMITTED != ''
&& isset($_POST['openid_identifier']) && $_POST['openid_identifier'] != ''
)
) {
$oids = SemanticScuttle_Service_Factory::get('OpenId');
$returnUrl = addProtocolToUrl(createURL('login', 'openidreturn'));
try {
if ($method == 'openidreturn') {
//part 2: handle response
$ret = $oids->handleIdResponse($returnUrl);
if ($ret['userId'] === null) {
//FIXME: ask to register
$tplVars['error'] = T_('OpenID login error');
} else {
$userservice->setCurrentUserId($ret['userId'], true);
$login = true;
}
//FIXME POST_KEEPPASS
} else {
//part 1: send request
$oids->sendIdRequest($_POST['openid_identifier'], $returnUrl);
}
} catch (Exception $e) {
$tplVars['error'] = SemanticScuttle_Exception::getErrorMessage($e);
}
} else if (POST_SUBMITTED!='' && POST_USERNAME!='' && POST_PASSWORD!='') {
$posteduser = trim(utf8_strtolower(POST_USERNAME)); $posteduser = trim(utf8_strtolower(POST_USERNAME));
$login = $userservice->login($posteduser, POST_PASSWORD, $keeppass); $login = $userservice->login($posteduser, POST_PASSWORD, $keeppass);
if ($login) { if (!$login) {
if (POST_QUERY)
header('Location: '. createURL('bookmarks', $posteduser .'?'. POST_QUERY));
else
header('Location: '. createURL('bookmarks', $posteduser));
} else {
$tplVars['error'] = T_('The details you have entered are incorrect. Please try again.'); $tplVars['error'] = T_('The details you have entered are incorrect. Please try again.');
} }
} }
if (!$login) {
if ($login) {
if (POST_QUERY)
header('Location: '. createURL('bookmarks', $posteduser .'?'. POST_QUERY));
else
header('Location: '. createURL('bookmarks', $posteduser));
} else {
if ($userservice->isLoggedOn()) { if ($userservice->isLoggedOn()) {
$cUser = $userservice->getCurrentObjectUser(); $cUser = $userservice->getCurrentObjectUser();
header('Location: '. createURL('bookmarks', strtolower($cUser->getUsername()))); header('Location: '. createURL('bookmarks', strtolower($cUser->getUsername())));

View File

@ -42,27 +42,27 @@ isset($_SESSION['token']) ? define('SESSION_TOKEN', $_SESSION['token']): define(
isset($_SESSION['token_stamp']) ? define('SESSION_TOKENSTAMP', $_SESSION['token_stamp']): define('SESSION_TOKENSTAMP', ''); isset($_SESSION['token_stamp']) ? define('SESSION_TOKENSTAMP', $_SESSION['token_stamp']): define('SESSION_TOKENSTAMP', '');
@list($url, $user) = isset($_SERVER['PATH_INFO']) ? explode('/', $_SERVER['PATH_INFO']) : NULL; @list($url, $user, $method) = isset($_SERVER['PATH_INFO'])
? explode('/', $_SERVER['PATH_INFO']) : NULL;
if ($user) { if (!$user) {
$tplVars['error'] = T_('Username was not specified');
if (is_int($user)) { $templateservice->loadTemplate('error.404.tpl', $tplVars);
$userid = intval($user); exit();
} else { }
$user = urldecode($user);
$userinfo = $userservice->getObjectUserByUsername($user); if (is_int($user)) {
if ($userinfo == NULL) { $userid = intval($user);
$tplVars['error'] = sprintf(T_('User with username %s was not found'), $user);
$templateservice->loadTemplate('error.404.tpl', $tplVars);
exit();
} else {
$userid = $userinfo->getId();
}
}
} else { } else {
$tplVars['error'] = T_('Username was not specified'); $user = urldecode($user);
$templateservice->loadTemplate('error.404.tpl', $tplVars); $userinfo = $userservice->getObjectUserByUsername($user);
exit(); if ($userinfo == NULL) {
$tplVars['error'] = sprintf(T_('User with username %s was not found'), $user);
$templateservice->loadTemplate('error.404.tpl', $tplVars);
exit();
} else {
$userid = $userinfo->getId();
}
} }
$tplVars['privateKeyIsEnabled'] = ''; $tplVars['privateKeyIsEnabled'] = '';
@ -92,54 +92,54 @@ if (POST_SUBMITTEDPK!='' && $currentUser->getId() == $userid) {
} }
if (POST_SUBMITTED!='' && $currentUser->getId() == $userid) { if (POST_SUBMITTED!='' && $currentUser->getId() == $userid) {
$error = false; $error = false;
$detPass = trim(POST_PASS); $detPass = trim(POST_PASS);
$detPassConf = trim(POST_PASSCONF); $detPassConf = trim(POST_PASSCONF);
$detName = trim(POST_NAME); $detName = trim(POST_NAME);
$detPrivateKey = trim(POST_PRIVATEKEY); $detPrivateKey = trim(POST_PRIVATEKEY);
$detEnablePrivateKey = trim(POST_ENABLEPRIVATEKEY); $detEnablePrivateKey = trim(POST_ENABLEPRIVATEKEY);
$detMail = trim(POST_MAIL); $detMail = trim(POST_MAIL);
$detPage = trim(POST_PAGE); $detPage = trim(POST_PAGE);
$detDesc = filter(POST_DESC); $detDesc = filter(POST_DESC);
// manage token preventing from CSRF vulnaribilities // manage token preventing from CSRF vulnaribilities
if ( SESSION_TOKEN == '' if ( SESSION_TOKEN == ''
|| time() - SESSION_TOKENSTAMP > 600 //limit token lifetime, optionnal || time() - SESSION_TOKENSTAMP > 600 //limit token lifetime, optionnal
|| SESSION_TOKEN != POST_TOKEN) { || SESSION_TOKEN != POST_TOKEN) {
$error = true; $error = true;
$tplVars['error'] = T_('Invalid Token'); $tplVars['error'] = T_('Invalid Token');
} }
if ($detPass != $detPassConf) { if ($detPass != $detPassConf) {
$error = true; $error = true;
$tplVars['error'] = T_('Password and confirmation do not match.'); $tplVars['error'] = T_('Password and confirmation do not match.');
} }
if ($detPass != "" && strlen($detPass) < 6) { if ($detPass != "" && strlen($detPass) < 6) {
$error = true; $error = true;
$tplVars['error'] = T_('Password must be at least 6 characters long.'); $tplVars['error'] = T_('Password must be at least 6 characters long.');
} }
if (!$userservice->isValidEmail($detMail)) { if (!$userservice->isValidEmail($detMail)) {
$error = true; $error = true;
$tplVars['error'] = T_('E-mail address is not valid.'); $tplVars['error'] = T_('E-mail address is not valid.');
} }
if (!$error) { if (!$error) {
if (!$userservice->updateUser($userid, $detPass, $detName, $detMail, $detPage, $detDesc, $detPrivateKey, $detEnablePrivateKey)) { if (!$userservice->updateUser($userid, $detPass, $detName, $detMail, $detPage, $detDesc, $detPrivateKey, $detEnablePrivateKey)) {
$tplVars['error'] = T_('An error occurred while saving your changes.'); $tplVars['error'] = T_('An error occurred while saving your changes.');
} else { } else {
$tplVars['msg'] = T_('Changes saved.'); $tplVars['msg'] = T_('Changes saved.');
} }
} }
$userinfo = $userservice->getObjectUserByUsername($user); $userinfo = $userservice->getObjectUserByUsername($user);
$tplVars['privateKey'] = $userinfo->getPrivateKey(true); $tplVars['privateKey'] = $userinfo->getPrivateKey(true);
if ($userservice->isPrivateKeyValid($userinfo->getPrivateKey())) { if ($userservice->isPrivateKeyValid($userinfo->getPrivateKey())) {
$tplVars['privateKeyIsEnabled'] = 'checked="checked"'; $tplVars['privateKeyIsEnabled'] = 'checked="checked"';
} else { } else {
$tplVars['privateKeyIsEnabled'] = ''; $tplVars['privateKeyIsEnabled'] = '';
} }
} }
if (!$userservice->isLoggedOn() || $currentUser->getId() != $userid) { if (!$userservice->isLoggedOn() || $currentUser->getId() != $userid) {
$templatename = 'profile.tpl.php'; $templatename = 'profile.tpl.php';
} else { } else {
$scert = SemanticScuttle_Service_Factory::get('User_SslClientCert'); $scert = SemanticScuttle_Service_Factory::get('User_SslClientCert');
@ -170,17 +170,65 @@ if (!$userservice->isLoggedOn() || $currentUser->getId() != $userid) {
} }
} }
//Token Init $oids = SemanticScuttle_Service_Factory::get('OpenId');
$_SESSION['token'] = md5(uniqid(rand(), true)); if (isset($_POST['action']) && $_POST['action'] == 'deleteOpenId'
$_SESSION['token_stamp'] = time(); && isset($_POST['openIdUrl'])
) {
$identifier = $_POST['openIdUrl'];
$openId = $oids->getId($identifier);
if ($openId === null || $openId->uId != $currentUser->getId()
) {
$tplVars['error'] = T_('OpenID not found.');
} else if (false === $oids->delete($openId->id)) {
$tplVars['error'] = T_('Failed to delete OpenID.');
} else {
$tplVars['msg'] = T_('OpenID deleted.');
}
}
$templatename = 'editprofile.tpl.php'; $openIdAction = false;
$openIdReturn = false;
if (isset($_POST['action']) && $_POST['action'] == 'registerOpenId'
&& isset($_POST['openid_identifier'])
) {
$openIdAction = true;
} else if (isset($method) && $method == 'openidreturn') {
$openIdAction = true;
$openIdReturn = true;
}
if ($openIdAction) {
$returnUrl = addProtocolToUrl(createURL('profile', $user . '/openidreturn'));
$tplVars['formaction'] = createURL('profile', $user); try {
$tplVars['token'] = $_SESSION['token']; if (!$openIdReturn) {
//part 1 of OpenID registration
$oids->sendIdRequest($_POST['openid_identifier'], $returnUrl);
} else {
//part 2
$ret = $oids->handleIdResponse($returnUrl);
$oids->register(
$currentUser->getId(), $ret['identifier'], $ret['email']
);
$tplVars['msg'] = T_('OpenID registered.');
}
} catch (Exception $e) {
$tplVars['error'] = SemanticScuttle_Exception::getErrorMessage($e);
}
}
$tplVars['sslClientCerts'] = $scert->getUserCerts($currentUser->getId());
$tplVars['currentCert'] = null; //Token Init
$_SESSION['token'] = md5(uniqid(rand(), true));
$_SESSION['token_stamp'] = time();
$templatename = 'editprofile.tpl.php';
$tplVars['formaction'] = createURL('profile', $user);
$tplVars['token'] = $_SESSION['token'];
$tplVars['sslClientCerts'] = $scert->getUserCerts($currentUser->getId());
$tplVars['openIds'] = $oids->getIds($currentUser->getId());
$tplVars['currentCert'] = null;
if ($scert->hasValidCert()) { if ($scert->hasValidCert()) {
$tplVars['currentCert'] = SemanticScuttle_Model_User_SslClientCert::fromCurrentCert(); $tplVars['currentCert'] = SemanticScuttle_Model_User_SslClientCert::fromCurrentCert();
} }