aboutsummaryrefslogtreecommitdiffstats
path: root/mod/id.php
diff options
context:
space:
mode:
Diffstat (limited to 'mod/id.php')
-rw-r--r--mod/id.php310
1 files changed, 310 insertions, 0 deletions
diff --git a/mod/id.php b/mod/id.php
new file mode 100644
index 000000000..bd4c1fa89
--- /dev/null
+++ b/mod/id.php
@@ -0,0 +1,310 @@
+<?php
+/**
+ * @file mod/id.php
+ * @brief OpenID implementation
+ */
+
+require 'library/openid/provider/provider.php';
+
+
+$attrMap = array(
+ 'namePerson/first' => t('First Name'),
+ 'namePerson/last' => t('Last Name'),
+ 'namePerson/friendly' => t('Nickname'),
+ 'namePerson' => t('Full Name'),
+ 'contact/internet/email' => t('Email'),
+ 'contact/email' => t('Email'),
+ 'media/image/aspect11' => t('Profile Photo'),
+ 'media/image' => t('Profile Photo'),
+ 'media/image/default' => t('Profile Photo'),
+ 'media/image/16x16' => t('Profile Photo 16px'),
+ 'media/image/32x32' => t('Profile Photo 32px'),
+ 'media/image/48x48' => t('Profile Photo 48px'),
+ 'media/image/64x64' => t('Profile Photo 64px'),
+ 'media/image/80x80' => t('Profile Photo 80px'),
+ 'media/image/128x128' => t('Profile Photo 128px'),
+ 'timezone' => t('Timezone'),
+ 'contact/web/default' => t('Homepage URL'),
+ 'language/pref' => t('Language'),
+ 'birthDate/birthYear' => t('Birth Year'),
+ 'birthDate/birthMonth' => t('Birth Month'),
+ 'birthDate/birthday' => t('Birth Day'),
+ 'birthDate' => t('Birthdate'),
+ 'gender' => t('Gender'),
+);
+
+
+/**
+ * @brief Entrypoint for the OpenID implementation.
+ *
+ * @param App &$a
+ */
+function id_init(&$a) {
+
+ logger('id: ' . print_r($_REQUEST, true));
+
+ if(argc() > 1) {
+ $which = argv(1);
+ } else {
+ $a->error = 404;
+ return;
+ }
+
+ $profile = '';
+ $channel = $a->get_channel();
+ profile_load($a,$which,$profile);
+
+ $op = new MysqlProvider;
+ $op->server();
+}
+
+/**
+ * @brief Returns user data needed for OpenID.
+ *
+ * If no $handle is provided we will use local_channel() by default.
+ *
+ * @param string $handle (default null)
+ * @return boolean|array
+ */
+function getUserData($handle = null) {
+ if (! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ get_app()->page['content'] = login();
+
+ return false;
+ }
+
+// logger('handle: ' . $handle);
+
+ if ($handle) {
+ $r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1",
+ dbesc($handle)
+ );
+ } else {
+ $r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d",
+ intval(local_channel())
+ );
+ }
+
+ if (! r)
+ return false;
+
+ $x = q("select * from account where account_id = %d limit 1",
+ intval($r[0]['channel_account_id'])
+ );
+ if ($x)
+ $r[0]['email'] = $x[0]['account_email'];
+
+ $p = q("select * from profile where is_default = 1 and uid = %d limit 1",
+ intval($r[0]['channel_account_id'])
+ );
+
+ $gender = '';
+ if ($p[0]['gender'] == t('Male'))
+ $gender = 'M';
+ if ($p[0]['gender'] == t('Female'))
+ $gender = 'F';
+
+ $r[0]['firstName'] = ((strpos($r[0]['channel_name'],' ')) ? substr($r[0]['channel_name'],0,strpos($r[0]['channel_name'],' ')) : $r[0]['channel_name']);
+ $r[0]['lastName'] = ((strpos($r[0]['channel_name'],' ')) ? substr($r[0]['channel_name'],strpos($r[0]['channel_name'],' ')+1) : '');
+ $r[0]['namePerson'] = $r[0]['channel_name'];
+ $r[0]['pphoto'] = $r[0]['xchan_photo_l'];
+ $r[0]['pphoto16'] = z_root() . '/photo/profile/16/' . $r[0]['channel_id'] . '.jpg';
+ $r[0]['pphoto32'] = z_root() . '/photo/profile/32/' . $r[0]['channel_id'] . '.jpg';
+ $r[0]['pphoto48'] = z_root() . '/photo/profile/48/' . $r[0]['channel_id'] . '.jpg';
+ $r[0]['pphoto64'] = z_root() . '/photo/profile/64/' . $r[0]['channel_id'] . '.jpg';
+ $r[0]['pphoto80'] = z_root() . '/photo/profile/80/' . $r[0]['channel_id'] . '.jpg';
+ $r[0]['pphoto128'] = z_root() . '/photo/profile/128/' . $r[0]['channel_id'] . '.jpg';
+ $r[0]['timezone'] = $r[0]['channel_timezone'];
+ $r[0]['url'] = $r[0]['xchan_url'];
+ $r[0]['language'] = (($x[0]['account_language']) ? $x[0]['account_language'] : 'en');
+ $r[0]['birthyear'] = ((intval(substr($p[0]['dob'],0,4))) ? intval(substr($p[0]['dob'],0,4)) : '');
+ $r[0]['birthmonth'] = ((intval(substr($p[0]['dob'],5,2))) ? intval(substr($p[0]['dob'],5,2)) : '');
+ $r[0]['birthday'] = ((intval(substr($p[0]['dob'],8,2))) ? intval(substr($p[0]['dob'],8,2)) : '');
+ $r[0]['birthdate'] = (($r[0]['birthyear'] && $r[0]['birthmonth'] && $r[0]['birthday']) ? $p[0]['dob'] : '');
+ $r[0]['gender'] = $gender;
+
+ return $r[0];
+
+/*
+* if(isset($_POST['login'],$_POST['password'])) {
+* $login = mysql_real_escape_string($_POST['login']);
+* $password = sha1($_POST['password']);
+* $q = mysql_query("SELECT * FROM Users WHERE login = '$login' AND password = '$password'");
+* if($data = mysql_fetch_assoc($q)) {
+* return $data;
+* }
+* if($handle) {
+* echo 'Wrong login/password.';
+* }
+* }
+* if($handle) {
+* ?>
+* <form action="" method="post">
+* <input type="hidden" name="openid.assoc_handle" value="<?php echo $handle?>">
+* Login: <input type="text" name="login"><br>
+* Password: <input type="password" name="password"><br>
+* <button>Submit</button>
+* </form>
+* <?php
+* die();
+* }
+*/
+
+}
+
+
+/**
+ * @brief MySQL provider for OpenID implementation.
+ *
+ */
+class MysqlProvider extends LightOpenIDProvider {
+
+ // See http://openid.net/specs/openid-attribute-properties-list-1_0-01.html
+ // This list contains a few variations of these attributes to maintain
+ // compatibility with legacy clients
+
+ private $attrFieldMap = array(
+ 'namePerson/first' => 'firstName',
+ 'namePerson/last' => 'lastName',
+ 'namePerson/friendly' => 'channel_address',
+ 'namePerson' => 'namePerson',
+ 'contact/internet/email' => 'email',
+ 'contact/email' => 'email',
+ 'media/image/aspect11' => 'pphoto',
+ 'media/image' => 'pphoto',
+ 'media/image/default' => 'pphoto',
+ 'media/image/16x16' => 'pphoto16',
+ 'media/image/32x32' => 'pphoto32',
+ 'media/image/48x48' => 'pphoto48',
+ 'media/image/64x64' => 'pphoto64',
+ 'media/image/80x80' => 'pphoto80',
+ 'media/image/128x128' => 'pphoto128',
+ 'timezone' => 'timezone',
+ 'contact/web/default' => 'url',
+ 'language/pref' => 'language',
+ 'birthDate/birthYear' => 'birthyear',
+ 'birthDate/birthMonth' => 'birthmonth',
+ 'birthDate/birthday' => 'birthday',
+ 'birthDate' => 'birthdate',
+ 'gender' => 'gender',
+ );
+
+ function setup($identity, $realm, $assoc_handle, $attributes) {
+ global $attrMap;
+
+// logger('identity: ' . $identity);
+// logger('realm: ' . $realm);
+// logger('assoc_handle: ' . $assoc_handle);
+// logger('attributes: ' . print_r($attributes,true));
+
+ $data = getUserData($assoc_handle);
+
+
+/** @FIXME this needs to be a template with localised strings */
+
+ $o .= '<form action="" method="post">'
+ . '<input type="hidden" name="openid.assoc_handle" value="' . $assoc_handle . '">'
+ . '<input type="hidden" name="login" value="' . $_POST['login'] .'">'
+ . '<input type="hidden" name="password" value="' . $_POST['password'] .'">'
+ . "<b>$realm</b> wishes to authenticate you.";
+ if($attributes['required'] || $attributes['optional']) {
+ $o .= " It also requests following information (required fields marked with *):"
+ . '<ul>';
+
+ foreach($attributes['required'] as $attr) {
+ if(isset($this->attrMap[$attr])) {
+ $o .= '<li>'
+ . '<input type="checkbox" name="attributes[' . $attr . ']"> '
+ . $this->attrMap[$attr] . ' <span class="required">*</span></li>';
+ }
+ }
+
+ foreach($attributes['optional'] as $attr) {
+ if(isset($this->attrMap[$attr])) {
+ $o .= '<li>'
+ . '<input type="checkbox" name="attributes[' . $attr . ']"> '
+ . $this->attrMap[$attr] . '</li>';
+ }
+ }
+ $o .= '</ul>';
+ }
+ $o .= '<br>'
+ . '<button name="once">Allow once</button> '
+ . '<button name="always">Always allow</button> '
+ . '<button name="cancel">cancel</button> '
+ . '</form>';
+
+ get_app()->page['content'] .= $o;
+ }
+
+ function checkid($realm, &$attributes) {
+
+ logger('checkid: ' . $realm);
+ logger('checkid attrs: ' . print_r($attributes,true));
+
+ if(isset($_POST['cancel'])) {
+ $this->cancel();
+ }
+
+ $data = getUserData();
+ if(! $data) {
+ return false;
+ }
+
+ $q = get_pconfig(local_channel(), 'openid', $realm);
+
+ $attrs = array();
+ if($q) {
+ $attrs = $q;
+ } elseif(isset($_POST['attributes'])) {
+ $attrs = array_keys($_POST['attributes']);
+ } elseif(!isset($_POST['once']) && !isset($_POST['always'])) {
+ return false;
+ }
+
+ $attributes = array();
+ foreach($attrs as $attr) {
+ if(isset($this->attrFieldMap[$attr])) {
+ $attributes[$attr] = $data[$this->attrFieldMap[$attr]];
+ }
+ }
+
+ if(isset($_POST['always'])) {
+ set_pconfig(local_channel(),'openid',$realm,array_keys($attributes));
+ }
+
+ return z_root() . '/id/' . $data['channel_address'];
+ }
+
+ function assoc_handle() {
+ logger('assoc_handle');
+ $channel = get_app()->get_channel();
+
+ return z_root() . '/channel/' . $channel['channel_address'];
+ }
+
+ function setAssoc($handle, $data) {
+ logger('setAssoc');
+ $channel = channelx_by_nick(basename($handle));
+ if($channel)
+ set_pconfig($channel['channel_id'],'openid','associate',$data);
+ }
+
+ function getAssoc($handle) {
+ logger('getAssoc: ' . $handle);
+
+ $channel = channelx_by_nick(basename($handle));
+ if($channel)
+ return get_pconfig($channel['channel_id'], 'openid', 'associate');
+
+ return false;
+ }
+
+ function delAssoc($handle) {
+ logger('delAssoc');
+ $channel = channelx_by_nick(basename($handle));
+ if($channel)
+ return del_pconfig($channel['channel_id'], 'openid', 'associate');
+ }
+}