From cb962ed4755f213042f72580180908033ef3276e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 13 Jan 2010 21:24:02 -0800 Subject: queue daemon fixes: path fix for xmpp, suppress warning in memcached init --- plugins/MemcachePlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/MemcachePlugin.php b/plugins/MemcachePlugin.php index fbc2802f7..bc7fd9076 100644 --- a/plugins/MemcachePlugin.php +++ b/plugins/MemcachePlugin.php @@ -166,7 +166,7 @@ class MemcachePlugin extends Plugin if (is_array($this->servers)) { foreach ($this->servers as $server) { - list($host, $port) = explode(';', $server); + list($host, $port) = @explode(';', $server); if (empty($port)) { $port = 11211; } -- cgit v1.2.3-54-g00ecf From 532a174fc0cbc1e2cecce8a5d732e21ef41c312e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 14 Jan 2010 14:07:24 -0800 Subject: Clean up host/port separation in memcached plugin -- use : not ; as separator and clean up some warnings --- plugins/MemcachePlugin.php | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'plugins') diff --git a/plugins/MemcachePlugin.php b/plugins/MemcachePlugin.php index bc7fd9076..5214ab9c8 100644 --- a/plugins/MemcachePlugin.php +++ b/plugins/MemcachePlugin.php @@ -165,20 +165,18 @@ class MemcachePlugin extends Plugin $this->_conn = new Memcache(); if (is_array($this->servers)) { - foreach ($this->servers as $server) { - list($host, $port) = @explode(';', $server); - if (empty($port)) { - $port = 11211; - } - - $this->_conn->addServer($host, $port, $this->persistent); - } + $servers = $this->servers; } else { - $this->_conn->addServer($this->servers, $this->persistent); - list($host, $port) = explode(';', $this->servers); - if (empty($port)) { + $servers = array($this->servers); + } + foreach ($servers as $server) { + if (strpos($server, ':') !== false) { + list($host, $port) = explode(':', $server); + } else { + $host = $server; $port = 11211; } + $this->_conn->addServer($host, $port, $this->persistent); } -- cgit v1.2.3-54-g00ecf From a27aef92060277120f8889136ed6972f5915709f Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Thu, 14 Jan 2010 19:43:03 -0500 Subject: Add nickname suggestion capability for use during autoregistration. --- lib/authenticationplugin.php | 56 +++++++++++++++++----- .../LdapAuthenticationPlugin.php | 16 +++++++ 2 files changed, 60 insertions(+), 12 deletions(-) (limited to 'plugins') diff --git a/lib/authenticationplugin.php b/lib/authenticationplugin.php index de479a576..17237086c 100644 --- a/lib/authenticationplugin.php +++ b/lib/authenticationplugin.php @@ -92,6 +92,19 @@ abstract class AuthenticationPlugin extends Plugin return false; } + /** + * Given a username, suggest what the nickname should be + * Used during autoregistration + * Useful if your usernames are ugly, and you want to suggest + * nice looking nicknames when users initially sign on + * @param username + * @return string nickname + */ + function suggestNicknameForUsername($username) + { + return $username; + } + //------------Below are the methods that connect StatusNet to the implementing Auth plugin------------\\ function onInitializePlugin(){ if(!isset($this->provider_name)){ @@ -108,10 +121,22 @@ abstract class AuthenticationPlugin extends Plugin function onAutoRegister($nickname, $provider_name, &$user) { if($provider_name == $this->provider_name && $this->autoregistration){ - $user = $this->autoregister($nickname); - if($user){ - User_username::register($user,$nickname,$this->provider_name); - return false; + $suggested_nickname = $this->suggestNicknameForUsername($nickname); + $test_user = User::staticGet('nickname', $suggested_nickname); + if($test_user) { + //someone already exists with the suggested nickname, so used the passed nickname + $suggested_nickname = $nickname; + } + $test_user = User::staticGet('nickname', $suggested_nickname); + if($test_user) { + //someone already exists with the suggested nickname + //not much else we can do + }else{ + $user = $this->autoregister($suggested_nickname); + if($user){ + User_username::register($user,$nickname,$this->provider_name); + return false; + } } } } @@ -122,23 +147,30 @@ abstract class AuthenticationPlugin extends Plugin $user_username->username=$nickname; $user_username->provider_name=$this->provider_name; if($user_username->find() && $user_username->fetch()){ - $username = $user_username->username; - $authenticated = $this->checkPassword($username, $password); + $authenticated = $this->checkPassword($user_username->username, $password); if($authenticated){ $authenticatedUser = User::staticGet('id', $user_username->user_id); return false; } }else{ - $user = User::staticGet('nickname', $nickname); + //$nickname is the username used to login + //$suggested_nickname is the nickname the auth provider suggests for that username + $suggested_nickname = $this->suggestNicknameForUsername($nickname); + $user = User::staticGet('nickname', $suggested_nickname); if($user){ - //make sure a different provider isn't handling this nickname + //make sure this user isn't claimed $user_username = new User_username(); - $user_username->username=$nickname; - if(!$user_username->find()){ - //no other provider claims this username, so it's safe for us to handle it + $user_username->user_id=$user->id; + $we_can_handle = false; + if($user_username->find()){ + //either this provider, or another one, has already claimed this user + //so we cannot. Let another plugin try. + return; + }else{ + //no other provider claims this user, so it's safe for us to handle it $authenticated = $this->checkPassword($nickname, $password); if($authenticated){ - $authenticatedUser = User::staticGet('nickname', $nickname); + $authenticatedUser = $user; User_username::register($authenticatedUser,$nickname,$this->provider_name); return false; } diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php index eb3a05117..1755033f1 100644 --- a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -153,6 +153,22 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin return false; } + + function suggestNicknameForUsername($username) + { + $entry = $this->ldap_get_user($username, $this->attributes); + if(!$entry){ + //this really shouldn't happen + return $username; + }else{ + $nickname = $entry->getValue($this->attributes['nickname'],'single'); + if($nickname){ + return $nickname; + }else{ + return $username; + } + } + } //---utility functions---// function ldap_get_config(){ -- cgit v1.2.3-54-g00ecf From 07de97a10339ae4a5adbe8dbb4a31c0304f677c3 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 17 Jan 2010 14:04:47 +0000 Subject: Inline script for maxlength is deprecated --- plugins/MobileProfile/MobileProfilePlugin.php | 2 -- 1 file changed, 2 deletions(-) (limited to 'plugins') diff --git a/plugins/MobileProfile/MobileProfilePlugin.php b/plugins/MobileProfile/MobileProfilePlugin.php index 14d2500e8..d426fc282 100644 --- a/plugins/MobileProfile/MobileProfilePlugin.php +++ b/plugins/MobileProfile/MobileProfilePlugin.php @@ -356,8 +356,6 @@ class MobileProfilePlugin extends WAP20Plugin $contentLimit = Notice::maxContent(); - $form->out->inlineScript('maxLength = ' . $contentLimit . ';'); - if ($contentLimit > 0) { $form->out->element('div', array('id' => 'notice_text-count'), $contentLimit); -- cgit v1.2.3-54-g00ecf From 3f589da24373f533de9a3fbbab1c6e80fa87b302 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 17 Jan 2010 19:45:35 +0000 Subject: Updated UI for notice aside content and notice options in MobileProfile --- plugins/MobileProfile/mp-screen.css | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/MobileProfile/mp-screen.css b/plugins/MobileProfile/mp-screen.css index 3eefc0c8e..472fbb001 100644 --- a/plugins/MobileProfile/mp-screen.css +++ b/plugins/MobileProfile/mp-screen.css @@ -179,10 +179,12 @@ padding-bottom:4px; } .notice div.entry-content { margin-left:0; -width:62.5%; +width:75%; +max-width:100%; +min-width:0; } .notice-options { -width:34%; +width:50px; margin-right:1%; } @@ -190,12 +192,29 @@ margin-right:1%; width:16px; height:16px; } -.notice-options a, -.notice-options input { +.notice .notice-options a, +.notice .notice-options input { box-shadow:none; -moz-box-shadow:none; -webkit-box-shadow:none; } +.notice .notice-options a, +.notice .notice-options form { +margin:-4px 0 0 0; +} +.notice .notice-options .notice_repeat, +.notice .notice-options .notice_delete { +margin-top:18px; +} +.notice .notice-options .notice_reply, +.notice .notice-options .notice_repeat { +margin-left:18px; +} + + +.notice .notice-options .notice_delete { +float:left; +} .entity_profile { width:auto; -- cgit v1.2.3-54-g00ecf From ae9f2bf18725d72952a7f884dc9faebe92dc0541 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 18 Jan 2010 09:37:42 -0800 Subject: add a quickie plugins/ dir readme mentioning how to add plugins, plus ref to wiki pages --- plugins/README-plugins | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 plugins/README-plugins (limited to 'plugins') diff --git a/plugins/README-plugins b/plugins/README-plugins new file mode 100644 index 000000000..cdce7eb18 --- /dev/null +++ b/plugins/README-plugins @@ -0,0 +1,21 @@ +Several example plugins are included in the plugins/ directory. You +can enable a plugin with the following line in config.php: + + addPlugin('Example', array('param1' => 'value1', + 'param2' => 'value2')); + +This will look for and load files named 'ExamplePlugin.php' or +'Example/ExamplePlugin.php' either in the plugins/ directory (for +plugins that ship with StatusNet) or in the local/ directory (for +plugins you write yourself or that you get from somewhere else) or +local/plugins/. + +Plugins are documented in their own directories. + + +Additional information on using and developing plugins can be found +on the StatusNet wiki: + +http://status.net/wiki/Plugins +http://status.net/wiki/Plugin_development + -- cgit v1.2.3-54-g00ecf From 0ddfcc5521e023db7be52fe783800a39701ff94f Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Mon, 18 Jan 2010 18:31:13 -0500 Subject: Added Plugin Version info to recaptcha plugin --- plugins/Recaptcha/RecaptchaPlugin.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/Recaptcha/RecaptchaPlugin.php b/plugins/Recaptcha/RecaptchaPlugin.php index 3665214f8..c585da43c 100644 --- a/plugins/Recaptcha/RecaptchaPlugin.php +++ b/plugins/Recaptcha/RecaptchaPlugin.php @@ -31,8 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -define('RECAPTCHA', '0.2'); - require_once(INSTALLDIR.'/plugins/Recaptcha/recaptchalib.php'); class RecaptchaPlugin extends Plugin @@ -88,4 +86,16 @@ class RecaptchaPlugin extends Plugin return false; } } + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'Recaptcha', + 'version' => STATUSNET_VERSION, + 'author' => 'Eric Helgeson', + 'homepage' => 'http://status.net/wiki/Plugin:Recaptcha', + 'rawdescription' => + _m('Uses Recaptcha service to add a '. + 'captcha to the registration page.')); + return true; + } } -- cgit v1.2.3-54-g00ecf From b87c80e0a903119e97484333445c8944607a6b0d Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 20 Jan 2010 18:32:24 +0100 Subject: Updated notice item view where a) notice text no longer wraps around (under author's photo) b) supplemental notice content and options will start right under notice text. --- plugins/MobileProfile/mp-screen.css | 12 +++++++++++- theme/base/css/display.css | 22 +++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/MobileProfile/mp-screen.css b/plugins/MobileProfile/mp-screen.css index 472fbb001..76071352d 100644 --- a/plugins/MobileProfile/mp-screen.css +++ b/plugins/MobileProfile/mp-screen.css @@ -176,8 +176,18 @@ margin-bottom:0; .profile { padding-top:4px; padding-bottom:4px; +min-height:65px; } -.notice div.entry-content { +#content .notice .entry-title { +float:left; +width:100%; +margin-left:0; +} +#content .notice .author .photo { +position:static; +float:left; +} +#content .notice div.entry-content { margin-left:0; width:75%; max-width:100%; diff --git a/theme/base/css/display.css b/theme/base/css/display.css index fbf3b6a5b..84e9426c7 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -1012,6 +1012,16 @@ float:left; #shownotice .vcard .photo { margin-bottom:4px; } +#content .notice .author .photo { +position:absolute; +top:11px; +left:0; +float:none; +} +#content .notice .entry-title { +margin-left:59px; +} + .vcard .url { text-decoration:none; } @@ -1020,13 +1030,19 @@ text-decoration:underline; } .notice .entry-title { -float:left; -width:100%; overflow:hidden; } .notice .entry-title.ov { overflow:visible; } +#showstream .notice .entry-title, +#showstream .notice div.entry-content { +margin-left:0; +} +#shownotice .notice .entry-title, +#shownotice .notice div.entry-content { +margin-left:110px; +} #shownotice .notice .entry-title { font-size:2.2em; } @@ -1056,7 +1072,6 @@ max-width:70%; } #showstream .notice div.entry-content, #shownotice .notice div.entry-content { -margin-left:0; max-width:79%; } @@ -1120,6 +1135,7 @@ position:relative; font-size:0.95em; width:113px; float:right; +margin-top:3px; margin-right:4px; } -- cgit v1.2.3-54-g00ecf From 6815ddafe011d534e7d6e16972833e120c36e4e3 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 20 Jan 2010 18:50:48 +0100 Subject: Better alignment for notice options in MobileProfile --- plugins/MobileProfile/mp-screen.css | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'plugins') diff --git a/plugins/MobileProfile/mp-screen.css b/plugins/MobileProfile/mp-screen.css index 76071352d..04fa5fb00 100644 --- a/plugins/MobileProfile/mp-screen.css +++ b/plugins/MobileProfile/mp-screen.css @@ -194,7 +194,7 @@ max-width:100%; min-width:0; } .notice-options { -width:50px; +width:43px; margin-right:1%; } @@ -202,6 +202,13 @@ margin-right:1%; width:16px; height:16px; } +.notice-options form.processing { +background-image:none; +} +#wrap .notice-options form.processing input.submit { +background-position:0 47%; +} + .notice .notice-options a, .notice .notice-options input { box-shadow:none; @@ -212,16 +219,16 @@ box-shadow:none; .notice .notice-options form { margin:-4px 0 0 0; } -.notice .notice-options .notice_repeat, +.notice .notice-options .form_repeat, .notice .notice-options .notice_delete { -margin-top:18px; +margin-top:11px; } -.notice .notice-options .notice_reply, -.notice .notice-options .notice_repeat { -margin-left:18px; +.notice .notice-options .form_favor, +.notice .notice-options .form_disfavor, +.notice .notice-options .form_repeat { +margin-right:11px; } - .notice .notice-options .notice_delete { float:left; } -- cgit v1.2.3-54-g00ecf From 8c54151dbd2dbf99b23124ec618b2fa5570ac2ee Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Sat, 23 Jan 2010 13:08:59 -0500 Subject: Use StartQueueDaemonIoManagers instead of removed StartIoManagerClasses event --- plugins/Imap/ImapPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/Imap/ImapPlugin.php b/plugins/Imap/ImapPlugin.php index 89a775a16..d1e920b00 100644 --- a/plugins/Imap/ImapPlugin.php +++ b/plugins/Imap/ImapPlugin.php @@ -86,7 +86,7 @@ class ImapPlugin extends Plugin } } - function onStartIoManagerClasses(&$classes) + function onStartQueueDaemonIoManagers(&$classes) { $classes[] = new ImapManager($this); } -- cgit v1.2.3-54-g00ecf From dd513b3e535ce298252e1861af07b38651e83b8e Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 24 Jan 2010 15:34:40 +0100 Subject: Added version info for MobileProfile plugin --- plugins/MobileProfile/MobileProfilePlugin.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/MobileProfile/MobileProfilePlugin.php b/plugins/MobileProfile/MobileProfilePlugin.php index d426fc282..5c913836d 100644 --- a/plugins/MobileProfile/MobileProfilePlugin.php +++ b/plugins/MobileProfile/MobileProfilePlugin.php @@ -414,7 +414,15 @@ class MobileProfilePlugin extends WAP20Plugin return $proto.'://'.$serverpart.'/'.$pathpart.$relative; } -} - -?> + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'MobileProfile', + 'version' => STATUSNET_VERSION, + 'author' => 'Sarven Capadisli', + 'homepage' => 'http://status.net/wiki/Plugin:MobileProfile', + 'rawdescription' => + _m('XHTML MobileProfile output for supporting user agents.')); + return true; + } +} -- cgit v1.2.3-54-g00ecf From a5836d33e4fcd0c51a6cb6d67863f109f454ccb0 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 22 Jan 2010 15:04:53 -0800 Subject: Fix for PoweredByStatusNetPlugin to be localizable (was broken for non-English word order) (Note the .po files will have to be added manually for now as we haven't set TranslateWiki up for plugins I think) --- .../PoweredByStatusNetPlugin.php | 5 ++-- .../locale/PoweredByStatusNet.po | 32 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 plugins/PoweredByStatusNet/locale/PoweredByStatusNet.po (limited to 'plugins') diff --git a/plugins/PoweredByStatusNet/PoweredByStatusNetPlugin.php b/plugins/PoweredByStatusNet/PoweredByStatusNetPlugin.php index c59fcca89..14d1608d3 100644 --- a/plugins/PoweredByStatusNet/PoweredByStatusNetPlugin.php +++ b/plugins/PoweredByStatusNet/PoweredByStatusNetPlugin.php @@ -46,8 +46,9 @@ class PoweredByStatusNetPlugin extends Plugin function onEndAddressData($action) { $action->elementStart('span', 'poweredby'); - $action->text(_('powered by')); - $action->element('a', array('href' => 'http://status.net/'), 'StatusNet'); + $action->raw(sprintf(_m('powered by %s'), + sprintf('%s', + _m('StatusNet')))); $action->elementEnd('span'); return true; diff --git a/plugins/PoweredByStatusNet/locale/PoweredByStatusNet.po b/plugins/PoweredByStatusNet/locale/PoweredByStatusNet.po new file mode 100644 index 000000000..bd39124ef --- /dev/null +++ b/plugins/PoweredByStatusNet/locale/PoweredByStatusNet.po @@ -0,0 +1,32 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-01-22 15:03-0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: PoweredByStatusNetPlugin.php:49 +#, php-format +msgid "powered by %s" +msgstr "" + +#: PoweredByStatusNetPlugin.php:51 +msgid "StatusNet" +msgstr "" + +#: PoweredByStatusNetPlugin.php:64 +msgid "" +"Outputs powered by StatusNet after site " +"name." +msgstr "" -- cgit v1.2.3-54-g00ecf From 3fc3a2b326a01cd443f36456fe3e7b43ed4b4f2b Mon Sep 17 00:00:00 2001 From: Julien C Date: Tue, 8 Dec 2009 22:16:03 +0100 Subject: Allow logging in using Twitter Signed-off-by: Julien C --- plugins/TwitterBridge/TwitterBridgePlugin.php | 26 ++ plugins/TwitterBridge/twitter_connect.gif | Bin 0 -> 2205 bytes plugins/TwitterBridge/twitterauthorization.php | 433 +++++++++++++++++++++++-- plugins/TwitterBridge/twitterlogin.php | 95 ++++++ 4 files changed, 527 insertions(+), 27 deletions(-) create mode 100644 plugins/TwitterBridge/twitter_connect.gif create mode 100644 plugins/TwitterBridge/twitterlogin.php (limited to 'plugins') diff --git a/plugins/TwitterBridge/TwitterBridgePlugin.php b/plugins/TwitterBridge/TwitterBridgePlugin.php index 57b3c1c99..e39ec7be0 100644 --- a/plugins/TwitterBridge/TwitterBridgePlugin.php +++ b/plugins/TwitterBridge/TwitterBridgePlugin.php @@ -72,9 +72,34 @@ class TwitterBridgePlugin extends Plugin $m->connect('twitter/authorization', array('action' => 'twitterauthorization')); $m->connect('settings/twitter', array('action' => 'twittersettings')); + + $m->connect('main/twitterlogin', array('action' => 'twitterlogin')); return true; } + + + + /* + * Add a login tab for Twitter Connect + * + * @param Action &action the current action + * + * @return void + */ + function onEndLoginGroupNav(&$action) + { + + $action_name = $action->trimmed('action'); + + $action->menuItem(common_local_url('twitterlogin'), + _('Twitter'), + _('Login or register using Twitter'), + 'twitterlogin' === $action_name); + + return true; + } + /** * Add the Twitter Settings page to the Connect Settings menu @@ -108,6 +133,7 @@ class TwitterBridgePlugin extends Plugin switch ($cls) { case 'TwittersettingsAction': case 'TwitterauthorizationAction': + case 'TwitterloginAction': include_once INSTALLDIR . '/plugins/TwitterBridge/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; return false; diff --git a/plugins/TwitterBridge/twitter_connect.gif b/plugins/TwitterBridge/twitter_connect.gif new file mode 100644 index 000000000..e3d8f3ed7 Binary files /dev/null and b/plugins/TwitterBridge/twitter_connect.gif differ diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index 4af2f0394..8ae725374 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -21,7 +21,7 @@ * * @category TwitterauthorizationAction * @package StatusNet - * @author Zach Copely + * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -50,6 +50,10 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php'; */ class TwitterauthorizationAction extends Action { + var $twuid = null; + var $tw_fields = null; + var $access_token = null; + /** * Initialize class members. Looks for 'oauth_token' parameter. * @@ -76,29 +80,56 @@ class TwitterauthorizationAction extends Action function handle($args) { parent::handle($args); - - if (!common_logged_in()) { - $this->clientError(_m('Not logged in.'), 403); + + if (common_logged_in()) { + $user = common_current_user(); + $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); + + // If there's already a foreign link record, it means we already + // have an access token, and this is unecessary. So go back. + + if (isset($flink)) { + common_redirect(common_local_url('twittersettings')); + } } - - $user = common_current_user(); - $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); - - // If there's already a foreign link record, it means we already - // have an access token, and this is unecessary. So go back. - - if (isset($flink)) { - common_redirect(common_local_url('twittersettings')); - } - - // $this->oauth_token is only populated once Twitter authorizes our - // request token. If it's empty we're at the beginning of the auth - // process - - if (empty($this->oauth_token)) { - $this->authorizeRequestToken(); + + + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + // User was not logged in to StatusNet before + $this->twuid = $this->trimmed('twuid'); + $this->tw_fields = array("name" => $this->trimmed('name'), "fullname" => $this->trimmed('fullname')); + $this->access_token = new OAuthToken($this->trimmed('access_token_key'), $this->trimmed('access_token_secret')); + + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->showForm(_('There was a problem with your session token. Try again, please.')); + return; + } + if ($this->arg('create')) { + if (!$this->boolean('license')) { + $this->showForm(_('You can\'t register if you don\'t agree to the license.'), + $this->trimmed('newname')); + return; + } + $this->createNewUser(); + } else if ($this->arg('connect')) { + $this->connectNewUser(); + } else { + common_debug('Twitter Connect Plugin - ' . + print_r($this->args, true)); + $this->showForm(_('Something weird happened.'), + $this->trimmed('newname')); + } } else { - $this->saveAccessToken(); + // $this->oauth_token is only populated once Twitter authorizes our + // request token. If it's empty we're at the beginning of the auth + // process + + if (empty($this->oauth_token)) { + $this->authorizeRequestToken(); + } else { + $this->saveAccessToken(); + } } } @@ -170,16 +201,25 @@ class TwitterauthorizationAction extends Action $this->serverError(_m('Couldn\'t link your Twitter account.')); } - // Save the access token and Twitter user info - - $this->saveForeignLink($atok, $twitter_user); + if (common_logged_in()) { + // Save the access token and Twitter user info + $this->saveForeignLink($atok, $twitter_user); + } + else{ + $this->twuid = $twitter_user->id; + $this->tw_fields = array("name" => $twitter_user->screen_name, "fullname" => $twitter_user->name); + $this->access_token = $atok; + $this->tryLogin(); + } // Clean up the the mess we made in the session unset($_SESSION['twitter_request_token']); unset($_SESSION['twitter_request_token_secret']); - - common_redirect(common_local_url('twittersettings')); + + if (common_logged_in()) { + common_redirect(common_local_url('twittersettings')); + } } /** @@ -220,5 +260,344 @@ class TwitterauthorizationAction extends Action save_twitter_user($twitter_user->id, $twitter_user->screen_name); } + + + + function showPageNotice() + { + if ($this->error) { + $this->element('div', array('class' => 'error'), $this->error); + } else { + $this->element('div', 'instructions', + sprintf(_('This is the first time you\'ve logged into %s so we must connect your Twitter account to a local account. You can either create a new account, or connect with your existing account, if you have one.'), common_config('site', 'name'))); + } + } + + function title() + { + return _('Twitter Account Setup'); + } + + function showForm($error=null, $username=null) + { + $this->error = $error; + $this->username = $username; + + $this->showPage(); + } + + function showPage() + { + parent::showPage(); + } + + function showContent() + { + if (!empty($this->message_text)) { + $this->element('p', null, $this->message); + return; + } + + $this->elementStart('form', array('method' => 'post', + 'id' => 'form_settings_twitter_connect', + 'class' => 'form_settings', + 'action' => common_local_url('twitterauthorization'))); + $this->elementStart('fieldset', array('id' => 'settings_twitter_connect_options')); + $this->element('legend', null, _('Connection options')); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + $this->element('input', array('type' => 'checkbox', + 'id' => 'license', + 'class' => 'checkbox', + 'name' => 'license', + 'value' => 'true')); + $this->elementStart('label', array('class' => 'checkbox', 'for' => 'license')); + $this->text(_('My text and files are available under ')); + $this->element('a', array('href' => common_config('license', 'url')), + common_config('license', 'title')); + $this->text(_(' except this private data: password, email address, IM address, phone number.')); + $this->elementEnd('label'); + $this->elementEnd('li'); + $this->elementEnd('ul'); + $this->hidden('access_token_key', $this->access_token->key); + $this->hidden('access_token_secret', $this->access_token->secret); + $this->hidden('twuid', $this->twuid); + $this->hidden('tw_fields_name', $this->tw_fields['name']); + $this->hidden('tw_fields_fullname', $this->tw_fields['fullname']); + + $this->elementStart('fieldset'); + $this->hidden('token', common_session_token()); + $this->element('legend', null, + _('Create new account')); + $this->element('p', null, + _('Create a new user with this nickname.')); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + $this->input('newname', _('New nickname'), + ($this->username) ? $this->username : '', + _('1-64 lowercase letters or numbers, no punctuation or spaces')); + $this->elementEnd('li'); + $this->elementEnd('ul'); + $this->submit('create', _('Create')); + $this->elementEnd('fieldset'); + + $this->elementStart('fieldset'); + $this->element('legend', null, + _('Connect existing account')); + $this->element('p', null, + _('If you already have an account, login with your username and password to connect it to your Twitter account.')); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + $this->input('nickname', _('Existing nickname')); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->password('password', _('Password')); + $this->elementEnd('li'); + $this->elementEnd('ul'); + $this->submit('connect', _('Connect')); + $this->elementEnd('fieldset'); + + $this->elementEnd('fieldset'); + $this->elementEnd('form'); + } + + function message($msg) + { + $this->message_text = $msg; + $this->showPage(); + } + + function createNewUser() + { + if (common_config('site', 'closed')) { + $this->clientError(_('Registration not allowed.')); + return; + } + + $invite = null; + + if (common_config('site', 'inviteonly')) { + $code = $_SESSION['invitecode']; + if (empty($code)) { + $this->clientError(_('Registration not allowed.')); + return; + } + + $invite = Invitation::staticGet($code); + + if (empty($invite)) { + $this->clientError(_('Not a valid invitation code.')); + return; + } + } + + $nickname = $this->trimmed('newname'); + + if (!Validate::string($nickname, array('min_length' => 1, + 'max_length' => 64, + 'format' => NICKNAME_FMT))) { + $this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.')); + return; + } + + if (!User::allowed_nickname($nickname)) { + $this->showForm(_('Nickname not allowed.')); + return; + } + + if (User::staticGet('nickname', $nickname)) { + $this->showForm(_('Nickname already in use. Try another one.')); + return; + } + + $fullname = trim($this->tw_fields['fullname']); + + $args = array('nickname' => $nickname, 'fullname' => $fullname); + + if (!empty($invite)) { + $args['code'] = $invite->code; + } + + $user = User::register($args); + + $result = $this->flinkUser($user->id, $this->twuid); + + if (!$result) { + $this->serverError(_('Error connecting user to Twitter.')); + return; + } + + common_set_user($user); + common_real_login(true); + + common_debug('Twitter Connect Plugin - ' . + "Registered new user $user->id from Twitter user $this->fbuid"); + + common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)), + 303); + } + + function connectNewUser() + { + $nickname = $this->trimmed('nickname'); + $password = $this->trimmed('password'); + + if (!common_check_user($nickname, $password)) { + $this->showForm(_('Invalid username or password.')); + return; + } + + $user = User::staticGet('nickname', $nickname); + + if (!empty($user)) { + common_debug('Twitter Connect Plugin - ' . + "Legit user to connect to Twitter: $nickname"); + } + + $result = $this->flinkUser($user->id, $this->twuid); + + if (!$result) { + $this->serverError(_('Error connecting user to Twitter.')); + return; + } + + common_debug('Twitter Connnect Plugin - ' . + "Connected Twitter user $this->fbuid to local user $user->id"); + + common_set_user($user); + common_real_login(true); + + $this->goHome($user->nickname); + } + + function connectUser() + { + $user = common_current_user(); + + $result = $this->flinkUser($user->id, $this->twuid); + + if (empty($result)) { + $this->serverError(_('Error connecting user to Twitter.')); + return; + } + + common_debug('Twitter Connect Plugin - ' . + "Connected Twitter user $this->fbuid to local user $user->id"); + + // Return to Twitter connection settings tab + common_redirect(common_local_url('twittersettings'), 303); + } + + function tryLogin() + { + common_debug('Twitter Connect Plugin - ' . + "Trying login for Twitter user $this->fbuid."); + + $flink = Foreign_link::getByForeignID($this->twuid, TWITTER_SERVICE); + + if (!empty($flink)) { + $user = $flink->getUser(); + + if (!empty($user)) { + + common_debug('Twitter Connect Plugin - ' . + "Logged in Twitter user $flink->foreign_id as user $user->id ($user->nickname)"); + + common_set_user($user); + common_real_login(true); + $this->goHome($user->nickname); + } + + } else { + + common_debug('Twitter Connect Plugin - ' . + "No flink found for twuid: $this->twuid - new user"); + + $this->showForm(null, $this->bestNewNickname()); + } + } + + function goHome($nickname) + { + $url = common_get_returnto(); + if ($url) { + // We don't have to return to it again + common_set_returnto(null); + } else { + $url = common_local_url('all', + array('nickname' => + $nickname)); + } + + common_redirect($url, 303); + } + + function flinkUser($user_id, $twuid) + { + $flink = new Foreign_link(); + + $flink->user_id = $user_id; + $flink->foreign_id = $twuid; + $flink->service = TWITTER_SERVICE; + + $creds = TwitterOAuthClient::packToken($this->access_token); + + $flink->credentials = $creds; + $flink->created = common_sql_now(); + + // Defaults: noticesync on, everything else off + + $flink->set_flags(true, false, false, false); + + $flink_id = $flink->insert(); + + if (empty($flink_id)) { + common_log_db_error($flink, 'INSERT', __FILE__); + $this->serverError(_('Couldn\'t link your Twitter account.')); + } + + save_twitter_user($twuid, $this->tw_fields['name']); + + return $flink_id; + } + + + function bestNewNickname() + { + if (!empty($this->tw_fields['name'])) { + $nickname = $this->nicknamize($this->tw_fields['name']); + if ($this->isNewNickname($nickname)) { + return $nickname; + } + } + + return null; + } + + // Given a string, try to make it work as a nickname + + function nicknamize($str) + { + $str = preg_replace('/\W/', '', $str); + $str = str_replace(array('-', '_'), '', $str); + return strtolower($str); + } + + function isNewNickname($str) + { + if (!Validate::string($str, array('min_length' => 1, + 'max_length' => 64, + 'format' => NICKNAME_FMT))) { + return false; + } + if (!User::allowed_nickname($str)) { + return false; + } + if (User::staticGet('nickname', $str)) { + return false; + } + return true; + } + } diff --git a/plugins/TwitterBridge/twitterlogin.php b/plugins/TwitterBridge/twitterlogin.php new file mode 100644 index 000000000..ae468ea15 --- /dev/null +++ b/plugins/TwitterBridge/twitterlogin.php @@ -0,0 +1,95 @@ +. + * + * @category Settings + * @package StatusNet + * @author Evan Prodromou + * @copyright 2008-2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php'; + +/** + * Settings for Twitter integration + * + * @category Settings + * @package StatusNet + * @author Evan Prodromou + * @author Julien Chaumond + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see SettingsAction + */ + + +class TwitterloginAction extends Action +{ + function handle($args) + { + parent::handle($args); + + if (common_is_real_login()) { + $this->clientError(_('Already logged in.')); + } + + $this->showPage(); + } + + function title() + { + return _('Twitter Login'); + } + + function getInstructions() + { + return _('Login with your Twitter Account'); + } + + function showPageNotice() + { + $instr = $this->getInstructions(); + $output = common_markup_to_html($instr); + $this->elementStart('div', 'instructions'); + $this->raw($output); + $this->elementEnd('div'); + } + + function showContent() + { + $this->elementStart('a', array('href' => common_local_url('twitterauthorization'))); + $this->element('img', array('src' => common_path('plugins/TwitterBridge/twitter_connect.gif'), + 'alt' => 'Connect my Twitter account')); + $this->elementEnd('a'); + } + + function showLocalNav() + { + $nav = new LoginGroupNav($this); + $nav->show(); + } +} -- cgit v1.2.3-54-g00ecf From d429710fe182abb5c9681a5c46e3c87d08a04574 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 26 Jan 2010 01:25:33 +0000 Subject: - Twitter username wasn't getting stored in Foreign_user when linking Twitter account (fixed) - Updates to comments --- plugins/TwitterBridge/twitterauthorization.php | 109 +++++++++++++------------ 1 file changed, 58 insertions(+), 51 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index 8ae725374..3f7316b7a 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -53,7 +53,7 @@ class TwitterauthorizationAction extends Action var $twuid = null; var $tw_fields = null; var $access_token = null; - + /** * Initialize class members. Looks for 'oauth_token' parameter. * @@ -80,31 +80,37 @@ class TwitterauthorizationAction extends Action function handle($args) { parent::handle($args); - + if (common_logged_in()) { $user = common_current_user(); $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); - + // If there's already a foreign link record, it means we already // have an access token, and this is unecessary. So go back. - + if (isset($flink)) { common_redirect(common_local_url('twittersettings')); } } - - + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + // User was not logged in to StatusNet before + $this->twuid = $this->trimmed('twuid'); - $this->tw_fields = array("name" => $this->trimmed('name'), "fullname" => $this->trimmed('fullname')); + + $this->tw_fields = array('name' => $this->trimmed('tw_fields_name'), + 'fullname' => $this->trimmed('tw_fields_fullname')); + $this->access_token = new OAuthToken($this->trimmed('access_token_key'), $this->trimmed('access_token_secret')); $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { $this->showForm(_('There was a problem with your session token. Try again, please.')); return; } + if ($this->arg('create')) { if (!$this->boolean('license')) { $this->showForm(_('You can\'t register if you don\'t agree to the license.'), @@ -124,7 +130,7 @@ class TwitterauthorizationAction extends Action // $this->oauth_token is only populated once Twitter authorizes our // request token. If it's empty we're at the beginning of the auth // process - + if (empty($this->oauth_token)) { $this->authorizeRequestToken(); } else { @@ -181,6 +187,8 @@ class TwitterauthorizationAction extends Action $this->serverError(_m('Couldn\'t link your Twitter account.')); } + $twitter_user = null; + try { $client = new TwitterOAuthClient($_SESSION['twitter_request_token'], @@ -196,16 +204,19 @@ class TwitterauthorizationAction extends Action $twitter_user = $client->verifyCredentials(); } catch (OAuthClientException $e) { - $msg = sprintf('OAuth client cURL error - code: %1$s, msg: %2$s', + $msg = sprintf('OAuth client error - code: %1$s, msg: %2$s', $e->getCode(), $e->getMessage()); $this->serverError(_m('Couldn\'t link your Twitter account.')); } if (common_logged_in()) { + // Save the access token and Twitter user info + $this->saveForeignLink($atok, $twitter_user); - } - else{ + + } else { + $this->twuid = $twitter_user->id; $this->tw_fields = array("name" => $twitter_user->screen_name, "fullname" => $twitter_user->name); $this->access_token = $atok; @@ -216,7 +227,7 @@ class TwitterauthorizationAction extends Action unset($_SESSION['twitter_request_token']); unset($_SESSION['twitter_request_token_secret']); - + if (common_logged_in()) { common_redirect(common_local_url('twittersettings')); } @@ -260,8 +271,34 @@ class TwitterauthorizationAction extends Action save_twitter_user($twitter_user->id, $twitter_user->screen_name); } + function flinkUser($user_id, $twuid) + { + $flink = new Foreign_link(); + + $flink->user_id = $user_id; + $flink->foreign_id = $twuid; + $flink->service = TWITTER_SERVICE; + + $creds = TwitterOAuthClient::packToken($this->access_token); + $flink->credentials = $creds; + $flink->created = common_sql_now(); + // Defaults: noticesync on, everything else off + + $flink->set_flags(true, false, false, false); + + $flink_id = $flink->insert(); + + if (empty($flink_id)) { + common_log_db_error($flink, 'INSERT', __FILE__); + $this->serverError(_('Couldn\'t link your Twitter account.')); + } + + save_twitter_user($twuid, $this->tw_fields['name']); + + return $flink_id; + } function showPageNotice() { @@ -430,7 +467,7 @@ class TwitterauthorizationAction extends Action common_set_user($user); common_real_login(true); - common_debug('Twitter Connect Plugin - ' . + common_debug('TwitterBridge Plugin - ' . "Registered new user $user->id from Twitter user $this->fbuid"); common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)), @@ -450,7 +487,7 @@ class TwitterauthorizationAction extends Action $user = User::staticGet('nickname', $nickname); if (!empty($user)) { - common_debug('Twitter Connect Plugin - ' . + common_debug('TwitterBridge Plugin - ' . "Legit user to connect to Twitter: $nickname"); } @@ -461,7 +498,7 @@ class TwitterauthorizationAction extends Action return; } - common_debug('Twitter Connnect Plugin - ' . + common_debug('TwitterBridge Plugin - ' . "Connected Twitter user $this->fbuid to local user $user->id"); common_set_user($user); @@ -481,17 +518,17 @@ class TwitterauthorizationAction extends Action return; } - common_debug('Twitter Connect Plugin - ' . + common_debug('TwitterBridge Plugin - ' . "Connected Twitter user $this->fbuid to local user $user->id"); // Return to Twitter connection settings tab common_redirect(common_local_url('twittersettings'), 303); } - + function tryLogin() { - common_debug('Twitter Connect Plugin - ' . - "Trying login for Twitter user $this->fbuid."); + common_debug('TwitterBridge Plugin - ' . + "Trying login for Twitter user $this->twuid."); $flink = Foreign_link::getByForeignID($this->twuid, TWITTER_SERVICE); @@ -500,7 +537,7 @@ class TwitterauthorizationAction extends Action if (!empty($user)) { - common_debug('Twitter Connect Plugin - ' . + common_debug('TwitterBridge Plugin - ' . "Logged in Twitter user $flink->foreign_id as user $user->id ($user->nickname)"); common_set_user($user); @@ -510,7 +547,7 @@ class TwitterauthorizationAction extends Action } else { - common_debug('Twitter Connect Plugin - ' . + common_debug('TwitterBridge Plugin - ' . "No flink found for twuid: $this->twuid - new user"); $this->showForm(null, $this->bestNewNickname()); @@ -531,37 +568,7 @@ class TwitterauthorizationAction extends Action common_redirect($url, 303); } - - function flinkUser($user_id, $twuid) - { - $flink = new Foreign_link(); - - $flink->user_id = $user_id; - $flink->foreign_id = $twuid; - $flink->service = TWITTER_SERVICE; - - $creds = TwitterOAuthClient::packToken($this->access_token); - - $flink->credentials = $creds; - $flink->created = common_sql_now(); - - // Defaults: noticesync on, everything else off - - $flink->set_flags(true, false, false, false); - - $flink_id = $flink->insert(); - if (empty($flink_id)) { - common_log_db_error($flink, 'INSERT', __FILE__); - $this->serverError(_('Couldn\'t link your Twitter account.')); - } - - save_twitter_user($twuid, $this->tw_fields['name']); - - return $flink_id; - } - - function bestNewNickname() { if (!empty($this->tw_fields['name'])) { -- cgit v1.2.3-54-g00ecf From e5bd707055fe2a4bec852efdca11b8b1f28dc126 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 26 Jan 2010 01:51:40 +0000 Subject: Ask the user to set a password before disconnecting from Twitter --- plugins/TwitterBridge/twittersettings.php | 33 ++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twittersettings.php b/plugins/TwitterBridge/twittersettings.php index bc9a636a1..0137060e9 100644 --- a/plugins/TwitterBridge/twittersettings.php +++ b/plugins/TwitterBridge/twittersettings.php @@ -121,8 +121,35 @@ class TwittersettingsAction extends ConnectSettingsAction $this->elementEnd('p'); $this->element('p', 'form_note', _m('Connected Twitter account')); + $this->elementEnd('fieldset'); + + $this->elementStart('fieldset'); + + $this->element('legend', null, _m('Disconnect my account from Twitter')); - $this->submit('remove', _m('Remove')); + if (!$user->password) { + + $this->elementStart('p', array('class' => 'form_guide')); + $this->text(_m('Disconnecting your Twitter ' . + 'could make it impossible to log in! Please ')); + $this->element('a', + array('href' => common_local_url('passwordsettings')), + _m('set a password')); + + $this->text(_m(' first.')); + $this->elementEnd('p'); + } else { + + $note = _m('Keep your %1$s account but disconnect from Twitter. ' . + 'You can use your %1$s password to log in.'); + + $site = common_config('site', 'name'); + + $this->element('p', 'instructions', + sprintf($note, $site)); + + $this->submit('disconnect', _m('Disconnect')); + } $this->elementEnd('fieldset'); @@ -205,7 +232,7 @@ class TwittersettingsAction extends ConnectSettingsAction if ($this->arg('save')) { $this->savePreferences(); - } else if ($this->arg('remove')) { + } else if ($this->arg('disconnect')) { $this->removeTwitterAccount(); } else { $this->showForm(_m('Unexpected form submission.')); @@ -231,7 +258,7 @@ class TwittersettingsAction extends ConnectSettingsAction return; } - $this->showForm(_m('Twitter account removed.'), true); + $this->showForm(_m('Twitter account disconnected.'), true); } /** -- cgit v1.2.3-54-g00ecf From 7064d15e67cd6818e0a03a74fb63d5ca215dd1bd Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 26 Jan 2010 02:40:44 +0000 Subject: Use "Sign in with Twitter" auth pattern and official Twitter button for Twitter-based login. See: http://apiwiki.twitter.com/Sign-in-with-Twitter --- plugins/TwitterBridge/twitter_connect.gif | Bin 2205 -> 0 bytes plugins/TwitterBridge/twitterauthorization.php | 8 +++++--- plugins/TwitterBridge/twitterlogin.php | 11 ++++++----- plugins/TwitterBridge/twitteroauthclient.php | 7 +++++-- 4 files changed, 16 insertions(+), 10 deletions(-) delete mode 100644 plugins/TwitterBridge/twitter_connect.gif (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitter_connect.gif b/plugins/TwitterBridge/twitter_connect.gif deleted file mode 100644 index e3d8f3ed7..000000000 Binary files a/plugins/TwitterBridge/twitter_connect.gif and /dev/null differ diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index 3f7316b7a..15408668f 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -50,9 +50,10 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php'; */ class TwitterauthorizationAction extends Action { - var $twuid = null; - var $tw_fields = null; + var $twuid = null; + var $tw_fields = null; var $access_token = null; + var $signin = null; /** * Initialize class members. Looks for 'oauth_token' parameter. @@ -65,6 +66,7 @@ class TwitterauthorizationAction extends Action { parent::prepare($args); + $this->signin = $this->boolean('signin'); $this->oauth_token = $this->arg('oauth_token'); return true; @@ -160,7 +162,7 @@ class TwitterauthorizationAction extends Action $_SESSION['twitter_request_token'] = $req_tok->key; $_SESSION['twitter_request_token_secret'] = $req_tok->secret; - $auth_link = $client->getAuthorizeLink($req_tok); + $auth_link = $client->getAuthorizeLink($req_tok, $this->signin); } catch (OAuthClientException $e) { $msg = sprintf('OAuth client cURL error - code: %1s, msg: %2s', diff --git a/plugins/TwitterBridge/twitterlogin.php b/plugins/TwitterBridge/twitterlogin.php index ae468ea15..ae67b4c15 100644 --- a/plugins/TwitterBridge/twitterlogin.php +++ b/plugins/TwitterBridge/twitterlogin.php @@ -46,7 +46,6 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php'; * @see SettingsAction */ - class TwitterloginAction extends Action { function handle($args) @@ -67,7 +66,7 @@ class TwitterloginAction extends Action function getInstructions() { - return _('Login with your Twitter Account'); + return _('Login with your Twitter account'); } function showPageNotice() @@ -81,9 +80,11 @@ class TwitterloginAction extends Action function showContent() { - $this->elementStart('a', array('href' => common_local_url('twitterauthorization'))); - $this->element('img', array('src' => common_path('plugins/TwitterBridge/twitter_connect.gif'), - 'alt' => 'Connect my Twitter account')); + $this->elementStart('a', array('href' => common_local_url('twitterauthorization', + null, + array('signin' => true)))); + $this->element('img', array('src' => common_path('plugins/TwitterBridge/Sign-in-with-Twitter-lighter.png'), + 'alt' => 'Sign in with Twitter')); $this->elementEnd('a'); } diff --git a/plugins/TwitterBridge/twitteroauthclient.php b/plugins/TwitterBridge/twitteroauthclient.php index bad2b74ca..277e7ab40 100644 --- a/plugins/TwitterBridge/twitteroauthclient.php +++ b/plugins/TwitterBridge/twitteroauthclient.php @@ -45,6 +45,7 @@ class TwitterOAuthClient extends OAuthClient { public static $requestTokenURL = 'https://twitter.com/oauth/request_token'; public static $authorizeURL = 'https://twitter.com/oauth/authorize'; + public static $signinUrl = 'https://twitter.com/oauth/authenticate'; public static $accessTokenURL = 'https://twitter.com/oauth/access_token'; /** @@ -97,9 +98,11 @@ class TwitterOAuthClient extends OAuthClient * * @return the link */ - function getAuthorizeLink($request_token) + function getAuthorizeLink($request_token, $signin = false) { - return parent::getAuthorizeLink(self::$authorizeURL, + $url = ($signin) ? self::$signinUrl : self::$authorizeURL; + + return parent::getAuthorizeLink($url, $request_token, common_local_url('twitterauthorization')); } -- cgit v1.2.3-54-g00ecf From 7a0a133401a3803b607e06d9f593f7e225be3a8a Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 26 Jan 2010 07:29:40 +0000 Subject: - Remove redundant function - clean up log msgs --- plugins/TwitterBridge/twitterauthorization.php | 74 ++++++++++---------------- 1 file changed, 28 insertions(+), 46 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index 15408668f..a95cdebb9 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -101,7 +101,7 @@ class TwitterauthorizationAction extends Action $this->twuid = $this->trimmed('twuid'); - $this->tw_fields = array('name' => $this->trimmed('tw_fields_name'), + $this->tw_fields = array('screen_name' => $this->trimmed('tw_fields_screen_name'), 'fullname' => $this->trimmed('tw_fields_fullname')); $this->access_token = new OAuthToken($this->trimmed('access_token_key'), $this->trimmed('access_token_secret')); @@ -215,12 +215,15 @@ class TwitterauthorizationAction extends Action // Save the access token and Twitter user info - $this->saveForeignLink($atok, $twitter_user); + $user = common_current_user(); + $this->saveForeignLink($user->id, $twitter_user->id, $atok); + save_twitter_user($twitter_user->id, $twitter_user->name); } else { $this->twuid = $twitter_user->id; - $this->tw_fields = array("name" => $twitter_user->screen_name, "fullname" => $twitter_user->name); + $this->tw_fields = array("screen_name" => $twitter_user->screen_name, + "name" => $twitter_user->name); $this->access_token = $atok; $this->tryLogin(); } @@ -239,41 +242,13 @@ class TwitterauthorizationAction extends Action * Saves a Foreign_link between Twitter user and local user, * which includes the access token and secret. * - * @param OAuthToken $access_token the access token to save - * @param mixed $twitter_user twitter API user object + * @param int $user_id StatusNet user ID + * @param int $twuid Twitter user ID + * @param OAuthToken $token the access token to save * * @return nothing */ - function saveForeignLink($access_token, $twitter_user) - { - $user = common_current_user(); - - $flink = new Foreign_link(); - - $flink->user_id = $user->id; - $flink->foreign_id = $twitter_user->id; - $flink->service = TWITTER_SERVICE; - - $creds = TwitterOAuthClient::packToken($access_token); - - $flink->credentials = $creds; - $flink->created = common_sql_now(); - - // Defaults: noticesync on, everything else off - - $flink->set_flags(true, false, false, false); - - $flink_id = $flink->insert(); - - if (empty($flink_id)) { - common_log_db_error($flink, 'INSERT', __FILE__); - $this->serverError(_m('Couldn\'t link your Twitter account.')); - } - - save_twitter_user($twitter_user->id, $twitter_user->screen_name); - } - - function flinkUser($user_id, $twuid) + function saveForeignLink($user_id, $twuid, $access_token) { $flink = new Foreign_link(); @@ -281,7 +256,7 @@ class TwitterauthorizationAction extends Action $flink->foreign_id = $twuid; $flink->service = TWITTER_SERVICE; - $creds = TwitterOAuthClient::packToken($this->access_token); + $creds = TwitterOAuthClient::packToken($access_token); $flink->credentials = $creds; $flink->created = common_sql_now(); @@ -297,8 +272,6 @@ class TwitterauthorizationAction extends Action $this->serverError(_('Couldn\'t link your Twitter account.')); } - save_twitter_user($twuid, $this->tw_fields['name']); - return $flink_id; } @@ -361,8 +334,8 @@ class TwitterauthorizationAction extends Action $this->hidden('access_token_key', $this->access_token->key); $this->hidden('access_token_secret', $this->access_token->secret); $this->hidden('twuid', $this->twuid); + $this->hidden('tw_fields_screen_name', $this->tw_fields['screen_name']); $this->hidden('tw_fields_name', $this->tw_fields['name']); - $this->hidden('tw_fields_fullname', $this->tw_fields['fullname']); $this->elementStart('fieldset'); $this->hidden('token', common_session_token()); @@ -449,7 +422,7 @@ class TwitterauthorizationAction extends Action return; } - $fullname = trim($this->tw_fields['fullname']); + $fullname = trim($this->tw_fields['name']); $args = array('nickname' => $nickname, 'fullname' => $fullname); @@ -459,7 +432,11 @@ class TwitterauthorizationAction extends Action $user = User::register($args); - $result = $this->flinkUser($user->id, $this->twuid); + $result = $this->saveForeignLink($user->id, + $this->twuid, + $this->access_token); + + save_twitter_user($this->twuid, $this->tw_fields['screen_name']); if (!$result) { $this->serverError(_('Error connecting user to Twitter.')); @@ -470,7 +447,7 @@ class TwitterauthorizationAction extends Action common_real_login(true); common_debug('TwitterBridge Plugin - ' . - "Registered new user $user->id from Twitter user $this->fbuid"); + "Registered new user $user->id from Twitter user $this->twuid"); common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)), 303); @@ -493,7 +470,11 @@ class TwitterauthorizationAction extends Action "Legit user to connect to Twitter: $nickname"); } - $result = $this->flinkUser($user->id, $this->twuid); + $result = $this->saveForeignLink($user->id, + $this->twuid, + $this->access_token); + + save_twitter_user($this->twuid, $this->tw_fields['screen_name']); if (!$result) { $this->serverError(_('Error connecting user to Twitter.')); @@ -501,7 +482,7 @@ class TwitterauthorizationAction extends Action } common_debug('TwitterBridge Plugin - ' . - "Connected Twitter user $this->fbuid to local user $user->id"); + "Connected Twitter user $this->twuid to local user $user->id"); common_set_user($user); common_real_login(true); @@ -521,7 +502,7 @@ class TwitterauthorizationAction extends Action } common_debug('TwitterBridge Plugin - ' . - "Connected Twitter user $this->fbuid to local user $user->id"); + "Connected Twitter user $this->twuid to local user $user->id"); // Return to Twitter connection settings tab common_redirect(common_local_url('twittersettings'), 303); @@ -532,7 +513,8 @@ class TwitterauthorizationAction extends Action common_debug('TwitterBridge Plugin - ' . "Trying login for Twitter user $this->twuid."); - $flink = Foreign_link::getByForeignID($this->twuid, TWITTER_SERVICE); + $flink = Foreign_link::getByForeignID($this->twuid, + TWITTER_SERVICE); if (!empty($flink)) { $user = $flink->getUser(); -- cgit v1.2.3-54-g00ecf From d6a0dec76537628ac680a9f483f75c5abdd01077 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 26 Jan 2010 07:50:01 +0000 Subject: Add Julien C to author comments --- plugins/TwitterBridge/TwitterBridgePlugin.php | 12 +++++------- plugins/TwitterBridge/twitterauthorization.php | 8 +++++--- plugins/TwitterBridge/twitterlogin.php | 15 ++++++++------- 3 files changed, 18 insertions(+), 17 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/TwitterBridgePlugin.php b/plugins/TwitterBridge/TwitterBridgePlugin.php index e39ec7be0..c7f57ffc7 100644 --- a/plugins/TwitterBridge/TwitterBridgePlugin.php +++ b/plugins/TwitterBridge/TwitterBridgePlugin.php @@ -20,7 +20,8 @@ * @category Plugin * @package StatusNet * @author Zach Copley - * @copyright 2009 Control Yourself, Inc. + * @author Julien C + * @copyright 2009-2010 Control Yourself, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ */ @@ -41,6 +42,7 @@ define('TWITTERBRIDGEPLUGIN_VERSION', '0.9'); * @category Plugin * @package StatusNet * @author Zach Copley + * @author Julien C * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ * @link http://twitter.com/ @@ -72,16 +74,13 @@ class TwitterBridgePlugin extends Plugin $m->connect('twitter/authorization', array('action' => 'twitterauthorization')); $m->connect('settings/twitter', array('action' => 'twittersettings')); - $m->connect('main/twitterlogin', array('action' => 'twitterlogin')); return true; } - - - + /* - * Add a login tab for Twitter Connect + * Add a login tab for 'Sign in with Twitter' * * @param Action &action the current action * @@ -99,7 +98,6 @@ class TwitterBridgePlugin extends Plugin return true; } - /** * Add the Twitter Settings page to the Connect Settings menu diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index a95cdebb9..b2657ff61 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -19,10 +19,11 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * - * @category TwitterauthorizationAction + * @category Plugin * @package StatusNet * @author Zach Copley - * @copyright 2009 StatusNet, Inc. + * @author Julien C + * @copyright 2009-2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -41,9 +42,10 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php'; * (Foreign_link) between the StatusNet user and Twitter user and stores the * access token and secret in the link. * - * @category Twitter + * @category Plugin * @package StatusNet * @author Zach Copley + * @author Julien C * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ * diff --git a/plugins/TwitterBridge/twitterlogin.php b/plugins/TwitterBridge/twitterlogin.php index ae67b4c15..79421fb27 100644 --- a/plugins/TwitterBridge/twitterlogin.php +++ b/plugins/TwitterBridge/twitterlogin.php @@ -2,7 +2,7 @@ /** * StatusNet, the distributed open-source microblogging tool * - * Settings for Twitter integration + * 'Sign in with Twitter' login page * * PHP version 5 * @@ -19,10 +19,11 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * - * @category Settings + * @category Login * @package StatusNet - * @author Evan Prodromou - * @copyright 2008-2009 StatusNet, Inc. + * @author Julien Chaumond + * @author Zach Copley + * @copyright 2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -34,12 +35,12 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php'; /** - * Settings for Twitter integration + * Page for logging in with Twitter * - * @category Settings + * @category Login * @package StatusNet - * @author Evan Prodromou * @author Julien Chaumond + * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ * -- cgit v1.2.3-54-g00ecf From 7695daebb7463a83ddddb06fb56bf8875973c695 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 26 Jan 2010 19:13:05 +0100 Subject: Updated geolocation sharing in notice form for Realtime pop --- plugins/Realtime/realtimeupdate.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.css b/plugins/Realtime/realtimeupdate.css index 56f869354..31e7c2ae6 100644 --- a/plugins/Realtime/realtimeupdate.css +++ b/plugins/Realtime/realtimeupdate.css @@ -18,7 +18,8 @@ display:none; } .realtime-popup #form_notice label[for=notice_data-attach], -.realtime-popup #form_notice #notice_data-attach { +.realtime-popup #form_notice #notice_data-attach, +.realtime-popup #form_notice label[for=notice_data-geo] { top:0; } -- cgit v1.2.3-54-g00ecf From b6dea910fcd3cafcec8d16ac621aaae02209052e Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 28 Jan 2010 04:46:10 +0000 Subject: Move faceboookapp.js to the Facebook plugin --- js/facebookapp.js | 33 --------------------------------- plugins/Facebook/facebookaction.php | 4 +--- plugins/Facebook/facebookapp.js | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 36 deletions(-) delete mode 100644 js/facebookapp.js create mode 100644 plugins/Facebook/facebookapp.js (limited to 'plugins') diff --git a/js/facebookapp.js b/js/facebookapp.js deleted file mode 100644 index 5deb6e42b..000000000 --- a/js/facebookapp.js +++ /dev/null @@ -1,33 +0,0 @@ -/* -* StatusNet - a distributed open-source microblogging tool -* Copyright (C) 2008, StatusNet, Inc. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see . -*/ - -var max = 140; -var noticeBox = document.getElementById('notice_data-text'); - -if (noticeBox) { - noticeBox.addEventListener('keyup', keypress); - noticeBox.addEventListener('keydown', keypress); - noticeBox.addEventListener('keypress', keypress); - noticeBox.addEventListener('change', keypress); -} - -// Do our the countdown -function keypress(evt) { - document.getElementById('notice_text-count').setTextValue( - max - noticeBox.getValue().length); -} diff --git a/plugins/Facebook/facebookaction.php b/plugins/Facebook/facebookaction.php index 389e1ea81..8437a705a 100644 --- a/plugins/Facebook/facebookaction.php +++ b/plugins/Facebook/facebookaction.php @@ -89,7 +89,7 @@ class FacebookAction extends Action function showScripts() { - $this->script('facebookapp.js'); + $this->script(common_path('plugins/Facebook/facebookapp.js')); } /** @@ -397,8 +397,6 @@ class FacebookAction extends Action return; } - - } } diff --git a/plugins/Facebook/facebookapp.js b/plugins/Facebook/facebookapp.js new file mode 100644 index 000000000..5deb6e42b --- /dev/null +++ b/plugins/Facebook/facebookapp.js @@ -0,0 +1,33 @@ +/* +* StatusNet - a distributed open-source microblogging tool +* Copyright (C) 2008, StatusNet, Inc. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +var max = 140; +var noticeBox = document.getElementById('notice_data-text'); + +if (noticeBox) { + noticeBox.addEventListener('keyup', keypress); + noticeBox.addEventListener('keydown', keypress); + noticeBox.addEventListener('keypress', keypress); + noticeBox.addEventListener('change', keypress); +} + +// Do our the countdown +function keypress(evt) { + document.getElementById('notice_text-count').setTextValue( + max - noticeBox.getValue().length); +} -- cgit v1.2.3-54-g00ecf From 664a82e836b6b5511e925c55983f122508c07232 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 28 Jan 2010 18:11:44 +0000 Subject: 'Sign in with Twitter' button img --- plugins/TwitterBridge/Sign-in-with-Twitter-lighter.png | Bin 0 -> 2490 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plugins/TwitterBridge/Sign-in-with-Twitter-lighter.png (limited to 'plugins') diff --git a/plugins/TwitterBridge/Sign-in-with-Twitter-lighter.png b/plugins/TwitterBridge/Sign-in-with-Twitter-lighter.png new file mode 100644 index 000000000..297bb0340 Binary files /dev/null and b/plugins/TwitterBridge/Sign-in-with-Twitter-lighter.png differ -- cgit v1.2.3-54-g00ecf From edf99dc45bcb28f60ea260e2a2a1bad148971a97 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 29 Jan 2010 15:43:37 +0000 Subject: Adds notice author's name to @title in Realtime response --- plugins/Realtime/realtimeupdate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index 52151f9de..fb9dcdbfb 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -132,11 +132,11 @@ RealtimeUpdate = { user = data['user']; html = data['html'].replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/&/g,'&'); source = data['source'].replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/&/g,'&'); - +console.log(data); ni = "
  • "+ "
    "+ ""+ - ""+ + ""+ "\""+user['screen_name']+"\"/"+ ""+user['screen_name']+""+ ""+ -- cgit v1.2.3-54-g00ecf From 61d4709eb855827e8d15a3e873760e4ad797b45b Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 29 Jan 2010 20:43:16 -0500 Subject: Pass username and nickname to autoregister so auth plugins can set the nickname correct when creating a new user. Continues fixing what Eric Helgeson pointed out in 01eb4e8f003bf62575ec16dfb6127d7534be9c88 --- lib/authenticationplugin.php | 12 ++++++++---- plugins/LdapAuthentication/LdapAuthenticationPlugin.php | 6 +++++- .../ReverseUsernameAuthenticationPlugin.php | 7 +++++-- 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'plugins') diff --git a/lib/authenticationplugin.php b/lib/authenticationplugin.php index f7f8f8655..5be3ea5b9 100644 --- a/lib/authenticationplugin.php +++ b/lib/authenticationplugin.php @@ -69,13 +69,17 @@ abstract class AuthenticationPlugin extends Plugin /** * Automatically register a user when they attempt to login with valid credentials. * User::register($data) is a very useful method for this implementation - * @param username + * @param username username (that is used to login and find the user in the authentication provider) of the user to be registered + * @param nickname nickname of the user in the SN system. If nickname is null, then set nickname = username * @return mixed instance of User, or false (if user couldn't be created) */ - function autoRegister($username) + function autoRegister($username, $nickname = null) { + if(is_null($nickname)){ + $nickname = $username; + } $registration_data = array(); - $registration_data['nickname'] = $username ; + $registration_data['nickname'] = $nickname ; return User::register($registration_data); } @@ -132,7 +136,7 @@ abstract class AuthenticationPlugin extends Plugin //someone already exists with the suggested nickname //not much else we can do }else{ - $user = $this->autoRegister($nickname); + $user = $this->autoRegister($nickname, $suggested_nickname); if($user){ User_username::register($user,$nickname,$this->provider_name); return false; diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php index 1755033f1..768f0fe7f 100644 --- a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -96,8 +96,11 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin } } - function autoRegister($username) + function autoRegister($username, $nickname) { + if(is_null($nickname)){ + $nickname = $username; + } $entry = $this->ldap_get_user($username,$this->attributes); if($entry){ $registration_data = array(); @@ -107,6 +110,7 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin if(isset($registration_data['email']) && !empty($registration_data['email'])){ $registration_data['email_confirmed']=true; } + $registration_data['nickname'] = $nickname; //set the database saved password to a random string. $registration_data['password']=common_good_rand(16); return User::register($registration_data); diff --git a/plugins/ReverseUsernameAuthentication/ReverseUsernameAuthenticationPlugin.php b/plugins/ReverseUsernameAuthentication/ReverseUsernameAuthenticationPlugin.php index d9d2137f8..dac5a1588 100644 --- a/plugins/ReverseUsernameAuthentication/ReverseUsernameAuthenticationPlugin.php +++ b/plugins/ReverseUsernameAuthentication/ReverseUsernameAuthenticationPlugin.php @@ -47,10 +47,13 @@ class ReverseUsernameAuthenticationPlugin extends AuthenticationPlugin return $username == strrev($password); } - function autoRegister($username) + function autoRegister($username, $nickname) { + if(is_null($nickname)){ + $nickname = $username; + } $registration_data = array(); - $registration_data['nickname'] = $username ; + $registration_data['nickname'] = $nickname ; return User::register($registration_data); } -- cgit v1.2.3-54-g00ecf From 72f72d17dbc2ddf5228d97079f992a99f2821373 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 4 Feb 2010 01:53:08 +0000 Subject: - Fix cache handling in TwitterStatusFetcher - Other stability fixes --- .../TwitterBridge/daemons/twitterstatusfetcher.php | 53 ++++++++++++++++++---- 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php index 36732ce46..bff657eb6 100755 --- a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php +++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php @@ -2,7 +2,7 @@ is_local = Notice::GATEWAY; if (Event::handle('StartNoticeSave', array(&$notice))) { - $id = $notice->insert(); + $notice->insert(); Event::handle('EndNoticeSave', array($notice)); } @@ -270,17 +270,41 @@ class TwitterStatusFetcher extends ParallelizingDaemon Inbox::insertNotice($flink->user_id, $notice->id); - $notice->blowCaches(); + $notice->blowOnInsert(); return $notice; } + /** + * Look up a Profile by profileurl field. Profile::staticGet() was + * not working consistently. + * + * @param string $url the profile url + * + * @return mixed the first profile with that url, or null + */ + + function getProfileByUrl($nickname, $profileurl) + { + $profile = new Profile(); + $profile->nickname = $nickname; + $profile->profileurl = $profileurl; + $profile->limit(1); + + if ($profile->find()) { + $profile->fetch(); + return $profile; + } + + return null; + } + function ensureProfile($user) { // check to see if there's already a profile for this user $profileurl = 'http://twitter.com/' . $user->screen_name; - $profile = Profile::staticGet('profileurl', $profileurl); + $profile = $this->getProfileByUrl($user->screen_name, $profileurl); if (!empty($profile)) { common_debug($this->name() . @@ -292,6 +316,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon return $profile->id; } else { + common_debug($this->name() . ' - Adding profile and remote profile ' . "for Twitter user: $profileurl."); @@ -306,7 +331,11 @@ class TwitterStatusFetcher extends ParallelizingDaemon $profile->profileurl = $profileurl; $profile->created = common_sql_now(); - $id = $profile->insert(); + try { + $id = $profile->insert(); + } catch(Exception $e) { + common_log(LOG_WARNING, $this->name . ' Couldn\'t insert profile - ' . $e->getMessage()); + } if (empty($id)) { common_log_db_error($profile, 'INSERT', __FILE__); @@ -326,7 +355,11 @@ class TwitterStatusFetcher extends ParallelizingDaemon $remote_pro->uri = $profileurl; $remote_pro->created = common_sql_now(); - $rid = $remote_pro->insert(); + try { + $rid = $remote_pro->insert(); + } catch (Exception $e) { + common_log(LOG_WARNING, $this->name() . ' Couldn\'t save remote profile - ' . $e->getMessage()); + } if (empty($rid)) { common_log_db_error($profile, 'INSERT', __FILE__); @@ -446,7 +479,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon if ($this->fetchAvatar($url, $filename)) { $this->newAvatar($id, $size, $mediatype, $filename); } else { - common_log(LOG_WARNING, $this->id() . + common_log(LOG_WARNING, $id() . " - Problem fetching Avatar: $url"); } } @@ -507,7 +540,11 @@ class TwitterStatusFetcher extends ParallelizingDaemon $avatar->created = common_sql_now(); - $id = $avatar->insert(); + try { + $id = $avatar->insert(); + } catch (Exception $e) { + common_log(LOG_WARNING, $this->name() . ' Couldn\'t insert avatar - ' . $e->getMessage()); + } if (empty($id)) { common_log_db_error($avatar, 'INSERT', __FILE__); -- cgit v1.2.3-54-g00ecf From feaf938ffd4dc27f2c03b4a532f78b172ddb35e4 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 4 Feb 2010 03:17:48 +0000 Subject: Make Twitter bridge truncate and add a link back to the original notice when notice content is > 140c --- plugins/TwitterBridge/twitter.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 33dfb788b..6944a1ace 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -1,7 +1,7 @@ content); // Convert !groups to #hashes + + // XXX: Make this an optional setting? + $statustxt = preg_replace('/(^|\s)!([A-Za-z0-9]{1,64})/', "\\1#\\2", $statustxt); + if (mb_strlen($statustxt) > 140) { + $noticeUrl = common_shorten_url($notice->uri); + $urlLen = mb_strlen($noticeUrl); + $statustxt = mb_substr($statustxt, 0, 140 - ($urlLen + 3)) . ' … ' . $noticeUrl; + } + return $statustxt; } -- cgit v1.2.3-54-g00ecf From e89107549475ee1e824bcf6f0bd66830fb724b2f Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 4 Feb 2010 19:39:46 +0000 Subject: Moved hardcoded identica theme out of MobileProfile. In this case, it will use whichever theme is loaded as its base and then add its own mobile styles. Of course, if a theme comes with its own mobile styles, it will use that instead as an addition to its own base. --- plugins/MobileProfile/MobileProfilePlugin.php | 10 ++++++++++ plugins/MobileProfile/mp-screen.css | 5 +---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/MobileProfile/MobileProfilePlugin.php b/plugins/MobileProfile/MobileProfilePlugin.php index 5c913836d..cd2531fa7 100644 --- a/plugins/MobileProfile/MobileProfilePlugin.php +++ b/plugins/MobileProfile/MobileProfilePlugin.php @@ -240,6 +240,8 @@ class MobileProfilePlugin extends WAP20Plugin return true; } + $action->cssLink('css/display.css'); + if (file_exists(Theme::file('css/mp-screen.css'))) { $action->cssLink('css/mp-screen.css', null, 'screen'); } else { @@ -256,6 +258,14 @@ class MobileProfilePlugin extends WAP20Plugin } + function onStartShowUAStyles($action) { + if (!$this->serveMobile) { + return true; + } + + return false; + } + function onStartShowHeader($action) { if (!$this->serveMobile) { diff --git a/plugins/MobileProfile/mp-screen.css b/plugins/MobileProfile/mp-screen.css index 04fa5fb00..0fc801612 100644 --- a/plugins/MobileProfile/mp-screen.css +++ b/plugins/MobileProfile/mp-screen.css @@ -1,15 +1,12 @@ /** theme: mobile profile screen * * @package StatusNet - * @author Sarven Capadisli + * @author Sarven Capadisli * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ -@import url(../../theme/base/css/display.css); -@import url(../../theme/identica/css/display.css); - #wrap { min-width:0; max-width:100%; -- cgit v1.2.3-54-g00ecf From a5f03484daf22f6e36bfc29a6b17907a7595c728 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 5 Feb 2010 21:39:29 -0800 Subject: Store Twitter screen_name, not name, for foreign_user.nickname when saving Twitter user. --- plugins/TwitterBridge/twitterauthorization.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index b2657ff61..dbef438a4 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -219,7 +219,7 @@ class TwitterauthorizationAction extends Action $user = common_current_user(); $this->saveForeignLink($user->id, $twitter_user->id, $atok); - save_twitter_user($twitter_user->id, $twitter_user->name); + save_twitter_user($twitter_user->id, $twitter_user->screen_name); } else { -- cgit v1.2.3-54-g00ecf From cfe4e460ca68b7c4d6c8213cf78df8a48414e342 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sat, 6 Feb 2010 06:46:00 +0000 Subject: Delete old Twitter user record when user changes screen name instead of updating. Simpler. --- plugins/TwitterBridge/twitter.php | 54 ++++++--------------------------------- 1 file changed, 8 insertions(+), 46 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 6944a1ace..5761074c2 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -26,38 +26,6 @@ define('TWITTER_SERVICE', 1); // Twitter is foreign_service ID 1 require_once INSTALLDIR . '/plugins/TwitterBridge/twitterbasicauthclient.php'; require_once INSTALLDIR . '/plugins/TwitterBridge/twitteroauthclient.php'; -function updateTwitter_user($twitter_id, $screen_name) -{ - $uri = 'http://twitter.com/' . $screen_name; - $fuser = new Foreign_user(); - - $fuser->query('BEGIN'); - - // Dropping down to SQL because regular DB_DataObject udpate stuff doesn't seem - // to work so good with tables that have multiple column primary keys - - // Any time we update the uri for a forein user we have to make sure there - // are no dupe entries first -- unique constraint on the uri column - - $qry = 'UPDATE foreign_user set uri = \'\' WHERE uri = '; - $qry .= '\'' . $uri . '\'' . ' AND service = ' . TWITTER_SERVICE; - - $fuser->query($qry); - - // Update the user - - $qry = 'UPDATE foreign_user SET nickname = '; - $qry .= '\'' . $screen_name . '\'' . ', uri = \'' . $uri . '\' '; - $qry .= 'WHERE id = ' . $twitter_id . ' AND service = ' . TWITTER_SERVICE; - - $fuser->query('COMMIT'); - - $fuser->free(); - unset($fuser); - - return true; -} - function add_twitter_user($twitter_id, $screen_name) { @@ -105,7 +73,6 @@ function add_twitter_user($twitter_id, $screen_name) // Creates or Updates a Twitter user function save_twitter_user($twitter_id, $screen_name) { - // Check to see whether the Twitter user is already in the system, // and update its screen name and uri if so. @@ -115,25 +82,20 @@ function save_twitter_user($twitter_id, $screen_name) $result = true; - // Only update if Twitter screen name has changed + // Delete old record if Twitter user changed screen name if ($fuser->nickname != $screen_name) { - $result = updateTwitter_user($twitter_id, $screen_name); - - common_debug('Twitter bridge - Updated nickname (and URI) for Twitter user ' . - "$fuser->id to $screen_name, was $fuser->nickname"); + $oldname = $fuser->nickname; + $fuser->delete(); + common_log(LOG_INFO, sprintf('Twitter bridge - Updated nickname (and URI) ' . + 'for Twitter user %1$d - %2$s, was %3$s.', + $fuser->id, + $screen_name, + $oldname)); } - return $result; - - } else { return add_twitter_user($twitter_id, $screen_name); } - - $fuser->free(); - unset($fuser); - - return true; } function is_twitter_bound($notice, $flink) { -- cgit v1.2.3-54-g00ecf From f3c2dfacf4b3b1ce44edcb82d8e76e75e2b7c9fa Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 10 Feb 2010 10:47:46 +0000 Subject: Fix to Realtime's repeat notice form legend and notice id --- plugins/Realtime/realtimeupdate.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index ab548958a..0f7a680d7 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -209,10 +209,10 @@ console.log(data); var rf; rf = "
    "+ "
    "+ - "Favor this notice"+ + "Repeat this notice?"+ ""+ - ""+ - ""+ + ""+ + ""+ "
    "+ "
    "; -- cgit v1.2.3-54-g00ecf From fe2ebec732ecae97b0616cdf627cbaeaf53dab48 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Feb 2010 21:10:45 +0000 Subject: Fix for regression introduced with my last update to the TwitterStatusFetcher: the Twitter bridge was not saving a foreign user record when making a foreign link. --- plugins/TwitterBridge/twitter.php | 7 ++++--- plugins/TwitterBridge/twitterauthorization.php | 14 +++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 5761074c2..1d46aa2c9 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -28,6 +28,7 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitteroauthclient.php'; function add_twitter_user($twitter_id, $screen_name) { + common_debug("Add Twitter user"); $new_uri = 'http://twitter.com/' . $screen_name; @@ -40,7 +41,7 @@ function add_twitter_user($twitter_id, $screen_name) $luser->service = TWITTER_SERVICE; $result = $luser->delete(); - if (empty($result)) { + if ($result != false) { common_log(LOG_WARNING, "Twitter bridge - removed invalid Twitter user squatting on uri: $new_uri"); } @@ -93,9 +94,9 @@ function save_twitter_user($twitter_id, $screen_name) $screen_name, $oldname)); } - - return add_twitter_user($twitter_id, $screen_name); } + + return add_twitter_user($twitter_id, $screen_name); } function is_twitter_bound($notice, $flink) { diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index dbef438a4..6822d33dd 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -89,11 +89,15 @@ class TwitterauthorizationAction extends Action $user = common_current_user(); $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); - // If there's already a foreign link record, it means we already - // have an access token, and this is unecessary. So go back. + // If there's already a foreign link record and a foreign user + // it means the accounts are already linked, and this is unecessary. + // So go back. if (isset($flink)) { - common_redirect(common_local_url('twittersettings')); + $fuser = $flink->getForeignUser(); + if (!empty($fuser)) { + common_redirect(common_local_url('twittersettings')); + } } } @@ -254,6 +258,10 @@ class TwitterauthorizationAction extends Action { $flink = new Foreign_link(); + $flink->user_id = $user_id; + $flink->service = TWITTER_SERVICE; + $flink->delete(); // delete stale flink, if any + $flink->user_id = $user_id; $flink->foreign_id = $twuid; $flink->service = TWITTER_SERVICE; -- cgit v1.2.3-54-g00ecf From ead595eee8d62a35272491061994da44c30c8174 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Feb 2010 21:23:26 +0000 Subject: Better log msgs. Removed debugging statement. --- plugins/TwitterBridge/twitter.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 1d46aa2c9..1aeba112f 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -28,8 +28,6 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitteroauthclient.php'; function add_twitter_user($twitter_id, $screen_name) { - common_debug("Add Twitter user"); - $new_uri = 'http://twitter.com/' . $screen_name; // Clear out any bad old foreign_users with the new user's legit URL @@ -42,8 +40,8 @@ function add_twitter_user($twitter_id, $screen_name) $result = $luser->delete(); if ($result != false) { - common_log(LOG_WARNING, - "Twitter bridge - removed invalid Twitter user squatting on uri: $new_uri"); + common_log(LOG_INFO, + "Twitter bridge - removed old Twitter user: $screen_name ($twitter_id)."); } $luser->free(); @@ -65,7 +63,8 @@ function add_twitter_user($twitter_id, $screen_name) "Twitter bridge - failed to add new Twitter user: $twitter_id - $screen_name."); common_log_db_error($fuser, 'INSERT', __FILE__); } else { - common_debug("Twitter bridge - Added new Twitter user: $screen_name ($twitter_id)."); + common_log(LOG_INFO, + "Twitter bridge - Added new Twitter user: $screen_name ($twitter_id)."); } return $result; -- cgit v1.2.3-54-g00ecf From 1996b709c64a1281ac623acc693b605881d34f54 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Feb 2010 21:53:49 +0000 Subject: Twitter-bridge: lookup old foreign_user by primary key not url --- plugins/TwitterBridge/twitter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 1aeba112f..40dbb1a8c 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -35,7 +35,7 @@ function add_twitter_user($twitter_id, $screen_name) // repoed, and things like that. $luser = new Foreign_user(); - $luser->uri = $new_uri; + $luser->id = $twitter_id; $luser->service = TWITTER_SERVICE; $result = $luser->delete(); -- cgit v1.2.3-54-g00ecf From 2e1e614abe8cac64d81a2042094128feac0cbb45 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Feb 2010 22:13:10 +0000 Subject: Use static class method for looking up Twitter user --- plugins/TwitterBridge/twitter.php | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 40dbb1a8c..2dd815d3c 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -28,15 +28,11 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitteroauthclient.php'; function add_twitter_user($twitter_id, $screen_name) { - $new_uri = 'http://twitter.com/' . $screen_name; - // Clear out any bad old foreign_users with the new user's legit URL // This can happen when users move around or fakester accounts get // repoed, and things like that. - $luser = new Foreign_user(); - $luser->id = $twitter_id; - $luser->service = TWITTER_SERVICE; + $luser = Foreign_user::getForeignUser($twitter_id, TWITTER_SERVICE); $result = $luser->delete(); if ($result != false) { @@ -44,11 +40,6 @@ function add_twitter_user($twitter_id, $screen_name) "Twitter bridge - removed old Twitter user: $screen_name ($twitter_id)."); } - $luser->free(); - unset($luser); - - // Otherwise, create a new Twitter user - $fuser = new Foreign_user(); $fuser->nickname = $screen_name; -- cgit v1.2.3-54-g00ecf From d4f6235d7b8a40bd1b51370e7eb405cdb14e61fb Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 16 Feb 2010 06:12:08 +0000 Subject: Upgrade Twitter bridge to use OAuth 1.0a. It's more secure, and allows us to automatically send in a callback url instead of having to manually configure one for each StatusNet instance. --- lib/oauthclient.php | 88 +++++++++++++++++++------- plugins/TwitterBridge/twitterauthorization.php | 10 +-- plugins/TwitterBridge/twitteroauthclient.php | 28 ++++++++ 3 files changed, 98 insertions(+), 28 deletions(-) (limited to 'plugins') diff --git a/lib/oauthclient.php b/lib/oauthclient.php index b22fd7897..bc7587183 100644 --- a/lib/oauthclient.php +++ b/lib/oauthclient.php @@ -90,20 +90,47 @@ class OAuthClient /** * Gets a request token from the given url * - * @param string $url OAuth endpoint for grabbing request tokens + * @param string $url OAuth endpoint for grabbing request tokens + * @param string $callback authorized request token callback * * @return OAuthToken $token the request token */ - function getRequestToken($url) + function getRequestToken($url, $callback = null) { - $response = $this->oAuthGet($url); + $params = null; + + if (!is_null($callback)) { + $params['oauth_callback'] = $callback; + } + + $response = $this->oAuthGet($url, $params); + $arr = array(); parse_str($response, $arr); - if (isset($arr['oauth_token']) && isset($arr['oauth_token_secret'])) { - $token = new OAuthToken($arr['oauth_token'], @$arr['oauth_token_secret']); + + $token = $arr['oauth_token']; + $secret = $arr['oauth_token_secret']; + $confirm = $arr['oauth_callback_confirmed']; + + if (isset($token) && isset($secret)) { + + $token = new OAuthToken($token, $secret); + + if (isset($confirm)) { + if ($confirm == 'true') { + common_debug('Twitter bridge - callback confirmed.'); + return $token; + } else { + throw new OAuthClientException( + 'Callback was not confirmed by Twitter.' + ); + } + } return $token; } else { - throw new OAuthClientException(); + throw new OAuthClientException( + 'Could not get a request token from Twitter.' + ); } } @@ -113,49 +140,64 @@ class OAuthClient * * @param string $url endpoint for authorizing request tokens * @param OAuthToken $request_token the request token to be authorized - * @param string $oauth_callback optional callback url * * @return string $authorize_url the url to redirect to */ - function getAuthorizeLink($url, $request_token, $oauth_callback = null) + function getAuthorizeLink($url, $request_token) { $authorize_url = $url . '?oauth_token=' . $request_token->key; - if (isset($oauth_callback)) { - $authorize_url .= '&oauth_callback=' . urlencode($oauth_callback); - } - return $authorize_url; } /** * Fetches an access token * - * @param string $url OAuth endpoint for exchanging authorized request tokens - * for access tokens + * @param string $url OAuth endpoint for exchanging authorized request tokens + * for access tokens + * @param string $verifier 1.0a verifier * * @return OAuthToken $token the access token */ - function getAccessToken($url) + function getAccessToken($url, $verifier = null) { - $response = $this->oAuthPost($url); - parse_str($response); - $token = new OAuthToken($oauth_token, $oauth_token_secret); - return $token; + $params = array(); + + if (!is_null($verifier)) { + $params['oauth_verifier'] = $verifier; + } + + $response = $this->oAuthPost($url, $params); + + $arr = array(); + parse_str($response, $arr); + + $token = $arr['oauth_token']; + $secret = $arr['oauth_token_secret']; + + if (isset($token) && isset($secret)) { + $token = new OAuthToken($token, $secret); + return $token; + } else { + throw new OAuthClientException( + 'Could not get a access token from Twitter.' + ); + } } /** - * Use HTTP GET to make a signed OAuth request + * Use HTTP GET to make a signed OAuth requesta * - * @param string $url OAuth endpoint + * @param string $url OAuth request token endpoint + * @param array $params additional parameters * * @return mixed the request */ - function oAuthGet($url) + function oAuthGet($url, $params = null) { $request = OAuthRequest::from_consumer_and_token($this->consumer, - $this->token, 'GET', $url, null); + $this->token, 'GET', $url, $params); $request->sign_request($this->sha1_method, $this->consumer, $this->token); diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index 6822d33dd..c154932bb 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -56,6 +56,7 @@ class TwitterauthorizationAction extends Action var $tw_fields = null; var $access_token = null; var $signin = null; + var $verifier = null; /** * Initialize class members. Looks for 'oauth_token' parameter. @@ -70,6 +71,7 @@ class TwitterauthorizationAction extends Action $this->signin = $this->boolean('signin'); $this->oauth_token = $this->arg('oauth_token'); + $this->verifier = $this->arg('oauth_verifier'); return true; } @@ -160,8 +162,7 @@ class TwitterauthorizationAction extends Action // Get a new request token and authorize it $client = new TwitterOAuthClient(); - $req_tok = - $client->getRequestToken(TwitterOAuthClient::$requestTokenURL); + $req_tok = $client->getRequestToken(); // Sock the request token away in the session temporarily @@ -171,7 +172,7 @@ class TwitterauthorizationAction extends Action $auth_link = $client->getAuthorizeLink($req_tok, $this->signin); } catch (OAuthClientException $e) { - $msg = sprintf('OAuth client cURL error - code: %1s, msg: %2s', + $msg = sprintf('OAuth client error - code: %1s, msg: %2s', $e->getCode(), $e->getMessage()); $this->serverError(_m('Couldn\'t link your Twitter account.')); } @@ -187,7 +188,6 @@ class TwitterauthorizationAction extends Action */ function saveAccessToken() { - // Check to make sure Twitter returned the same request // token we sent them @@ -204,7 +204,7 @@ class TwitterauthorizationAction extends Action // Exchange the request token for an access token - $atok = $client->getAccessToken(TwitterOAuthClient::$accessTokenURL); + $atok = $client->getAccessToken($this->verifier); // Test the access token and get the user's Twitter info diff --git a/plugins/TwitterBridge/twitteroauthclient.php b/plugins/TwitterBridge/twitteroauthclient.php index 277e7ab40..ba45b533d 100644 --- a/plugins/TwitterBridge/twitteroauthclient.php +++ b/plugins/TwitterBridge/twitteroauthclient.php @@ -91,6 +91,19 @@ class TwitterOAuthClient extends OAuthClient } } + /** + * Gets a request token from Twitter + * + * @return OAuthToken $token the request token + */ + function getRequestToken() + { + return parent::getRequestToken( + self::$requestTokenURL, + common_local_url('twitterauthorization') + ); + } + /** * Builds a link to Twitter's endpoint for authorizing a request token * @@ -107,6 +120,21 @@ class TwitterOAuthClient extends OAuthClient common_local_url('twitterauthorization')); } + /** + * Fetches an access token from Twitter + * + * @param string $verifier 1.0a verifier + * + * @return OAuthToken $token the access token + */ + function getAccessToken($verifier = null) + { + return parent::getAccessToken( + self::$accessTokenURL, + $verifier + ); + } + /** * Calls Twitter's /account/verify_credentials API method * -- cgit v1.2.3-54-g00ecf From 389e6d54bfcabd0eb2f6849c914684808aefa53c Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 17 Feb 2010 10:29:08 -0500 Subject: Fix script references in infinite scroll plugin and autocomplete plugin Add indicator.gif used by autocomplete plugin --- plugins/Autocomplete/AutocompletePlugin.php | 4 ++-- plugins/Autocomplete/jquery-autocomplete/indicator.gif | Bin 0 -> 673 bytes plugins/InfiniteScroll/InfiniteScrollPlugin.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 plugins/Autocomplete/jquery-autocomplete/indicator.gif (limited to 'plugins') diff --git a/plugins/Autocomplete/AutocompletePlugin.php b/plugins/Autocomplete/AutocompletePlugin.php index d586631a4..a28c65a29 100644 --- a/plugins/Autocomplete/AutocompletePlugin.php +++ b/plugins/Autocomplete/AutocompletePlugin.php @@ -42,8 +42,8 @@ class AutocompletePlugin extends Plugin function onEndShowScripts($action){ if (common_logged_in()) { - $action->script('plugins/Autocomplete/jquery-autocomplete/jquery.autocomplete.pack.js'); - $action->script('plugins/Autocomplete/Autocomplete.js'); + $action->script(common_path('plugins/Autocomplete/jquery-autocomplete/jquery.autocomplete.pack.js')); + $action->script(common_path('plugins/Autocomplete/Autocomplete.js')); } } diff --git a/plugins/Autocomplete/jquery-autocomplete/indicator.gif b/plugins/Autocomplete/jquery-autocomplete/indicator.gif new file mode 100644 index 000000000..d0bce1542 Binary files /dev/null and b/plugins/Autocomplete/jquery-autocomplete/indicator.gif differ diff --git a/plugins/InfiniteScroll/InfiniteScrollPlugin.php b/plugins/InfiniteScroll/InfiniteScrollPlugin.php index a4d1a5d05..77ad83a51 100644 --- a/plugins/InfiniteScroll/InfiniteScrollPlugin.php +++ b/plugins/InfiniteScroll/InfiniteScrollPlugin.php @@ -40,8 +40,8 @@ class InfiniteScrollPlugin extends Plugin function onEndShowScripts($action) { - $action->script('plugins/InfiniteScroll/jquery.infinitescroll.js'); - $action->script('plugins/InfiniteScroll/infinitescroll.js'); + $action->script(common_path('plugins/InfiniteScroll/jquery.infinitescroll.js')); + $action->script(common_path('plugins/InfiniteScroll/infinitescroll.js')); } function onPluginVersion(&$versions) -- cgit v1.2.3-54-g00ecf From c19300272f0074359b2713c35d2fb46bbd1b42ec Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 17 Feb 2010 12:02:59 -0500 Subject: parse_url returns an associative array - not an object --- lib/htmloutputter.php | 2 +- plugins/Minify/MinifyPlugin.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/lib/htmloutputter.php b/lib/htmloutputter.php index 47e56fc8f..7315fe2ad 100644 --- a/lib/htmloutputter.php +++ b/lib/htmloutputter.php @@ -439,7 +439,7 @@ class HTMLOutputter extends XMLOutputter { if(Event::handle('StartCssLinkElement', array($this,&$src,&$theme,&$media))) { $url = parse_url($src); - if( empty($url->scheme) && empty($url->host) && empty($url->query) && empty($url->fragment)) + if( empty($url['scheme']) && empty($url['host']) && empty($url['query']) && empty($url['fragment'])) { if(file_exists(Theme::file($src,$theme))){ $src = Theme::path($src, $theme); diff --git a/plugins/Minify/MinifyPlugin.php b/plugins/Minify/MinifyPlugin.php index b49b6a4ba..fe1883ded 100644 --- a/plugins/Minify/MinifyPlugin.php +++ b/plugins/Minify/MinifyPlugin.php @@ -96,7 +96,7 @@ class MinifyPlugin extends Plugin && is_null(common_config('theme', 'path')) && is_null(common_config('theme', 'server')); $url = parse_url($src); - if( empty($url->scheme) && empty($url->host) && empty($url->query) && empty($url->fragment)) + if( empty($url['scheme']) && empty($url['host']) && empty($url['query']) && empty($url['fragment'])) { if(!isset($theme)) { $theme = common_config('site', 'theme'); -- cgit v1.2.3-54-g00ecf From 46e9aa13aa87955b441bc63b7cf2f58622b131b0 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 17 Feb 2010 12:03:14 -0500 Subject: htmloutputter->script() special cases src's that begin with plugin/ or local/ so that plugins don't need to include common_path() in every call to $action->script() Adjust plugins to not call common_path() when it's not necessary Fix minify plugin --- lib/htmloutputter.php | 55 ++++++++++++++----------- plugins/Autocomplete/AutocompletePlugin.php | 4 +- plugins/Comet/CometPlugin.php | 2 +- plugins/Facebook/FacebookPlugin.php | 2 +- plugins/Facebook/facebookaction.php | 2 +- plugins/InfiniteScroll/InfiniteScrollPlugin.php | 4 +- plugins/Minify/MinifyPlugin.php | 6 ++- plugins/OStatus/OStatusPlugin.php | 4 +- plugins/Orbited/OrbitedPlugin.php | 4 +- plugins/Realtime/RealtimePlugin.php | 4 +- 10 files changed, 49 insertions(+), 38 deletions(-) (limited to 'plugins') diff --git a/lib/htmloutputter.php b/lib/htmloutputter.php index 7315fe2ad..7786b5941 100644 --- a/lib/htmloutputter.php +++ b/lib/htmloutputter.php @@ -356,40 +356,47 @@ class HTMLOutputter extends XMLOutputter if( empty($url['scheme']) && empty($url['host']) && empty($url['query']) && empty($url['fragment'])) { - $path = common_config('javascript', 'path'); + if (strpos($src, 'plugins/') === 0 || strpos($src, 'local/') === 0) { - if (empty($path)) { - $path = common_config('site', 'path') . '/js/'; - } + $src = common_path($src) . '?version=' . STATUSNET_VERSION; - if ($path[strlen($path)-1] != '/') { - $path .= '/'; - } + }else{ - if ($path[0] != '/') { - $path = '/'.$path; - } + $path = common_config('javascript', 'path'); - $server = common_config('javascript', 'server'); + if (empty($path)) { + $path = common_config('site', 'path') . '/js/'; + } - if (empty($server)) { - $server = common_config('site', 'server'); - } + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } - $ssl = common_config('javascript', 'ssl'); + if ($path[0] != '/') { + $path = '/'.$path; + } + + $server = common_config('javascript', 'server'); - if (is_null($ssl)) { // null -> guess - if (common_config('site', 'ssl') == 'always' && - !common_config('javascript', 'server')) { - $ssl = true; - } else { - $ssl = false; + if (empty($server)) { + $server = common_config('site', 'server'); } - } - $protocol = ($ssl) ? 'https' : 'http'; + $ssl = common_config('javascript', 'ssl'); - $src = $protocol.'://'.$server.$path.$src . '?version=' . STATUSNET_VERSION; + if (is_null($ssl)) { // null -> guess + if (common_config('site', 'ssl') == 'always' && + !common_config('javascript', 'server')) { + $ssl = true; + } else { + $ssl = false; + } + } + + $protocol = ($ssl) ? 'https' : 'http'; + + $src = $protocol.'://'.$server.$path.$src . '?version=' . STATUSNET_VERSION; + } } $this->element('script', array('type' => $type, diff --git a/plugins/Autocomplete/AutocompletePlugin.php b/plugins/Autocomplete/AutocompletePlugin.php index a28c65a29..d586631a4 100644 --- a/plugins/Autocomplete/AutocompletePlugin.php +++ b/plugins/Autocomplete/AutocompletePlugin.php @@ -42,8 +42,8 @@ class AutocompletePlugin extends Plugin function onEndShowScripts($action){ if (common_logged_in()) { - $action->script(common_path('plugins/Autocomplete/jquery-autocomplete/jquery.autocomplete.pack.js')); - $action->script(common_path('plugins/Autocomplete/Autocomplete.js')); + $action->script('plugins/Autocomplete/jquery-autocomplete/jquery.autocomplete.pack.js'); + $action->script('plugins/Autocomplete/Autocomplete.js'); } } diff --git a/plugins/Comet/CometPlugin.php b/plugins/Comet/CometPlugin.php index 300d1e9a2..29cb3004b 100644 --- a/plugins/Comet/CometPlugin.php +++ b/plugins/Comet/CometPlugin.php @@ -68,7 +68,7 @@ class CometPlugin extends RealtimePlugin $ours = array('jquery.comet.js', 'cometupdate.js'); foreach ($ours as $script) { - $scripts[] = common_path('plugins/Comet/'.$script); + $scripts[] = 'plugins/Comet/'.$script; } return $scripts; diff --git a/plugins/Facebook/FacebookPlugin.php b/plugins/Facebook/FacebookPlugin.php index 4266b886d..78c9054e1 100644 --- a/plugins/Facebook/FacebookPlugin.php +++ b/plugins/Facebook/FacebookPlugin.php @@ -181,7 +181,7 @@ class FacebookPlugin extends Plugin if ($this->reqFbScripts($action)) { $apikey = common_config('facebook', 'apikey'); - $plugin_path = common_path('plugins/Facebook'); + $plugin_path = 'plugins/Facebook'; $login_url = common_local_url('FBConnectAuth'); $logout_url = common_local_url('logout'); diff --git a/plugins/Facebook/facebookaction.php b/plugins/Facebook/facebookaction.php index 8437a705a..f65b97c86 100644 --- a/plugins/Facebook/facebookaction.php +++ b/plugins/Facebook/facebookaction.php @@ -89,7 +89,7 @@ class FacebookAction extends Action function showScripts() { - $this->script(common_path('plugins/Facebook/facebookapp.js')); + $this->script('plugins/Facebook/facebookapp.js'); } /** diff --git a/plugins/InfiniteScroll/InfiniteScrollPlugin.php b/plugins/InfiniteScroll/InfiniteScrollPlugin.php index 77ad83a51..a4d1a5d05 100644 --- a/plugins/InfiniteScroll/InfiniteScrollPlugin.php +++ b/plugins/InfiniteScroll/InfiniteScrollPlugin.php @@ -40,8 +40,8 @@ class InfiniteScrollPlugin extends Plugin function onEndShowScripts($action) { - $action->script(common_path('plugins/InfiniteScroll/jquery.infinitescroll.js')); - $action->script(common_path('plugins/InfiniteScroll/infinitescroll.js')); + $action->script('plugins/InfiniteScroll/jquery.infinitescroll.js'); + $action->script('plugins/InfiniteScroll/infinitescroll.js'); } function onPluginVersion(&$versions) diff --git a/plugins/Minify/MinifyPlugin.php b/plugins/Minify/MinifyPlugin.php index fe1883ded..69def6064 100644 --- a/plugins/Minify/MinifyPlugin.php +++ b/plugins/Minify/MinifyPlugin.php @@ -86,7 +86,11 @@ class MinifyPlugin extends Plugin $url = parse_url($src); if( empty($url['scheme']) && empty($url['host']) && empty($url['query']) && empty($url['fragment'])) { - $src = $this->minifyUrl($src); + if (strpos($src, 'plugins/') === 0 || strpos($src, 'local/') === 0) { + $src = $this->minifyUrl($src); + } else { + $src = $this->minifyUrl('js/'.$src); + } } } diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index 3b1329d6c..a30f68cb3 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -281,12 +281,12 @@ class OStatusPlugin extends Plugin } function onEndShowStatusNetStyles($action) { - $action->cssLink(common_path('plugins/OStatus/theme/base/css/ostatus.css')); + $action->cssLink('plugins/OStatus/theme/base/css/ostatus.css'); return true; } function onEndShowStatusNetScripts($action) { - $action->script(common_path('plugins/OStatus/js/ostatus.js')); + $action->script('plugins/OStatus/js/ostatus.js'); return true; } } diff --git a/plugins/Orbited/OrbitedPlugin.php b/plugins/Orbited/OrbitedPlugin.php index ba87b266a..8af71af74 100644 --- a/plugins/Orbited/OrbitedPlugin.php +++ b/plugins/Orbited/OrbitedPlugin.php @@ -77,9 +77,9 @@ class OrbitedPlugin extends RealtimePlugin $root = 'http://'.$server.(($port == 80) ? '':':'.$port); $scripts[] = $root.'/static/Orbited.js'; - $scripts[] = common_path('plugins/Orbited/orbitedextra.js'); + $scripts[] = 'plugins/Orbited/orbitedextra.js'; $scripts[] = $root.'/static/protocols/stomp/stomp.js'; - $scripts[] = common_path('plugins/Orbited/orbitedupdater.js'); + $scripts[] = 'plugins/Orbited/orbitedupdater.js'; return $scripts; } diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php index 6c212453e..e8c44a743 100644 --- a/plugins/Realtime/RealtimePlugin.php +++ b/plugins/Realtime/RealtimePlugin.php @@ -117,7 +117,7 @@ class RealtimePlugin extends Plugin function onEndShowStatusNetStyles($action) { - $action->cssLink(common_path('plugins/Realtime/realtimeupdate.css'), + $action->cssLink('plugins/Realtime/realtimeupdate.css', null, 'screen, projection, tv'); return true; } @@ -307,7 +307,7 @@ class RealtimePlugin extends Plugin function _getScripts() { - return array(common_path('plugins/Realtime/realtimeupdate.js')); + return array('plugins/Realtime/realtimeupdate.js'); } function _updateInitialize($timeline, $user_id) -- cgit v1.2.3-54-g00ecf From 4d97f83740401ca98f4cd6d6d285dba0000d34dd Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Feb 2010 19:24:38 +0000 Subject: Better logging for Twitter bridge account linking process --- plugins/TwitterBridge/twitterauthorization.php | 31 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index c154932bb..8bfdacee9 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -131,8 +131,7 @@ class TwitterauthorizationAction extends Action } else if ($this->arg('connect')) { $this->connectNewUser(); } else { - common_debug('Twitter Connect Plugin - ' . - print_r($this->args, true)); + common_debug('Twitter bridge - ' . print_r($this->args, true)); $this->showForm(_('Something weird happened.'), $this->trimmed('newname')); } @@ -172,9 +171,15 @@ class TwitterauthorizationAction extends Action $auth_link = $client->getAuthorizeLink($req_tok, $this->signin); } catch (OAuthClientException $e) { - $msg = sprintf('OAuth client error - code: %1s, msg: %2s', - $e->getCode(), $e->getMessage()); - $this->serverError(_m('Couldn\'t link your Twitter account.')); + $msg = sprintf( + 'OAuth client error - code: %1s, msg: %2s', + $e->getCode(), + $e->getMessage() + ); + common_log(LOG_INFO, 'Twitter bridge - ' . $msg); + $this->serverError( + _m('Couldn\'t link your Twitter account: ') . $e->getMessage() + ); } common_redirect($auth_link); @@ -192,7 +197,9 @@ class TwitterauthorizationAction extends Action // token we sent them if ($_SESSION['twitter_request_token'] != $this->oauth_token) { - $this->serverError(_m('Couldn\'t link your Twitter account.')); + $this->serverError( + _m('Couldn\'t link your Twitter account: oauth_token mismatch.') + ); } $twitter_user = null; @@ -212,9 +219,15 @@ class TwitterauthorizationAction extends Action $twitter_user = $client->verifyCredentials(); } catch (OAuthClientException $e) { - $msg = sprintf('OAuth client error - code: %1$s, msg: %2$s', - $e->getCode(), $e->getMessage()); - $this->serverError(_m('Couldn\'t link your Twitter account.')); + $msg = sprintf( + 'OAuth client error - code: %1$s, msg: %2$s', + $e->getCode(), + $e->getMessage() + ); + common_log(LOG_INFO, 'Twitter bridge - ' . $msg); + $this->serverError( + _m('Couldn\'t link your Twitter account: ') . $e-getMessage() + ); } if (common_logged_in()) { -- cgit v1.2.3-54-g00ecf From a80fdf3142d05bdae77874acc7413cbbd70fad3d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Feb 2010 20:53:16 +0000 Subject: Twitter bridge - fix for Ticket #2192 --- plugins/TwitterBridge/twitter.php | 12 ++++++++---- plugins/TwitterBridge/twitterauthorization.php | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 2dd815d3c..13e499d65 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -33,11 +33,15 @@ function add_twitter_user($twitter_id, $screen_name) // repoed, and things like that. $luser = Foreign_user::getForeignUser($twitter_id, TWITTER_SERVICE); - $result = $luser->delete(); - if ($result != false) { - common_log(LOG_INFO, - "Twitter bridge - removed old Twitter user: $screen_name ($twitter_id)."); + if (!empty($luser)) { + $result = $luser->delete(); + if ($result != false) { + common_log( + LOG_INFO, + "Twitter bridge - removed old Twitter user: $screen_name ($twitter_id)." + ); + } } $fuser = new Foreign_user(); diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index 8bfdacee9..cabf69d7a 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -178,7 +178,7 @@ class TwitterauthorizationAction extends Action ); common_log(LOG_INFO, 'Twitter bridge - ' . $msg); $this->serverError( - _m('Couldn\'t link your Twitter account: ') . $e->getMessage() + _m('Couldn\'t link your Twitter account.') ); } @@ -226,7 +226,7 @@ class TwitterauthorizationAction extends Action ); common_log(LOG_INFO, 'Twitter bridge - ' . $msg); $this->serverError( - _m('Couldn\'t link your Twitter account: ') . $e-getMessage() + _m('Couldn\'t link your Twitter account.') ); } @@ -292,7 +292,7 @@ class TwitterauthorizationAction extends Action if (empty($flink_id)) { common_log_db_error($flink, 'INSERT', __FILE__); - $this->serverError(_('Couldn\'t link your Twitter account.')); + $this->serverError(_('Couldn\'t link your Twitter account.')); } return $flink_id; -- cgit v1.2.3-54-g00ecf From 86f2f530ef60fdb601720885d493cf5b2a446e6b Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Sat, 20 Feb 2010 21:57:05 +0000 Subject: Fixed incorrect link on registration successful page --- plugins/OpenID/OpenIDPlugin.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/OpenID/OpenIDPlugin.php b/plugins/OpenID/OpenIDPlugin.php index 248afe3fa..6b35ec3e1 100644 --- a/plugins/OpenID/OpenIDPlugin.php +++ b/plugins/OpenID/OpenIDPlugin.php @@ -235,9 +235,14 @@ class OpenIDPlugin extends Plugin switch ($name) { case 'register': - $instr = '(Have an [OpenID](http://openid.net/)? ' . - 'Try our [OpenID registration]'. - '(%%action.openidlogin%%)!)'; + if (common_logged_in()) { + $instr = '(Have an [OpenID](http://openid.net/)? ' . + '[Add an OpenID to your account](%%action.openidsettings%%)!'; + } else { + $instr = '(Have an [OpenID](http://openid.net/)? ' . + 'Try our [OpenID registration]'. + '(%%action.openidlogin%%)!)'; + } break; case 'login': $instr = '(Have an [OpenID](http://openid.net/)? ' . -- cgit v1.2.3-54-g00ecf From bdf0dfc30d3c44ee6117e55c1c8faef59654e596 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 24 Feb 2010 22:29:46 -0500 Subject: Improve description of what the provide_name parameter means --- plugins/LdapAuthentication/README | 5 ++++- plugins/LdapAuthorization/README | 5 ++++- plugins/ReverseUsernameAuthentication/README | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/LdapAuthentication/README b/plugins/LdapAuthentication/README index 0460fb639..c188f2dbc 100644 --- a/plugins/LdapAuthentication/README +++ b/plugins/LdapAuthentication/README @@ -9,7 +9,10 @@ to the bottom of your config.php Settings ======== -provider_name*: a unique name for this authentication provider. +provider_name*: This is a identifier designated to the connection. + It's how StatusNet will refer to the authentication source. + For the most part, any name can be used, so long as each authentication source has a different identifier. + In most cases there will be only one authentication source used. authoritative (false): Set to true if LDAP's responses are authoritative (if authorative and LDAP fails, no other password checking will be done). autoregistration (false): Set to true if users should be automatically created diff --git a/plugins/LdapAuthorization/README b/plugins/LdapAuthorization/README index 44239d8e0..3a6d8d25e 100644 --- a/plugins/LdapAuthorization/README +++ b/plugins/LdapAuthorization/README @@ -11,7 +11,10 @@ You *cannot* use this plugin without the LDAP Authentication plugin Settings ======== -provider_name*: name of the LDAP authentication provider that this plugin works with. +provider_name*: This is a identifier designated to the connection. + It's how StatusNet will refer to the authentication source. + For the most part, any name can be used, so long as each authentication source has a different identifier. + In most cases there will be only one authentication source used. authoritative (false): should this plugin be authoritative for authorization? uniqueMember_attribute ('uniqueMember')*: the attribute of a group diff --git a/plugins/ReverseUsernameAuthentication/README b/plugins/ReverseUsernameAuthentication/README index e9160ed9b..57b53219e 100644 --- a/plugins/ReverseUsernameAuthentication/README +++ b/plugins/ReverseUsernameAuthentication/README @@ -8,7 +8,10 @@ add "addPlugin('reverseUsernameAuthentication', array('setting'=>'value', 'setti Settings ======== -provider_name*: a unique name for this authentication provider. +provider_name*: This is a identifier designated to the connection. + It's how StatusNet will refer to the authentication source. + For the most part, any name can be used, so long as each authentication source has a different identifier. + In most cases there will be only one authentication source used. password_changeable*: must be set to false. This plugin does not support changing passwords. authoritative (false): Set to true if this plugin's responses are authoritative (meaning if this fails, do check any other plugins or the internal password database). autoregistration (false): Set to true if users should be automatically created when they attempt to login. -- cgit v1.2.3-54-g00ecf From 489bd935ebdaf607e18f0befe2ad85ed905728ad Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 24 Feb 2010 23:20:34 -0500 Subject: Make LDAP connection error fatal - there really is no way to recover from that. --- plugins/LdapAuthentication/LdapAuthenticationPlugin.php | 3 +-- plugins/LdapAuthorization/LdapAuthorizationPlugin.php | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php index 768f0fe7f..1b5dc92e3 100644 --- a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -199,8 +199,7 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin $ldap->setErrorHandling(PEAR_ERROR_RETURN); $err=$ldap->bind(); if (Net_LDAP2::isError($err)) { - common_log(LOG_WARNING, 'Could not connect to LDAP server: '.$err->getMessage()); - return false; + throw new Exception('Could not connect to LDAP server: '.$err->getMessage()); } if($config == null) $this->default_ldap=$ldap; diff --git a/plugins/LdapAuthorization/LdapAuthorizationPlugin.php b/plugins/LdapAuthorization/LdapAuthorizationPlugin.php index 7f48ce5e1..19aff42b8 100644 --- a/plugins/LdapAuthorization/LdapAuthorizationPlugin.php +++ b/plugins/LdapAuthorization/LdapAuthorizationPlugin.php @@ -167,7 +167,7 @@ class LdapAuthorizationPlugin extends AuthorizationPlugin $ldap->setErrorHandling(PEAR_ERROR_RETURN); $err=$ldap->bind(); if (Net_LDAP2::isError($err)) { - common_log(LOG_WARNING, 'Could not connect to LDAP server: '.$err->getMessage()); + throw new Exception('Could not connect to LDAP server: '.$err->getMessage()); return false; } if($config == null) $this->default_ldap=$ldap; @@ -185,6 +185,9 @@ class LdapAuthorizationPlugin extends AuthorizationPlugin if($ldap==null) { $ldap = $this->ldap_get_connection(); } + if(! $ldap) { + throw new Exception("Could not connect to LDAP"); + } $filter = Net_LDAP2_Filter::create($this->attributes['username'], 'equals', $username); $options = array( 'attributes' => $attributes -- cgit v1.2.3-54-g00ecf From eb724bfdc85d0b50d6f5be60e1e11296ebe11247 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Thu, 25 Feb 2010 15:34:01 -0500 Subject: Add TabFocus (for die-hard Twitter users) plugin --- plugins/TabFocus/TabFocusPlugin.php | 57 +++++++++++++++++++++++++++++++++++++ plugins/TabFocus/tabfocus.js | 7 +++++ 2 files changed, 64 insertions(+) create mode 100644 plugins/TabFocus/TabFocusPlugin.php create mode 100644 plugins/TabFocus/tabfocus.js (limited to 'plugins') diff --git a/plugins/TabFocus/TabFocusPlugin.php b/plugins/TabFocus/TabFocusPlugin.php new file mode 100644 index 000000000..bf89c478c --- /dev/null +++ b/plugins/TabFocus/TabFocusPlugin.php @@ -0,0 +1,57 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @author Paul Irish + * @copyright 2009 Craig Andrews http://candrews.integralblue.com + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +class TabFocusPlugin extends Plugin +{ + function __construct() + { + parent::__construct(); + } + + function onEndShowScripts($action) + { + $action->script('plugins/TabFocus/tabfocus.js'); + } + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'TabFocus', + 'version' => STATUSNET_VERSION, + 'author' => 'Craig Andrews and Paul Irish', + 'homepage' => 'http://status.net/wiki/Plugin:TabFocus', + 'rawdescription' => + _m('TabFocus changes the notice form behavior so that, while in the text area, pressing the tab key focuses the "Send" button, matching the behavor of Twitter.')); + return true; + } +} diff --git a/plugins/TabFocus/tabfocus.js b/plugins/TabFocus/tabfocus.js new file mode 100644 index 000000000..e2c1c6521 --- /dev/null +++ b/plugins/TabFocus/tabfocus.js @@ -0,0 +1,7 @@ +jQuery(function($){ + $('#notice_data-text').bind('keydown',function(e){ + if (e.which==9) { + setTimeout(function(){ $('#notice_action-submit').focus(); },15); + } + }); +}); -- cgit v1.2.3-54-g00ecf From 74bcc6929db15b18b761564232a1cb674ffbdce2 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 26 Feb 2010 15:50:51 -0500 Subject: Show messaging on the login and registration forms informing users that they may use their LDAP credentials --- .../LdapAuthenticationPlugin.php | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'plugins') diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php index 1b5dc92e3..d6a945f49 100644 --- a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -76,6 +76,32 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin return false; } } + + function onEndShowPageNotice($action) + { + $name = $action->trimmed('action'); + $instr = false; + + switch ($name) + { + case 'register': + if($this->autoregistration) { + $instr = 'Have an LDAP account? Use your standard username and password.'; + } + break; + case 'login': + $instr = 'Have an LDAP account? Use your standard username and password.'; + break; + default: + return true; + } + + if($instr) { + $output = common_markup_to_html($instr); + $action->raw($output); + } + return true; + } //---interface implementation---// -- cgit v1.2.3-54-g00ecf From 3bfe3345df1c2faf0288f1b18d205d793e740aae Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Mon, 1 Mar 2010 11:48:46 -0500 Subject: Use common_nicknamize() in better places. --- lib/authenticationplugin.php | 8 +++++--- plugins/LdapAuthentication/LdapAuthenticationPlugin.php | 9 ++++----- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'plugins') diff --git a/lib/authenticationplugin.php b/lib/authenticationplugin.php index 97e9d52de..0a3763e2e 100644 --- a/lib/authenticationplugin.php +++ b/lib/authenticationplugin.php @@ -79,7 +79,7 @@ abstract class AuthenticationPlugin extends Plugin $nickname = $username; } $registration_data = array(); - $registration_data['nickname'] = common_nicknamize($nickname); + $registration_data['nickname'] = $nickname; return User::register($registration_data); } @@ -101,12 +101,14 @@ abstract class AuthenticationPlugin extends Plugin * Used during autoregistration * Useful if your usernames are ugly, and you want to suggest * nice looking nicknames when users initially sign on + * All nicknames returned by this function should be valid + * implementations may want to use common_nicknamize() to ensure validity * @param username * @return string nickname */ function suggestNicknameForUsername($username) { - return $username; + return common_nicknamize($username); } //------------Below are the methods that connect StatusNet to the implementing Auth plugin------------\\ @@ -129,7 +131,7 @@ abstract class AuthenticationPlugin extends Plugin $test_user = User::staticGet('nickname', $suggested_nickname); if($test_user) { //someone already exists with the suggested nickname, so used the passed nickname - $suggested_nickname = $nickname; + $suggested_nickname = common_nicknamize($nickname); } $test_user = User::staticGet('nickname', $suggested_nickname); if($test_user) { diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php index d6a945f49..e0fd615dd 100644 --- a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -189,15 +189,14 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin $entry = $this->ldap_get_user($username, $this->attributes); if(!$entry){ //this really shouldn't happen - return $username; + $nickname = $username; }else{ $nickname = $entry->getValue($this->attributes['nickname'],'single'); - if($nickname){ - return $nickname; - }else{ - return $username; + if(!$nickname){ + $nickname = $username; } } + return common_nicknamize($nickname); } //---utility functions---// -- cgit v1.2.3-54-g00ecf From 380439ba77c305a2e74c2329d7d34f9eba0a957e Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Tue, 2 Mar 2010 15:09:28 -0500 Subject: Redirect to main page when transparent SSO is in place for the CAS plugin (which is what the user expects) --- plugins/CasAuthentication/CasAuthenticationPlugin.php | 1 + plugins/CasAuthentication/caslogin.php | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/CasAuthentication/CasAuthenticationPlugin.php b/plugins/CasAuthentication/CasAuthenticationPlugin.php index 483b060ab..203e5fe42 100644 --- a/plugins/CasAuthentication/CasAuthenticationPlugin.php +++ b/plugins/CasAuthentication/CasAuthenticationPlugin.php @@ -137,6 +137,7 @@ class CasAuthenticationPlugin extends AuthenticationPlugin $casSettings['server']=$this->server; $casSettings['port']=$this->port; $casSettings['path']=$this->path; + $casSettings['takeOverLogin']=$this->takeOverLogin; } function onPluginVersion(&$versions) diff --git a/plugins/CasAuthentication/caslogin.php b/plugins/CasAuthentication/caslogin.php index 390a75d8b..a66774dc1 100644 --- a/plugins/CasAuthentication/caslogin.php +++ b/plugins/CasAuthentication/caslogin.php @@ -54,9 +54,18 @@ class CasloginAction extends Action // We don't have to return to it again common_set_returnto(null); } else { - $url = common_local_url('all', - array('nickname' => - $user->nickname)); + if(common_config('site', 'private') && $casSettings['takeOverLogin']) { + //SSO users expect to just go to the URL they entered + //if we don't have a returnto set, the user entered the + //main StatusNet url, so send them there. + $url = common_local_url('public'); + } else { + //With normal logins (regular form-based username/password), + //the user would expect to go to their home after logging in. + $url = common_local_url('public', + array('nickname' => + $user->nickname)); + } } common_redirect($url, 303); -- cgit v1.2.3-54-g00ecf From 358556057a87c0cb9291223a2026782e6548ff2e Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Tue, 2 Mar 2010 23:24:50 -0500 Subject: Bump to phpCAS 1.1.0RC6 --- plugins/CasAuthentication/extlib/CAS.php | 3086 ++++++++++---------- .../extlib/CAS/PGTStorage/pgt-db.php | 378 +-- .../extlib/CAS/PGTStorage/pgt-file.php | 496 ++-- .../extlib/CAS/PGTStorage/pgt-main.php | 374 +-- plugins/CasAuthentication/extlib/CAS/client.php | 552 +++- .../extlib/CAS/domxml-php4-php5.php | 277 -- .../extlib/CAS/domxml-php4-to-php5.php | 499 ++++ .../extlib/CAS/languages/catalan.php | 54 +- .../extlib/CAS/languages/english.php | 52 +- .../extlib/CAS/languages/french.php | 54 +- .../extlib/CAS/languages/german.php | 52 +- .../extlib/CAS/languages/greek.php | 52 +- .../extlib/CAS/languages/japanese.php | 12 +- .../extlib/CAS/languages/languages.php | 46 +- .../extlib/CAS/languages/spanish.php | 54 +- 15 files changed, 3391 insertions(+), 2647 deletions(-) delete mode 100644 plugins/CasAuthentication/extlib/CAS/domxml-php4-php5.php create mode 100644 plugins/CasAuthentication/extlib/CAS/domxml-php4-to-php5.php (limited to 'plugins') diff --git a/plugins/CasAuthentication/extlib/CAS.php b/plugins/CasAuthentication/extlib/CAS.php index f5ea0b12a..e75437419 100644 --- a/plugins/CasAuthentication/extlib/CAS.php +++ b/plugins/CasAuthentication/extlib/CAS.php @@ -1,1471 +1,1615 @@ -=')) { - require_once(dirname(__FILE__).'/CAS/domxml-php4-php5.php'); -} - -/** - * @file CAS/CAS.php - * Interface class of the phpCAS library - * - * @ingroup public - */ - -// ######################################################################## -// CONSTANTS -// ######################################################################## - -// ------------------------------------------------------------------------ -// CAS VERSIONS -// ------------------------------------------------------------------------ - -/** - * phpCAS version. accessible for the user by phpCAS::getVersion(). - */ -define('PHPCAS_VERSION','1.0.1'); - -// ------------------------------------------------------------------------ -// CAS VERSIONS -// ------------------------------------------------------------------------ - /** - * @addtogroup public - * @{ - */ - -/** - * CAS version 1.0 - */ -define("CAS_VERSION_1_0",'1.0'); -/*! - * CAS version 2.0 - */ -define("CAS_VERSION_2_0",'2.0'); - -/** @} */ - /** - * @addtogroup publicPGTStorage - * @{ - */ -// ------------------------------------------------------------------------ -// FILE PGT STORAGE -// ------------------------------------------------------------------------ - /** - * Default path used when storing PGT's to file - */ -define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH",'/tmp'); -/** - * phpCAS::setPGTStorageFile()'s 2nd parameter to write plain text files - */ -define("CAS_PGT_STORAGE_FILE_FORMAT_PLAIN",'plain'); -/** - * phpCAS::setPGTStorageFile()'s 2nd parameter to write xml files - */ -define("CAS_PGT_STORAGE_FILE_FORMAT_XML",'xml'); -/** - * Default format used when storing PGT's to file - */ -define("CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT",CAS_PGT_STORAGE_FILE_FORMAT_PLAIN); -// ------------------------------------------------------------------------ -// DATABASE PGT STORAGE -// ------------------------------------------------------------------------ - /** - * default database type when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_DATABASE_TYPE",'mysql'); -/** - * default host when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_HOSTNAME",'localhost'); -/** - * default port when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_PORT",''); -/** - * default database when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_DATABASE",'phpCAS'); -/** - * default table when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_TABLE",'pgt'); - -/** @} */ -// ------------------------------------------------------------------------ -// SERVICE ACCESS ERRORS -// ------------------------------------------------------------------------ - /** - * @addtogroup publicServices - * @{ - */ - -/** - * phpCAS::service() error code on success - */ -define("PHPCAS_SERVICE_OK",0); -/** - * phpCAS::service() error code when the PT could not retrieve because - * the CAS server did not respond. - */ -define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE",1); -/** - * phpCAS::service() error code when the PT could not retrieve because - * the response of the CAS server was ill-formed. - */ -define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE",2); -/** - * phpCAS::service() error code when the PT could not retrieve because - * the CAS server did not want to. - */ -define("PHPCAS_SERVICE_PT_FAILURE",3); -/** - * phpCAS::service() error code when the service was not available. - */ -define("PHPCAS_SERVICE_NOT AVAILABLE",4); - -/** @} */ -// ------------------------------------------------------------------------ -// LANGUAGES -// ------------------------------------------------------------------------ - /** - * @addtogroup publicLang - * @{ - */ - -define("PHPCAS_LANG_ENGLISH", 'english'); -define("PHPCAS_LANG_FRENCH", 'french'); -define("PHPCAS_LANG_GREEK", 'greek'); -define("PHPCAS_LANG_GERMAN", 'german'); -define("PHPCAS_LANG_JAPANESE", 'japanese'); -define("PHPCAS_LANG_SPANISH", 'spanish'); -define("PHPCAS_LANG_CATALAN", 'catalan'); - -/** @} */ - -/** - * @addtogroup internalLang - * @{ - */ - -/** - * phpCAS default language (when phpCAS::setLang() is not used) - */ -define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH); - -/** @} */ -// ------------------------------------------------------------------------ -// DEBUG -// ------------------------------------------------------------------------ - /** - * @addtogroup publicDebug - * @{ - */ - -/** - * The default directory for the debug file under Unix. - */ -define('DEFAULT_DEBUG_DIR','/tmp/'); - -/** @} */ -// ------------------------------------------------------------------------ -// MISC -// ------------------------------------------------------------------------ - /** - * @addtogroup internalMisc - * @{ - */ - -/** - * This global variable is used by the interface class phpCAS. - * - * @hideinitializer - */ -$GLOBALS['PHPCAS_CLIENT'] = null; - -/** - * This global variable is used to store where the initializer is called from - * (to print a comprehensive error in case of multiple calls). - * - * @hideinitializer - */ -$GLOBALS['PHPCAS_INIT_CALL'] = array('done' => FALSE, - 'file' => '?', - 'line' => -1, - 'method' => '?'); - -/** - * This global variable is used to store where the method checking - * the authentication is called from (to print comprehensive errors) - * - * @hideinitializer - */ -$GLOBALS['PHPCAS_AUTH_CHECK_CALL'] = array('done' => FALSE, - 'file' => '?', - 'line' => -1, - 'method' => '?', - 'result' => FALSE); - -/** - * This global variable is used to store phpCAS debug mode. - * - * @hideinitializer - */ -$GLOBALS['PHPCAS_DEBUG'] = array('filename' => FALSE, - 'indent' => 0, - 'unique_id' => ''); - -/** @} */ - -// ######################################################################## -// CLIENT CLASS -// ######################################################################## - -// include client class -include_once(dirname(__FILE__).'/CAS/client.php'); - -// ######################################################################## -// INTERFACE CLASS -// ######################################################################## - -/** - * @class phpCAS - * The phpCAS class is a simple container for the phpCAS library. It provides CAS - * authentication for web applications written in PHP. - * - * @ingroup public - * @author Pascal Aubry - * - * \internal All its methods access the same object ($PHPCAS_CLIENT, declared - * at the end of CAS/client.php). - */ - - - -class phpCAS -{ - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * @addtogroup publicInit - * @{ - */ - - /** - * phpCAS client initializer. - * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be - * called, only once, and before all other methods (except phpCAS::getVersion() - * and phpCAS::setDebug()). - * - * @param $server_version the version of the CAS server - * @param $server_hostname the hostname of the CAS server - * @param $server_port the port the CAS server is running on - * @param $server_uri the URI the CAS server is responding on - * @param $start_session Have phpCAS start PHP sessions (default true) - * - * @return a newly created CASClient object - */ - function client($server_version, - $server_hostname, - $server_port, - $server_uri, - $start_session = true) - { - global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL; - - phpCAS::traceBegin(); - if ( is_object($PHPCAS_CLIENT) ) { - phpCAS::error($PHPCAS_INIT_CALL['method'].'() has already been called (at '.$PHPCAS_INIT_CALL['file'].':'.$PHPCAS_INIT_CALL['line'].')'); - } - if ( gettype($server_version) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_version (should be `string\')'); - } - if ( gettype($server_hostname) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_hostname (should be `string\')'); - } - if ( gettype($server_port) != 'integer' ) { - phpCAS::error('type mismatched for parameter $server_port (should be `integer\')'); - } - if ( gettype($server_uri) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_uri (should be `string\')'); - } - - // store where the initialzer is called from - $dbg = phpCAS::backtrace(); - $PHPCAS_INIT_CALL = array('done' => TRUE, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__.'::'.__FUNCTION__); - - // initialize the global object $PHPCAS_CLIENT - $PHPCAS_CLIENT = new CASClient($server_version,FALSE/*proxy*/,$server_hostname,$server_port,$server_uri,$start_session); - phpCAS::traceEnd(); - } - - /** - * phpCAS proxy initializer. - * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be - * called, only once, and before all other methods (except phpCAS::getVersion() - * and phpCAS::setDebug()). - * - * @param $server_version the version of the CAS server - * @param $server_hostname the hostname of the CAS server - * @param $server_port the port the CAS server is running on - * @param $server_uri the URI the CAS server is responding on - * @param $start_session Have phpCAS start PHP sessions (default true) - * - * @return a newly created CASClient object - */ - function proxy($server_version, - $server_hostname, - $server_port, - $server_uri, - $start_session = true) - { - global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL; - - phpCAS::traceBegin(); - if ( is_object($PHPCAS_CLIENT) ) { - phpCAS::error($PHPCAS_INIT_CALL['method'].'() has already been called (at '.$PHPCAS_INIT_CALL['file'].':'.$PHPCAS_INIT_CALL['line'].')'); - } - if ( gettype($server_version) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_version (should be `string\')'); - } - if ( gettype($server_hostname) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_hostname (should be `string\')'); - } - if ( gettype($server_port) != 'integer' ) { - phpCAS::error('type mismatched for parameter $server_port (should be `integer\')'); - } - if ( gettype($server_uri) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_uri (should be `string\')'); - } - - // store where the initialzer is called from - $dbg = phpCAS::backtrace(); - $PHPCAS_INIT_CALL = array('done' => TRUE, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__.'::'.__FUNCTION__); - - // initialize the global object $PHPCAS_CLIENT - $PHPCAS_CLIENT = new CASClient($server_version,TRUE/*proxy*/,$server_hostname,$server_port,$server_uri,$start_session); - phpCAS::traceEnd(); - } - - /** @} */ - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * @addtogroup publicDebug - * @{ - */ - - /** - * Set/unset debug mode - * - * @param $filename the name of the file used for logging, or FALSE to stop debugging. - */ - function setDebug($filename='') - { - global $PHPCAS_DEBUG; - - if ( $filename != FALSE && gettype($filename) != 'string' ) { - phpCAS::error('type mismatched for parameter $dbg (should be FALSE or the name of the log file)'); - } - - if ( empty($filename) ) { - if ( preg_match('/^Win.*/',getenv('OS')) ) { - if ( isset($_ENV['TMP']) ) { - $debugDir = $_ENV['TMP'].'/'; - } else if ( isset($_ENV['TEMP']) ) { - $debugDir = $_ENV['TEMP'].'/'; - } else { - $debugDir = ''; - } - } else { - $debugDir = DEFAULT_DEBUG_DIR; - } - $filename = $debugDir . 'phpCAS.log'; - } - - if ( empty($PHPCAS_DEBUG['unique_id']) ) { - $PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))),0,4); - } - - $PHPCAS_DEBUG['filename'] = $filename; - - phpCAS::trace('START ******************'); - } - - /** @} */ - /** - * @addtogroup internalDebug - * @{ - */ - - /** - * This method is a wrapper for debug_backtrace() that is not available - * in all PHP versions (>= 4.3.0 only) - */ - function backtrace() - { - if ( function_exists('debug_backtrace') ) { - return debug_backtrace(); - } else { - // poor man's hack ... but it does work ... - return array(); - } - } - - /** - * Logs a string in debug mode. - * - * @param $str the string to write - * - * @private - */ - function log($str) - { - $indent_str = "."; - global $PHPCAS_DEBUG; - - if ( $PHPCAS_DEBUG['filename'] ) { - for ($i=0;$i<$PHPCAS_DEBUG['indent'];$i++) { - $indent_str .= '| '; - } - error_log($PHPCAS_DEBUG['unique_id'].' '.$indent_str.$str."\n",3,$PHPCAS_DEBUG['filename']); - } - - } - - /** - * This method is used by interface methods to print an error and where the function - * was originally called from. - * - * @param $msg the message to print - * - * @private - */ - function error($msg) - { - $dbg = phpCAS::backtrace(); - $function = '?'; - $file = '?'; - $line = '?'; - if ( is_array($dbg) ) { - for ( $i=1; $i\nphpCAS error: ".__CLASS__."::".$function.'(): '.htmlentities($msg)." in ".$file." on line ".$line."
    \n"; - phpCAS::trace($msg); - phpCAS::traceExit(); - exit(); - } - - /** - * This method is used to log something in debug mode. - */ - function trace($str) - { - $dbg = phpCAS::backtrace(); - phpCAS::log($str.' ['.basename($dbg[1]['file']).':'.$dbg[1]['line'].']'); - } - - /** - * This method is used to indicate the start of the execution of a function in debug mode. - */ - function traceBegin() - { - global $PHPCAS_DEBUG; - - $dbg = phpCAS::backtrace(); - $str = '=> '; - if ( !empty($dbg[2]['class']) ) { - $str .= $dbg[2]['class'].'::'; - } - $str .= $dbg[2]['function'].'('; - if ( is_array($dbg[2]['args']) ) { - foreach ($dbg[2]['args'] as $index => $arg) { - if ( $index != 0 ) { - $str .= ', '; - } - $str .= str_replace("\n","",var_export($arg,TRUE)); - } - } - $str .= ') ['.basename($dbg[2]['file']).':'.$dbg[2]['line'].']'; - phpCAS::log($str); - $PHPCAS_DEBUG['indent'] ++; - } - - /** - * This method is used to indicate the end of the execution of a function in debug mode. - * - * @param $res the result of the function - */ - function traceEnd($res='') - { - global $PHPCAS_DEBUG; - - $PHPCAS_DEBUG['indent'] --; - $dbg = phpCAS::backtrace(); - $str = ''; - $str .= '<= '.str_replace("\n","",var_export($res,TRUE)); - phpCAS::log($str); - } - - /** - * This method is used to indicate the end of the execution of the program - */ - function traceExit() - { - global $PHPCAS_DEBUG; - - phpCAS::log('exit()'); - while ( $PHPCAS_DEBUG['indent'] > 0 ) { - phpCAS::log('-'); - $PHPCAS_DEBUG['indent'] --; - } - } - - /** @} */ - // ######################################################################## - // INTERNATIONALIZATION - // ######################################################################## - /** - * @addtogroup publicLang - * @{ - */ - - /** - * This method is used to set the language used by phpCAS. - * @note Can be called only once. - * - * @param $lang a string representing the language. - * - * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH - */ - function setLang($lang) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - if ( gettype($lang) != 'string' ) { - phpCAS::error('type mismatched for parameter $lang (should be `string\')'); - } - $PHPCAS_CLIENT->setLang($lang); - } - - /** @} */ - // ######################################################################## - // VERSION - // ######################################################################## - /** - * @addtogroup public - * @{ - */ - - /** - * This method returns the phpCAS version. - * - * @return the phpCAS version. - */ - function getVersion() - { - return PHPCAS_VERSION; - } - - /** @} */ - // ######################################################################## - // HTML OUTPUT - // ######################################################################## - /** - * @addtogroup publicOutput - * @{ - */ - - /** - * This method sets the HTML header used for all outputs. - * - * @param $header the HTML header. - */ - function setHTMLHeader($header) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - if ( gettype($header) != 'string' ) { - phpCAS::error('type mismatched for parameter $header (should be `string\')'); - } - $PHPCAS_CLIENT->setHTMLHeader($header); - } - - /** - * This method sets the HTML footer used for all outputs. - * - * @param $footer the HTML footer. - */ - function setHTMLFooter($footer) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - if ( gettype($footer) != 'string' ) { - phpCAS::error('type mismatched for parameter $footer (should be `string\')'); - } - $PHPCAS_CLIENT->setHTMLFooter($footer); - } - - /** @} */ - // ######################################################################## - // PGT STORAGE - // ######################################################################## - /** - * @addtogroup publicPGTStorage - * @{ - */ - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests onto the filesystem. - * - * @param $format the format used to store the PGT's (`plain' and `xml' allowed) - * @param $path the path where the PGT's should be stored - */ - function setPGTStorageFile($format='', - $path='') - { - global $PHPCAS_CLIENT,$PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( $PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called before '.$PHPCAS_AUTH_CHECK_CALL['method'].'() (called at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].')'); - } - if ( gettype($format) != 'string' ) { - phpCAS::error('type mismatched for parameter $format (should be `string\')'); - } - if ( gettype($path) != 'string' ) { - phpCAS::error('type mismatched for parameter $format (should be `string\')'); - } - $PHPCAS_CLIENT->setPGTStorageFile($format,$path); - phpCAS::traceEnd(); - } - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests into a database. - * @note The connection to the database is done only when needed. - * As a consequence, bad parameters are detected only when - * initializing PGT storage, except in debug mode. - * - * @param $user the user to access the data with - * @param $password the user's password - * @param $database_type the type of the database hosting the data - * @param $hostname the server hosting the database - * @param $port the port the server is listening on - * @param $database the name of the database - * @param $table the name of the table storing the data - */ - function setPGTStorageDB($user, - $password, - $database_type='', - $hostname='', - $port=0, - $database='', - $table='') - { - global $PHPCAS_CLIENT,$PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( $PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called before '.$PHPCAS_AUTH_CHECK_CALL['method'].'() (called at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].')'); - } - if ( gettype($user) != 'string' ) { - phpCAS::error('type mismatched for parameter $user (should be `string\')'); - } - if ( gettype($password) != 'string' ) { - phpCAS::error('type mismatched for parameter $password (should be `string\')'); - } - if ( gettype($database_type) != 'string' ) { - phpCAS::error('type mismatched for parameter $database_type (should be `string\')'); - } - if ( gettype($hostname) != 'string' ) { - phpCAS::error('type mismatched for parameter $hostname (should be `string\')'); - } - if ( gettype($port) != 'integer' ) { - phpCAS::error('type mismatched for parameter $port (should be `integer\')'); - } - if ( gettype($database) != 'string' ) { - phpCAS::error('type mismatched for parameter $database (should be `string\')'); - } - if ( gettype($table) != 'string' ) { - phpCAS::error('type mismatched for parameter $table (should be `string\')'); - } - $PHPCAS_CLIENT->setPGTStorageDB($this,$user,$password,$hostname,$port,$database,$table); - phpCAS::traceEnd(); - } - - /** @} */ - // ######################################################################## - // ACCESS TO EXTERNAL SERVICES - // ######################################################################## - /** - * @addtogroup publicServices - * @{ - */ - - /** - * This method is used to access an HTTP[S] service. - * - * @param $url the service to access. - * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on - * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, - * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE. - * @param $output the output of the service (also used to give an error - * message on failure). - * - * @return TRUE on success, FALSE otherwise (in this later case, $err_code - * gives the reason why it failed and $output contains an error message). - */ - function serviceWeb($url,&$err_code,&$output) - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called after the programmer is sure the user has been authenticated (by calling '.__CLASS__.'::checkAuthentication() or '.__CLASS__.'::forceAuthentication()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { - phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - - $res = $PHPCAS_CLIENT->serviceWeb($url,$err_code,$output); - - phpCAS::traceEnd($res); - return $res; - } - - /** - * This method is used to access an IMAP/POP3/NNTP service. - * - * @param $url a string giving the URL of the service, including the mailing box - * for IMAP URLs, as accepted by imap_open(). - * @param $flags options given to imap_open(). - * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on - * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, - * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE. - * @param $err_msg an error message on failure - * @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL - * on success, FALSE on error). - * - * @return an IMAP stream on success, FALSE otherwise (in this later case, $err_code - * gives the reason why it failed and $err_msg contains an error message). - */ - function serviceMail($url,$flags,&$err_code,&$err_msg,&$pt) - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called after the programmer is sure the user has been authenticated (by calling '.__CLASS__.'::checkAuthentication() or '.__CLASS__.'::forceAuthentication()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { - phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - - if ( gettype($flags) != 'integer' ) { - phpCAS::error('type mismatched for parameter $flags (should be `integer\')'); - } - - $res = $PHPCAS_CLIENT->serviceMail($url,$flags,$err_code,$err_msg,$pt); - - phpCAS::traceEnd($res); - return $res; - } - - /** @} */ - // ######################################################################## - // AUTHENTICATION - // ######################################################################## - /** - * @addtogroup publicAuth - * @{ - */ - - /** - * Set the times authentication will be cached before really accessing the CAS server in gateway mode: - * - -1: check only once, and then never again (until you pree login) - * - 0: always check - * - n: check every "n" time - * - * @param $n an integer. - */ - function setCacheTimesForAuthRecheck($n) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - if ( gettype($n) != 'integer' ) { - phpCAS::error('type mismatched for parameter $header (should be `string\')'); - } - $PHPCAS_CLIENT->setCacheTimesForAuthRecheck($n); - } - - /** - * This method is called to check if the user is authenticated (use the gateway feature). - * @return TRUE when the user is authenticated; otherwise FALSE. - */ - function checkAuthentication() - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - - $auth = $PHPCAS_CLIENT->checkAuthentication(); - - // store where the authentication has been checked and the result - $dbg = phpCAS::backtrace(); - $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__.'::'.__FUNCTION__, - 'result' => $auth ); - phpCAS::traceEnd($auth); - return $auth; - } - - /** - * This method is called to force authentication if the user was not already - * authenticated. If the user is not authenticated, halt by redirecting to - * the CAS server. - */ - function forceAuthentication() - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - - $auth = $PHPCAS_CLIENT->forceAuthentication(); - - // store where the authentication has been checked and the result - $dbg = phpCAS::backtrace(); - $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__.'::'.__FUNCTION__, - 'result' => $auth ); - - if ( !$auth ) { - phpCAS::trace('user is not authenticated, redirecting to the CAS server'); - $PHPCAS_CLIENT->forceAuthentication(); - } else { - phpCAS::trace('no need to authenticate (user `'.phpCAS::getUser().'\' is already authenticated)'); - } - - phpCAS::traceEnd(); - return $auth; - } - - /** - * This method is called to renew the authentication. - **/ - function renewAuthentication() { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before'.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - - // store where the authentication has been checked and the result - $dbg = phpCAS::backtrace(); - $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, 'file' => $dbg[0]['file'], 'line' => $dbg[0]['line'], 'method' => __CLASS__.'::'.__FUNCTION__, 'result' => $auth ); - - $PHPCAS_CLIENT->renewAuthentication(); - phpCAS::traceEnd(); - } - - /** - * This method has been left from version 0.4.1 for compatibility reasons. - */ - function authenticate() - { - phpCAS::error('this method is deprecated. You should use '.__CLASS__.'::forceAuthentication() instead'); - } - - /** - * This method is called to check if the user is authenticated (previously or by - * tickets given in the URL). - * - * @return TRUE when the user is authenticated. - */ - function isAuthenticated() - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - - // call the isAuthenticated method of the global $PHPCAS_CLIENT object - $auth = $PHPCAS_CLIENT->isAuthenticated(); - - // store where the authentication has been checked and the result - $dbg = phpCAS::backtrace(); - $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__.'::'.__FUNCTION__, - 'result' => $auth ); - phpCAS::traceEnd($auth); - return $auth; - } - - /** - * Checks whether authenticated based on $_SESSION. Useful to avoid - * server calls. - * @return true if authenticated, false otherwise. - * @since 0.4.22 by Brendan Arnold - */ - function isSessionAuthenticated () - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - return($PHPCAS_CLIENT->isSessionAuthenticated()); - } - - /** - * This method returns the CAS user's login name. - * @warning should not be called only after phpCAS::forceAuthentication() - * or phpCAS::checkAuthentication(). - * - * @return the login name of the authenticated user - */ - function getUser() - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { - phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); - } - return $PHPCAS_CLIENT->getUser(); - } - - /** - * Handle logout requests. - */ - function handleLogoutRequests($check_client=true, $allowed_clients=false) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - return($PHPCAS_CLIENT->handleLogoutRequests($check_client, $allowed_clients)); - } - - /** - * This method returns the URL to be used to login. - * or phpCAS::isAuthenticated(). - * - * @return the login name of the authenticated user - */ - function getServerLoginURL() - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - return $PHPCAS_CLIENT->getServerLoginURL(); - } - - /** - * Set the login URL of the CAS server. - * @param $url the login URL - * @since 0.4.21 by Wyman Chan - */ - function setServerLoginURL($url='') - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after - '.__CLASS__.'::client()'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be - `string\')'); - } - $PHPCAS_CLIENT->setServerLoginURL($url); - phpCAS::traceEnd(); - } - - /** - * This method returns the URL to be used to login. - * or phpCAS::isAuthenticated(). - * - * @return the login name of the authenticated user - */ - function getServerLogoutURL() - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - return $PHPCAS_CLIENT->getServerLogoutURL(); - } - - /** - * Set the logout URL of the CAS server. - * @param $url the logout URL - * @since 0.4.21 by Wyman Chan - */ - function setServerLogoutURL($url='') - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after - '.__CLASS__.'::client()'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be - `string\')'); - } - $PHPCAS_CLIENT->setServerLogoutURL($url); - phpCAS::traceEnd(); - } - - /** - * This method is used to logout from CAS. - * @params $params an array that contains the optional url and service parameters that will be passed to the CAS server - * @public - */ - function logout($params = "") { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if (!is_object($PHPCAS_CLIENT)) { - phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); - } - $parsedParams = array(); - if ($params != "") { - if (is_string($params)) { - phpCAS::error('method `phpCAS::logout($url)\' is now deprecated, use `phpCAS::logoutWithUrl($url)\' instead'); - } - if (!is_array($params)) { - phpCAS::error('type mismatched for parameter $params (should be `array\')'); - } - foreach ($params as $key => $value) { - if ($key != "service" && $key != "url") { - phpCAS::error('only `url\' and `service\' parameters are allowed for method `phpCAS::logout($params)\''); - } - $parsedParams[$key] = $value; - } - } - $PHPCAS_CLIENT->logout($parsedParams); - // never reached - phpCAS::traceEnd(); - } - - /** - * This method is used to logout from CAS. Halts by redirecting to the CAS server. - * @param $service a URL that will be transmitted to the CAS server - */ - function logoutWithRedirectService($service) { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); - } - if (!is_string($service)) { - phpCAS::error('type mismatched for parameter $service (should be `string\')'); - } - $PHPCAS_CLIENT->logout(array("service" => $service)); - // never reached - phpCAS::traceEnd(); - } - - /** - * This method is used to logout from CAS. Halts by redirecting to the CAS server. - * @param $url a URL that will be transmitted to the CAS server - */ - function logoutWithUrl($url) { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); - } - if (!is_string($url)) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - $PHPCAS_CLIENT->logout(array("url" => $url)); - // never reached - phpCAS::traceEnd(); - } - - /** - * This method is used to logout from CAS. Halts by redirecting to the CAS server. - * @param $service a URL that will be transmitted to the CAS server - * @param $url a URL that will be transmitted to the CAS server - */ - function logoutWithRedirectServiceAndUrl($service, $url) { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); - } - if (!is_string($service)) { - phpCAS::error('type mismatched for parameter $service (should be `string\')'); - } - if (!is_string($url)) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - $PHPCAS_CLIENT->logout(array("service" => $service, "url" => $url)); - // never reached - phpCAS::traceEnd(); - } - - /** - * Set the fixed URL that will be used by the CAS server to transmit the PGT. - * When this method is not called, a phpCAS script uses its own URL for the callback. - * - * @param $url the URL - */ - function setFixedCallbackURL($url='') - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - $PHPCAS_CLIENT->setCallbackURL($url); - phpCAS::traceEnd(); - } - - /** - * Set the fixed URL that will be set as the CAS service parameter. When this - * method is not called, a phpCAS script uses its own URL. - * - * @param $url the URL - */ - function setFixedServiceURL($url) - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - $PHPCAS_CLIENT->setURL($url); - phpCAS::traceEnd(); - } - - /** - * Get the URL that is set as the CAS service parameter. - */ - function getServiceURL() - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - return($PHPCAS_CLIENT->getURL()); - } - - /** - * Retrieve a Proxy Ticket from the CAS server. - */ - function retrievePT($target_service,&$err_code,&$err_msg) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( gettype($target_service) != 'string' ) { - phpCAS::error('type mismatched for parameter $target_service(should be `string\')'); - } - return($PHPCAS_CLIENT->retrievePT($target_service,$err_code,$err_msg)); - } - - /** - * Set the certificate of the CAS server. - * - * @param $cert the PEM certificate - */ - function setCasServerCert($cert) - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); - } - if ( gettype($cert) != 'string' ) { - phpCAS::error('type mismatched for parameter $cert (should be `string\')'); - } - $PHPCAS_CLIENT->setCasServerCert($cert); - phpCAS::traceEnd(); - } - - /** - * Set the certificate of the CAS server CA. - * - * @param $cert the CA certificate - */ - function setCasServerCACert($cert) - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); - } - if ( gettype($cert) != 'string' ) { - phpCAS::error('type mismatched for parameter $cert (should be `string\')'); - } - $PHPCAS_CLIENT->setCasServerCACert($cert); - phpCAS::traceEnd(); - } - - /** - * Set no SSL validation for the CAS server. - */ - function setNoCasServerValidation() - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); - } - $PHPCAS_CLIENT->setNoCasServerValidation(); - phpCAS::traceEnd(); - } - - /** @} */ - - /** - * Change CURL options. - * CURL is used to connect through HTTPS to CAS server - * @param $key the option key - * @param $value the value to set - */ - function setExtraCurlOption($key, $value) - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); - } - $PHPCAS_CLIENT->setExtraCurlOption($key, $value); - phpCAS::traceEnd(); - } - -} - -// ######################################################################## -// DOCUMENTATION -// ######################################################################## - -// ######################################################################## -// MAIN PAGE - -/** - * @mainpage - * - * The following pages only show the source documentation. - * - */ - -// ######################################################################## -// MODULES DEFINITION - -/** @defgroup public User interface */ - -/** @defgroup publicInit Initialization - * @ingroup public */ - -/** @defgroup publicAuth Authentication - * @ingroup public */ - -/** @defgroup publicServices Access to external services - * @ingroup public */ - -/** @defgroup publicConfig Configuration - * @ingroup public */ - -/** @defgroup publicLang Internationalization - * @ingroup publicConfig */ - -/** @defgroup publicOutput HTML output - * @ingroup publicConfig */ - -/** @defgroup publicPGTStorage PGT storage - * @ingroup publicConfig */ - -/** @defgroup publicDebug Debugging - * @ingroup public */ - - -/** @defgroup internal Implementation */ - -/** @defgroup internalAuthentication Authentication - * @ingroup internal */ - -/** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets) - * @ingroup internal */ - -/** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets) - * @ingroup internal */ - -/** @defgroup internalPGTStorage PGT storage - * @ingroup internalProxy */ - -/** @defgroup internalPGTStorageDB PGT storage in a database - * @ingroup internalPGTStorage */ - -/** @defgroup internalPGTStorageFile PGT storage on the filesystem - * @ingroup internalPGTStorage */ - -/** @defgroup internalCallback Callback from the CAS server - * @ingroup internalProxy */ - -/** @defgroup internalProxied CAS proxied client features (CAS 2.0, Proxy Tickets) - * @ingroup internal */ - -/** @defgroup internalConfig Configuration - * @ingroup internal */ - -/** @defgroup internalOutput HTML output - * @ingroup internalConfig */ - -/** @defgroup internalLang Internationalization - * @ingroup internalConfig - * - * To add a new language: - * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php - * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php - * - 3. Make the translations - */ - -/** @defgroup internalDebug Debugging - * @ingroup internal */ - -/** @defgroup internalMisc Miscellaneous - * @ingroup internal */ - -// ######################################################################## -// EXAMPLES - -/** - * @example example_simple.php - */ - /** - * @example example_proxy.php - */ - /** - * @example example_proxy2.php - */ - /** - * @example example_lang.php - */ - /** - * @example example_html.php - */ - /** - * @example example_file.php - */ - /** - * @example example_db.php - */ - /** - * @example example_service.php - */ - /** - * @example example_session_proxy.php - */ - /** - * @example example_session_service.php - */ - /** - * @example example_gateway.php - */ - - - -?> +=')) { + require_once(dirname(__FILE__).'/CAS/domxml-php4-to-php5.php'); +} + +/** + * @file CAS/CAS.php + * Interface class of the phpCAS library + * + * @ingroup public + */ + +// ######################################################################## +// CONSTANTS +// ######################################################################## + +// ------------------------------------------------------------------------ +// CAS VERSIONS +// ------------------------------------------------------------------------ + +/** + * phpCAS version. accessible for the user by phpCAS::getVersion(). + */ +define('PHPCAS_VERSION','1.1.0RC6'); + +// ------------------------------------------------------------------------ +// CAS VERSIONS +// ------------------------------------------------------------------------ + /** + * @addtogroup public + * @{ + */ + +/** + * CAS version 1.0 + */ +define("CAS_VERSION_1_0",'1.0'); +/*! + * CAS version 2.0 + */ +define("CAS_VERSION_2_0",'2.0'); + +// ------------------------------------------------------------------------ +// SAML defines +// ------------------------------------------------------------------------ + +/** + * SAML protocol + */ +define("SAML_VERSION_1_1", 'S1'); + +/** + * XML header for SAML POST + */ +define("SAML_XML_HEADER", ''); + +/** + * SOAP envelope for SAML POST + */ +define ("SAML_SOAP_ENV", ''); + +/** + * SOAP body for SAML POST + */ +define ("SAML_SOAP_BODY", ''); + +/** + * SAMLP request + */ +define ("SAMLP_REQUEST", ''); +define ("SAMLP_REQUEST_CLOSE", ''); + +/** + * SAMLP artifact tag (for the ticket) + */ +define ("SAML_ASSERTION_ARTIFACT", ''); + +/** + * SAMLP close + */ +define ("SAML_ASSERTION_ARTIFACT_CLOSE", ''); + +/** + * SOAP body close + */ +define ("SAML_SOAP_BODY_CLOSE", ''); + +/** + * SOAP envelope close + */ +define ("SAML_SOAP_ENV_CLOSE", ''); + +/** + * SAML Attributes + */ +define("SAML_ATTRIBUTES", 'SAMLATTRIBS'); + + + +/** @} */ + /** + * @addtogroup publicPGTStorage + * @{ + */ +// ------------------------------------------------------------------------ +// FILE PGT STORAGE +// ------------------------------------------------------------------------ + /** + * Default path used when storing PGT's to file + */ +define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH",'/tmp'); +/** + * phpCAS::setPGTStorageFile()'s 2nd parameter to write plain text files + */ +define("CAS_PGT_STORAGE_FILE_FORMAT_PLAIN",'plain'); +/** + * phpCAS::setPGTStorageFile()'s 2nd parameter to write xml files + */ +define("CAS_PGT_STORAGE_FILE_FORMAT_XML",'xml'); +/** + * Default format used when storing PGT's to file + */ +define("CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT",CAS_PGT_STORAGE_FILE_FORMAT_PLAIN); +// ------------------------------------------------------------------------ +// DATABASE PGT STORAGE +// ------------------------------------------------------------------------ + /** + * default database type when storing PGT's to database + */ +define("CAS_PGT_STORAGE_DB_DEFAULT_DATABASE_TYPE",'mysql'); +/** + * default host when storing PGT's to database + */ +define("CAS_PGT_STORAGE_DB_DEFAULT_HOSTNAME",'localhost'); +/** + * default port when storing PGT's to database + */ +define("CAS_PGT_STORAGE_DB_DEFAULT_PORT",''); +/** + * default database when storing PGT's to database + */ +define("CAS_PGT_STORAGE_DB_DEFAULT_DATABASE",'phpCAS'); +/** + * default table when storing PGT's to database + */ +define("CAS_PGT_STORAGE_DB_DEFAULT_TABLE",'pgt'); + +/** @} */ +// ------------------------------------------------------------------------ +// SERVICE ACCESS ERRORS +// ------------------------------------------------------------------------ + /** + * @addtogroup publicServices + * @{ + */ + +/** + * phpCAS::service() error code on success + */ +define("PHPCAS_SERVICE_OK",0); +/** + * phpCAS::service() error code when the PT could not retrieve because + * the CAS server did not respond. + */ +define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE",1); +/** + * phpCAS::service() error code when the PT could not retrieve because + * the response of the CAS server was ill-formed. + */ +define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE",2); +/** + * phpCAS::service() error code when the PT could not retrieve because + * the CAS server did not want to. + */ +define("PHPCAS_SERVICE_PT_FAILURE",3); +/** + * phpCAS::service() error code when the service was not available. + */ +define("PHPCAS_SERVICE_NOT AVAILABLE",4); + +/** @} */ +// ------------------------------------------------------------------------ +// LANGUAGES +// ------------------------------------------------------------------------ + /** + * @addtogroup publicLang + * @{ + */ + +define("PHPCAS_LANG_ENGLISH", 'english'); +define("PHPCAS_LANG_FRENCH", 'french'); +define("PHPCAS_LANG_GREEK", 'greek'); +define("PHPCAS_LANG_GERMAN", 'german'); +define("PHPCAS_LANG_JAPANESE", 'japanese'); +define("PHPCAS_LANG_SPANISH", 'spanish'); +define("PHPCAS_LANG_CATALAN", 'catalan'); + +/** @} */ + +/** + * @addtogroup internalLang + * @{ + */ + +/** + * phpCAS default language (when phpCAS::setLang() is not used) + */ +define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH); + +/** @} */ +// ------------------------------------------------------------------------ +// DEBUG +// ------------------------------------------------------------------------ + /** + * @addtogroup publicDebug + * @{ + */ + +/** + * The default directory for the debug file under Unix. + */ +define('DEFAULT_DEBUG_DIR','/tmp/'); + +/** @} */ +// ------------------------------------------------------------------------ +// MISC +// ------------------------------------------------------------------------ + /** + * @addtogroup internalMisc + * @{ + */ + +/** + * This global variable is used by the interface class phpCAS. + * + * @hideinitializer + */ +$GLOBALS['PHPCAS_CLIENT'] = null; + +/** + * This global variable is used to store where the initializer is called from + * (to print a comprehensive error in case of multiple calls). + * + * @hideinitializer + */ +$GLOBALS['PHPCAS_INIT_CALL'] = array('done' => FALSE, + 'file' => '?', + 'line' => -1, + 'method' => '?'); + +/** + * This global variable is used to store where the method checking + * the authentication is called from (to print comprehensive errors) + * + * @hideinitializer + */ +$GLOBALS['PHPCAS_AUTH_CHECK_CALL'] = array('done' => FALSE, + 'file' => '?', + 'line' => -1, + 'method' => '?', + 'result' => FALSE); + +/** + * This global variable is used to store phpCAS debug mode. + * + * @hideinitializer + */ +$GLOBALS['PHPCAS_DEBUG'] = array('filename' => FALSE, + 'indent' => 0, + 'unique_id' => ''); + +/** @} */ + +// ######################################################################## +// CLIENT CLASS +// ######################################################################## + +// include client class +include_once(dirname(__FILE__).'/CAS/client.php'); + +// ######################################################################## +// INTERFACE CLASS +// ######################################################################## + +/** + * @class phpCAS + * The phpCAS class is a simple container for the phpCAS library. It provides CAS + * authentication for web applications written in PHP. + * + * @ingroup public + * @author Pascal Aubry + * + * \internal All its methods access the same object ($PHPCAS_CLIENT, declared + * at the end of CAS/client.php). + */ + + + +class phpCAS +{ + + // ######################################################################## + // INITIALIZATION + // ######################################################################## + + /** + * @addtogroup publicInit + * @{ + */ + + /** + * phpCAS client initializer. + * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be + * called, only once, and before all other methods (except phpCAS::getVersion() + * and phpCAS::setDebug()). + * + * @param $server_version the version of the CAS server + * @param $server_hostname the hostname of the CAS server + * @param $server_port the port the CAS server is running on + * @param $server_uri the URI the CAS server is responding on + * @param $start_session Have phpCAS start PHP sessions (default true) + * + * @return a newly created CASClient object + */ + function client($server_version, + $server_hostname, + $server_port, + $server_uri, + $start_session = true) + { + global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL; + + phpCAS::traceBegin(); + if ( is_object($PHPCAS_CLIENT) ) { + phpCAS::error($PHPCAS_INIT_CALL['method'].'() has already been called (at '.$PHPCAS_INIT_CALL['file'].':'.$PHPCAS_INIT_CALL['line'].')'); + } + if ( gettype($server_version) != 'string' ) { + phpCAS::error('type mismatched for parameter $server_version (should be `string\')'); + } + if ( gettype($server_hostname) != 'string' ) { + phpCAS::error('type mismatched for parameter $server_hostname (should be `string\')'); + } + if ( gettype($server_port) != 'integer' ) { + phpCAS::error('type mismatched for parameter $server_port (should be `integer\')'); + } + if ( gettype($server_uri) != 'string' ) { + phpCAS::error('type mismatched for parameter $server_uri (should be `string\')'); + } + + // store where the initializer is called from + $dbg = phpCAS::backtrace(); + $PHPCAS_INIT_CALL = array('done' => TRUE, + 'file' => $dbg[0]['file'], + 'line' => $dbg[0]['line'], + 'method' => __CLASS__.'::'.__FUNCTION__); + + // initialize the global object $PHPCAS_CLIENT + $PHPCAS_CLIENT = new CASClient($server_version,FALSE/*proxy*/,$server_hostname,$server_port,$server_uri,$start_session); + phpCAS::traceEnd(); + } + + /** + * phpCAS proxy initializer. + * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be + * called, only once, and before all other methods (except phpCAS::getVersion() + * and phpCAS::setDebug()). + * + * @param $server_version the version of the CAS server + * @param $server_hostname the hostname of the CAS server + * @param $server_port the port the CAS server is running on + * @param $server_uri the URI the CAS server is responding on + * @param $start_session Have phpCAS start PHP sessions (default true) + * + * @return a newly created CASClient object + */ + function proxy($server_version, + $server_hostname, + $server_port, + $server_uri, + $start_session = true) + { + global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL; + + phpCAS::traceBegin(); + if ( is_object($PHPCAS_CLIENT) ) { + phpCAS::error($PHPCAS_INIT_CALL['method'].'() has already been called (at '.$PHPCAS_INIT_CALL['file'].':'.$PHPCAS_INIT_CALL['line'].')'); + } + if ( gettype($server_version) != 'string' ) { + phpCAS::error('type mismatched for parameter $server_version (should be `string\')'); + } + if ( gettype($server_hostname) != 'string' ) { + phpCAS::error('type mismatched for parameter $server_hostname (should be `string\')'); + } + if ( gettype($server_port) != 'integer' ) { + phpCAS::error('type mismatched for parameter $server_port (should be `integer\')'); + } + if ( gettype($server_uri) != 'string' ) { + phpCAS::error('type mismatched for parameter $server_uri (should be `string\')'); + } + + // store where the initialzer is called from + $dbg = phpCAS::backtrace(); + $PHPCAS_INIT_CALL = array('done' => TRUE, + 'file' => $dbg[0]['file'], + 'line' => $dbg[0]['line'], + 'method' => __CLASS__.'::'.__FUNCTION__); + + // initialize the global object $PHPCAS_CLIENT + $PHPCAS_CLIENT = new CASClient($server_version,TRUE/*proxy*/,$server_hostname,$server_port,$server_uri,$start_session); + phpCAS::traceEnd(); + } + + /** @} */ + // ######################################################################## + // DEBUGGING + // ######################################################################## + + /** + * @addtogroup publicDebug + * @{ + */ + + /** + * Set/unset debug mode + * + * @param $filename the name of the file used for logging, or FALSE to stop debugging. + */ + function setDebug($filename='') + { + global $PHPCAS_DEBUG; + + if ( $filename != FALSE && gettype($filename) != 'string' ) { + phpCAS::error('type mismatched for parameter $dbg (should be FALSE or the name of the log file)'); + } + + if ( empty($filename) ) { + if ( preg_match('/^Win.*/',getenv('OS')) ) { + if ( isset($_ENV['TMP']) ) { + $debugDir = $_ENV['TMP'].'/'; + } else if ( isset($_ENV['TEMP']) ) { + $debugDir = $_ENV['TEMP'].'/'; + } else { + $debugDir = ''; + } + } else { + $debugDir = DEFAULT_DEBUG_DIR; + } + $filename = $debugDir . 'phpCAS.log'; + } + + if ( empty($PHPCAS_DEBUG['unique_id']) ) { + $PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))),0,4); + } + + $PHPCAS_DEBUG['filename'] = $filename; + + phpCAS::trace('START ******************'); + } + + /** @} */ + /** + * @addtogroup internalDebug + * @{ + */ + + /** + * This method is a wrapper for debug_backtrace() that is not available + * in all PHP versions (>= 4.3.0 only) + */ + function backtrace() + { + if ( function_exists('debug_backtrace') ) { + return debug_backtrace(); + } else { + // poor man's hack ... but it does work ... + return array(); + } + } + + /** + * Logs a string in debug mode. + * + * @param $str the string to write + * + * @private + */ + function log($str) + { + $indent_str = "."; + global $PHPCAS_DEBUG; + + if ( $PHPCAS_DEBUG['filename'] ) { + for ($i=0;$i<$PHPCAS_DEBUG['indent'];$i++) { + $indent_str .= '| '; + } + error_log($PHPCAS_DEBUG['unique_id'].' '.$indent_str.$str."\n",3,$PHPCAS_DEBUG['filename']); + } + + } + + /** + * This method is used by interface methods to print an error and where the function + * was originally called from. + * + * @param $msg the message to print + * + * @private + */ + function error($msg) + { + $dbg = phpCAS::backtrace(); + $function = '?'; + $file = '?'; + $line = '?'; + if ( is_array($dbg) ) { + for ( $i=1; $i\nphpCAS error: ".__CLASS__."::".$function.'(): '.htmlentities($msg)." in ".$file." on line ".$line."
    \n"; + phpCAS::trace($msg); + phpCAS::traceExit(); + exit(); + } + + /** + * This method is used to log something in debug mode. + */ + function trace($str) + { + $dbg = phpCAS::backtrace(); + phpCAS::log($str.' ['.basename($dbg[1]['file']).':'.$dbg[1]['line'].']'); + } + + /** + * This method is used to indicate the start of the execution of a function in debug mode. + */ + function traceBegin() + { + global $PHPCAS_DEBUG; + + $dbg = phpCAS::backtrace(); + $str = '=> '; + if ( !empty($dbg[2]['class']) ) { + $str .= $dbg[2]['class'].'::'; + } + $str .= $dbg[2]['function'].'('; + if ( is_array($dbg[2]['args']) ) { + foreach ($dbg[2]['args'] as $index => $arg) { + if ( $index != 0 ) { + $str .= ', '; + } + $str .= str_replace("\n","",var_export($arg,TRUE)); + } + } + $str .= ') ['.basename($dbg[2]['file']).':'.$dbg[2]['line'].']'; + phpCAS::log($str); + $PHPCAS_DEBUG['indent'] ++; + } + + /** + * This method is used to indicate the end of the execution of a function in debug mode. + * + * @param $res the result of the function + */ + function traceEnd($res='') + { + global $PHPCAS_DEBUG; + + $PHPCAS_DEBUG['indent'] --; + $dbg = phpCAS::backtrace(); + $str = ''; + $str .= '<= '.str_replace("\n","",var_export($res,TRUE)); + phpCAS::log($str); + } + + /** + * This method is used to indicate the end of the execution of the program + */ + function traceExit() + { + global $PHPCAS_DEBUG; + + phpCAS::log('exit()'); + while ( $PHPCAS_DEBUG['indent'] > 0 ) { + phpCAS::log('-'); + $PHPCAS_DEBUG['indent'] --; + } + } + + /** @} */ + // ######################################################################## + // INTERNATIONALIZATION + // ######################################################################## + /** + * @addtogroup publicLang + * @{ + */ + + /** + * This method is used to set the language used by phpCAS. + * @note Can be called only once. + * + * @param $lang a string representing the language. + * + * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH + */ + function setLang($lang) + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + if ( gettype($lang) != 'string' ) { + phpCAS::error('type mismatched for parameter $lang (should be `string\')'); + } + $PHPCAS_CLIENT->setLang($lang); + } + + /** @} */ + // ######################################################################## + // VERSION + // ######################################################################## + /** + * @addtogroup public + * @{ + */ + + /** + * This method returns the phpCAS version. + * + * @return the phpCAS version. + */ + function getVersion() + { + return PHPCAS_VERSION; + } + + /** @} */ + // ######################################################################## + // HTML OUTPUT + // ######################################################################## + /** + * @addtogroup publicOutput + * @{ + */ + + /** + * This method sets the HTML header used for all outputs. + * + * @param $header the HTML header. + */ + function setHTMLHeader($header) + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + if ( gettype($header) != 'string' ) { + phpCAS::error('type mismatched for parameter $header (should be `string\')'); + } + $PHPCAS_CLIENT->setHTMLHeader($header); + } + + /** + * This method sets the HTML footer used for all outputs. + * + * @param $footer the HTML footer. + */ + function setHTMLFooter($footer) + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + if ( gettype($footer) != 'string' ) { + phpCAS::error('type mismatched for parameter $footer (should be `string\')'); + } + $PHPCAS_CLIENT->setHTMLFooter($footer); + } + + /** @} */ + // ######################################################################## + // PGT STORAGE + // ######################################################################## + /** + * @addtogroup publicPGTStorage + * @{ + */ + + /** + * This method is used to tell phpCAS to store the response of the + * CAS server to PGT requests onto the filesystem. + * + * @param $format the format used to store the PGT's (`plain' and `xml' allowed) + * @param $path the path where the PGT's should be stored + */ + function setPGTStorageFile($format='', + $path='') + { + global $PHPCAS_CLIENT,$PHPCAS_AUTH_CHECK_CALL; + + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( !$PHPCAS_CLIENT->isProxy() ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( $PHPCAS_AUTH_CHECK_CALL['done'] ) { + phpCAS::error('this method should only be called before '.$PHPCAS_AUTH_CHECK_CALL['method'].'() (called at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].')'); + } + if ( gettype($format) != 'string' ) { + phpCAS::error('type mismatched for parameter $format (should be `string\')'); + } + if ( gettype($path) != 'string' ) { + phpCAS::error('type mismatched for parameter $format (should be `string\')'); + } + $PHPCAS_CLIENT->setPGTStorageFile($format,$path); + phpCAS::traceEnd(); + } + + /** + * This method is used to tell phpCAS to store the response of the + * CAS server to PGT requests into a database. + * @note The connection to the database is done only when needed. + * As a consequence, bad parameters are detected only when + * initializing PGT storage, except in debug mode. + * + * @param $user the user to access the data with + * @param $password the user's password + * @param $database_type the type of the database hosting the data + * @param $hostname the server hosting the database + * @param $port the port the server is listening on + * @param $database the name of the database + * @param $table the name of the table storing the data + */ + function setPGTStorageDB($user, + $password, + $database_type='', + $hostname='', + $port=0, + $database='', + $table='') + { + global $PHPCAS_CLIENT,$PHPCAS_AUTH_CHECK_CALL; + + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( !$PHPCAS_CLIENT->isProxy() ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( $PHPCAS_AUTH_CHECK_CALL['done'] ) { + phpCAS::error('this method should only be called before '.$PHPCAS_AUTH_CHECK_CALL['method'].'() (called at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].')'); + } + if ( gettype($user) != 'string' ) { + phpCAS::error('type mismatched for parameter $user (should be `string\')'); + } + if ( gettype($password) != 'string' ) { + phpCAS::error('type mismatched for parameter $password (should be `string\')'); + } + if ( gettype($database_type) != 'string' ) { + phpCAS::error('type mismatched for parameter $database_type (should be `string\')'); + } + if ( gettype($hostname) != 'string' ) { + phpCAS::error('type mismatched for parameter $hostname (should be `string\')'); + } + if ( gettype($port) != 'integer' ) { + phpCAS::error('type mismatched for parameter $port (should be `integer\')'); + } + if ( gettype($database) != 'string' ) { + phpCAS::error('type mismatched for parameter $database (should be `string\')'); + } + if ( gettype($table) != 'string' ) { + phpCAS::error('type mismatched for parameter $table (should be `string\')'); + } + $PHPCAS_CLIENT->setPGTStorageDB($user,$password,$database_type,$hostname,$port,$database,$table); + phpCAS::traceEnd(); + } + + /** @} */ + // ######################################################################## + // ACCESS TO EXTERNAL SERVICES + // ######################################################################## + /** + * @addtogroup publicServices + * @{ + */ + + /** + * This method is used to access an HTTP[S] service. + * + * @param $url the service to access. + * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on + * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, + * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE. + * @param $output the output of the service (also used to give an error + * message on failure). + * + * @return TRUE on success, FALSE otherwise (in this later case, $err_code + * gives the reason why it failed and $output contains an error message). + */ + function serviceWeb($url,&$err_code,&$output) + { + global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; + + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( !$PHPCAS_CLIENT->isProxy() ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { + phpCAS::error('this method should only be called after the programmer is sure the user has been authenticated (by calling '.__CLASS__.'::checkAuthentication() or '.__CLASS__.'::forceAuthentication()'); + } + if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { + phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); + } + if ( gettype($url) != 'string' ) { + phpCAS::error('type mismatched for parameter $url (should be `string\')'); + } + + $res = $PHPCAS_CLIENT->serviceWeb($url,$err_code,$output); + + phpCAS::traceEnd($res); + return $res; + } + + /** + * This method is used to access an IMAP/POP3/NNTP service. + * + * @param $url a string giving the URL of the service, including the mailing box + * for IMAP URLs, as accepted by imap_open(). + * @param $service a string giving for CAS retrieve Proxy ticket + * @param $flags options given to imap_open(). + * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on + * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, + * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE. + * @param $err_msg an error message on failure + * @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL + * on success, FALSE on error). + * + * @return an IMAP stream on success, FALSE otherwise (in this later case, $err_code + * gives the reason why it failed and $err_msg contains an error message). + */ + function serviceMail($url,$service,$flags,&$err_code,&$err_msg,&$pt) + { + global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; + + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( !$PHPCAS_CLIENT->isProxy() ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { + phpCAS::error('this method should only be called after the programmer is sure the user has been authenticated (by calling '.__CLASS__.'::checkAuthentication() or '.__CLASS__.'::forceAuthentication()'); + } + if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { + phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); + } + if ( gettype($url) != 'string' ) { + phpCAS::error('type mismatched for parameter $url (should be `string\')'); + } + + if ( gettype($flags) != 'integer' ) { + phpCAS::error('type mismatched for parameter $flags (should be `integer\')'); + } + + $res = $PHPCAS_CLIENT->serviceMail($url,$service,$flags,$err_code,$err_msg,$pt); + + phpCAS::traceEnd($res); + return $res; + } + + /** @} */ + // ######################################################################## + // AUTHENTICATION + // ######################################################################## + /** + * @addtogroup publicAuth + * @{ + */ + + /** + * Set the times authentication will be cached before really accessing the CAS server in gateway mode: + * - -1: check only once, and then never again (until you pree login) + * - 0: always check + * - n: check every "n" time + * + * @param $n an integer. + */ + function setCacheTimesForAuthRecheck($n) + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + if ( gettype($n) != 'integer' ) { + phpCAS::error('type mismatched for parameter $header (should be `string\')'); + } + $PHPCAS_CLIENT->setCacheTimesForAuthRecheck($n); + } + + /** + * This method is called to check if the user is authenticated (use the gateway feature). + * @return TRUE when the user is authenticated; otherwise FALSE. + */ + function checkAuthentication() + { + global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; + + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + + $auth = $PHPCAS_CLIENT->checkAuthentication(); + + // store where the authentication has been checked and the result + $dbg = phpCAS::backtrace(); + $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, + 'file' => $dbg[0]['file'], + 'line' => $dbg[0]['line'], + 'method' => __CLASS__.'::'.__FUNCTION__, + 'result' => $auth ); + phpCAS::traceEnd($auth); + return $auth; + } + + /** + * This method is called to force authentication if the user was not already + * authenticated. If the user is not authenticated, halt by redirecting to + * the CAS server. + */ + function forceAuthentication() + { + global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; + + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + + $auth = $PHPCAS_CLIENT->forceAuthentication(); + + // store where the authentication has been checked and the result + $dbg = phpCAS::backtrace(); + $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, + 'file' => $dbg[0]['file'], + 'line' => $dbg[0]['line'], + 'method' => __CLASS__.'::'.__FUNCTION__, + 'result' => $auth ); + + if ( !$auth ) { + phpCAS::trace('user is not authenticated, redirecting to the CAS server'); + $PHPCAS_CLIENT->forceAuthentication(); + } else { + phpCAS::trace('no need to authenticate (user `'.phpCAS::getUser().'\' is already authenticated)'); + } + + phpCAS::traceEnd(); + return $auth; + } + + /** + * This method is called to renew the authentication. + **/ + function renewAuthentication() { + global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; + + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before'.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + + // store where the authentication has been checked and the result + $dbg = phpCAS::backtrace(); + $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, 'file' => $dbg[0]['file'], 'line' => $dbg[0]['line'], 'method' => __CLASS__.'::'.__FUNCTION__, 'result' => $auth ); + + $PHPCAS_CLIENT->renewAuthentication(); + phpCAS::traceEnd(); + } + + /** + * This method has been left from version 0.4.1 for compatibility reasons. + */ + function authenticate() + { + phpCAS::error('this method is deprecated. You should use '.__CLASS__.'::forceAuthentication() instead'); + } + + /** + * This method is called to check if the user is authenticated (previously or by + * tickets given in the URL). + * + * @return TRUE when the user is authenticated. + */ + function isAuthenticated() + { + global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; + + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + + // call the isAuthenticated method of the global $PHPCAS_CLIENT object + $auth = $PHPCAS_CLIENT->isAuthenticated(); + + // store where the authentication has been checked and the result + $dbg = phpCAS::backtrace(); + $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, + 'file' => $dbg[0]['file'], + 'line' => $dbg[0]['line'], + 'method' => __CLASS__.'::'.__FUNCTION__, + 'result' => $auth ); + phpCAS::traceEnd($auth); + return $auth; + } + + /** + * Checks whether authenticated based on $_SESSION. Useful to avoid + * server calls. + * @return true if authenticated, false otherwise. + * @since 0.4.22 by Brendan Arnold + */ + function isSessionAuthenticated () + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + return($PHPCAS_CLIENT->isSessionAuthenticated()); + } + + /** + * This method returns the CAS user's login name. + * @warning should not be called only after phpCAS::forceAuthentication() + * or phpCAS::checkAuthentication(). + * + * @return the login name of the authenticated user + */ + function getUser() + { + global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'); + } + if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { + phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); + } + return $PHPCAS_CLIENT->getUser(); + } + + /** + * This method returns the CAS user's login name. + * @warning should not be called only after phpCAS::forceAuthentication() + * or phpCAS::checkAuthentication(). + * + * @return the login name of the authenticated user + */ + function getAttributes() + { + global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'); + } + if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { + phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); + } + return $PHPCAS_CLIENT->getAttributes(); + } + /** + * Handle logout requests. + */ + function handleLogoutRequests($check_client=true, $allowed_clients=false) + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + return($PHPCAS_CLIENT->handleLogoutRequests($check_client, $allowed_clients)); + } + + /** + * This method returns the URL to be used to login. + * or phpCAS::isAuthenticated(). + * + * @return the login name of the authenticated user + */ + function getServerLoginURL() + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + return $PHPCAS_CLIENT->getServerLoginURL(); + } + + /** + * Set the login URL of the CAS server. + * @param $url the login URL + * @since 0.4.21 by Wyman Chan + */ + function setServerLoginURL($url='') + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after + '.__CLASS__.'::client()'); + } + if ( gettype($url) != 'string' ) { + phpCAS::error('type mismatched for parameter $url (should be + `string\')'); + } + $PHPCAS_CLIENT->setServerLoginURL($url); + phpCAS::traceEnd(); + } + + + /** + * Set the serviceValidate URL of the CAS server. + * @param $url the serviceValidate URL + * @since 1.1.0 by Joachim Fritschi + */ + function setServerServiceValidateURL($url='') + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after + '.__CLASS__.'::client()'); + } + if ( gettype($url) != 'string' ) { + phpCAS::error('type mismatched for parameter $url (should be + `string\')'); + } + $PHPCAS_CLIENT->setServerServiceValidateURL($url); + phpCAS::traceEnd(); + } + + + /** + * Set the proxyValidate URL of the CAS server. + * @param $url the proxyValidate URL + * @since 1.1.0 by Joachim Fritschi + */ + function setServerProxyValidateURL($url='') + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after + '.__CLASS__.'::client()'); + } + if ( gettype($url) != 'string' ) { + phpCAS::error('type mismatched for parameter $url (should be + `string\')'); + } + $PHPCAS_CLIENT->setServerProxyValidateURL($url); + phpCAS::traceEnd(); + } + + /** + * Set the samlValidate URL of the CAS server. + * @param $url the samlValidate URL + * @since 1.1.0 by Joachim Fritschi + */ + function setServerSamlValidateURL($url='') + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after + '.__CLASS__.'::client()'); + } + if ( gettype($url) != 'string' ) { + phpCAS::error('type mismatched for parameter $url (should be + `string\')'); + } + $PHPCAS_CLIENT->setServerSamlValidateURL($url); + phpCAS::traceEnd(); + } + + /** + * This method returns the URL to be used to login. + * or phpCAS::isAuthenticated(). + * + * @return the login name of the authenticated user + */ + function getServerLogoutURL() + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); + } + return $PHPCAS_CLIENT->getServerLogoutURL(); + } + + /** + * Set the logout URL of the CAS server. + * @param $url the logout URL + * @since 0.4.21 by Wyman Chan + */ + function setServerLogoutURL($url='') + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after + '.__CLASS__.'::client()'); + } + if ( gettype($url) != 'string' ) { + phpCAS::error('type mismatched for parameter $url (should be + `string\')'); + } + $PHPCAS_CLIENT->setServerLogoutURL($url); + phpCAS::traceEnd(); + } + + /** + * This method is used to logout from CAS. + * @params $params an array that contains the optional url and service parameters that will be passed to the CAS server + * @public + */ + function logout($params = "") { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if (!is_object($PHPCAS_CLIENT)) { + phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); + } + $parsedParams = array(); + if ($params != "") { + if (is_string($params)) { + phpCAS::error('method `phpCAS::logout($url)\' is now deprecated, use `phpCAS::logoutWithUrl($url)\' instead'); + } + if (!is_array($params)) { + phpCAS::error('type mismatched for parameter $params (should be `array\')'); + } + foreach ($params as $key => $value) { + if ($key != "service" && $key != "url") { + phpCAS::error('only `url\' and `service\' parameters are allowed for method `phpCAS::logout($params)\''); + } + $parsedParams[$key] = $value; + } + } + $PHPCAS_CLIENT->logout($parsedParams); + // never reached + phpCAS::traceEnd(); + } + + /** + * This method is used to logout from CAS. Halts by redirecting to the CAS server. + * @param $service a URL that will be transmitted to the CAS server + */ + function logoutWithRedirectService($service) { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); + } + if (!is_string($service)) { + phpCAS::error('type mismatched for parameter $service (should be `string\')'); + } + $PHPCAS_CLIENT->logout(array("service" => $service)); + // never reached + phpCAS::traceEnd(); + } + + /** + * This method is used to logout from CAS. Halts by redirecting to the CAS server. + * @param $url a URL that will be transmitted to the CAS server + */ + function logoutWithUrl($url) { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); + } + if (!is_string($url)) { + phpCAS::error('type mismatched for parameter $url (should be `string\')'); + } + $PHPCAS_CLIENT->logout(array("url" => $url)); + // never reached + phpCAS::traceEnd(); + } + + /** + * This method is used to logout from CAS. Halts by redirecting to the CAS server. + * @param $service a URL that will be transmitted to the CAS server + * @param $url a URL that will be transmitted to the CAS server + */ + function logoutWithRedirectServiceAndUrl($service, $url) { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); + } + if (!is_string($service)) { + phpCAS::error('type mismatched for parameter $service (should be `string\')'); + } + if (!is_string($url)) { + phpCAS::error('type mismatched for parameter $url (should be `string\')'); + } + $PHPCAS_CLIENT->logout(array("service" => $service, "url" => $url)); + // never reached + phpCAS::traceEnd(); + } + + /** + * Set the fixed URL that will be used by the CAS server to transmit the PGT. + * When this method is not called, a phpCAS script uses its own URL for the callback. + * + * @param $url the URL + */ + function setFixedCallbackURL($url='') + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( !$PHPCAS_CLIENT->isProxy() ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( gettype($url) != 'string' ) { + phpCAS::error('type mismatched for parameter $url (should be `string\')'); + } + $PHPCAS_CLIENT->setCallbackURL($url); + phpCAS::traceEnd(); + } + + /** + * Set the fixed URL that will be set as the CAS service parameter. When this + * method is not called, a phpCAS script uses its own URL. + * + * @param $url the URL + */ + function setFixedServiceURL($url) + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( gettype($url) != 'string' ) { + phpCAS::error('type mismatched for parameter $url (should be `string\')'); + } + $PHPCAS_CLIENT->setURL($url); + phpCAS::traceEnd(); + } + + /** + * Get the URL that is set as the CAS service parameter. + */ + function getServiceURL() + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + return($PHPCAS_CLIENT->getURL()); + } + + /** + * Retrieve a Proxy Ticket from the CAS server. + */ + function retrievePT($target_service,&$err_code,&$err_msg) + { + global $PHPCAS_CLIENT; + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); + } + if ( gettype($target_service) != 'string' ) { + phpCAS::error('type mismatched for parameter $target_service(should be `string\')'); + } + return($PHPCAS_CLIENT->retrievePT($target_service,$err_code,$err_msg)); + } + + /** + * Set the certificate of the CAS server. + * + * @param $cert the PEM certificate + */ + function setCasServerCert($cert) + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); + } + if ( gettype($cert) != 'string' ) { + phpCAS::error('type mismatched for parameter $cert (should be `string\')'); + } + $PHPCAS_CLIENT->setCasServerCert($cert); + phpCAS::traceEnd(); + } + + /** + * Set the certificate of the CAS server CA. + * + * @param $cert the CA certificate + */ + function setCasServerCACert($cert) + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); + } + if ( gettype($cert) != 'string' ) { + phpCAS::error('type mismatched for parameter $cert (should be `string\')'); + } + $PHPCAS_CLIENT->setCasServerCACert($cert); + phpCAS::traceEnd(); + } + + /** + * Set no SSL validation for the CAS server. + */ + function setNoCasServerValidation() + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); + } + $PHPCAS_CLIENT->setNoCasServerValidation(); + phpCAS::traceEnd(); + } + + /** @} */ + + /** + * Change CURL options. + * CURL is used to connect through HTTPS to CAS server + * @param $key the option key + * @param $value the value to set + */ + function setExtraCurlOption($key, $value) + { + global $PHPCAS_CLIENT; + phpCAS::traceBegin(); + if ( !is_object($PHPCAS_CLIENT) ) { + phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); + } + $PHPCAS_CLIENT->setExtraCurlOption($key, $value); + phpCAS::traceEnd(); + } + +} + +// ######################################################################## +// DOCUMENTATION +// ######################################################################## + +// ######################################################################## +// MAIN PAGE + +/** + * @mainpage + * + * The following pages only show the source documentation. + * + */ + +// ######################################################################## +// MODULES DEFINITION + +/** @defgroup public User interface */ + +/** @defgroup publicInit Initialization + * @ingroup public */ + +/** @defgroup publicAuth Authentication + * @ingroup public */ + +/** @defgroup publicServices Access to external services + * @ingroup public */ + +/** @defgroup publicConfig Configuration + * @ingroup public */ + +/** @defgroup publicLang Internationalization + * @ingroup publicConfig */ + +/** @defgroup publicOutput HTML output + * @ingroup publicConfig */ + +/** @defgroup publicPGTStorage PGT storage + * @ingroup publicConfig */ + +/** @defgroup publicDebug Debugging + * @ingroup public */ + + +/** @defgroup internal Implementation */ + +/** @defgroup internalAuthentication Authentication + * @ingroup internal */ + +/** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets) + * @ingroup internal */ + +/** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets) + * @ingroup internal */ + +/** @defgroup internalPGTStorage PGT storage + * @ingroup internalProxy */ + +/** @defgroup internalPGTStorageDB PGT storage in a database + * @ingroup internalPGTStorage */ + +/** @defgroup internalPGTStorageFile PGT storage on the filesystem + * @ingroup internalPGTStorage */ + +/** @defgroup internalCallback Callback from the CAS server + * @ingroup internalProxy */ + +/** @defgroup internalProxied CAS proxied client features (CAS 2.0, Proxy Tickets) + * @ingroup internal */ + +/** @defgroup internalConfig Configuration + * @ingroup internal */ + +/** @defgroup internalOutput HTML output + * @ingroup internalConfig */ + +/** @defgroup internalLang Internationalization + * @ingroup internalConfig + * + * To add a new language: + * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php + * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php + * - 3. Make the translations + */ + +/** @defgroup internalDebug Debugging + * @ingroup internal */ + +/** @defgroup internalMisc Miscellaneous + * @ingroup internal */ + +// ######################################################################## +// EXAMPLES + +/** + * @example example_simple.php + */ + /** + * @example example_proxy.php + */ + /** + * @example example_proxy2.php + */ + /** + * @example example_lang.php + */ + /** + * @example example_html.php + */ + /** + * @example example_file.php + */ + /** + * @example example_db.php + */ + /** + * @example example_service.php + */ + /** + * @example example_session_proxy.php + */ + /** + * @example example_session_service.php + */ + /** + * @example example_gateway.php + */ + + + +?> diff --git a/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-db.php b/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-db.php index 00797b9c5..5a589e4b2 100644 --- a/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-db.php +++ b/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-db.php @@ -1,190 +1,190 @@ - - * - * @ingroup internalPGTStorageDB - */ - -class PGTStorageDB extends PGTStorage -{ - /** - * @addtogroup internalPGTStorageDB - * @{ - */ - - /** - * a string representing a PEAR DB URL to connect to the database. Written by - * PGTStorageDB::PGTStorageDB(), read by getURL(). - * - * @hideinitializer - * @private - */ - var $_url=''; - - /** - * This method returns the PEAR DB URL to use to connect to the database. - * - * @return a PEAR DB URL - * - * @private - */ - function getURL() - { - return $this->_url; - } - - /** - * The handle of the connection to the database where PGT's are stored. Written by - * PGTStorageDB::init(), read by getLink(). - * - * @hideinitializer - * @private - */ - var $_link = null; - - /** - * This method returns the handle of the connection to the database where PGT's are - * stored. - * - * @return a handle of connection. - * - * @private - */ - function getLink() - { - return $this->_link; - } - - /** - * The name of the table where PGT's are stored. Written by - * PGTStorageDB::PGTStorageDB(), read by getTable(). - * - * @hideinitializer - * @private - */ - var $_table = ''; - - /** - * This method returns the name of the table where PGT's are stored. - * - * @return the name of a table. - * - * @private - */ - function getTable() - { - return $this->_table; - } - - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * This method returns an informational string giving the type of storage - * used by the object (used for debugging purposes). - * - * @return an informational string. - * @public - */ - function getStorageType() - { - return "database"; - } - - /** - * This method returns an informational string giving informations on the - * parameters of the storage.(used for debugging purposes). - * - * @public - */ - function getStorageInfo() - { - return 'url=`'.$this->getURL().'\', table=`'.$this->getTable().'\''; - } - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - - /** - * The class constructor, called by CASClient::SetPGTStorageDB(). - * - * @param $cas_parent the CASClient instance that creates the object. - * @param $user the user to access the data with - * @param $password the user's password - * @param $database_type the type of the database hosting the data - * @param $hostname the server hosting the database - * @param $port the port the server is listening on - * @param $database the name of the database - * @param $table the name of the table storing the data - * - * @public - */ - function PGTStorageDB($cas_parent,$user,$password,$database_type,$hostname,$port,$database,$table) - { - phpCAS::traceBegin(); - - // call the ancestor's constructor - $this->PGTStorage($cas_parent); - - if ( empty($database_type) ) $database_type = CAS_PGT_STORAGE_DB_DEFAULT_DATABASE_TYPE; - if ( empty($hostname) ) $hostname = CAS_PGT_STORAGE_DB_DEFAULT_HOSTNAME; - if ( $port==0 ) $port = CAS_PGT_STORAGE_DB_DEFAULT_PORT; - if ( empty($database) ) $database = CAS_PGT_STORAGE_DB_DEFAULT_DATABASE; - if ( empty($table) ) $table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE; - - // build and store the PEAR DB URL - $this->_url = $database_type.':'.'//'.$user.':'.$password.'@'.$hostname.':'.$port.'/'.$database; - - // XXX should use setURL and setTable - phpCAS::traceEnd(); - } - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * This method is used to initialize the storage. Halts on error. - * - * @public - */ - function init() - { - phpCAS::traceBegin(); - // if the storage has already been initialized, return immediatly - if ( $this->isInitialized() ) - return; - // call the ancestor's method (mark as initialized) - parent::init(); - - //include phpDB library (the test was introduced in release 0.4.8 for - //the integration into Tikiwiki). - if (!class_exists('DB')) { - include_once('DB.php'); - } - - // try to connect to the database - $this->_link = DB::connect($this->getURL()); - if ( DB::isError($this->_link) ) { - phpCAS::error('could not connect to database ('.DB::errorMessage($this->_link).')'); - } - var_dump($this->_link); - phpCAS::traceBEnd(); - } - - /** @} */ -} - + + * + * @ingroup internalPGTStorageDB + */ + +class PGTStorageDB extends PGTStorage +{ + /** + * @addtogroup internalPGTStorageDB + * @{ + */ + + /** + * a string representing a PEAR DB URL to connect to the database. Written by + * PGTStorageDB::PGTStorageDB(), read by getURL(). + * + * @hideinitializer + * @private + */ + var $_url=''; + + /** + * This method returns the PEAR DB URL to use to connect to the database. + * + * @return a PEAR DB URL + * + * @private + */ + function getURL() + { + return $this->_url; + } + + /** + * The handle of the connection to the database where PGT's are stored. Written by + * PGTStorageDB::init(), read by getLink(). + * + * @hideinitializer + * @private + */ + var $_link = null; + + /** + * This method returns the handle of the connection to the database where PGT's are + * stored. + * + * @return a handle of connection. + * + * @private + */ + function getLink() + { + return $this->_link; + } + + /** + * The name of the table where PGT's are stored. Written by + * PGTStorageDB::PGTStorageDB(), read by getTable(). + * + * @hideinitializer + * @private + */ + var $_table = ''; + + /** + * This method returns the name of the table where PGT's are stored. + * + * @return the name of a table. + * + * @private + */ + function getTable() + { + return $this->_table; + } + + // ######################################################################## + // DEBUGGING + // ######################################################################## + + /** + * This method returns an informational string giving the type of storage + * used by the object (used for debugging purposes). + * + * @return an informational string. + * @public + */ + function getStorageType() + { + return "database"; + } + + /** + * This method returns an informational string giving informations on the + * parameters of the storage.(used for debugging purposes). + * + * @public + */ + function getStorageInfo() + { + return 'url=`'.$this->getURL().'\', table=`'.$this->getTable().'\''; + } + + // ######################################################################## + // CONSTRUCTOR + // ######################################################################## + + /** + * The class constructor, called by CASClient::SetPGTStorageDB(). + * + * @param $cas_parent the CASClient instance that creates the object. + * @param $user the user to access the data with + * @param $password the user's password + * @param $database_type the type of the database hosting the data + * @param $hostname the server hosting the database + * @param $port the port the server is listening on + * @param $database the name of the database + * @param $table the name of the table storing the data + * + * @public + */ + function PGTStorageDB($cas_parent,$user,$password,$database_type,$hostname,$port,$database,$table) + { + phpCAS::traceBegin(); + + // call the ancestor's constructor + $this->PGTStorage($cas_parent); + + if ( empty($database_type) ) $database_type = CAS_PGT_STORAGE_DB_DEFAULT_DATABASE_TYPE; + if ( empty($hostname) ) $hostname = CAS_PGT_STORAGE_DB_DEFAULT_HOSTNAME; + if ( $port==0 ) $port = CAS_PGT_STORAGE_DB_DEFAULT_PORT; + if ( empty($database) ) $database = CAS_PGT_STORAGE_DB_DEFAULT_DATABASE; + if ( empty($table) ) $table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE; + + // build and store the PEAR DB URL + $this->_url = $database_type.':'.'//'.$user.':'.$password.'@'.$hostname.':'.$port.'/'.$database; + + // XXX should use setURL and setTable + phpCAS::traceEnd(); + } + + // ######################################################################## + // INITIALIZATION + // ######################################################################## + + /** + * This method is used to initialize the storage. Halts on error. + * + * @public + */ + function init() + { + phpCAS::traceBegin(); + // if the storage has already been initialized, return immediatly + if ( $this->isInitialized() ) + return; + // call the ancestor's method (mark as initialized) + parent::init(); + + //include phpDB library (the test was introduced in release 0.4.8 for + //the integration into Tikiwiki). + if (!class_exists('DB')) { + include_once('DB.php'); + } + + // try to connect to the database + $this->_link = DB::connect($this->getURL()); + if ( DB::isError($this->_link) ) { + phpCAS::error('could not connect to database ('.DB::errorMessage($this->_link).')'); + } + var_dump($this->_link); + phpCAS::traceBEnd(); + } + + /** @} */ +} + ?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-file.php b/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-file.php index d48a60d67..bc07485b8 100644 --- a/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-file.php +++ b/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-file.php @@ -1,249 +1,249 @@ - - * - * @ingroup internalPGTStorageFile - */ - -class PGTStorageFile extends PGTStorage -{ - /** - * @addtogroup internalPGTStorageFile - * @{ - */ - - /** - * a string telling where PGT's should be stored on the filesystem. Written by - * PGTStorageFile::PGTStorageFile(), read by getPath(). - * - * @private - */ - var $_path; - - /** - * This method returns the name of the directory where PGT's should be stored - * on the filesystem. - * - * @return the name of a directory (with leading and trailing '/') - * - * @private - */ - function getPath() - { - return $this->_path; - } - - /** - * a string telling the format to use to store PGT's (plain or xml). Written by - * PGTStorageFile::PGTStorageFile(), read by getFormat(). - * - * @private - */ - var $_format; - - /** - * This method returns the format to use when storing PGT's on the filesystem. - * - * @return a string corresponding to the format used (plain or xml). - * - * @private - */ - function getFormat() - { - return $this->_format; - } - - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * This method returns an informational string giving the type of storage - * used by the object (used for debugging purposes). - * - * @return an informational string. - * @public - */ - function getStorageType() - { - return "file"; - } - - /** - * This method returns an informational string giving informations on the - * parameters of the storage.(used for debugging purposes). - * - * @return an informational string. - * @public - */ - function getStorageInfo() - { - return 'path=`'.$this->getPath().'\', format=`'.$this->getFormat().'\''; - } - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - - /** - * The class constructor, called by CASClient::SetPGTStorageFile(). - * - * @param $cas_parent the CASClient instance that creates the object. - * @param $format the format used to store the PGT's (`plain' and `xml' allowed). - * @param $path the path where the PGT's should be stored - * - * @public - */ - function PGTStorageFile($cas_parent,$format,$path) - { - phpCAS::traceBegin(); - // call the ancestor's constructor - $this->PGTStorage($cas_parent); - - if (empty($format) ) $format = CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT; - if (empty($path) ) $path = CAS_PGT_STORAGE_FILE_DEFAULT_PATH; - - // check that the path is an absolute path - if (getenv("OS")=="Windows_NT"){ - - if (!preg_match('`^[a-zA-Z]:`', $path)) { - phpCAS::error('an absolute path is needed for PGT storage to file'); - } - - } - else - { - - if ( $path[0] != '/' ) { - phpCAS::error('an absolute path is needed for PGT storage to file'); - } - - // store the path (with a leading and trailing '/') - $path = preg_replace('|[/]*$|','/',$path); - $path = preg_replace('|^[/]*|','/',$path); - } - - $this->_path = $path; - // check the format and store it - switch ($format) { - case CAS_PGT_STORAGE_FILE_FORMAT_PLAIN: - case CAS_PGT_STORAGE_FILE_FORMAT_XML: - $this->_format = $format; - break; - default: - phpCAS::error('unknown PGT file storage format (`'.CAS_PGT_STORAGE_FILE_FORMAT_PLAIN.'\' and `'.CAS_PGT_STORAGE_FILE_FORMAT_XML.'\' allowed)'); - } - phpCAS::traceEnd(); - } - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * This method is used to initialize the storage. Halts on error. - * - * @public - */ - function init() - { - phpCAS::traceBegin(); - // if the storage has already been initialized, return immediatly - if ( $this->isInitialized() ) - return; - // call the ancestor's method (mark as initialized) - parent::init(); - phpCAS::traceEnd(); - } - - // ######################################################################## - // PGT I/O - // ######################################################################## - - /** - * This method returns the filename corresponding to a PGT Iou. - * - * @param $pgt_iou the PGT iou. - * - * @return a filename - * @private - */ - function getPGTIouFilename($pgt_iou) - { - phpCAS::traceBegin(); - $filename = $this->getPath().$pgt_iou.'.'.$this->getFormat(); - phpCAS::traceEnd($filename); - return $filename; - } - - /** - * This method stores a PGT and its corresponding PGT Iou into a file. Echoes a - * warning on error. - * - * @param $pgt the PGT - * @param $pgt_iou the PGT iou - * - * @public - */ - function write($pgt,$pgt_iou) - { - phpCAS::traceBegin(); - $fname = $this->getPGTIouFilename($pgt_iou); - if ( $f=fopen($fname,"w") ) { - if ( fputs($f,$pgt) === FALSE ) { - phpCAS::error('could not write PGT to `'.$fname.'\''); - } - fclose($f); - } else { - phpCAS::error('could not open `'.$fname.'\''); - } - phpCAS::traceEnd(); - } - - /** - * This method reads a PGT corresponding to a PGT Iou and deletes the - * corresponding file. - * - * @param $pgt_iou the PGT iou - * - * @return the corresponding PGT, or FALSE on error - * - * @public - */ - function read($pgt_iou) - { - phpCAS::traceBegin(); - $pgt = FALSE; - $fname = $this->getPGTIouFilename($pgt_iou); - if ( !($f=fopen($fname,"r")) ) { - phpCAS::trace('could not open `'.$fname.'\''); - } else { - if ( ($pgt=fgets($f)) === FALSE ) { - phpCAS::trace('could not read PGT from `'.$fname.'\''); - } - fclose($f); - } - - // delete the PGT file - @unlink($fname); - - phpCAS::traceEnd($pgt); - return $pgt; - } - - /** @} */ - -} - - + + * + * @ingroup internalPGTStorageFile + */ + +class PGTStorageFile extends PGTStorage +{ + /** + * @addtogroup internalPGTStorageFile + * @{ + */ + + /** + * a string telling where PGT's should be stored on the filesystem. Written by + * PGTStorageFile::PGTStorageFile(), read by getPath(). + * + * @private + */ + var $_path; + + /** + * This method returns the name of the directory where PGT's should be stored + * on the filesystem. + * + * @return the name of a directory (with leading and trailing '/') + * + * @private + */ + function getPath() + { + return $this->_path; + } + + /** + * a string telling the format to use to store PGT's (plain or xml). Written by + * PGTStorageFile::PGTStorageFile(), read by getFormat(). + * + * @private + */ + var $_format; + + /** + * This method returns the format to use when storing PGT's on the filesystem. + * + * @return a string corresponding to the format used (plain or xml). + * + * @private + */ + function getFormat() + { + return $this->_format; + } + + // ######################################################################## + // DEBUGGING + // ######################################################################## + + /** + * This method returns an informational string giving the type of storage + * used by the object (used for debugging purposes). + * + * @return an informational string. + * @public + */ + function getStorageType() + { + return "file"; + } + + /** + * This method returns an informational string giving informations on the + * parameters of the storage.(used for debugging purposes). + * + * @return an informational string. + * @public + */ + function getStorageInfo() + { + return 'path=`'.$this->getPath().'\', format=`'.$this->getFormat().'\''; + } + + // ######################################################################## + // CONSTRUCTOR + // ######################################################################## + + /** + * The class constructor, called by CASClient::SetPGTStorageFile(). + * + * @param $cas_parent the CASClient instance that creates the object. + * @param $format the format used to store the PGT's (`plain' and `xml' allowed). + * @param $path the path where the PGT's should be stored + * + * @public + */ + function PGTStorageFile($cas_parent,$format,$path) + { + phpCAS::traceBegin(); + // call the ancestor's constructor + $this->PGTStorage($cas_parent); + + if (empty($format) ) $format = CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT; + if (empty($path) ) $path = CAS_PGT_STORAGE_FILE_DEFAULT_PATH; + + // check that the path is an absolute path + if (getenv("OS")=="Windows_NT"){ + + if (!preg_match('`^[a-zA-Z]:`', $path)) { + phpCAS::error('an absolute path is needed for PGT storage to file'); + } + + } + else + { + + if ( $path[0] != '/' ) { + phpCAS::error('an absolute path is needed for PGT storage to file'); + } + + // store the path (with a leading and trailing '/') + $path = preg_replace('|[/]*$|','/',$path); + $path = preg_replace('|^[/]*|','/',$path); + } + + $this->_path = $path; + // check the format and store it + switch ($format) { + case CAS_PGT_STORAGE_FILE_FORMAT_PLAIN: + case CAS_PGT_STORAGE_FILE_FORMAT_XML: + $this->_format = $format; + break; + default: + phpCAS::error('unknown PGT file storage format (`'.CAS_PGT_STORAGE_FILE_FORMAT_PLAIN.'\' and `'.CAS_PGT_STORAGE_FILE_FORMAT_XML.'\' allowed)'); + } + phpCAS::traceEnd(); + } + + // ######################################################################## + // INITIALIZATION + // ######################################################################## + + /** + * This method is used to initialize the storage. Halts on error. + * + * @public + */ + function init() + { + phpCAS::traceBegin(); + // if the storage has already been initialized, return immediatly + if ( $this->isInitialized() ) + return; + // call the ancestor's method (mark as initialized) + parent::init(); + phpCAS::traceEnd(); + } + + // ######################################################################## + // PGT I/O + // ######################################################################## + + /** + * This method returns the filename corresponding to a PGT Iou. + * + * @param $pgt_iou the PGT iou. + * + * @return a filename + * @private + */ + function getPGTIouFilename($pgt_iou) + { + phpCAS::traceBegin(); + $filename = $this->getPath().$pgt_iou.'.'.$this->getFormat(); + phpCAS::traceEnd($filename); + return $filename; + } + + /** + * This method stores a PGT and its corresponding PGT Iou into a file. Echoes a + * warning on error. + * + * @param $pgt the PGT + * @param $pgt_iou the PGT iou + * + * @public + */ + function write($pgt,$pgt_iou) + { + phpCAS::traceBegin(); + $fname = $this->getPGTIouFilename($pgt_iou); + if ( $f=fopen($fname,"w") ) { + if ( fputs($f,$pgt) === FALSE ) { + phpCAS::error('could not write PGT to `'.$fname.'\''); + } + fclose($f); + } else { + phpCAS::error('could not open `'.$fname.'\''); + } + phpCAS::traceEnd(); + } + + /** + * This method reads a PGT corresponding to a PGT Iou and deletes the + * corresponding file. + * + * @param $pgt_iou the PGT iou + * + * @return the corresponding PGT, or FALSE on error + * + * @public + */ + function read($pgt_iou) + { + phpCAS::traceBegin(); + $pgt = FALSE; + $fname = $this->getPGTIouFilename($pgt_iou); + if ( !($f=fopen($fname,"r")) ) { + phpCAS::trace('could not open `'.$fname.'\''); + } else { + if ( ($pgt=fgets($f)) === FALSE ) { + phpCAS::trace('could not read PGT from `'.$fname.'\''); + } + fclose($f); + } + + // delete the PGT file + @unlink($fname); + + phpCAS::traceEnd($pgt); + return $pgt; + } + + /** @} */ + +} + + ?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-main.php b/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-main.php index 8fd3c9e12..cd9b49967 100644 --- a/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-main.php +++ b/plugins/CasAuthentication/extlib/CAS/PGTStorage/pgt-main.php @@ -1,188 +1,188 @@ - - * - * @ingroup internalPGTStorage - */ - -class PGTStorage -{ - /** - * @addtogroup internalPGTStorage - * @{ - */ - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - - /** - * The constructor of the class, should be called only by inherited classes. - * - * @param $cas_parent the CASclient instance that creates the current object. - * - * @protected - */ - function PGTStorage($cas_parent) - { - phpCAS::traceBegin(); - if ( !$cas_parent->isProxy() ) { - phpCAS::error('defining PGT storage makes no sense when not using a CAS proxy'); - } - phpCAS::traceEnd(); - } - - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * This virtual method returns an informational string giving the type of storage - * used by the object (used for debugging purposes). - * - * @public - */ - function getStorageType() - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - /** - * This virtual method returns an informational string giving informations on the - * parameters of the storage.(used for debugging purposes). - * - * @public - */ - function getStorageInfo() - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - // ######################################################################## - // ERROR HANDLING - // ######################################################################## - - /** - * string used to store an error message. Written by PGTStorage::setErrorMessage(), - * read by PGTStorage::getErrorMessage(). - * - * @hideinitializer - * @private - * @deprecated not used. - */ - var $_error_message=FALSE; - - /** - * This method sets en error message, which can be read later by - * PGTStorage::getErrorMessage(). - * - * @param $error_message an error message - * - * @protected - * @deprecated not used. - */ - function setErrorMessage($error_message) - { - $this->_error_message = $error_message; - } - - /** - * This method returns an error message set by PGTStorage::setErrorMessage(). - * - * @return an error message when set by PGTStorage::setErrorMessage(), FALSE - * otherwise. - * - * @public - * @deprecated not used. - */ - function getErrorMessage() - { - return $this->_error_message; - } - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * a boolean telling if the storage has already been initialized. Written by - * PGTStorage::init(), read by PGTStorage::isInitialized(). - * - * @hideinitializer - * @private - */ - var $_initialized = FALSE; - - /** - * This method tells if the storage has already been intialized. - * - * @return a boolean - * - * @protected - */ - function isInitialized() - { - return $this->_initialized; - } - - /** - * This virtual method initializes the object. - * - * @protected - */ - function init() - { - $this->_initialized = TRUE; - } - - // ######################################################################## - // PGT I/O - // ######################################################################## - - /** - * This virtual method stores a PGT and its corresponding PGT Iuo. - * @note Should never be called. - * - * @param $pgt the PGT - * @param $pgt_iou the PGT iou - * - * @protected - */ - function write($pgt,$pgt_iou) - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - /** - * This virtual method reads a PGT corresponding to a PGT Iou and deletes - * the corresponding storage entry. - * @note Should never be called. - * - * @param $pgt_iou the PGT iou - * - * @protected - */ - function read($pgt_iou) - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - /** @} */ - -} - -// include specific PGT storage classes -include_once(dirname(__FILE__).'/pgt-file.php'); -include_once(dirname(__FILE__).'/pgt-db.php'); - + + * + * @ingroup internalPGTStorage + */ + +class PGTStorage +{ + /** + * @addtogroup internalPGTStorage + * @{ + */ + + // ######################################################################## + // CONSTRUCTOR + // ######################################################################## + + /** + * The constructor of the class, should be called only by inherited classes. + * + * @param $cas_parent the CASclient instance that creates the current object. + * + * @protected + */ + function PGTStorage($cas_parent) + { + phpCAS::traceBegin(); + if ( !$cas_parent->isProxy() ) { + phpCAS::error('defining PGT storage makes no sense when not using a CAS proxy'); + } + phpCAS::traceEnd(); + } + + // ######################################################################## + // DEBUGGING + // ######################################################################## + + /** + * This virtual method returns an informational string giving the type of storage + * used by the object (used for debugging purposes). + * + * @public + */ + function getStorageType() + { + phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); + } + + /** + * This virtual method returns an informational string giving informations on the + * parameters of the storage.(used for debugging purposes). + * + * @public + */ + function getStorageInfo() + { + phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); + } + + // ######################################################################## + // ERROR HANDLING + // ######################################################################## + + /** + * string used to store an error message. Written by PGTStorage::setErrorMessage(), + * read by PGTStorage::getErrorMessage(). + * + * @hideinitializer + * @private + * @deprecated not used. + */ + var $_error_message=FALSE; + + /** + * This method sets en error message, which can be read later by + * PGTStorage::getErrorMessage(). + * + * @param $error_message an error message + * + * @protected + * @deprecated not used. + */ + function setErrorMessage($error_message) + { + $this->_error_message = $error_message; + } + + /** + * This method returns an error message set by PGTStorage::setErrorMessage(). + * + * @return an error message when set by PGTStorage::setErrorMessage(), FALSE + * otherwise. + * + * @public + * @deprecated not used. + */ + function getErrorMessage() + { + return $this->_error_message; + } + + // ######################################################################## + // INITIALIZATION + // ######################################################################## + + /** + * a boolean telling if the storage has already been initialized. Written by + * PGTStorage::init(), read by PGTStorage::isInitialized(). + * + * @hideinitializer + * @private + */ + var $_initialized = FALSE; + + /** + * This method tells if the storage has already been intialized. + * + * @return a boolean + * + * @protected + */ + function isInitialized() + { + return $this->_initialized; + } + + /** + * This virtual method initializes the object. + * + * @protected + */ + function init() + { + $this->_initialized = TRUE; + } + + // ######################################################################## + // PGT I/O + // ######################################################################## + + /** + * This virtual method stores a PGT and its corresponding PGT Iuo. + * @note Should never be called. + * + * @param $pgt the PGT + * @param $pgt_iou the PGT iou + * + * @protected + */ + function write($pgt,$pgt_iou) + { + phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); + } + + /** + * This virtual method reads a PGT corresponding to a PGT Iou and deletes + * the corresponding storage entry. + * @note Should never be called. + * + * @param $pgt_iou the PGT iou + * + * @protected + */ + function read($pgt_iou) + { + phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); + } + + /** @} */ + +} + +// include specific PGT storage classes +include_once(dirname(__FILE__).'/pgt-file.php'); +include_once(dirname(__FILE__).'/pgt-db.php'); + ?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/client.php b/plugins/CasAuthentication/extlib/CAS/client.php index bbde55a28..ad5a23f83 100644 --- a/plugins/CasAuthentication/extlib/CAS/client.php +++ b/plugins/CasAuthentication/extlib/CAS/client.php @@ -351,6 +351,43 @@ class CASClient { return $this->_server['login_url'] = $url; } + + + /** + * This method sets the serviceValidate URL of the CAS server. + * @param $url the serviceValidate URL + * @private + * @since 1.1.0 by Joachim Fritschi + */ + function setServerServiceValidateURL($url) + { + return $this->_server['service_validate_url'] = $url; + } + + + /** + * This method sets the proxyValidate URL of the CAS server. + * @param $url the proxyValidate URL + * @private + * @since 1.1.0 by Joachim Fritschi + */ + function setServerProxyValidateURL($url) + { + return $this->_server['proxy_validate_url'] = $url; + } + + + /** + * This method sets the samlValidate URL of the CAS server. + * @param $url the samlValidate URL + * @private + * @since 1.1.0 by Joachim Fritschi + */ + function setServerSamlValidateURL($url) + { + return $this->_server['saml_validate_url'] = $url; + } + /** * This method is used to retrieve the service validating URL of the CAS server. @@ -373,7 +410,25 @@ class CASClient // return $this->_server['service_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL()); return $this->_server['service_validate_url'].'?service='.urlencode($this->getURL()); } - + /** + * This method is used to retrieve the SAML validating URL of the CAS server. + * @return a URL. + * @private + */ + function getServerSamlValidateURL() + { + phpCAS::traceBegin(); + // the URL is build only when needed + if ( empty($this->_server['saml_validate_url']) ) { + switch ($this->getServerVersion()) { + case SAML_VERSION_1_1: + $this->_server['saml_validate_url'] = $this->getServerBaseURL().'samlValidate'; + break; + } + } + phpCAS::traceEnd($this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL())); + return $this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL()); + } /** * This method is used to retrieve the proxy validating URL of the CAS server. * @return a URL. @@ -497,31 +552,51 @@ class CASClient phpCAS::traceBegin(); - if (!$this->isLogoutRequest() && !empty($_GET['ticket']) && $start_session) { - // copy old session vars and destroy the current session - if (!isset($_SESSION)) { - session_start(); - } - $old_session = $_SESSION; - session_destroy(); - // set up a new session, of name based on the ticket - $session_id = preg_replace('/[^\w]/','',$_GET['ticket']); - phpCAS::LOG("Session ID: " . $session_id); - session_id($session_id); - if (!isset($_SESSION)) { - session_start(); - } - // restore old session vars - $_SESSION = $old_session; - // Redirect to location without ticket. - header('Location: '.$this->getURL()); - } - - //activate session mechanism if desired - if (!$this->isLogoutRequest() && $start_session) { - session_start(); + // the redirect header() call and DOM parsing code from domxml-php4-php5.php won't work in PHP4 compatibility mode + if (version_compare(PHP_VERSION,'5','>=') && ini_get('zend.ze1_compatibility_mode')) { + phpCAS::error('phpCAS cannot support zend.ze1_compatibility_mode. Sorry.'); + } + // skip Session Handling for logout requests and if don't want it' + if ($start_session && !$this->isLogoutRequest()) { + phpCAS::trace("Starting session handling"); + // Check for Tickets from the CAS server + if (empty($_GET['ticket'])){ + phpCAS::trace("No ticket found"); + // only create a session if necessary + if (!isset($_SESSION)) { + phpCAS::trace("No session found, creating new session"); + session_start(); + } + }else{ + phpCAS::trace("Ticket found"); + // We have to copy any old data before renaming the session + if (isset($_SESSION)) { + phpCAS::trace("Old active session found, saving old data and destroying session"); + $old_session = $_SESSION; + session_destroy(); + }else{ + session_start(); + phpCAS::trace("Starting possible old session to copy variables"); + $old_session = $_SESSION; + session_destroy(); + } + // set up a new session, of name based on the ticket + $session_id = preg_replace('/[^\w]/','',$_GET['ticket']); + phpCAS::LOG("Session ID: " . $session_id); + session_id($session_id); + session_start(); + // restore old session vars + if(isset($old_session)){ + phpCAS::trace("Restoring old session vars"); + $_SESSION = $old_session; + } + } + }else{ + phpCAS::trace("Skipping session creation"); } + + // are we in proxy mode ? $this->_proxy = $proxy; //check version @@ -533,6 +608,8 @@ class CASClient break; case CAS_VERSION_2_0: break; + case SAML_VERSION_1_1: + break; default: phpCAS::error('this version of CAS (`' .$server_version @@ -541,29 +618,29 @@ class CASClient } $this->_server['version'] = $server_version; - //check hostname + // check hostname if ( empty($server_hostname) || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/',$server_hostname) ) { phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')'); } $this->_server['hostname'] = $server_hostname; - //check port + // check port if ( $server_port == 0 || !is_int($server_port) ) { phpCAS::error('bad CAS server port (`'.$server_hostname.'\')'); } $this->_server['port'] = $server_port; - //check URI + // check URI if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/',$server_uri) ) { phpCAS::error('bad CAS server URI (`'.$server_uri.'\')'); } - //add leading and trailing `/' and remove doubles + // add leading and trailing `/' and remove doubles $server_uri = preg_replace('/\/\//','/','/'.$server_uri.'/'); $this->_server['uri'] = $server_uri; - //set to callback mode if PgtIou and PgtId CGI GET parameters are provided + // set to callback mode if PgtIou and PgtId CGI GET parameters are provided if ( $this->isProxy() ) { $this->setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId'])); } @@ -590,8 +667,12 @@ class CASClient } break; case CAS_VERSION_2_0: // check for a Service or Proxy Ticket - if( preg_match('/^[SP]T-/',$ticket) ) { - phpCAS::trace('ST or PT \''.$ticket.'\' found'); + if (preg_match('/^ST-/', $ticket)) { + phpCAS::trace('ST \'' . $ticket . '\' found'); + $this->setST($ticket); + unset ($_GET['ticket']); + } else if (preg_match('/^PT-/', $ticket)) { + phpCAS::trace('PT \'' . $ticket . '\' found'); $this->setPT($ticket); unset($_GET['ticket']); } else if ( !empty($ticket) ) { @@ -599,6 +680,16 @@ class CASClient phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')'); } break; + case SAML_VERSION_1_1: // SAML just does Service Tickets + if( preg_match('/^[SP]T-/',$ticket) ) { + phpCAS::trace('SA \''.$ticket.'\' found'); + $this->setSA($ticket); + unset($_GET['ticket']); + } else if ( !empty($ticket) ) { + //ill-formed ticket, halt + phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')'); + } + break; } } phpCAS::traceEnd(); @@ -652,6 +743,45 @@ class CASClient } return $this->_user; } + + + + /*********************************************************************************************************************** + * Atrributes section + * + * @author Matthias Crauwels , Ghent University, Belgium + * + ***********************************************************************************************************************/ + /** + * The Authenticated users attributes. Written by CASClient::setAttributes(), read by CASClient::getAttributes(). + * @attention client applications should use phpCAS::getAttributes(). + * + * @hideinitializer + * @private + */ + var $_attributes = array(); + + function setAttributes($attributes) + { $this->_attributes = $attributes; } + + function getAttributes() { + if ( empty($this->_user) ) { // if no user is set, there shouldn't be any attributes also... + phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'); + } + return $this->_attributes; + } + + function hasAttributes() + { return !empty($this->_attributes); } + + function hasAttribute($key) + { return (is_array($this->_attributes) && array_key_exists($key, $this->_attributes)); } + + function getAttribute($key) { + if($this->hasAttribute($key)) { + return $this->_attributes[$key]; + } + } /** * This method is called to renew the authentication of the user @@ -778,55 +908,72 @@ class CASClient * This method is called to check if the user is authenticated (previously or by * tickets given in the URL). * - * @return TRUE when the user is authenticated. + * @return TRUE when the user is authenticated. Also may redirect to the same URL without the ticket. * * @public */ function isAuthenticated() { - phpCAS::traceBegin(); - $res = FALSE; - $validate_url = ''; - - if ( $this->wasPreviouslyAuthenticated() ) { - // the user has already (previously during the session) been - // authenticated, nothing to be done. - phpCAS::trace('user was already authenticated, no need to look for tickets'); - $res = TRUE; - } - elseif ( $this->hasST() ) { - // if a Service Ticket was given, validate it - phpCAS::trace('ST `'.$this->getST().'\' is present'); - $this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts - phpCAS::trace('ST `'.$this->getST().'\' was validated'); - if ( $this->isProxy() ) { - $this->validatePGT($validate_url,$text_response,$tree_response); // idem - phpCAS::trace('PGT `'.$this->getPGT().'\' was validated'); - $_SESSION['phpCAS']['pgt'] = $this->getPGT(); + phpCAS::traceBegin(); + $res = FALSE; + $validate_url = ''; + + if ( $this->wasPreviouslyAuthenticated() ) { + // the user has already (previously during the session) been + // authenticated, nothing to be done. + phpCAS::trace('user was already authenticated, no need to look for tickets'); + $res = TRUE; } - $_SESSION['phpCAS']['user'] = $this->getUser(); - $res = TRUE; - } - elseif ( $this->hasPT() ) { - // if a Proxy Ticket was given, validate it - phpCAS::trace('PT `'.$this->getPT().'\' is present'); - $this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts - phpCAS::trace('PT `'.$this->getPT().'\' was validated'); - if ( $this->isProxy() ) { - $this->validatePGT($validate_url,$text_response,$tree_response); // idem - phpCAS::trace('PGT `'.$this->getPGT().'\' was validated'); - $_SESSION['phpCAS']['pgt'] = $this->getPGT(); + else { + if ( $this->hasST() ) { + // if a Service Ticket was given, validate it + phpCAS::trace('ST `'.$this->getST().'\' is present'); + $this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts + phpCAS::trace('ST `'.$this->getST().'\' was validated'); + if ( $this->isProxy() ) { + $this->validatePGT($validate_url,$text_response,$tree_response); // idem + phpCAS::trace('PGT `'.$this->getPGT().'\' was validated'); + $_SESSION['phpCAS']['pgt'] = $this->getPGT(); + } + $_SESSION['phpCAS']['user'] = $this->getUser(); + $res = TRUE; + } + elseif ( $this->hasPT() ) { + // if a Proxy Ticket was given, validate it + phpCAS::trace('PT `'.$this->getPT().'\' is present'); + $this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts + phpCAS::trace('PT `'.$this->getPT().'\' was validated'); + if ( $this->isProxy() ) { + $this->validatePGT($validate_url,$text_response,$tree_response); // idem + phpCAS::trace('PGT `'.$this->getPGT().'\' was validated'); + $_SESSION['phpCAS']['pgt'] = $this->getPGT(); + } + $_SESSION['phpCAS']['user'] = $this->getUser(); + $res = TRUE; + } + elseif ( $this->hasSA() ) { + // if we have a SAML ticket, validate it. + phpCAS::trace('SA `'.$this->getSA().'\' is present'); + $this->validateSA($validate_url,$text_response,$tree_response); // if it fails, it halts + phpCAS::trace('SA `'.$this->getSA().'\' was validated'); + $_SESSION['phpCAS']['user'] = $this->getUser(); + $_SESSION['phpCAS']['attributes'] = $this->getAttributes(); + $res = TRUE; + } + else { + // no ticket given, not authenticated + phpCAS::trace('no ticket found'); + } + if ($res) { + // if called with a ticket parameter, we need to redirect to the app without the ticket so that CAS-ification is transparent to the browser (for later POSTS) + // most of the checks and errors should have been made now, so we're safe for redirect without masking error messages. + header('Location: '.$this->getURL()); + phpCAS::log( "Prepare redirect to : ".$this->getURL() ); + } } - $_SESSION['phpCAS']['user'] = $this->getUser(); - $res = TRUE; - } - else { - // no ticket given, not authenticated - phpCAS::trace('no ticket found'); - } - - phpCAS::traceEnd($res); - return $res; + + phpCAS::traceEnd($res); + return $res; } /** @@ -889,6 +1036,9 @@ class CASClient if ( $this->isSessionAuthenticated() ) { // authentication already done $this->setUser($_SESSION['phpCAS']['user']); + if(isset($_SESSION['phpCAS']['attributes'])){ + $this->setAttributes($_SESSION['phpCAS']['attributes']); + } phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\''); $auth = TRUE; } else { @@ -917,6 +1067,7 @@ class CASClient printf('

    '.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'

    ',$cas_url); $this->printHTMLFooter(); + phpCAS::traceExit(); exit(); } @@ -962,11 +1113,15 @@ class CASClient $cas_url = $cas_url . $paramSeparator . "service=" . urlencode($params['service']); } header('Location: '.$cas_url); + phpCAS::log( "Prepare redirect to : ".$cas_url ); + session_unset(); session_destroy(); + $this->printHTMLHeader($this->getString(CAS_STR_LOGOUT)); printf('

    '.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'

    ',$cas_url); $this->printHTMLFooter(); + phpCAS::traceExit(); exit(); } @@ -1009,10 +1164,10 @@ class CASClient } $client_ip = $_SERVER['REMOTE_ADDR']; $client = gethostbyaddr($client_ip); - phpCAS::log("Client: ".$client); + phpCAS::log("Client: ".$client."/".$client_ip); $allowed = false; foreach ($allowed_clients as $allowed_client) { - if ($client == $allowed_client) { + if (($client == $allowed_client) or ($client_ip == $allowed_client)) { phpCAS::log("Allowed client '".$allowed_client."' matches, logout request is allowed"); $allowed = true; break; @@ -1284,6 +1439,151 @@ class CASClient phpCAS::traceEnd(TRUE); return TRUE; } + + // ######################################################################## + // SAML VALIDATION + // ######################################################################## + /** + * @addtogroup internalBasic + * @{ + */ + + /** + * This method is used to validate a SAML TICKET; halt on failure, and sets $validate_url, + * $text_reponse and $tree_response on success. These parameters are used later + * by CASClient::validatePGT() for CAS proxies. + * + * @param $validate_url the URL of the request to the CAS server. + * @param $text_response the response of the CAS server, as is (XML text). + * @param $tree_response the response of the CAS server, as a DOM XML tree. + * + * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError(). + * + * @private + */ + function validateSA($validate_url,&$text_response,&$tree_response) + { + phpCAS::traceBegin(); + + // build the URL to validate the ticket + $validate_url = $this->getServerSamlValidateURL(); + + // open and read the URL + if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) { + phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')'); + $this->authError('SA not validated', $validate_url, TRUE/*$no_response*/); + } + + phpCAS::trace('server version: '.$this->getServerVersion()); + + // analyze the result depending on the version + switch ($this->getServerVersion()) { + case SAML_VERSION_1_1: + + // read the response of the CAS server into a DOM object + if ( !($dom = domxml_open_mem($text_response))) { + phpCAS::trace('domxml_open_mem() failed'); + $this->authError('SA not validated', + $validate_url, + FALSE/*$no_response*/, + TRUE/*$bad_response*/, + $text_response); + } + // read the root node of the XML tree + if ( !($tree_response = $dom->document_element()) ) { + phpCAS::trace('document_element() failed'); + $this->authError('SA not validated', + $validate_url, + FALSE/*$no_response*/, + TRUE/*$bad_response*/, + $text_response); + } + // insure that tag name is 'Envelope' + if ( $tree_response->node_name() != 'Envelope' ) { + phpCAS::trace('bad XML root node (should be `Envelope\' instead of `'.$tree_response->node_name().'\''); + $this->authError('SA not validated', + $validate_url, + FALSE/*$no_response*/, + TRUE/*$bad_response*/, + $text_response); + } + // check for the NameIdentifier tag in the SAML response + if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("NameIdentifier")) != 0) { + phpCAS::trace('NameIdentifier found'); + $user = trim($success_elements[0]->get_content()); + phpCAS::trace('user = `'.$user.'`'); + $this->setUser($user); + $this->setSessionAttributes($text_response); + } else { + phpCAS::trace('no tag found in SAML payload'); + $this->authError('SA not validated', + $validate_url, + FALSE/*$no_response*/, + TRUE/*$bad_response*/, + $text_response); + } + break; + } + + // at this step, ST has been validated and $this->_user has been set, + phpCAS::traceEnd(TRUE); + return TRUE; + } + + /** + * This method will parse the DOM and pull out the attributes from the SAML + * payload and put them into an array, then put the array into the session. + * + * @param $text_response the SAML payload. + * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError(). + * + * @private + */ + function setSessionAttributes($text_response) + { + phpCAS::traceBegin(); + + $result = FALSE; + + if (isset($_SESSION[SAML_ATTRIBUTES])) { + phpCAS::trace("session attrs already set."); //testbml - do we care? + } + + $attr_array = array(); + + if (($dom = domxml_open_mem($text_response))) { + $xPath = $dom->xpath_new_context(); + $xPath->xpath_register_ns('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol'); + $xPath->xpath_register_ns('saml', 'urn:oasis:names:tc:SAML:1.0:assertion'); + $nodelist = $xPath->xpath_eval("//saml:Attribute"); + $attrs = $nodelist->nodeset; + phpCAS::trace($text_response); + foreach($attrs as $attr){ + $xres = $xPath->xpath_eval("saml:AttributeValue", $attr); + $name = $attr->get_attribute("AttributeName"); + $value_array = array(); + foreach($xres->nodeset as $node){ + $value_array[] = $node->get_content(); + + } + phpCAS::trace("* " . $name . "=" . $value_array); + $attr_array[$name] = $value_array; + } + $_SESSION[SAML_ATTRIBUTES] = $attr_array; + // UGent addition... + foreach($attr_array as $attr_key => $attr_value) { + if(count($attr_value) > 1) { + $this->_attributes[$attr_key] = $attr_value; + } + else { + $this->_attributes[$attr_key] = $attr_value[0]; + } + } + $result = TRUE; + } + phpCAS::traceEnd($result); + return $result; + } /** @} */ @@ -1495,6 +1795,7 @@ class CASClient $this->storePGT($pgt,$pgt_iou); $this->printHTMLFooter(); phpCAS::traceExit(); + exit(); } /** @} */ @@ -1585,7 +1886,7 @@ class CASClient } // create the storage object - $this->_pgt_storage = &new PGTStorageFile($this,$format,$path); + $this->_pgt_storage = new PGTStorageFile($this,$format,$path); } /** @@ -1622,7 +1923,7 @@ class CASClient trigger_error('PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING); // create the storage object - $this->_pgt_storage = & new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table); + $this->_pgt_storage = new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table); } // ######################################################################## @@ -1643,7 +1944,8 @@ class CASClient */ function validatePGT(&$validate_url,$text_response,$tree_response) { - phpCAS::traceBegin(); + // here cannot use phpCAS::traceBegin(); alongside domxml-php4-to-php5.php + phpCAS::log('start validatePGT()'); if ( sizeof($arr = $tree_response->get_elements_by_tagname("proxyGrantingTicket")) == 0) { phpCAS::trace(' not found'); // authentication succeded, but no PGT Iou was transmitted @@ -1666,7 +1968,8 @@ class CASClient } $this->setPGT($pgt); } - phpCAS::traceEnd(TRUE); + // here, cannot use phpCAS::traceEnd(TRUE); alongside domxml-php4-to-php5.php + phpCAS::log('end validatePGT()'); return TRUE; } @@ -1819,7 +2122,15 @@ class CASClient if ($this->_cas_server_cert == '' && $this->_cas_server_ca_cert == '' && !$this->_no_cas_server_validation) { phpCAS::error('one of the methods phpCAS::setCasServerCert(), phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.'); } - if ($this->_cas_server_cert != '' ) { + if ($this->_cas_server_cert != '' && $this->_cas_server_ca_cert != '') { + // This branch added by IDMS. Seems phpCAS implementor got a bit confused about the curl options CURLOPT_SSLCERT and CURLOPT_CAINFO + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); + curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert); + curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert); + curl_setopt($ch, CURLOPT_VERBOSE, '1'); + phpCAS::trace('CURL: Set all required opts for mutual authentication ------'); + } else if ($this->_cas_server_cert != '' ) { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert); } else if ($this->_cas_server_ca_cert != '') { @@ -1839,11 +2150,28 @@ class CASClient if ( is_array($cookies) ) { curl_setopt($ch,CURLOPT_COOKIE,implode(';',$cookies)); } + // add extra stuff if SAML + if ($this->hasSA()) { + $more_headers = array ("soapaction: http://www.oasis-open.org/committees/security", + "cache-control: no-cache", + "pragma: no-cache", + "accept: text/xml", + "connection: keep-alive", + "content-type: text/xml"); + + curl_setopt($ch, CURLOPT_HTTPHEADER, $more_headers); + curl_setopt($ch, CURLOPT_POST, 1); + $data = $this->buildSAMLPayload(); + //phpCAS::trace('SAML Payload: '.print_r($data, TRUE)); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + } // perform the query $buf = curl_exec ($ch); + //phpCAS::trace('CURL: Call completed. Response body is: \''.$buf.'\''); if ( $buf === FALSE ) { phpCAS::trace('curl_exec() failed'); $err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch); + //phpCAS::trace('curl error: '.$err_msg); // close the CURL session curl_close ($ch); $res = FALSE; @@ -1858,7 +2186,28 @@ class CASClient phpCAS::traceEnd($res); return $res; } - + + /** + * This method is used to build the SAML POST body sent to /samlValidate URL. + * + * @return the SOAP-encased SAMLP artifact (the ticket). + * + * @private + */ + function buildSAMLPayload() + { + phpCAS::traceBegin(); + + //get the ticket + $sa = $this->getSA(); + //phpCAS::trace("SA: ".$sa); + + $body=SAML_SOAP_ENV.SAML_SOAP_BODY.SAMLP_REQUEST.SAML_ASSERTION_ARTIFACT.$sa.SAML_ASSERTION_ARTIFACT_CLOSE.SAMLP_REQUEST_CLOSE.SAML_SOAP_BODY_CLOSE.SAML_SOAP_ENV_CLOSE; + + phpCAS::traceEnd($body); + return ($body); + } + /** * This method is the callback used by readURL method to request HTTP headers. */ @@ -1951,6 +2300,7 @@ class CASClient * * @param $url a string giving the URL of the service, including the mailing box * for IMAP URLs, as accepted by imap_open(). + * @param $service a string giving for CAS retrieve Proxy ticket * @param $flags options given to imap_open(). * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, @@ -1964,11 +2314,11 @@ class CASClient * * @public */ - function serviceMail($url,$flags,&$err_code,&$err_msg,&$pt) + function serviceMail($url,$service,$flags,&$err_code,&$err_msg,&$pt) { phpCAS::traceBegin(); // at first retrieve a PT - $pt = $this->retrievePT($target_service,$err_code,$output); + $pt = $this->retrievePT($service,$err_code,$output); $stream = FALSE; @@ -2049,7 +2399,30 @@ class CASClient */ function hasPT() { return !empty($this->_pt); } - + /** + * This method returns the SAML Ticket provided in the URL of the request. + * @return The SAML ticket. + * @private + */ + function getSA() + { return 'ST'.substr($this->_sa, 2); } + + /** + * This method stores the SAML Ticket. + * @param $sa The SAML Ticket. + * @private + */ + function setSA($sa) + { $this->_sa = $sa; } + + /** + * This method tells if a SAML Ticket was stored. + * @return TRUE if a SAML Ticket has been stored. + * @private + */ + function hasSA() + { return !empty($this->_sa); } + /** @} */ // ######################################################################## // PT VALIDATION @@ -2213,8 +2586,13 @@ class CASClient } } - $final_uri .= strtok($_SERVER['REQUEST_URI'],"?"); - $cgi_params = '?'.strtok("?"); + $php_is_for_sissies = split("\?", $_SERVER['REQUEST_URI'], 2); + $final_uri .= $php_is_for_sissies[0]; + if(sizeof($php_is_for_sissies) > 1){ + $cgi_params = '?' . $php_is_for_sissies[1]; + } else { + $cgi_params = '?'; + } // remove the ticket if present in the CGI parameters $cgi_params = preg_replace('/&ticket=[^&]*/','',$cgi_params); $cgi_params = preg_replace('/\?ticket=[^&;]*/','?',$cgi_params); @@ -2294,4 +2672,4 @@ class CASClient /** @} */ } -?> \ No newline at end of file +?> diff --git a/plugins/CasAuthentication/extlib/CAS/domxml-php4-php5.php b/plugins/CasAuthentication/extlib/CAS/domxml-php4-php5.php deleted file mode 100644 index a0dfb99c7..000000000 --- a/plugins/CasAuthentication/extlib/CAS/domxml-php4-php5.php +++ /dev/null @@ -1,277 +0,0 @@ - - * { - * if (version_compare(PHP_VERSION,'5','>=')) - * require_once('domxml-php4-to-php5.php'); - * } - * - * - * Version 1.5.5, 2005-01-18, http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/ - * - * ------------------------------------------------------------------
    - * Written by Alexandre Alapetite, http://alexandre.alapetite.net/cv/ - * - * Copyright 2004, Licence: Creative Commons "Attribution-ShareAlike 2.0 France" BY-SA (FR), - * http://creativecommons.org/licenses/by-sa/2.0/fr/ - * http://alexandre.alapetite.net/divers/apropos/#by-sa - * - Attribution. You must give the original author credit - * - Share Alike. If you alter, transform, or build upon this work, - * you may distribute the resulting work only under a license identical to this one - * - The French law is authoritative - * - Any of these conditions can be waived if you get permission from Alexandre Alapetite - * - Please send to Alexandre Alapetite the modifications you make, - * in order to improve this file for the benefit of everybody - * - * If you want to distribute this code, please do it as a link to: - * http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/ - */ - -function domxml_new_doc($version) {return new php4DOMDocument('');} -function domxml_open_file($filename) {return new php4DOMDocument($filename);} -function domxml_open_mem($str) -{ - $dom=new php4DOMDocument(''); - $dom->myDOMNode->loadXML($str); - return $dom; -} -function xpath_eval($xpath_context,$eval_str,$contextnode=null) {return $xpath_context->query($eval_str,$contextnode);} -function xpath_new_context($dom_document) {return new php4DOMXPath($dom_document);} - -class php4DOMAttr extends php4DOMNode -{ - function php4DOMAttr($aDOMAttr) {$this->myDOMNode=$aDOMAttr;} - function Name() {return $this->myDOMNode->name;} - function Specified() {return $this->myDOMNode->specified;} - function Value() {return $this->myDOMNode->value;} -} - -class php4DOMDocument extends php4DOMNode -{ - function php4DOMDocument($filename='') - { - $this->myDOMNode=new DOMDocument(); - if ($filename!='') $this->myDOMNode->load($filename); - } - function create_attribute($name,$value) - { - $myAttr=$this->myDOMNode->createAttribute($name); - $myAttr->value=$value; - return new php4DOMAttr($myAttr,$this); - } - function create_cdata_section($content) {return new php4DOMNode($this->myDOMNode->createCDATASection($content),$this);} - function create_comment($data) {return new php4DOMNode($this->myDOMNode->createComment($data),$this);} - function create_element($name) {return new php4DOMElement($this->myDOMNode->createElement($name),$this);} - function create_text_node($content) {return new php4DOMNode($this->myDOMNode->createTextNode($content),$this);} - function document_element() {return new php4DOMElement($this->myDOMNode->documentElement,$this);} - function dump_file($filename,$compressionmode=false,$format=false) {return $this->myDOMNode->save($filename);} - function dump_mem($format=false,$encoding=false) {return $this->myDOMNode->saveXML();} - function get_element_by_id($id) {return new php4DOMElement($this->myDOMNode->getElementById($id),$this);} - function get_elements_by_tagname($name) - { - $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name); - $nodeSet=array(); - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - $nodeSet[]=new php4DOMElement($node,$this); - $i++; - } - return $nodeSet; - } - function html_dump_mem() {return $this->myDOMNode->saveHTML();} - function root() {return new php4DOMElement($this->myDOMNode->documentElement,$this);} -} - -class php4DOMElement extends php4DOMNode -{ - function get_attribute($name) {return $this->myDOMNode->getAttribute($name);} - function get_elements_by_tagname($name) - { - $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name); - $nodeSet=array(); - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - $nodeSet[]=new php4DOMElement($node,$this->myOwnerDocument); - $i++; - } - return $nodeSet; - } - function has_attribute($name) {return $this->myDOMNode->hasAttribute($name);} - function remove_attribute($name) {return $this->myDOMNode->removeAttribute($name);} - function set_attribute($name,$value) {return $this->myDOMNode->setAttribute($name,$value);} - function tagname() {return $this->myDOMNode->tagName;} -} - -class php4DOMNode -{ - var $myDOMNode; - var $myOwnerDocument; - function php4DOMNode($aDomNode,$aOwnerDocument) - { - $this->myDOMNode=$aDomNode; - $this->myOwnerDocument=$aOwnerDocument; - } - function __get($name) - { - if ($name=='type') return $this->myDOMNode->nodeType; - elseif ($name=='tagname') return $this->myDOMNode->tagName; - elseif ($name=='content') return $this->myDOMNode->textContent; - else - { - $myErrors=debug_backtrace(); - trigger_error('Undefined property: '.get_class($this).'::$'.$name.' ['.$myErrors[0]['file'].':'.$myErrors[0]['line'].']',E_USER_NOTICE); - return false; - } - } - function append_child($newnode) {return new php4DOMElement($this->myDOMNode->appendChild($newnode->myDOMNode),$this->myOwnerDocument);} - function append_sibling($newnode) {return new php4DOMElement($this->myDOMNode->parentNode->appendChild($newnode->myDOMNode),$this->myOwnerDocument);} - function attributes() - { - $myDOMNodeList=$this->myDOMNode->attributes; - $nodeSet=array(); - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - $nodeSet[]=new php4DOMAttr($node,$this->myOwnerDocument); - $i++; - } - return $nodeSet; - } - function child_nodes() - { - $myDOMNodeList=$this->myDOMNode->childNodes; - $nodeSet=array(); - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - $nodeSet[]=new php4DOMElement($node,$this->myOwnerDocument); - $i++; - } - return $nodeSet; - } - function children() {return $this->child_nodes();} - function clone_node($deep=false) {return new php4DOMElement($this->myDOMNode->cloneNode($deep),$this->myOwnerDocument);} - function first_child() {return new php4DOMElement($this->myDOMNode->firstChild,$this->myOwnerDocument);} - function get_content() {return $this->myDOMNode->textContent;} - function has_attributes() {return $this->myDOMNode->hasAttributes();} - function has_child_nodes() {return $this->myDOMNode->hasChildNodes();} - function insert_before($newnode,$refnode) {return new php4DOMElement($this->myDOMNode->insertBefore($newnode->myDOMNode,$refnode->myDOMNode),$this->myOwnerDocument);} - function is_blank_node() - { - $myDOMNodeList=$this->myDOMNode->childNodes; - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - if (($node->nodeType==XML_ELEMENT_NODE)|| - (($node->nodeType==XML_TEXT_NODE)&&!ereg('^([[:cntrl:]]|[[:space:]])*$',$node->nodeValue))) - return false; - $i++; - } - return true; - } - function last_child() {return new php4DOMElement($this->myDOMNode->lastChild,$this->myOwnerDocument);} - function new_child($name,$content) - { - $mySubNode=$this->myDOMNode->ownerDocument->createElement($name); - $mySubNode->appendChild($this->myDOMNode->ownerDocument->createTextNode($content)); - $this->myDOMNode->appendChild($mySubNode); - return new php4DOMElement($mySubNode,$this->myOwnerDocument); - } - function next_sibling() {return new php4DOMElement($this->myDOMNode->nextSibling,$this->myOwnerDocument);} - function node_name() {return $this->myDOMNode->localName;} - function node_type() {return $this->myDOMNode->nodeType;} - function node_value() {return $this->myDOMNode->nodeValue;} - function owner_document() {return $this->myOwnerDocument;} - function parent_node() {return new php4DOMElement($this->myDOMNode->parentNode,$this->myOwnerDocument);} - function prefix() {return $this->myDOMNode->prefix;} - function previous_sibling() {return new php4DOMElement($this->myDOMNode->previousSibling,$this->myOwnerDocument);} - function remove_child($oldchild) {return new php4DOMElement($this->myDOMNode->removeChild($oldchild->myDOMNode),$this->myOwnerDocument);} - function replace_child($oldnode,$newnode) {return new php4DOMElement($this->myDOMNode->replaceChild($oldnode->myDOMNode,$newnode->myDOMNode),$this->myOwnerDocument);} - function set_content($text) - { - if (($this->myDOMNode->hasChildNodes())&&($this->myDOMNode->firstChild->nodeType==XML_TEXT_NODE)) - $this->myDOMNode->removeChild($this->myDOMNode->firstChild); - return $this->myDOMNode->appendChild($this->myDOMNode->ownerDocument->createTextNode($text)); - } -} - -class php4DOMNodelist -{ - var $myDOMNodelist; - var $nodeset; - function php4DOMNodelist($aDOMNodelist,$aOwnerDocument) - { - $this->myDOMNodelist=$aDOMNodelist; - $this->nodeset=array(); - $i=0; - if (isset($this->myDOMNodelist)) - while ($node=$this->myDOMNodelist->item($i)) - { - $this->nodeset[]=new php4DOMElement($node,$aOwnerDocument); - $i++; - } - } -} - -class php4DOMXPath -{ - var $myDOMXPath; - var $myOwnerDocument; - function php4DOMXPath($dom_document) - { - $this->myOwnerDocument=$dom_document; - $this->myDOMXPath=new DOMXPath($dom_document->myDOMNode); - } - function query($eval_str,$contextnode) - { - if (isset($contextnode)) return new php4DOMNodelist($this->myDOMXPath->query($eval_str,$contextnode->myDOMNode),$this->myOwnerDocument); - else return new php4DOMNodelist($this->myDOMXPath->query($eval_str),$this->myOwnerDocument); - } - function xpath_register_ns($prefix,$namespaceURI) {return $this->myDOMXPath->registerNamespace($prefix,$namespaceURI);} -} - -if (extension_loaded('xsl')) -{//See also: http://alexandre.alapetite.net/doc-alex/xslt-php4-php5/ - function domxml_xslt_stylesheet($xslstring) {return new php4DomXsltStylesheet(DOMDocument::loadXML($xslstring));} - function domxml_xslt_stylesheet_doc($dom_document) {return new php4DomXsltStylesheet($dom_document);} - function domxml_xslt_stylesheet_file($xslfile) {return new php4DomXsltStylesheet(DOMDocument::load($xslfile));} - class php4DomXsltStylesheet - { - var $myxsltProcessor; - function php4DomXsltStylesheet($dom_document) - { - $this->myxsltProcessor=new xsltProcessor(); - $this->myxsltProcessor->importStyleSheet($dom_document); - } - function process($dom_document,$xslt_parameters=array(),$param_is_xpath=false) - { - foreach ($xslt_parameters as $param=>$value) - $this->myxsltProcessor->setParameter('',$param,$value); - $myphp4DOMDocument=new php4DOMDocument(); - $myphp4DOMDocument->myDOMNode=$this->myxsltProcessor->transformToDoc($dom_document->myDOMNode); - return $myphp4DOMDocument; - } - function result_dump_file($dom_document,$filename) - { - $html=$dom_document->myDOMNode->saveHTML(); - file_put_contents($filename,$html); - return $html; - } - function result_dump_mem($dom_document) {return $dom_document->myDOMNode->saveHTML();} - } -} -?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/domxml-php4-to-php5.php b/plugins/CasAuthentication/extlib/CAS/domxml-php4-to-php5.php new file mode 100644 index 000000000..1dc4e4b97 --- /dev/null +++ b/plugins/CasAuthentication/extlib/CAS/domxml-php4-to-php5.php @@ -0,0 +1,499 @@ +=5.1 for XPath evaluation functions, and PHP>=5.1/libxml for DOMXML error reports) + + Typical use: + { + if (PHP_VERSION>='5') + require_once('domxml-php4-to-php5.php'); + } + + Version 1.21, 2008-12-05, http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/ + + ------------------------------------------------------------------ + Written by Alexandre Alapetite, http://alexandre.alapetite.net/cv/ + + Copyright 2004-2008, GNU Lesser General Public License, + http://www.gnu.org/licenses/lgpl.html + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see + + == Rights and obligations == + - Attribution: You must give the original author credit. + - Share Alike: If you alter or transform this library, + you may distribute the resulting library only under the same license GNU/LGPL. + - In case of jurisdiction dispute, the French law is authoritative. + - Any of these conditions can be waived if you get permission from Alexandre Alapetite. + - Not required, but please send to Alexandre Alapetite the modifications you make, + in order to improve this file for the benefit of everybody. + + If you want to distribute this code, please do it as a link to: + http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/ +*/ + +define('DOMXML_LOAD_PARSING',0); +define('DOMXML_LOAD_VALIDATING',1); +define('DOMXML_LOAD_RECOVERING',2); +define('DOMXML_LOAD_SUBSTITUTE_ENTITIES',4); +//define('DOMXML_LOAD_COMPLETE_ATTRS',8); +define('DOMXML_LOAD_DONT_KEEP_BLANKS',16); + +function domxml_new_doc($version) {return new php4DOMDocument();} +function domxml_new_xmldoc($version) {return new php4DOMDocument();} +function domxml_open_file($filename,$mode=DOMXML_LOAD_PARSING,&$error=null) +{ + $dom=new php4DOMDocument($mode); + $errorMode=(func_num_args()>2)&&defined('LIBXML_VERSION'); + if ($errorMode) libxml_use_internal_errors(true); + if (!$dom->myDOMNode->load($filename)) $dom=null; + if ($errorMode) + { + $error=array_map('_error_report',libxml_get_errors()); + libxml_clear_errors(); + } + return $dom; +} +function domxml_open_mem($str,$mode=DOMXML_LOAD_PARSING,&$error=null) +{ + $dom=new php4DOMDocument($mode); + $errorMode=(func_num_args()>2)&&defined('LIBXML_VERSION'); + if ($errorMode) libxml_use_internal_errors(true); + if (!$dom->myDOMNode->loadXML($str)) $dom=null; + if ($errorMode) + { + $error=array_map('_error_report',libxml_get_errors()); + libxml_clear_errors(); + } + return $dom; +} +function html_doc($html_doc,$from_file=false) +{ + $dom=new php4DOMDocument(); + if ($from_file) $result=$dom->myDOMNode->loadHTMLFile($html_doc); + else $result=$dom->myDOMNode->loadHTML($html_doc); + return $result ? $dom : null; +} +function html_doc_file($filename) {return html_doc($filename,true);} +function xmldoc($str) {return domxml_open_mem($str);} +function xmldocfile($filename) {return domxml_open_file($filename);} +function xpath_eval($xpath_context,$eval_str,$contextnode=null) {return $xpath_context->xpath_eval($eval_str,$contextnode);} +function xpath_new_context($dom_document) {return new php4DOMXPath($dom_document);} +function xpath_register_ns($xpath_context,$prefix,$namespaceURI) {return $xpath_context->myDOMXPath->registerNamespace($prefix,$namespaceURI);} +function _entityDecode($text) {return html_entity_decode(strtr($text,array('''=>'\'')),ENT_QUOTES,'UTF-8');} +function _error_report($error) {return array('errormessage'=>$error->message,'nodename'=>'','line'=>$error->line,'col'=>$error->column)+($error->file==''?array():array('directory'=>dirname($error->file),'file'=>basename($error->file)));} + +class php4DOMAttr extends php4DOMNode +{ + function __get($name) + { + if ($name==='name') return $this->myDOMNode->name; + else return parent::__get($name); + } + function name() {return $this->myDOMNode->name;} + function set_content($text) {} + //function set_value($content) {return $this->myDOMNode->value=htmlspecialchars($content,ENT_QUOTES);} + function specified() {return $this->myDOMNode->specified;} + function value() {return $this->myDOMNode->value;} +} + +class php4DOMDocument extends php4DOMNode +{ + function php4DOMDocument($mode=DOMXML_LOAD_PARSING) + { + $this->myDOMNode=new DOMDocument(); + $this->myOwnerDocument=$this; + if ($mode & DOMXML_LOAD_VALIDATING) $this->myDOMNode->validateOnParse=true; + if ($mode & DOMXML_LOAD_RECOVERING) $this->myDOMNode->recover=true; + if ($mode & DOMXML_LOAD_SUBSTITUTE_ENTITIES) $this->myDOMNode->substituteEntities=true; + if ($mode & DOMXML_LOAD_DONT_KEEP_BLANKS) $this->myDOMNode->preserveWhiteSpace=false; + } + function add_root($name) + { + if ($this->myDOMNode->hasChildNodes()) $this->myDOMNode->removeChild($this->myDOMNode->firstChild); + return new php4DOMElement($this->myDOMNode->appendChild($this->myDOMNode->createElement($name)),$this->myOwnerDocument); + } + function create_attribute($name,$value) + { + $myAttr=$this->myDOMNode->createAttribute($name); + $myAttr->value=htmlspecialchars($value,ENT_QUOTES); + return new php4DOMAttr($myAttr,$this); + } + function create_cdata_section($content) {return new php4DOMNode($this->myDOMNode->createCDATASection($content),$this);} + function create_comment($data) {return new php4DOMNode($this->myDOMNode->createComment($data),$this);} + function create_element($name) {return new php4DOMElement($this->myDOMNode->createElement($name),$this);} + function create_element_ns($uri,$name,$prefix=null) + { + if ($prefix==null) $prefix=$this->myDOMNode->lookupPrefix($uri); + if (($prefix==null)&&(($this->myDOMNode->documentElement==null)||(!$this->myDOMNode->documentElement->isDefaultNamespace($uri)))) $prefix='a'.sprintf('%u',crc32($uri)); + return new php4DOMElement($this->myDOMNode->createElementNS($uri,$prefix==null ? $name : $prefix.':'.$name),$this); + } + function create_entity_reference($content) {return new php4DOMNode($this->myDOMNode->createEntityReference($content),$this);} //By Walter Ebert 2007-01-22 + function create_processing_instruction($target,$data=''){return new php4DomProcessingInstruction($this->myDOMNode->createProcessingInstruction($target,$data),$this);} + function create_text_node($content) {return new php4DOMText($this->myDOMNode->createTextNode($content),$this);} + function document_element() {return parent::_newDOMElement($this->myDOMNode->documentElement,$this);} + function dump_file($filename,$compressionmode=false,$format=false) + { + $format0=$this->myDOMNode->formatOutput; + $this->myDOMNode->formatOutput=$format; + $res=$this->myDOMNode->save($filename); + $this->myDOMNode->formatOutput=$format0; + return $res; + } + function dump_mem($format=false,$encoding=false) + { + $format0=$this->myDOMNode->formatOutput; + $this->myDOMNode->formatOutput=$format; + $encoding0=$this->myDOMNode->encoding; + if ($encoding) $this->myDOMNode->encoding=$encoding; + $dump=$this->myDOMNode->saveXML(); + $this->myDOMNode->formatOutput=$format0; + if ($encoding) $this->myDOMNode->encoding= $encoding0=='' ? 'UTF-8' : $encoding0; //UTF-8 is XML default encoding + return $dump; + } + function free() + { + if ($this->myDOMNode->hasChildNodes()) $this->myDOMNode->removeChild($this->myDOMNode->firstChild); + $this->myDOMNode=null; + $this->myOwnerDocument=null; + } + function get_element_by_id($id) {return parent::_newDOMElement($this->myDOMNode->getElementById($id),$this);} + function get_elements_by_tagname($name) + { + $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name); + $nodeSet=array(); + $i=0; + if (isset($myDOMNodeList)) + while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMElement($node,$this); + return $nodeSet; + } + function html_dump_mem() {return $this->myDOMNode->saveHTML();} + function root() {return parent::_newDOMElement($this->myDOMNode->documentElement,$this);} + function xinclude() {return $this->myDOMNode->xinclude();} + function xpath_new_context() {return new php4DOMXPath($this);} +} + +class php4DOMElement extends php4DOMNode +{ + function add_namespace($uri,$prefix) + { + if ($this->myDOMNode->hasAttributeNS('http://www.w3.org/2000/xmlns/',$prefix)) return false; + else + { + $this->myDOMNode->setAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:'.$prefix,$uri); //By Daniel Walker 2006-09-08 + return true; + } + } + function get_attribute($name) {return $this->myDOMNode->getAttribute($name);} + function get_attribute_node($name) {return parent::_newDOMElement($this->myDOMNode->getAttributeNode($name),$this->myOwnerDocument);} + function get_elements_by_tagname($name) + { + $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name); + $nodeSet=array(); + $i=0; + if (isset($myDOMNodeList)) + while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMElement($node,$this->myOwnerDocument); + return $nodeSet; + } + function has_attribute($name) {return $this->myDOMNode->hasAttribute($name);} + function remove_attribute($name) {return $this->myDOMNode->removeAttribute($name);} + function set_attribute($name,$value) + { + //return $this->myDOMNode->setAttribute($name,$value); //Does not return a DomAttr + $myAttr=$this->myDOMNode->ownerDocument->createAttribute($name); + $myAttr->value=htmlspecialchars($value,ENT_QUOTES); //Entity problem reported by AL-DesignWorks 2007-09-07 + $this->myDOMNode->setAttributeNode($myAttr); + return new php4DOMAttr($myAttr,$this->myOwnerDocument); + } + /*function set_attribute_node($attr) + { + $this->myDOMNode->setAttributeNode($this->_importNode($attr)); + return $attr; + }*/ + function set_name($name) + { + if ($this->myDOMNode->prefix=='') $newNode=$this->myDOMNode->ownerDocument->createElement($name); + else $newNode=$this->myDOMNode->ownerDocument->createElementNS($this->myDOMNode->namespaceURI,$this->myDOMNode->prefix.':'.$name); + $myDOMNodeList=$this->myDOMNode->attributes; + $i=0; + if (isset($myDOMNodeList)) + while ($node=$myDOMNodeList->item($i++)) + if ($node->namespaceURI=='') $newNode->setAttribute($node->name,$node->value); + else $newNode->setAttributeNS($node->namespaceURI,$node->nodeName,$node->value); + $myDOMNodeList=$this->myDOMNode->childNodes; + if (isset($myDOMNodeList)) + while ($node=$myDOMNodeList->item(0)) $newNode->appendChild($node); + $this->myDOMNode->parentNode->replaceChild($newNode,$this->myDOMNode); + $this->myDOMNode=$newNode; + return true; + } + function tagname() {return $this->tagname;} +} + +class php4DOMNode +{ + public $myDOMNode; + public $myOwnerDocument; + function php4DOMNode($aDomNode,$aOwnerDocument) + { + $this->myDOMNode=$aDomNode; + $this->myOwnerDocument=$aOwnerDocument; + } + function __get($name) + { + switch ($name) + { + case 'type': return $this->myDOMNode->nodeType; + case 'tagname': return ($this->myDOMNode->nodeType===XML_ELEMENT_NODE) ? $this->myDOMNode->localName : $this->myDOMNode->tagName; //Avoid namespace prefix for DOMElement + case 'content': return $this->myDOMNode->textContent; + case 'value': return $this->myDOMNode->value; + default: + $myErrors=debug_backtrace(); + trigger_error('Undefined property: '.get_class($this).'::$'.$name.' ['.$myErrors[0]['file'].':'.$myErrors[0]['line'].']',E_USER_NOTICE); + return false; + } + } + function add_child($newnode) {return append_child($newnode);} + function add_namespace($uri,$prefix) {return false;} + function append_child($newnode) {return self::_newDOMElement($this->myDOMNode->appendChild($this->_importNode($newnode)),$this->myOwnerDocument);} + function append_sibling($newnode) {return self::_newDOMElement($this->myDOMNode->parentNode->appendChild($this->_importNode($newnode)),$this->myOwnerDocument);} + function attributes() + { + $myDOMNodeList=$this->myDOMNode->attributes; + if (!(isset($myDOMNodeList)&&$this->myDOMNode->hasAttributes())) return null; + $nodeSet=array(); + $i=0; + while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMAttr($node,$this->myOwnerDocument); + return $nodeSet; + } + function child_nodes() + { + $myDOMNodeList=$this->myDOMNode->childNodes; + $nodeSet=array(); + $i=0; + if (isset($myDOMNodeList)) + while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=self::_newDOMElement($node,$this->myOwnerDocument); + return $nodeSet; + } + function children() {return $this->child_nodes();} + function clone_node($deep=false) {return self::_newDOMElement($this->myDOMNode->cloneNode($deep),$this->myOwnerDocument);} + //dump_node($node) should only be called on php4DOMDocument + function dump_node($node=null) {return $node==null ? $this->myOwnerDocument->myDOMNode->saveXML($this->myDOMNode) : $this->myOwnerDocument->myDOMNode->saveXML($node->myDOMNode);} + function first_child() {return self::_newDOMElement($this->myDOMNode->firstChild,$this->myOwnerDocument);} + function get_content() {return $this->myDOMNode->textContent;} + function has_attributes() {return $this->myDOMNode->hasAttributes();} + function has_child_nodes() {return $this->myDOMNode->hasChildNodes();} + function insert_before($newnode,$refnode) {return self::_newDOMElement($this->myDOMNode->insertBefore($this->_importNode($newnode),$refnode==null?null:$refnode->myDOMNode),$this->myOwnerDocument);} + function is_blank_node() {return ($this->myDOMNode->nodeType===XML_TEXT_NODE)&&preg_match('%^\s*$%',$this->myDOMNode->nodeValue);} + function last_child() {return self::_newDOMElement($this->myDOMNode->lastChild,$this->myOwnerDocument);} + function new_child($name,$content) + { + $mySubNode=$this->myDOMNode->ownerDocument->createElement($name); + $mySubNode->appendChild($this->myDOMNode->ownerDocument->createTextNode(_entityDecode($content))); + $this->myDOMNode->appendChild($mySubNode); + return new php4DOMElement($mySubNode,$this->myOwnerDocument); + } + function next_sibling() {return self::_newDOMElement($this->myDOMNode->nextSibling,$this->myOwnerDocument);} + function node_name() {return ($this->myDOMNode->nodeType===XML_ELEMENT_NODE) ? $this->myDOMNode->localName : $this->myDOMNode->nodeName;} //Avoid namespace prefix for DOMElement + function node_type() {return $this->myDOMNode->nodeType;} + function node_value() {return $this->myDOMNode->nodeValue;} + function owner_document() {return $this->myOwnerDocument;} + function parent_node() {return self::_newDOMElement($this->myDOMNode->parentNode,$this->myOwnerDocument);} + function prefix() {return $this->myDOMNode->prefix;} + function previous_sibling() {return self::_newDOMElement($this->myDOMNode->previousSibling,$this->myOwnerDocument);} + function remove_child($oldchild) {return self::_newDOMElement($this->myDOMNode->removeChild($oldchild->myDOMNode),$this->myOwnerDocument);} + function replace_child($newnode,$oldnode) {return self::_newDOMElement($this->myDOMNode->replaceChild($this->_importNode($newnode),$oldnode->myDOMNode),$this->myOwnerDocument);} + function replace_node($newnode) {return self::_newDOMElement($this->myDOMNode->parentNode->replaceChild($this->_importNode($newnode),$this->myDOMNode),$this->myOwnerDocument);} + function set_content($text) {return $this->myDOMNode->appendChild($this->myDOMNode->ownerDocument->createTextNode(_entityDecode($text)));} //Entity problem reported by AL-DesignWorks 2007-09-07 + //function set_name($name) {return $this->myOwnerDocument->renameNode($this->myDOMNode,$this->myDOMNode->namespaceURI,$name);} + function set_namespace($uri,$prefix=null) + {//Contributions by Daniel Walker 2006-09-08 + $nsprefix=$this->myDOMNode->lookupPrefix($uri); + if ($nsprefix==null) + { + $nsprefix= $prefix==null ? $nsprefix='a'.sprintf('%u',crc32($uri)) : $prefix; + if ($this->myDOMNode->nodeType===XML_ATTRIBUTE_NODE) + { + if (($prefix!=null)&&$this->myDOMNode->ownerElement->hasAttributeNS('http://www.w3.org/2000/xmlns/',$nsprefix)&& + ($this->myDOMNode->ownerElement->getAttributeNS('http://www.w3.org/2000/xmlns/',$nsprefix)!=$uri)) + {//Remove namespace + $parent=$this->myDOMNode->ownerElement; + $parent->removeAttributeNode($this->myDOMNode); + $parent->setAttribute($this->myDOMNode->localName,$this->myDOMNode->nodeValue); + $this->myDOMNode=$parent->getAttributeNode($this->myDOMNode->localName); + return; + } + $this->myDOMNode->ownerElement->setAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:'.$nsprefix,$uri); + } + } + if ($this->myDOMNode->nodeType===XML_ATTRIBUTE_NODE) + { + $parent=$this->myDOMNode->ownerElement; + $parent->removeAttributeNode($this->myDOMNode); + $parent->setAttributeNS($uri,$nsprefix.':'.$this->myDOMNode->localName,$this->myDOMNode->nodeValue); + $this->myDOMNode=$parent->getAttributeNodeNS($uri,$this->myDOMNode->localName); + } + elseif ($this->myDOMNode->nodeType===XML_ELEMENT_NODE) + { + $NewNode=$this->myDOMNode->ownerDocument->createElementNS($uri,$nsprefix.':'.$this->myDOMNode->localName); + foreach ($this->myDOMNode->attributes as $n) $NewNode->appendChild($n->cloneNode(true)); + foreach ($this->myDOMNode->childNodes as $n) $NewNode->appendChild($n->cloneNode(true)); + $xpath=new DOMXPath($this->myDOMNode->ownerDocument); + $myDOMNodeList=$xpath->query('namespace::*[name()!="xml"]',$this->myDOMNode); //Add old namespaces + foreach ($myDOMNodeList as $n) $NewNode->setAttributeNS('http://www.w3.org/2000/xmlns/',$n->nodeName,$n->nodeValue); + $this->myDOMNode->parentNode->replaceChild($NewNode,$this->myDOMNode); + $this->myDOMNode=$NewNode; + } + } + function unlink_node() + { + if ($this->myDOMNode->parentNode!=null) + { + if ($this->myDOMNode->nodeType===XML_ATTRIBUTE_NODE) $this->myDOMNode->parentNode->removeAttributeNode($this->myDOMNode); + else $this->myDOMNode->parentNode->removeChild($this->myDOMNode); + } + } + protected function _importNode($newnode) {return $this->myOwnerDocument===$newnode->myOwnerDocument ? $newnode->myDOMNode : $this->myOwnerDocument->myDOMNode->importNode($newnode->myDOMNode,true);} //To import DOMNode from another DOMDocument + static function _newDOMElement($aDOMNode,$aOwnerDocument) + {//Check the PHP5 DOMNode before creating a new associated PHP4 DOMNode wrapper + if ($aDOMNode==null) return null; + switch ($aDOMNode->nodeType) + { + case XML_ELEMENT_NODE: return new php4DOMElement($aDOMNode,$aOwnerDocument); + case XML_TEXT_NODE: return new php4DOMText($aDOMNode,$aOwnerDocument); + case XML_ATTRIBUTE_NODE: return new php4DOMAttr($aDOMNode,$aOwnerDocument); + case XML_PI_NODE: return new php4DomProcessingInstruction($aDOMNode,$aOwnerDocument); + default: return new php4DOMNode($aDOMNode,$aOwnerDocument); + } + } +} + +class php4DomProcessingInstruction extends php4DOMNode +{ + function data() {return $this->myDOMNode->data;} + function target() {return $this->myDOMNode->target;} +} + +class php4DOMText extends php4DOMNode +{ + function __get($name) + { + if ($name==='tagname') return '#text'; + else return parent::__get($name); + } + function tagname() {return '#text';} + function set_content($text) {$this->myDOMNode->nodeValue=$text; return true;} +} + +if (!defined('XPATH_NODESET')) +{ + define('XPATH_UNDEFINED',0); + define('XPATH_NODESET',1); + define('XPATH_BOOLEAN',2); + define('XPATH_NUMBER',3); + define('XPATH_STRING',4); + /*define('XPATH_POINT',5); + define('XPATH_RANGE',6); + define('XPATH_LOCATIONSET',7); + define('XPATH_USERS',8); + define('XPATH_XSLT_TREE',9);*/ +} + +class php4DOMNodelist +{ + private $myDOMNodelist; + public $nodeset; + public $type=XPATH_UNDEFINED; + public $value; + function php4DOMNodelist($aDOMNodelist,$aOwnerDocument) + { + if (!isset($aDOMNodelist)) return; + elseif (is_object($aDOMNodelist)||is_array($aDOMNodelist)) + { + if ($aDOMNodelist->length>0) + { + $this->myDOMNodelist=$aDOMNodelist; + $this->nodeset=array(); + $this->type=XPATH_NODESET; + $i=0; + while ($node=$this->myDOMNodelist->item($i++)) $this->nodeset[]=php4DOMNode::_newDOMElement($node,$aOwnerDocument); + } + } + elseif (is_int($aDOMNodelist)||is_float($aDOMNodelist)) + { + $this->type=XPATH_NUMBER; + $this->value=$aDOMNodelist; + } + elseif (is_bool($aDOMNodelist)) + { + $this->type=XPATH_BOOLEAN; + $this->value=$aDOMNodelist; + } + elseif (is_string($aDOMNodelist)) + { + $this->type=XPATH_STRING; + $this->value=$aDOMNodelist; + } + } +} + +class php4DOMXPath +{ + public $myDOMXPath; + private $myOwnerDocument; + function php4DOMXPath($dom_document) + { + //TODO: If $dom_document is a DomElement, make that default $contextnode and modify XPath. Ex: '/test' + $this->myOwnerDocument=$dom_document->myOwnerDocument; + $this->myDOMXPath=new DOMXPath($this->myOwnerDocument->myDOMNode); + } + function xpath_eval($eval_str,$contextnode=null) + { + if (method_exists($this->myDOMXPath,'evaluate')) $xp=isset($contextnode) ? $this->myDOMXPath->evaluate($eval_str,$contextnode->myDOMNode) : $this->myDOMXPath->evaluate($eval_str); + else $xp=isset($contextnode) ? $this->myDOMXPath->query($eval_str,$contextnode->myDOMNode) : $this->myDOMXPath->query($eval_str); + $xp=new php4DOMNodelist($xp,$this->myOwnerDocument); + return ($xp->type===XPATH_UNDEFINED) ? false : $xp; + } + function xpath_register_ns($prefix,$namespaceURI) {return $this->myDOMXPath->registerNamespace($prefix,$namespaceURI);} +} + +if (extension_loaded('xsl')) +{//See also: http://alexandre.alapetite.net/doc-alex/xslt-php4-php5/ + function domxml_xslt_stylesheet($xslstring) {return new php4DomXsltStylesheet(DOMDocument::loadXML($xslstring));} + function domxml_xslt_stylesheet_doc($dom_document) {return new php4DomXsltStylesheet($dom_document);} + function domxml_xslt_stylesheet_file($xslfile) {return new php4DomXsltStylesheet(DOMDocument::load($xslfile));} + class php4DomXsltStylesheet + { + private $myxsltProcessor; + function php4DomXsltStylesheet($dom_document) + { + $this->myxsltProcessor=new xsltProcessor(); + $this->myxsltProcessor->importStyleSheet($dom_document); + } + function process($dom_document,$xslt_parameters=array(),$param_is_xpath=false) + { + foreach ($xslt_parameters as $param=>$value) $this->myxsltProcessor->setParameter('',$param,$value); + $myphp4DOMDocument=new php4DOMDocument(); + $myphp4DOMDocument->myDOMNode=$this->myxsltProcessor->transformToDoc($dom_document->myDOMNode); + return $myphp4DOMDocument; + } + function result_dump_file($dom_document,$filename) + { + $html=$dom_document->myDOMNode->saveHTML(); + file_put_contents($filename,$html); + return $html; + } + function result_dump_mem($dom_document) {return $dom_document->myDOMNode->saveHTML();} + } +} +?> diff --git a/plugins/CasAuthentication/extlib/CAS/languages/catalan.php b/plugins/CasAuthentication/extlib/CAS/languages/catalan.php index 0b139c7ca..3d67473d9 100644 --- a/plugins/CasAuthentication/extlib/CAS/languages/catalan.php +++ b/plugins/CasAuthentication/extlib/CAS/languages/catalan.php @@ -1,27 +1,27 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -$this->_strings = array( - CAS_STR_USING_SERVER - => 'usant servidor', - CAS_STR_AUTHENTICATION_WANTED - => 'Autentificació CAS necessària!', - CAS_STR_LOGOUT - => 'Sortida de CAS necessària!', - CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'Ja hauria d\ haver estat redireccionat al servidor CAS. Feu click aquí per a continuar.', - CAS_STR_AUTHENTICATION_FAILED - => 'Autentificació CAS fallida!', - CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

    No estàs autentificat.

    Pots tornar a intentar-ho fent click aquí.

    Si el problema persisteix hauría de contactar amb l\'administrador d\'aquest llocc.

    ', - CAS_STR_SERVICE_UNAVAILABLE - => 'El servei `%s\' no està disponible (%s).' -); - -?> + + * @sa @link internalLang Internationalization @endlink + * @ingroup internalLang + */ + +$this->_strings = array( + CAS_STR_USING_SERVER + => 'usant servidor', + CAS_STR_AUTHENTICATION_WANTED + => 'Autentificació CAS necessària!', + CAS_STR_LOGOUT + => 'Sortida de CAS necessària!', + CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED + => 'Ja hauria d\ haver estat redireccionat al servidor CAS. Feu click aquí per a continuar.', + CAS_STR_AUTHENTICATION_FAILED + => 'Autentificació CAS fallida!', + CAS_STR_YOU_WERE_NOT_AUTHENTICATED + => '

    No estàs autentificat.

    Pots tornar a intentar-ho fent click aquí.

    Si el problema persisteix hauría de contactar amb l\'administrador d\'aquest llocc.

    ', + CAS_STR_SERVICE_UNAVAILABLE + => 'El servei `%s\' no està disponible (%s).' +); + +?> diff --git a/plugins/CasAuthentication/extlib/CAS/languages/english.php b/plugins/CasAuthentication/extlib/CAS/languages/english.php index d38d42c1f..c14345031 100644 --- a/plugins/CasAuthentication/extlib/CAS/languages/english.php +++ b/plugins/CasAuthentication/extlib/CAS/languages/english.php @@ -1,27 +1,27 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -$this->_strings = array( - CAS_STR_USING_SERVER - => 'using server', - CAS_STR_AUTHENTICATION_WANTED - => 'CAS Authentication wanted!', - CAS_STR_LOGOUT - => 'CAS logout wanted!', - CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'You should already have been redirected to the CAS server. Click here to continue.', - CAS_STR_AUTHENTICATION_FAILED - => 'CAS Authentication failed!', - CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

    You were not authenticated.

    You may submit your request again by clicking here.

    If the problem persists, you may contact the administrator of this site.

    ', - CAS_STR_SERVICE_UNAVAILABLE - => 'The service `%s\' is not available (%s).' -); - + + * @sa @link internalLang Internationalization @endlink + * @ingroup internalLang + */ + +$this->_strings = array( + CAS_STR_USING_SERVER + => 'using server', + CAS_STR_AUTHENTICATION_WANTED + => 'CAS Authentication wanted!', + CAS_STR_LOGOUT + => 'CAS logout wanted!', + CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED + => 'You should already have been redirected to the CAS server. Click here to continue.', + CAS_STR_AUTHENTICATION_FAILED + => 'CAS Authentication failed!', + CAS_STR_YOU_WERE_NOT_AUTHENTICATED + => '

    You were not authenticated.

    You may submit your request again by clicking here.

    If the problem persists, you may contact the administrator of this site.

    ', + CAS_STR_SERVICE_UNAVAILABLE + => 'The service `%s\' is not available (%s).' +); + ?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/languages/french.php b/plugins/CasAuthentication/extlib/CAS/languages/french.php index 32d141685..b077ec02e 100644 --- a/plugins/CasAuthentication/extlib/CAS/languages/french.php +++ b/plugins/CasAuthentication/extlib/CAS/languages/french.php @@ -1,28 +1,28 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -$this->_strings = array( - CAS_STR_USING_SERVER - => 'utilisant le serveur', - CAS_STR_AUTHENTICATION_WANTED - => 'Authentication CAS nécessaire !', - CAS_STR_LOGOUT - => 'Déconnexion demandée !', - CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'Vous auriez du etre redirigé(e) vers le serveur CAS. Cliquez ici pour continuer.', - CAS_STR_AUTHENTICATION_FAILED - => 'Authentification CAS infructueuse !', - CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

    Vous n\'avez pas été authentifié(e).

    Vous pouvez soumettre votre requete à nouveau en cliquant ici.

    Si le problème persiste, vous pouvez contacter l\'administrateur de ce site.

    ', - CAS_STR_SERVICE_UNAVAILABLE - => 'Le service `%s\' est indisponible (%s)' - -); - + + * @sa @link internalLang Internationalization @endlink + * @ingroup internalLang + */ + +$this->_strings = array( + CAS_STR_USING_SERVER + => 'utilisant le serveur', + CAS_STR_AUTHENTICATION_WANTED + => 'Authentication CAS n�cessaire !', + CAS_STR_LOGOUT + => 'D�connexion demand�e !', + CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED + => 'Vous auriez du etre redirig�(e) vers le serveur CAS. Cliquez ici pour continuer.', + CAS_STR_AUTHENTICATION_FAILED + => 'Authentification CAS infructueuse !', + CAS_STR_YOU_WERE_NOT_AUTHENTICATED + => '

    Vous n\'avez pas �t� authentifi�(e).

    Vous pouvez soumettre votre requete � nouveau en cliquant ici.

    Si le probl�me persiste, vous pouvez contacter l\'administrateur de ce site.

    ', + CAS_STR_SERVICE_UNAVAILABLE + => 'Le service `%s\' est indisponible (%s)' + +); + ?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/languages/german.php b/plugins/CasAuthentication/extlib/CAS/languages/german.php index 55c3238fd..29daeb35d 100644 --- a/plugins/CasAuthentication/extlib/CAS/languages/german.php +++ b/plugins/CasAuthentication/extlib/CAS/languages/german.php @@ -1,27 +1,27 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -$this->_strings = array( - CAS_STR_USING_SERVER - => 'via Server', - CAS_STR_AUTHENTICATION_WANTED - => 'CAS Authentifizierung erforderlich!', - CAS_STR_LOGOUT - => 'CAS Abmeldung!', - CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'eigentlich häten Sie zum CAS Server weitergeleitet werden sollen. Drücken Sie hier um fortzufahren.', - CAS_STR_AUTHENTICATION_FAILED - => 'CAS Anmeldung fehlgeschlagen!', - CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

    Sie wurden nicht angemeldet.

    Um es erneut zu versuchen klicken Sie hier.

    Wenn das Problem bestehen bleibt, kontkatieren Sie den Administrator dieser Seite.

    ', - CAS_STR_SERVICE_UNAVAILABLE - => 'Der Dienst `%s\' ist nicht verfügbar (%s).' -); - + + * @sa @link internalLang Internationalization @endlink + * @ingroup internalLang + */ + +$this->_strings = array( + CAS_STR_USING_SERVER + => 'via Server', + CAS_STR_AUTHENTICATION_WANTED + => 'CAS Authentifizierung erforderlich!', + CAS_STR_LOGOUT + => 'CAS Abmeldung!', + CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED + => 'eigentlich häten Sie zum CAS Server weitergeleitet werden sollen. Drücken Sie hier um fortzufahren.', + CAS_STR_AUTHENTICATION_FAILED + => 'CAS Anmeldung fehlgeschlagen!', + CAS_STR_YOU_WERE_NOT_AUTHENTICATED + => '

    Sie wurden nicht angemeldet.

    Um es erneut zu versuchen klicken Sie hier.

    Wenn das Problem bestehen bleibt, kontkatieren Sie den Administrator dieser Seite.

    ', + CAS_STR_SERVICE_UNAVAILABLE + => 'Der Dienst `%s\' ist nicht verfügbar (%s).' +); + ?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/languages/greek.php b/plugins/CasAuthentication/extlib/CAS/languages/greek.php index d41bf783b..fdff77e4e 100644 --- a/plugins/CasAuthentication/extlib/CAS/languages/greek.php +++ b/plugins/CasAuthentication/extlib/CAS/languages/greek.php @@ -1,27 +1,27 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -$this->_strings = array( - CAS_STR_USING_SERVER - => '÷ñçóéìïðïéåßôáé ï åîõðçñåôçôÞò', - CAS_STR_AUTHENTICATION_WANTED - => 'Áðáéôåßôáé ç ôáõôïðïßçóç CAS!', - CAS_STR_LOGOUT - => 'Áðáéôåßôáé ç áðïóýíäåóç áðü CAS!', - CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'Èá Ýðñåðå íá åß÷áôå áíáêáôåõèõíèåß óôïí åîõðçñåôçôÞ CAS. ÊÜíôå êëßê åäþ ãéá íá óõíå÷ßóåôå.', - CAS_STR_AUTHENTICATION_FAILED - => 'Ç ôáõôïðïßçóç CAS áðÝôõ÷å!', - CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

    Äåí ôáõôïðïéçèÞêáôå.

    Ìðïñåßôå íá îáíáðñïóðáèÞóåôå, êÜíïíôáò êëßê åäþ.

    Åáí ôï ðñüâëçìá åðéìåßíåé, åëÜôå óå åðáöÞ ìå ôïí äéá÷åéñéóôÞ.

    ', - CAS_STR_SERVICE_UNAVAILABLE - => 'Ç õðçñåóßá `%s\' äåí åßíáé äéáèÝóéìç (%s).' -); - + + * @sa @link internalLang Internationalization @endlink + * @ingroup internalLang + */ + +$this->_strings = array( + CAS_STR_USING_SERVER + => '��������������� � ������������', + CAS_STR_AUTHENTICATION_WANTED + => '���������� � ����������� CAS!', + CAS_STR_LOGOUT + => '���������� � ���������� ��� CAS!', + CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED + => '�� ������ �� ������ �������������� ���� ����������� CAS. ����� ���� ��� ��� �� ����������.', + CAS_STR_AUTHENTICATION_FAILED + => '� ����������� CAS �������!', + CAS_STR_YOU_WERE_NOT_AUTHENTICATED + => '

    ��� ���������������.

    �������� �� ����������������, �������� ���� ���.

    ��� �� �������� ���������, ����� �� ����� �� ��� �����������.

    ', + CAS_STR_SERVICE_UNAVAILABLE + => '� �������� `%s\' ��� ����� ��������� (%s).' +); + ?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/languages/japanese.php b/plugins/CasAuthentication/extlib/CAS/languages/japanese.php index 333bb17b6..76ebe77bc 100644 --- a/plugins/CasAuthentication/extlib/CAS/languages/japanese.php +++ b/plugins/CasAuthentication/extlib/CAS/languages/japanese.php @@ -11,17 +11,17 @@ $this->_strings = array( CAS_STR_USING_SERVER => 'using server', CAS_STR_AUTHENTICATION_WANTED - => 'CAS¤Ë¤è¤ëǧ¾Ú¤ò¹Ô¤¤¤Þ¤¹', + => 'CAS�ˤ��ǧ�ڤ�Ԥ��ޤ�', CAS_STR_LOGOUT - => 'CAS¤«¤é¥í¥°¥¢¥¦¥È¤·¤Þ¤¹!', + => 'CAS����?�����Ȥ��ޤ�!', CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'CAS¥µ¡¼¥Ð¤Ë¹Ô¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡£¼«Æ°Åª¤ËžÁ÷¤µ¤ì¤Ê¤¤¾ì¹ç¤Ï ¤³¤Á¤é ¤ò¥¯¥ê¥Ã¥¯¤·¤ÆÂ³¹Ô¤·¤Þ¤¹¡£', + => 'CAS�����Ф˹Ԥ�ɬ�פ�����ޤ�����ưŪ��ž������ʤ����� ������ �ò¥¯¥ï¿½Ã¥ï¿½ï¿½ï¿½ï¿½ï¿½Â³ï¿½Ô¤ï¿½ï¿½Þ¤ï¿½ï¿½ï¿½', CAS_STR_AUTHENTICATION_FAILED - => 'CAS¤Ë¤è¤ëǧ¾Ú¤Ë¼ºÇÔ¤·¤Þ¤·¤¿', + => 'CAS�ˤ��ǧ�ڤ˼��Ԥ��ޤ���', CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

    ǧ¾Ú¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿.

    ¤â¤¦°ìÅ٥ꥯ¥¨¥¹¥È¤òÁ÷¿®¤¹¤ë¾ì¹ç¤Ï¤³¤Á¤é¤ò¥¯¥ê¥Ã¥¯.

    ÌäÂ꤬²ò·è¤·¤Ê¤¤¾ì¹ç¤Ï ¤³¤Î¥µ¥¤¥È¤Î´ÉÍý¼Ô¤ËÌ䤤¹ç¤ï¤»¤Æ¤¯¤À¤µ¤¤.

    ', + => '

    ǧ�ڤǤ��ޤ���Ǥ���.

    �⤦���٥ꥯ�����Ȥ�������������������򥯥�å�.

    ���꤬��褷�ʤ����� ���Υ����Ȥδ�������䤤��碌�Ƥ�������.

    ', CAS_STR_SERVICE_UNAVAILABLE - => '¥µ¡¼¥Ó¥¹ `%s\' ¤ÏÍøÍѤǤ­¤Þ¤»¤ó (%s).' + => '�����ӥ� `%s\' �����ѤǤ��ޤ��� (%s).' ); ?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/languages/languages.php b/plugins/CasAuthentication/extlib/CAS/languages/languages.php index 001cfe445..2c6f8bb3b 100644 --- a/plugins/CasAuthentication/extlib/CAS/languages/languages.php +++ b/plugins/CasAuthentication/extlib/CAS/languages/languages.php @@ -1,24 +1,24 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -//@{ -/** - * a phpCAS string index - */ -define("CAS_STR_USING_SERVER", 1); -define("CAS_STR_AUTHENTICATION_WANTED", 2); -define("CAS_STR_LOGOUT", 3); -define("CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED", 4); -define("CAS_STR_AUTHENTICATION_FAILED", 5); -define("CAS_STR_YOU_WERE_NOT_AUTHENTICATED", 6); -define("CAS_STR_SERVICE_UNAVAILABLE", 7); -//@} - + + * @sa @link internalLang Internationalization @endlink + * @ingroup internalLang + */ + +//@{ +/** + * a phpCAS string index + */ +define("CAS_STR_USING_SERVER", 1); +define("CAS_STR_AUTHENTICATION_WANTED", 2); +define("CAS_STR_LOGOUT", 3); +define("CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED", 4); +define("CAS_STR_AUTHENTICATION_FAILED", 5); +define("CAS_STR_YOU_WERE_NOT_AUTHENTICATED", 6); +define("CAS_STR_SERVICE_UNAVAILABLE", 7); +//@} + ?> \ No newline at end of file diff --git a/plugins/CasAuthentication/extlib/CAS/languages/spanish.php b/plugins/CasAuthentication/extlib/CAS/languages/spanish.php index 04067ca03..3a8ffc253 100644 --- a/plugins/CasAuthentication/extlib/CAS/languages/spanish.php +++ b/plugins/CasAuthentication/extlib/CAS/languages/spanish.php @@ -1,27 +1,27 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -$this->_strings = array( - CAS_STR_USING_SERVER - => 'usando servidor', - CAS_STR_AUTHENTICATION_WANTED - => '¡Autentificación CAS necesaria!', - CAS_STR_LOGOUT - => '¡Salida CAS necesaria!', - CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'Ya debería haber sido redireccionado al servidor CAS. Haga click aquí para continuar.', - CAS_STR_AUTHENTICATION_FAILED - => '¡Autentificación CAS fallida!', - CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

    No estás autentificado.

    Puedes volver a intentarlo haciendo click aquí.

    Si el problema persiste debería contactar con el administrador de este sitio.

    ', - CAS_STR_SERVICE_UNAVAILABLE - => 'El servicio `%s\' no está disponible (%s).' -); - -?> + + * @sa @link internalLang Internationalization @endlink + * @ingroup internalLang + */ + +$this->_strings = array( + CAS_STR_USING_SERVER + => 'usando servidor', + CAS_STR_AUTHENTICATION_WANTED + => '¡Autentificación CAS necesaria!', + CAS_STR_LOGOUT + => '¡Salida CAS necesaria!', + CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED + => 'Ya debería haber sido redireccionado al servidor CAS. Haga click aquí para continuar.', + CAS_STR_AUTHENTICATION_FAILED + => '¡Autentificación CAS fallida!', + CAS_STR_YOU_WERE_NOT_AUTHENTICATED + => '

    No estás autentificado.

    Puedes volver a intentarlo haciendo click aquí.

    Si el problema persiste debería contactar con el administrador de este sitio.

    ', + CAS_STR_SERVICE_UNAVAILABLE + => 'El servicio `%s\' no está disponible (%s).' +); + +?> -- cgit v1.2.3-54-g00ecf From 6aac7cc6cd011b3c86f3f4c8e00a14f992a78306 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 5 Mar 2010 02:27:01 +0000 Subject: Fix for errant deletion of all Twitter foreign_links --- plugins/TwitterBridge/twitter.php | 11 ++++++++++- plugins/TwitterBridge/twitterauthorization.php | 13 ++++++++++++- plugins/TwitterBridge/twittersettings.php | 11 ++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 13e499d65..90805bfc4 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -273,7 +273,16 @@ function remove_twitter_link($flink) common_log(LOG_INFO, 'Removing Twitter bridge Foreign link for ' . "user $user->nickname (user id: $user->id)."); - $result = $flink->delete(); + $result = false; + + // Be extra careful to make sure we have a good flink + // before deleting + if (!empty($flink->user_id) + && !empty($flink->foreign_id) + && !empty($flink->service)) + { + $result = $flink->delete(); + } if (empty($result)) { common_log(LOG_ERR, 'Could not remove Twitter bridge ' . diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index cabf69d7a..bce679622 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -273,7 +273,13 @@ class TwitterauthorizationAction extends Action $flink->user_id = $user_id; $flink->service = TWITTER_SERVICE; - $flink->delete(); // delete stale flink, if any + + // delete stale flink, if any + $result = $flink->find(true); + + if (!empty($result)) { + $flink->delete(); + } $flink->user_id = $user_id; $flink->foreign_id = $twuid; @@ -455,6 +461,11 @@ class TwitterauthorizationAction extends Action $user = User::register($args); + if (empty($user)) { + $this->serverError(_('Error registering user.')); + return; + } + $result = $this->saveForeignLink($user->id, $this->twuid, $this->access_token); diff --git a/plugins/TwitterBridge/twittersettings.php b/plugins/TwitterBridge/twittersettings.php index 0137060e9..f22a059f7 100644 --- a/plugins/TwitterBridge/twittersettings.php +++ b/plugins/TwitterBridge/twittersettings.php @@ -250,7 +250,16 @@ class TwittersettingsAction extends ConnectSettingsAction $user = common_current_user(); $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); - $result = $flink->delete(); + $result = false; + + // Be extra careful to make sure we have a good flink + // before deleting + if (!empty($flink->user_id) + && !empty($flink->foreign_id) + && !empty($flink->service)) + { + $result = $flink->delete(); + } if (empty($result)) { common_log_db_error($flink, 'DELETE', __FILE__); -- cgit v1.2.3-54-g00ecf From e3c4b0c85d3fbae9604b22d3666fe36a3c1c7551 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 5 Mar 2010 03:14:40 +0000 Subject: A better way to safely delete Foreign_links --- classes/Foreign_link.php | 17 +++++++++++++++++ plugins/TwitterBridge/twitter.php | 11 +---------- plugins/TwitterBridge/twitterauthorization.php | 2 +- plugins/TwitterBridge/twittersettings.php | 11 +---------- 4 files changed, 20 insertions(+), 21 deletions(-) (limited to 'plugins') diff --git a/classes/Foreign_link.php b/classes/Foreign_link.php index ae8c22fd8..e47b2e309 100644 --- a/classes/Foreign_link.php +++ b/classes/Foreign_link.php @@ -113,4 +113,21 @@ class Foreign_link extends Memcached_DataObject return User::staticGet($this->user_id); } + // Make sure we only ever delete one record at a time + function safeDelete() + { + if (!empty($this->user_id) + && !empty($this->foreign_id) + && !empty($this->service)) + { + return $this->delete(); + } else { + common_debug(LOG_WARNING, + 'Foreign_link::safeDelete() tried to delete a ' + . 'Foreign_link without a fully specified compound key: ' + . var_export($this, true)); + return false; + } + } + } diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 90805bfc4..2805b3ab5 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -273,16 +273,7 @@ function remove_twitter_link($flink) common_log(LOG_INFO, 'Removing Twitter bridge Foreign link for ' . "user $user->nickname (user id: $user->id)."); - $result = false; - - // Be extra careful to make sure we have a good flink - // before deleting - if (!empty($flink->user_id) - && !empty($flink->foreign_id) - && !empty($flink->service)) - { - $result = $flink->delete(); - } + $result = $flink->safeDelete(); if (empty($result)) { common_log(LOG_ERR, 'Could not remove Twitter bridge ' . diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index bce679622..e20731e5c 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -278,7 +278,7 @@ class TwitterauthorizationAction extends Action $result = $flink->find(true); if (!empty($result)) { - $flink->delete(); + $flink->safeDelete(); } $flink->user_id = $user_id; diff --git a/plugins/TwitterBridge/twittersettings.php b/plugins/TwitterBridge/twittersettings.php index f22a059f7..631b29f52 100644 --- a/plugins/TwitterBridge/twittersettings.php +++ b/plugins/TwitterBridge/twittersettings.php @@ -250,16 +250,7 @@ class TwittersettingsAction extends ConnectSettingsAction $user = common_current_user(); $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); - $result = false; - - // Be extra careful to make sure we have a good flink - // before deleting - if (!empty($flink->user_id) - && !empty($flink->foreign_id) - && !empty($flink->service)) - { - $result = $flink->delete(); - } + $result = $flink->safeDelete(); if (empty($result)) { common_log_db_error($flink, 'DELETE', __FILE__); -- cgit v1.2.3-54-g00ecf From 982edc653f36c45f49165b85c3538fb62d2684e7 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 2 Mar 2010 22:09:52 -0800 Subject: Another typo --- plugins/TwitterBridge/daemons/synctwitterfriends.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php index 671e3c7af..df7da0943 100755 --- a/plugins/TwitterBridge/daemons/synctwitterfriends.php +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -221,7 +221,7 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon // Twitter friend if (!save_twitter_user($friend_id, $friend_name)) { - common_log(LOG_WARNING, $this-name() . + common_log(LOG_WARNING, $this->name() . " - Couldn't save $screen_name's friend, $friend_name."); continue; } -- cgit v1.2.3-54-g00ecf From 3f696ff0ed4be5791edd38cf7b2a98a364b95676 Mon Sep 17 00:00:00 2001 From: Jeffery To Date: Fri, 5 Mar 2010 17:54:53 +0800 Subject: ldap_get_connection() to return null when passed a config with bad user/pw. This mainly affects login; before if the user enters a valid username but invalid password, ldap_get_connection() throws an LDAP_INVALID_CREDENTIALS error. Now the user sees the regular "Incorrect username of password" error message. --- plugins/LdapAuthentication/LdapAuthenticationPlugin.php | 5 +++++ plugins/LdapAuthorization/LdapAuthorizationPlugin.php | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'plugins') diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php index e0fd615dd..483209676 100644 --- a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -224,6 +224,11 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin $ldap->setErrorHandling(PEAR_ERROR_RETURN); $err=$ldap->bind(); if (Net_LDAP2::isError($err)) { + // if we were called with a config, assume caller will handle + // incorrect username/password (LDAP_INVALID_CREDENTIALS) + if (isset($config) && $err->getCode() == 0x31) { + return null; + } throw new Exception('Could not connect to LDAP server: '.$err->getMessage()); } if($config == null) $this->default_ldap=$ldap; diff --git a/plugins/LdapAuthorization/LdapAuthorizationPlugin.php b/plugins/LdapAuthorization/LdapAuthorizationPlugin.php index 19aff42b8..2608025dd 100644 --- a/plugins/LdapAuthorization/LdapAuthorizationPlugin.php +++ b/plugins/LdapAuthorization/LdapAuthorizationPlugin.php @@ -167,6 +167,11 @@ class LdapAuthorizationPlugin extends AuthorizationPlugin $ldap->setErrorHandling(PEAR_ERROR_RETURN); $err=$ldap->bind(); if (Net_LDAP2::isError($err)) { + // if we were called with a config, assume caller will handle + // incorrect username/password (LDAP_INVALID_CREDENTIALS) + if (isset($config) && $err->getCode() == 0x31) { + return null; + } throw new Exception('Could not connect to LDAP server: '.$err->getMessage()); return false; } -- cgit v1.2.3-54-g00ecf From 51a245f18c1e4a830c5eb94f3e60c6b4b3e560ee Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Thu, 4 Mar 2010 18:24:32 -0500 Subject: Added Memcached plugin (using pecl/memcached versus pecl/memcache) --- lib/statusnet.php | 6 +- plugins/MemcachedPlugin.php | 223 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 plugins/MemcachedPlugin.php (limited to 'plugins') diff --git a/lib/statusnet.php b/lib/statusnet.php index eba9ab9b8..ef3adebf9 100644 --- a/lib/statusnet.php +++ b/lib/statusnet.php @@ -342,7 +342,11 @@ class StatusNet if (array_key_exists('memcached', $config)) { if ($config['memcached']['enabled']) { - addPlugin('Memcache', array('servers' => $config['memcached']['server'])); + if(class_exists('Memcached')) { + addPlugin('Memcached', array('servers' => $config['memcached']['server'])); + } else { + addPlugin('Memcache', array('servers' => $config['memcached']['server'])); + } } if (!empty($config['memcached']['base'])) { diff --git a/plugins/MemcachedPlugin.php b/plugins/MemcachedPlugin.php new file mode 100644 index 000000000..707e6db9a --- /dev/null +++ b/plugins/MemcachedPlugin.php @@ -0,0 +1,223 @@ +. + * + * @category Cache + * @package StatusNet + * @author Evan Prodromou , Craig Andrews + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * A plugin to use memcached for the cache interface + * + * This used to be encoded as config-variable options in the core code; + * it's now broken out to a separate plugin. The same interface can be + * implemented by other plugins. + * + * @category Cache + * @package StatusNet + * @author Evan Prodromou , Craig Andrews + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class MemcachedPlugin extends Plugin +{ + static $cacheInitialized = false; + + private $_conn = null; + public $servers = array('127.0.0.1;11211'); + + public $defaultExpiry = 86400; // 24h + + /** + * Initialize the plugin + * + * Note that onStartCacheGet() may have been called before this! + * + * @return boolean flag value + */ + + function onInitializePlugin() + { + $this->_ensureConn(); + self::$cacheInitialized = true; + return true; + } + + /** + * Get a value associated with a key + * + * The value should have been set previously. + * + * @param string &$key in; Lookup key + * @param mixed &$value out; value associated with key + * + * @return boolean hook success + */ + + function onStartCacheGet(&$key, &$value) + { + $this->_ensureConn(); + $value = $this->_conn->get($key); + Event::handle('EndCacheGet', array($key, &$value)); + return false; + } + + /** + * Associate a value with a key + * + * @param string &$key in; Key to use for lookups + * @param mixed &$value in; Value to associate + * @param integer &$flag in; Flag empty or Cache::COMPRESSED + * @param integer &$expiry in; Expiry (passed through to Memcache) + * @param boolean &$success out; Whether the set was successful + * + * @return boolean hook success + */ + + function onStartCacheSet(&$key, &$value, &$flag, &$expiry, &$success) + { + $this->_ensureConn(); + if ($expiry === null) { + $expiry = $this->defaultExpiry; + } + $success = $this->_conn->set($key, $value, $expiry); + Event::handle('EndCacheSet', array($key, $value, $flag, + $expiry)); + return false; + } + + /** + * Atomically increment an existing numeric key value. + * Existing expiration time will not be changed. + * + * @param string &$key in; Key to use for lookups + * @param int &$step in; Amount to increment (default 1) + * @param mixed &$value out; Incremented value, or false if key not set. + * + * @return boolean hook success + */ + function onStartCacheIncrement(&$key, &$step, &$value) + { + $this->_ensureConn(); + $value = $this->_conn->increment($key, $step); + Event::handle('EndCacheIncrement', array($key, $step, $value)); + return false; + } + + /** + * Delete a value associated with a key + * + * @param string &$key in; Key to lookup + * @param boolean &$success out; whether it worked + * + * @return boolean hook success + */ + + function onStartCacheDelete(&$key, &$success) + { + $this->_ensureConn(); + $success = $this->_conn->delete($key); + Event::handle('EndCacheDelete', array($key)); + return false; + } + + function onStartCacheReconnect(&$success) + { + // nothing to do + return true; + } + + /** + * Ensure that a connection exists + * + * Checks the instance $_conn variable and connects + * if it is empty. + * + * @return void + */ + + private function _ensureConn() + { + if (empty($this->_conn)) { + $this->_conn = new Memcached(common_config('site', 'nickname')); + + if (!count($this->_conn->getServerList())) { + if (is_array($this->servers)) { + $servers = $this->servers; + } else { + $servers = array($this->servers); + } + foreach ($servers as $server) { + if (strpos($server, ';') !== false) { + list($host, $port) = explode(';', $server); + } else { + $host = $server; + $port = 11211; + } + + $this->_conn->addServer($host, $port); + } + + // Compress items stored in the cache. + + // Allows the cache to store objects larger than 1MB (if they + // compress to less than 1MB), and improves cache memory efficiency. + + $this->_conn->setOption(Memcached::OPT_COMPRESSION, true); + } + } + } + + /** + * Translate general flags to Memcached-specific flags + * @param int $flag + * @return int + */ + protected function flag($flag) + { + //no flags are presently supported + return $flag; + } + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'Memcached', + 'version' => STATUSNET_VERSION, + 'author' => 'Evan Prodromou, Craig Andrews', + 'homepage' => 'http://status.net/wiki/Plugin:Memcached', + 'rawdescription' => + _m('Use Memcached to cache query results.')); + return true; + } +} + -- cgit v1.2.3-54-g00ecf From f8c5996758250dce4d0f922cdbc10dff653f73c5 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 8 Mar 2010 22:53:43 +0000 Subject: Only allow RSSCloud subs to canonical RSS2 profile feeds --- plugins/RSSCloud/RSSCloudRequestNotify.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/RSSCloud/RSSCloudRequestNotify.php b/plugins/RSSCloud/RSSCloudRequestNotify.php index d76c08d37..030529534 100644 --- a/plugins/RSSCloud/RSSCloudRequestNotify.php +++ b/plugins/RSSCloud/RSSCloudRequestNotify.php @@ -270,13 +270,14 @@ class RSSCloudRequestNotifyAction extends Action function userFromFeed($feed) { - // We only do profile feeds + // We only do canonical RSS2 profile feeds (specified by ID), e.g.: + // http://www.example.com/api/statuses/user_timeline/2.rss $path = common_path('api/statuses/user_timeline/'); - $valid = '%^' . $path . '(?.*)\.rss$%'; + $valid = '%^' . $path . '(?.*)\.rss$%'; if (preg_match($valid, $feed, $matches)) { - $user = User::staticGet('nickname', $matches['nickname']); + $user = User::staticGet('id', $matches['id']); if (!empty($user)) { return $user; } -- cgit v1.2.3-54-g00ecf From 9466546705b6849bcc22ab0073bd9e6bfad8f2c8 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Mon, 8 Mar 2010 21:43:09 -0500 Subject: On the OpenID settings page, allow users to remove trustroots. --- plugins/OpenID/openidsettings.php | 70 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'plugins') diff --git a/plugins/OpenID/openidsettings.php b/plugins/OpenID/openidsettings.php index 3fc3d6128..16142cf48 100644 --- a/plugins/OpenID/openidsettings.php +++ b/plugins/OpenID/openidsettings.php @@ -176,6 +176,43 @@ class OpenidsettingsAction extends AccountSettingsAction } } } + + $this->elementStart('form', array('method' => 'post', + 'id' => 'form_settings_openid_trustroots', + 'class' => 'form_settings', + 'action' => + common_local_url('openidsettings'))); + $this->elementStart('fieldset', array('id' => 'settings_openid_trustroots')); + $this->element('legend', null, _m('OpenID Trusted Sites')); + $this->hidden('token', common_session_token()); + $this->element('p', 'form_guide', + _m('The following sites are allowed to access your ' . + 'identity and log you in. You can remove a site from ' . + 'this list to deny it access to your OpenID.')); + $this->elementStart('ul', 'form_data'); + $user_openid_trustroot = new User_openid_trustroot(); + $user_openid_trustroot->user_id=$user->id; + if($user_openid_trustroot->find()) { + while($user_openid_trustroot->fetch()) { + $this->elementStart('li'); + $this->element('input', array('name' => 'openid_trustroot[]', + 'type' => 'checkbox', + 'class' => 'checkbox', + 'value' => $user_openid_trustroot->trustroot, + 'id' => 'openid_trustroot_' . crc32($user_openid_trustroot->trustroot))); + $this->element('label', array('class'=>'checkbox', 'for' => 'openid_trustroot_' . crc32($user_openid_trustroot->trustroot)), + $user_openid_trustroot->trustroot); + $this->elementEnd('li'); + } + } + $this->elementEnd('ul'); + $this->element('input', array('type' => 'submit', + 'id' => 'settings_openid_trustroots_action-submit', + 'name' => 'remove_trustroots', + 'class' => 'submit', + 'value' => _m('Remove'))); + $this->elementEnd('fieldset'); + $this->elementEnd('form'); } /** @@ -204,11 +241,44 @@ class OpenidsettingsAction extends AccountSettingsAction } } else if ($this->arg('remove')) { $this->removeOpenid(); + } else if($this->arg('remove_trustroots')) { + $this->removeTrustroots(); } else { $this->showForm(_m('Something weird happened.')); } } + /** + * Handles a request to remove OpenID trustroots from the user's account + * + * Validates input and, if everything is OK, deletes the trustroots. + * Reloads the form with a success or error notification. + * + * @return void + */ + + function removeTrustroots() + { + $user = common_current_user(); + $trustroots = $this->arg('openid_trustroot'); + if($trustroots) { + foreach($trustroots as $trustroot) { + $user_openid_trustroot = User_openid_trustroot::pkeyGet( + array('user_id'=>$user->id, 'trustroot'=>$trustroot)); + if($user_openid_trustroot) { + $user_openid_trustroot->delete(); + } else { + $this->showForm(_m('No such OpenID trustroot.')); + return; + } + } + $this->showForm(_m('Trustroots removed'), true); + } else { + $this->showForm(); + } + return; + } + /** * Handles a request to remove an OpenID from the user's account * -- cgit v1.2.3-54-g00ecf From 311da86762d1cc3baabeca65a5123d15ecbc3a96 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 9 Mar 2010 11:06:08 +0000 Subject: Use canonical URL for notification in RSSCloud plugin --- plugins/RSSCloud/RSSCloudNotifier.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/RSSCloud/RSSCloudNotifier.php b/plugins/RSSCloud/RSSCloudNotifier.php index d454691c8..9e7b53680 100644 --- a/plugins/RSSCloud/RSSCloudNotifier.php +++ b/plugins/RSSCloud/RSSCloudNotifier.php @@ -152,7 +152,7 @@ class RSSCloudNotifier function notify($profile) { $feed = common_path('api/statuses/user_timeline/') . - $profile->nickname . '.rss'; + $profile->id . '.rss'; $cloudSub = new RSSCloudSubscription(); -- cgit v1.2.3-54-g00ecf From 9653cb9f0a590417245063f905a2089f03b9e7b2 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Tue, 9 Mar 2010 21:26:12 -0500 Subject: Fix error logging --- plugins/LdapAuthorization/LdapAuthorizationPlugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/LdapAuthorization/LdapAuthorizationPlugin.php b/plugins/LdapAuthorization/LdapAuthorizationPlugin.php index 2608025dd..042b2db8d 100644 --- a/plugins/LdapAuthorization/LdapAuthorizationPlugin.php +++ b/plugins/LdapAuthorization/LdapAuthorizationPlugin.php @@ -131,13 +131,13 @@ class LdapAuthorizationPlugin extends AuthorizationPlugin { $ldap = $this->ldap_get_connection(); $link = $ldap->getLink(); - $r = ldap_compare($link, $groupDn, $this->uniqueMember_attribute, $userDn); + $r = @ldap_compare($link, $groupDn, $this->uniqueMember_attribute, $userDn); if ($r === true){ return true; }else if($r === false){ return false; }else{ - common_log(LOG_ERR, ldap_error($r)); + common_log(LOG_ERR, "LDAP error determining if userDn=$userDn is a member of groupDn=groupDn using uniqueMember_attribute=$this->uniqueMember_attribute error: ".ldap_error($link)); return false; } } -- cgit v1.2.3-54-g00ecf From 66518df4356ea878bfd8693191f0354caebfb549 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 10 Mar 2010 17:00:05 -0800 Subject: OStatus: reject attempts to create a remote profile for a local user or group. Some stray shadow entries were ending up getting created, which would steal group posts from remote users. Run plugins/OStatus/scripts/fixup-shadow.php for each site to remove any existing ones. --- plugins/OStatus/OStatusPlugin.php | 37 ++++++++++++++++ plugins/OStatus/classes/Ostatus_profile.php | 19 +++++--- plugins/OStatus/scripts/fixup-shadow.php | 69 +++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 plugins/OStatus/scripts/fixup-shadow.php (limited to 'plugins') diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index a97f3475b..ef28ab22e 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -929,4 +929,41 @@ class OStatusPlugin extends Plugin return true; } + + /** + * Utility function to check if the given URL is a canonical group profile + * page, and if so return the ID number. + * + * @param string $url + * @return mixed int or false + */ + public static function localGroupFromUrl($url) + { + $template = common_local_url('groupbyid', array('id' => '31337')); + $template = preg_quote($template, '/'); + $template = str_replace('31337', '(\d+)', $template); + if (preg_match("/$template/", $url, $matches)) { + return intval($matches[1]); + } + return false; + } + + /** + * Utility function to check if the given URL is a canonical user profile + * page, and if so return the ID number. + * + * @param string $url + * @return mixed int or false + */ + public static function localProfileFromUrl($url) + { + $template = common_local_url('userbyid', array('id' => '31337')); + $template = preg_quote($template, '/'); + $template = str_replace('31337', '(\d+)', $template); + if (preg_match("/$template/", $url, $matches)) { + return intval($matches[1]); + } + return false; + } + } diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index abc8100ce..6ae8e4fd5 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -675,13 +675,10 @@ class Ostatus_profile extends Memcached_DataObject } // Is the recipient a local group? - // @fixme we need a uri on user_group + // @fixme uri on user_group isn't reliable yet // $group = User_group::staticGet('uri', $recipient); - $template = common_local_url('groupbyid', array('id' => '31337')); - $template = preg_quote($template, '/'); - $template = str_replace('31337', '(\d+)', $template); - if (preg_match("/$template/", $recipient, $matches)) { - $id = $matches[1]; + $id = OStatusPlugin::localGroupFromUrl($recipient); + if ($id) { $group = User_group::staticGet('id', $id); if ($group) { // Deliver to all members of this local group if allowed. @@ -992,7 +989,15 @@ class Ostatus_profile extends Memcached_DataObject if (!$homeuri) { common_log(LOG_DEBUG, __METHOD__ . " empty actor profile URI: " . var_export($activity, true)); - throw new ServerException("No profile URI"); + throw new Exception("No profile URI"); + } + + if (OStatusPlugin::localProfileFromUrl($homeuri)) { + throw new Exception("Local user can't be referenced as remote."); + } + + if (OStatusPlugin::localGroupFromUrl($homeuri)) { + throw new Exception("Local group can't be referenced as remote."); } if (array_key_exists('feedurl', $hints)) { diff --git a/plugins/OStatus/scripts/fixup-shadow.php b/plugins/OStatus/scripts/fixup-shadow.php new file mode 100644 index 000000000..0171b77bc --- /dev/null +++ b/plugins/OStatus/scripts/fixup-shadow.php @@ -0,0 +1,69 @@ +#!/usr/bin/env php +. + */ + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); + +$longoptions = array('dry-run'); + +$helptext = << $marker)); +$encProfile = $oprofile->escape($profileTemplate, true); +$encProfile = str_replace($marker, '%', $encProfile); + +$groupTemplate = common_local_url('groupbyid', array('id' => $marker)); +$encGroup = $oprofile->escape($groupTemplate, true); +$encGroup = str_replace($marker, '%', $encGroup); + +$sql = "SELECT * FROM ostatus_profile WHERE uri LIKE '%s' OR uri LIKE '%s'"; +$oprofile->query(sprintf($sql, $encProfile, $encGroup)); + +echo "Found $oprofile->N bogus ostatus_profile entries:\n"; + +while ($oprofile->fetch()) { + echo "$oprofile->uri"; + + if ($dry) { + echo " (unchanged)\n"; + } else { + echo " deleting..."; + $evil = clone($oprofile); + $evil->delete(); + echo " ok\n"; + } +} + +echo "done.\n"; + -- cgit v1.2.3-54-g00ecf From 89582e72262bdba65e6b07699536555d5fa6a497 Mon Sep 17 00:00:00 2001 From: James Walker Date: Tue, 9 Mar 2010 18:12:37 -0500 Subject: base64_encode/decode -> base64_url_encode/decode --- plugins/OStatus/lib/magicenvelope.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/OStatus/lib/magicenvelope.php b/plugins/OStatus/lib/magicenvelope.php index fb8c57c71..e8835165c 100644 --- a/plugins/OStatus/lib/magicenvelope.php +++ b/plugins/OStatus/lib/magicenvelope.php @@ -70,7 +70,7 @@ class MagicEnvelope public function signMessage($text, $mimetype, $keypair) { $signature_alg = Magicsig::fromString($keypair); - $armored_text = base64_encode($text); + $armored_text = base64_url_encode($text); return array( 'data' => $armored_text, @@ -108,7 +108,7 @@ class MagicEnvelope public function unfold($env) { $dom = new DOMDocument(); - $dom->loadXML(base64_decode($env['data'])); + $dom->loadXML(base64_url_decode($env['data'])); if ($dom->documentElement->tagName != 'entry') { return false; @@ -165,7 +165,7 @@ class MagicEnvelope return false; } - $text = base64_decode($env['data']); + $text = base64_url_decode($env['data']); $signer_uri = $this->getAuthor($text); try { -- cgit v1.2.3-54-g00ecf From 06612e35e433109e00167ac62d65299210ef0032 Mon Sep 17 00:00:00 2001 From: James Walker Date: Tue, 9 Mar 2010 18:47:20 -0500 Subject: remove hard-coded me:env check in magicenvelope --- plugins/OStatus/lib/magicenvelope.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/OStatus/lib/magicenvelope.php b/plugins/OStatus/lib/magicenvelope.php index e8835165c..c927209e4 100644 --- a/plugins/OStatus/lib/magicenvelope.php +++ b/plugins/OStatus/lib/magicenvelope.php @@ -193,11 +193,12 @@ class MagicEnvelope public function fromDom($dom) { - if ($dom->documentElement->tagName == 'entry') { + $env_element = $dom->getElementsByTagNameNS(MagicEnvelope::NS, 'env')->item(0); + if (!$env_element) { $env_element = $dom->getElementsByTagNameNS(MagicEnvelope::NS, 'provenance')->item(0); - } else if ($dom->documentElement->tagName == 'me:env') { - $env_element = $dom->documentElement; - } else { + } + + if (!$env_element) { return false; } -- cgit v1.2.3-54-g00ecf From 512e51105372daf9c85af9284de1463084f03aa9 Mon Sep 17 00:00:00 2001 From: James Walker Date: Thu, 11 Mar 2010 14:32:22 -0500 Subject: fix invalid separator in magic-public-key XRD and matching parsing. --- plugins/OStatus/lib/magicenvelope.php | 6 +++++- plugins/OStatus/lib/xrdaction.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/OStatus/lib/magicenvelope.php b/plugins/OStatus/lib/magicenvelope.php index c927209e4..9266cab5c 100644 --- a/plugins/OStatus/lib/magicenvelope.php +++ b/plugins/OStatus/lib/magicenvelope.php @@ -59,7 +59,11 @@ class MagicEnvelope } if ($xrd->links) { if ($link = Discovery::getService($xrd->links, Magicsig::PUBLICKEYREL)) { - list($type, $keypair) = explode(';', $link['href']); + list($type, $keypair) = explode(',', $link['href']); + if (empty($keypair)) { + // Backwards compatibility check for separator bug in 0.9.0 + list($type, $keypair) = explode(';', $link['href']); + } return $keypair; } } diff --git a/plugins/OStatus/lib/xrdaction.php b/plugins/OStatus/lib/xrdaction.php index 6881292ad..b3c1d8453 100644 --- a/plugins/OStatus/lib/xrdaction.php +++ b/plugins/OStatus/lib/xrdaction.php @@ -91,7 +91,7 @@ class XrdAction extends Action } $xrd->links[] = array('rel' => Magicsig::PUBLICKEYREL, - 'href' => 'data:application/magic-public-key;'. $magickey->toString(false)); + 'href' => 'data:application/magic-public-key,'. $magickey->toString(false)); // TODO - finalize where the redirect should go on the publisher $url = common_local_url('ostatussub') . '?profile={uri}'; -- cgit v1.2.3-54-g00ecf From ea7c1bab2e9b17ab6101f4143fcee02d93357930 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 12 Mar 2010 11:13:05 -0500 Subject: Plugin to open up rel="external" links on a new window or tab --- .../OpenExternalLinkTargetPlugin.php | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 plugins/OpenExternalLinkTarget/OpenExternalLinkTargetPlugin.php (limited to 'plugins') diff --git a/plugins/OpenExternalLinkTarget/OpenExternalLinkTargetPlugin.php b/plugins/OpenExternalLinkTarget/OpenExternalLinkTargetPlugin.php new file mode 100644 index 000000000..ebb0189e0 --- /dev/null +++ b/plugins/OpenExternalLinkTarget/OpenExternalLinkTargetPlugin.php @@ -0,0 +1,64 @@ +. + * + * @category Action + * @package StatusNet + * @author Sarven Capadisli + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * Opens links with rel=external on a new window or tab + * + * @category Plugin + * @package StatusNet + * @author Sarven Capadisli + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class OpenExternalLinkTargetPlugin extends Plugin +{ + function onEndShowScripts($action) + { + $action->inlineScript('$("a[rel~=external]").click(function(){ window.open(this.href); return false; });'); + + return true; + } + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'OpenExternalLinkTarget', + 'version' => STATUSNET_VERSION, + 'author' => 'Sarven Capadisli', + 'homepage' => 'http://status.net/wiki/Plugin:OpenExternalLinkTarget', + 'rawdescription' => + _m('Opens external links (i.e., with rel=external) on a new window or tab')); + return true; + } +} + -- cgit v1.2.3-54-g00ecf From 4d7479dcbc3d0f658de230c139242e7176d0ba16 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 12 Mar 2010 10:07:32 -0800 Subject: OpenID fixes: - avoid notice spew when checking sreg items that weren't provided - fix keys spec for user_openid, clears up problems with removing openid associations - fix keys spec for user_openid_trustroot --- plugins/OpenID/User_openid.php | 5 +++++ plugins/OpenID/User_openid_trustroot.php | 5 +++++ plugins/OpenID/openid.php | 6 +++--- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/OpenID/User_openid.php b/plugins/OpenID/User_openid.php index 5ef05b4c7..1beff9ea3 100644 --- a/plugins/OpenID/User_openid.php +++ b/plugins/OpenID/User_openid.php @@ -44,6 +44,11 @@ class User_openid extends Memcached_DataObject * Unique keys used for lookup *MUST* be listed to ensure proper caching. */ function keys() + { + return array_keys($this->keyTypes()); + } + + function keyTypes() { return array('canonical' => 'K', 'display' => 'U', 'user_id' => 'U'); } diff --git a/plugins/OpenID/User_openid_trustroot.php b/plugins/OpenID/User_openid_trustroot.php index 0b411b8f7..17c03afb0 100644 --- a/plugins/OpenID/User_openid_trustroot.php +++ b/plugins/OpenID/User_openid_trustroot.php @@ -42,6 +42,11 @@ class User_openid_trustroot extends Memcached_DataObject } function keys() + { + return array_keys($this->keyTypes()); + } + + function keyTypes() { return array('trustroot' => 'K', 'user_id' => 'K'); } diff --git a/plugins/OpenID/openid.php b/plugins/OpenID/openid.php index 8f949c9c5..9e02c7a88 100644 --- a/plugins/OpenID/openid.php +++ b/plugins/OpenID/openid.php @@ -225,11 +225,11 @@ function oid_update_user(&$user, &$sreg) $orig_profile = clone($profile); - if ($sreg['fullname'] && strlen($sreg['fullname']) <= 255) { + if (!empty($sreg['fullname']) && strlen($sreg['fullname']) <= 255) { $profile->fullname = $sreg['fullname']; } - if ($sreg['country']) { + if (!empty($sreg['country'])) { if ($sreg['postcode']) { # XXX: use postcode to get city and region # XXX: also, store postcode somewhere -- it's valuable! @@ -249,7 +249,7 @@ function oid_update_user(&$user, &$sreg) $orig_user = clone($user); - if ($sreg['email'] && Validate::email($sreg['email'], common_config('email', 'check_domain'))) { + if (!empty($sreg['email']) && Validate::email($sreg['email'], common_config('email', 'check_domain'))) { $user->email = $sreg['email']; } -- cgit v1.2.3-54-g00ecf From 9e9ab23e1f936eb62014d8f7b0051f0314ae482c Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 12 Mar 2010 11:19:56 -0800 Subject: Fixes for updating indices, charset/collation and engine type on plugin-created tables. Under MySQL, new tables will be created as InnoDB with UTF-8 (utf8/utf8_bin) same as core tables. Existing plugin tables will have table engine and default charset/collation updated, and string columns will have charset updated, at checkschema time. Switched from 'DESCRIBE' to INFORMATION_SCHEMA for pulling column information in order to get charset. A second hit to INFORMATION_SCHEMA is also needed to get table properties. Indices were only being created at table creation time, which ain't so hot. Now also adding/dropping indices when they change. Fixed up some schema defs in OStatus plugin that were a bit flaky, causing extra alter tables to be run. TODO: Generalize this infrastructure a bit more up to base schema & pg schema classes. --- lib/mysqlschema.php | 236 +++++++++++++++++++++++++++++------ lib/schema.php | 6 + plugins/OStatus/classes/FeedSub.php | 3 +- plugins/OStatus/classes/HubSub.php | 2 +- plugins/OStatus/classes/Magicsig.php | 4 +- 5 files changed, 209 insertions(+), 42 deletions(-) (limited to 'plugins') diff --git a/lib/mysqlschema.php b/lib/mysqlschema.php index 485096ac4..455695366 100644 --- a/lib/mysqlschema.php +++ b/lib/mysqlschema.php @@ -90,15 +90,24 @@ class MysqlSchema extends Schema * @param string $name Name of the table to get * * @return TableDef tabledef for that table. + * @throws SchemaTableMissingException */ public function getTableDef($name) { - $res = $this->conn->query('DESCRIBE ' . $name); + $query = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS " . + "WHERE TABLE_SCHEMA='%s' AND TABLE_NAME='%s'"; + $schema = $this->conn->dsn['database']; + $sql = sprintf($query, $schema, $name); + $res = $this->conn->query($sql); if (PEAR::isError($res)) { throw new Exception($res->getMessage()); } + if ($res->numRows() == 0) { + $res->free(); + throw new SchemaTableMissingException("No such table: $name"); + } $td = new TableDef(); @@ -111,9 +120,9 @@ class MysqlSchema extends Schema $cd = new ColumnDef(); - $cd->name = $row['Field']; + $cd->name = $row['COLUMN_NAME']; - $packed = $row['Type']; + $packed = $row['COLUMN_TYPE']; if (preg_match('/^(\w+)\((\d+)\)$/', $packed, $match)) { $cd->type = $match[1]; @@ -122,17 +131,57 @@ class MysqlSchema extends Schema $cd->type = $packed; } - $cd->nullable = ($row['Null'] == 'YES') ? true : false; - $cd->key = $row['Key']; - $cd->default = $row['Default']; - $cd->extra = $row['Extra']; + $cd->nullable = ($row['IS_NULLABLE'] == 'YES') ? true : false; + $cd->key = $row['COLUMN_KEY']; + $cd->default = $row['COLUMN_DEFAULT']; + $cd->extra = $row['EXTRA']; + + // Autoincrement is stuck into the extra column. + // Pull it out so we don't accidentally mod it every time... + $extra = preg_replace('/(^|\s)auto_increment(\s|$)/i', '$1$2', $cd->extra); + if ($extra != $cd->extra) { + $cd->extra = trim($extra); + $cd->auto_increment = true; + } + + // mysql extensions -- not (yet) used by base class + $cd->charset = $row['CHARACTER_SET_NAME']; + $cd->collate = $row['COLLATION_NAME']; $td->columns[] = $cd; } + $res->free(); return $td; } + /** + * Pull the given table properties from INFORMATION_SCHEMA. + * Most of the good stuff is MySQL extensions. + * + * @return array + * @throws Exception if table info can't be looked up + */ + + function getTableProperties($table, $props) + { + $query = "SELECT %s FROM INFORMATION_SCHEMA.TABLES " . + "WHERE TABLE_SCHEMA='%s' AND TABLE_NAME='%s'"; + $schema = $this->conn->dsn['database']; + $sql = sprintf($query, implode(',', $props), $schema, $table); + $res = $this->conn->query($sql); + + $row = array(); + $ok = $res->fetchInto($row, DB_FETCHMODE_ASSOC); + $res->free(); + + if ($ok) { + return $row; + } else { + throw new SchemaTableMissingException("No such table: $table"); + } + } + /** * Gets a ColumnDef object for a single column. * @@ -185,35 +234,26 @@ class MysqlSchema extends Schema } $sql .= $this->_columnSql($cd); - - switch ($cd->key) { - case 'UNI': - $uniques[] = $cd->name; - break; - case 'PRI': - $primary[] = $cd->name; - break; - case 'MUL': - $indices[] = $cd->name; - break; - } } - if (count($primary) > 0) { // it really should be... - $sql .= ",\nconstraint primary key (" . implode(',', $primary) . ")"; + $idx = $this->_indexList($columns); + + if ($idx['primary']) { + $sql .= ",\nconstraint primary key (" . implode(',', $idx['primary']) . ")"; } - foreach ($uniques as $u) { - $sql .= ",\nunique index {$name}_{$u}_idx ($u)"; + foreach ($idx['uniques'] as $u) { + $key = $this->_uniqueKey($name, $u); + $sql .= ",\nunique index $key ($u)"; } - foreach ($indices as $i) { - $sql .= ",\nindex {$name}_{$i}_idx ($i)"; + foreach ($idx['indices'] as $i) { + $key = $this->_key($name, $i); + $sql .= ",\nindex $key ($i)"; } - $sql .= "); "; + $sql .= ") ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; "; - common_log(LOG_INFO, $sql); $res = $this->conn->query($sql); if (PEAR::isError($res)) { @@ -223,6 +263,47 @@ class MysqlSchema extends Schema return true; } + /** + * Look over a list of column definitions and list up which + * indices will be present + */ + private function _indexList(array $columns) + { + $list = array('uniques' => array(), + 'primary' => array(), + 'indices' => array()); + foreach ($columns as $cd) { + switch ($cd->key) { + case 'UNI': + $list['uniques'][] = $cd->name; + break; + case 'PRI': + $list['primary'][] = $cd->name; + break; + case 'MUL': + $list['indices'][] = $cd->name; + break; + } + } + return $list; + } + + /** + * Get the unique index key name for a given column on this table + */ + function _uniqueKey($tableName, $columnName) + { + return $this->_key($tableName, $columnName); + } + + /** + * Get the index key name for a given column on this table + */ + function _key($tableName, $columnName) + { + return "{$tableName}_{$columnName}_idx"; + } + /** * Drops a table from the schema * @@ -394,21 +475,20 @@ class MysqlSchema extends Schema try { $td = $this->getTableDef($tableName); - } catch (Exception $e) { - if (preg_match('/no such table/', $e->getMessage())) { - return $this->createTable($tableName, $columns); - } else { - throw $e; - } + } catch (SchemaTableMissingException $e) { + return $this->createTable($tableName, $columns); } $cur = $this->_names($td->columns); $new = $this->_names($columns); - $toadd = array_diff($new, $cur); - $todrop = array_diff($cur, $new); - $same = array_intersect($new, $cur); - $tomod = array(); + $dropIndex = array(); + $toadd = array_diff($new, $cur); + $todrop = array_diff($cur, $new); + $same = array_intersect($new, $cur); + $tomod = array(); + $addIndex = array(); + $tableProps = array(); foreach ($same as $m) { $curCol = $this->_byName($td->columns, $m); @@ -416,10 +496,64 @@ class MysqlSchema extends Schema if (!$newCol->equals($curCol)) { $tomod[] = $newCol->name; + continue; + } + + // Earlier versions may have accidentally left tables at default + // charsets which might be latin1 or other freakish things. + if ($this->_isString($curCol)) { + if ($curCol->charset != 'utf8') { + $tomod[] = $newCol->name; + continue; + } + } + } + + // Find any indices we have to change... + $curIdx = $this->_indexList($td->columns); + $newIdx = $this->_indexList($columns); + + if ($curIdx['primary'] != $newIdx['primary']) { + if ($curIdx['primary']) { + $dropIndex[] = 'drop primary key'; + } + if ($newIdx['primary']) { + $keys = implode(',', $newIdx['primary']); + $addIndex[] = "add constraint primary key ($keys)"; } } - if (count($toadd) + count($todrop) + count($tomod) == 0) { + $dropUnique = array_diff($curIdx['uniques'], $newIdx['uniques']); + $addUnique = array_diff($newIdx['uniques'], $curIdx['uniques']); + foreach ($dropUnique as $columnName) { + $dropIndex[] = 'drop key ' . $this->_uniqueKey($tableName, $columnName); + } + foreach ($addUnique as $columnName) { + $addIndex[] = 'add constraint unique key ' . $this->_uniqueKey($tableName, $columnName) . " ($columnName)";; + } + + $dropMultiple = array_diff($curIdx['indices'], $newIdx['indices']); + $addMultiple = array_diff($newIdx['indices'], $curIdx['indices']); + foreach ($dropMultiple as $columnName) { + $dropIndex[] = 'drop key ' . $this->_key($tableName, $columnName); + } + foreach ($addMultiple as $columnName) { + $addIndex[] = 'add key ' . $this->_key($tableName, $columnName) . " ($columnName)"; + } + + // Check for table properties: make sure we're using a sane + // engine type and charset/collation. + // @fixme make the default engine configurable? + $oldProps = $this->getTableProperties($tableName, array('ENGINE', 'TABLE_COLLATION')); + if (strtolower($oldProps['ENGINE']) != 'innodb') { + $tableProps['ENGINE'] = 'InnoDB'; + } + if (strtolower($oldProps['TABLE_COLLATION']) != 'utf8_bin') { + $tableProps['DEFAULT CHARSET'] = 'utf8'; + $tableProps['COLLATE'] = 'utf8_bin'; + } + + if (count($dropIndex) + count($toadd) + count($todrop) + count($tomod) + count($addIndex) + count($tableProps) == 0) { // nothing to do return true; } @@ -429,6 +563,10 @@ class MysqlSchema extends Schema $phrase = array(); + foreach ($dropIndex as $indexSql) { + $phrase[] = $indexSql; + } + foreach ($toadd as $columnName) { $cd = $this->_byName($columns, $columnName); @@ -445,8 +583,17 @@ class MysqlSchema extends Schema $phrase[] = 'MODIFY COLUMN ' . $this->_columnSql($cd); } + foreach ($addIndex as $indexSql) { + $phrase[] = $indexSql; + } + + foreach ($tableProps as $key => $val) { + $phrase[] = "$key=$val"; + } + $sql = 'ALTER TABLE ' . $tableName . ' ' . implode(', ', $phrase); + common_log(LOG_DEBUG, __METHOD__ . ': ' . $sql); $res = $this->conn->query($sql); if (PEAR::isError($res)) { @@ -519,6 +666,10 @@ class MysqlSchema extends Schema $sql .= "{$cd->type} "; } + if ($this->_isString($cd)) { + $sql .= " CHARACTER SET utf8 "; + } + if (!empty($cd->default)) { $sql .= "default {$cd->default} "; } else { @@ -535,4 +686,13 @@ class MysqlSchema extends Schema return $sql; } + + /** + * Is this column a string type? + */ + private function _isString(ColumnDef $cd) + { + $strings = array('char', 'varchar', 'text'); + return in_array(strtolower($cd->type), $strings); + } } diff --git a/lib/schema.php b/lib/schema.php index 137b814e0..1503c96d4 100644 --- a/lib/schema.php +++ b/lib/schema.php @@ -485,3 +485,9 @@ class Schema return $sql; } } + +class SchemaTableMissingException extends Exception +{ + // no-op +} + diff --git a/plugins/OStatus/classes/FeedSub.php b/plugins/OStatus/classes/FeedSub.php index b848b6b1d..80ba37bc1 100644 --- a/plugins/OStatus/classes/FeedSub.php +++ b/plugins/OStatus/classes/FeedSub.php @@ -110,7 +110,7 @@ class FeedSub extends Memcached_DataObject /*size*/ null, /*nullable*/ false, /*key*/ 'PRI', - /*default*/ '0', + /*default*/ null, /*extra*/ null, /*auto_increment*/ true), new ColumnDef('uri', 'varchar', @@ -450,3 +450,4 @@ class FeedSub extends Memcached_DataObject } } + diff --git a/plugins/OStatus/classes/HubSub.php b/plugins/OStatus/classes/HubSub.php index c420b3eef..cdace3c1f 100644 --- a/plugins/OStatus/classes/HubSub.php +++ b/plugins/OStatus/classes/HubSub.php @@ -77,7 +77,7 @@ class HubSub extends Memcached_DataObject new ColumnDef('topic', 'varchar', /*size*/255, /*nullable*/false, - /*key*/'KEY'), + /*key*/'MUL'), new ColumnDef('callback', 'varchar', 255, false), new ColumnDef('secret', 'text', diff --git a/plugins/OStatus/classes/Magicsig.php b/plugins/OStatus/classes/Magicsig.php index 5a46aeeb6..b0a411e5d 100644 --- a/plugins/OStatus/classes/Magicsig.php +++ b/plugins/OStatus/classes/Magicsig.php @@ -70,7 +70,7 @@ class Magicsig extends Memcached_DataObject static function schemaDef() { return array(new ColumnDef('user_id', 'integer', - null, true, 'PRI'), + null, false, 'PRI'), new ColumnDef('keypair', 'varchar', 255, false), new ColumnDef('alg', 'varchar', @@ -230,4 +230,4 @@ function base64_url_encode($input) function base64_url_decode($input) { return base64_decode(strtr($input, '-_', '+/')); -} \ No newline at end of file +} -- cgit v1.2.3-54-g00ecf