From: Brion Vibber Date: Tue, 7 Dec 2010 18:50:05 +0000 (-0800) Subject: Merge branch '0.9.x' into merge X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=9df856e667a12cd217576263efbc72fff12692d9;p=quix0rs-gnu-social.git Merge branch '0.9.x' into merge Conflicts: README actions/hostmeta.php classes/File_redirection.php lib/common.php lib/designsettings.php lib/router.php lib/util.php lib/xmppmanager.php plugins/OStatus/OStatusPlugin.php --- 9df856e667a12cd217576263efbc72fff12692d9 diff --cc README index 7531d3f248,3bebb11ee0..3d23e2393b --- a/README +++ b/README @@@ -1538,22 -1538,18 +1536,35 @@@ external: external links in notices. On nofollowed on profile, notice, and favorites page. Default is 'sometimes'. +url +--- + +Everybody loves URL shorteners. These are some options for fine-tuning +how and when the server shortens URLs. + +shortener: URL shortening service to use by default. Users can override + individually. 'ur1.ca' by default. +maxlength: If an URL is strictly longer than this limit, it will be + shortened. Note that the URL shortener service may return an + URL longer than this limit. Defaults to 25. Users can + override. If set to 0, all URLs will be shortened. +maxnoticelength: If a notice is strictly longer than this limit, all + URLs in the notice will be shortened. Users can override. + -1 means the text limit for notices. + + router + ------ + + We use a router class for mapping URLs to code. This section controls + how that router works. + + cache: whether to cache the router in memcache (or another caching + mechanism). Defaults to true, but may be set to false for + developers (who might be actively adding pages, so won't want the + router cached) or others who see strange behavior. You're unlikely + to need this unless you're a developer. + ++ Plugins ======= diff --cc actions/hostmeta.php index b7beee5a86,2587bb6b91..331fc8a999 --- a/actions/hostmeta.php +++ b/actions/hostmeta.php @@@ -51,6 -51,11 +51,11 @@@ class HostMetaAction extends Actio $xrd->host = $domain; if(Event::handle('StartHostMetaLinks', array(&$xrd->links))) { - $url = common_local_url('userxrd'); - $url.= '?uri={uri}'; - $xrd->links[] = array('rel' => Discovery::LRDD_REL, - 'template' => $url, - 'title' => array('Resource Descriptor')); ++ $url = common_local_url('userxrd'); ++ $url.= '?uri={uri}'; ++ $xrd->links[] = array('rel' => Discovery::LRDD_REL, ++ 'template' => $url, ++ 'title' => array('Resource Descriptor')); Event::handle('EndHostMetaLinks', array(&$xrd->links)); } diff --cc classes/File_redirection.php index 92f0125a40,53c15bf8b2..1096f500bf --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@@ -174,54 -187,25 +187,54 @@@ class File_redirection extends Memcache * may be saved. * * @param string $long_url + * @param User $user whose shortening options to use; defaults to the current web session user * @return string */ - function makeShort($long_url, $user=null) { -- - function makeShort($long_url) ++ function makeShort($long_url, $user=null) + { $canon = File_redirection::_canonUrl($long_url); - $short_url = File_redirection::_userMakeShort($canon); + $short_url = File_redirection::_userMakeShort($canon, $user); // Did we get one? Is it shorter? - if (!empty($short_url) && mb_strlen($short_url) < mb_strlen($long_url)) { + + if (!empty($short_url)) { + return $short_url; + } else { + return $long_url; + } + } + + /** + * Shorten a URL with the current user's configured shortening + * options, if applicable. + * + * If it cannot be shortened or the "short" URL is longer than the + * original, the original is returned. + * + * If the referenced item has not been seen before, embedding data + * may be saved. + * + * @param string $long_url + * @return string + */ + - function forceShort($long_url) ++ function forceShort($long_url, $user) + { + $canon = File_redirection::_canonUrl($long_url); + - $short_url = File_redirection::_userMakeShort($canon, true); ++ $short_url = File_redirection::_userMakeShort($canon, $user, true); + + // Did we get one? Is it shorter? + if (!empty($short_url)) { return $short_url; } else { return $long_url; } } - function _userMakeShort($long_url, $force = false) { - $short_url = common_shorten_url($long_url, $force); - function _userMakeShort($long_url, User $user=null) { - $short_url = common_shorten_url($long_url, $user); ++ function _userMakeShort($long_url, User $user=null, $force = false) { ++ $short_url = common_shorten_url($long_url, $user, $force); if (!empty($short_url) && $short_url != $long_url) { $short_url = (string)$short_url; // store it diff --cc classes/Profile.php index b56e508c6a,8dbdcbd973..05df8899e9 --- a/classes/Profile.php +++ b/classes/Profile.php @@@ -494,9 -502,32 +502,32 @@@ class Profile extends Memcached_DataObj return $cnt; } + /** + * Is this profile subscribed to another profile? + * + * @param Profile $other + * @return boolean + */ + function isSubscribed($other) + { + return Subscription::exists($this, $other); + } + + /** + * Are these two profiles subscribed to each other? + * + * @param Profile $other + * @return boolean + */ + function mutuallySubscribed($other) + { + return $this->isSubscribed($other) && + $other->isSubscribed($this); + } + function hasFave($notice) { - $cache = common_memcache(); + $cache = Cache::instance(); // XXX: Kind of a hack. diff --cc lib/designform.php index 4163cfc1a6,0000000000..7702b873fe mode 100644,000000..100644 --- a/lib/designform.php +++ b/lib/designform.php @@@ -1,304 -1,0 +1,324 @@@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @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/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * Form for choosing a design + * + * Used for choosing a site design, user design, or group design. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @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 DesignForm extends Form +{ + /** + * Return-to args + */ + + var $design = null; + var $actionurl = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param Design $design initial design + * @param Design $actionurl url of action (for form posting) + */ + + function __construct($out, $design, $actionurl) + { + parent::__construct($out); + + $this->design = $design; + $this->actionurl = $actionurl; + } + + /** + * ID of the form + * + * @return int ID of the form + */ + + function id() + { + return 'design'; + } + + /** + * class of the form + * + * @return string class of the form + */ + + function formClass() + { + return 'form_design'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return $this->actionurl; + } + + /** + * Legend of the Form + * + * @return void + */ + function formLegend() + { + $this->out->element('legend', null, _('Change design')); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->backgroundData(); + + $this->out->elementEnd('fieldset'); + + $this->out->elementStart('fieldset', array('id' => 'settings_design_color')); ++ // TRANS: Fieldset legend on profile design page to change profile page colours. + $this->out->element('legend', null, _('Change colours')); + $this->colourData(); + $this->out->elementEnd('fieldset'); + + $this->out->elementStart('fieldset'); + ++ // TRANS: Button text on profile design page to immediately reset all colour settings to default. + $this->out->submit('defaults', _('Use defaults'), 'submit form_action-default', ++ // TRANS: Title for button on profile design page to reset all colour settings to default. + 'defaults', _('Restore default designs')); + + $this->out->element('input', array('id' => 'settings_design_reset', + 'type' => 'reset', - 'value' => 'Reset', ++ // TRANS: Button text on profile design page to reset all colour settings to default without saving. ++ 'value' => _m('BUTTON', 'Reset'), + 'class' => 'submit form_action-primary', ++ // TRANS: Title for button on profile design page to reset all colour settings to default without saving. + 'title' => _('Reset back to default'))); + } + + function backgroundData() + { + $this->out->elementStart('ul', 'form_data'); + $this->out->elementStart('li'); + $this->out->element('label', array('for' => 'design_background-image_file'), ++ // TRANS: Label in form on profile design page. ++ // TRANS: Field contains file name on user's computer that could be that user's custom profile background image. + _('Upload file')); + $this->out->element('input', array('name' => 'design_background-image_file', + 'type' => 'file', + 'id' => 'design_background-image_file')); ++ // TRANS: Instructions for form on profile design page. + $this->out->element('p', 'form_guide', _('You can upload your personal ' . + 'background image. The maximum file size is 2Mb.')); + $this->out->element('input', array('name' => 'MAX_FILE_SIZE', + 'type' => 'hidden', + 'id' => 'MAX_FILE_SIZE', + 'value' => ImageFile::maxFileSizeInt())); + $this->out->elementEnd('li'); + + if (!empty($this->design->backgroundimage)) { + + $this->out->elementStart('li', array('id' => + 'design_background-image_onoff')); + + $this->out->element('img', array('src' => + Design::url($this->design->backgroundimage))); + + $attrs = array('name' => 'design_background-image_onoff', + 'type' => 'radio', + 'id' => 'design_background-image_on', + 'class' => 'radio', + 'value' => 'on'); + + if ($this->design->disposition & BACKGROUND_ON) { + $attrs['checked'] = 'checked'; + } + + $this->out->element('input', $attrs); + + $this->out->element('label', array('for' => 'design_background-image_on', + 'class' => 'radio'), - _('On')); ++ // TRANS: Radio button on profile design page that will enable use of the uploaded profile image. ++ _m('RADIO', 'On')); + + $attrs = array('name' => 'design_background-image_onoff', + 'type' => 'radio', + 'id' => 'design_background-image_off', + 'class' => 'radio', + 'value' => 'off'); + + if ($this->design->disposition & BACKGROUND_OFF) { + $attrs['checked'] = 'checked'; + } + + $this->out->element('input', $attrs); + + $this->out->element('label', array('for' => 'design_background-image_off', + 'class' => 'radio'), - _('Off')); ++ // TRANS: Radio button on profile design page that will disable use of the uploaded profile image. ++ _m('RADIO', 'Off')); ++ // TRANS: Form guide for a set of radio buttons on the profile design page that will enable or disable ++ // TRANS: use of the uploaded profile image. + $this->out->element('p', 'form_guide', _('Turn background image on or off.')); + $this->out->elementEnd('li'); + + $this->out->elementStart('li'); + $this->out->checkbox('design_background-image_repeat', ++ // TRANS: Checkbox label on profile design page that will cause the profile image to be tiled. + _('Tile background image'), + ($this->design->disposition & BACKGROUND_TILE) ? true : false); + $this->out->elementEnd('li'); + } + + $this->out->elementEnd('ul'); + } + + function colourData() + { + $this->out->elementStart('ul', 'form_data'); + + try { + + $bgcolor = new WebColor($this->design->backgroundcolor); + + $this->out->elementStart('li'); ++ // TRANS: Label on profile design page for setting a profile page background colour. + $this->out->element('label', array('for' => 'swatch-1'), _('Background')); + $this->out->element('input', array('name' => 'design_background', + 'type' => 'text', + 'id' => 'swatch-1', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '')); + $this->out->elementEnd('li'); + + $ccolor = new WebColor($this->design->contentcolor); + + $this->out->elementStart('li'); ++ // TRANS: Label on profile design page for setting a profile page content colour. + $this->out->element('label', array('for' => 'swatch-2'), _('Content')); + $this->out->element('input', array('name' => 'design_content', + 'type' => 'text', + 'id' => 'swatch-2', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '')); + $this->out->elementEnd('li'); + + $sbcolor = new WebColor($this->design->sidebarcolor); + + $this->out->elementStart('li'); ++ // TRANS: Label on profile design page for setting a profile page sidebar colour. + $this->out->element('label', array('for' => 'swatch-3'), _('Sidebar')); + $this->out->element('input', array('name' => 'design_sidebar', + 'type' => 'text', + 'id' => 'swatch-3', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '')); + $this->out->elementEnd('li'); + + $tcolor = new WebColor($this->design->textcolor); + + $this->out->elementStart('li'); ++ // TRANS: Label on profile design page for setting a profile page text colour. + $this->out->element('label', array('for' => 'swatch-4'), _('Text')); + $this->out->element('input', array('name' => 'design_text', + 'type' => 'text', + 'id' => 'swatch-4', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '')); + $this->out->elementEnd('li'); + + $lcolor = new WebColor($this->design->linkcolor); + + $this->out->elementStart('li'); ++ // TRANS: Label on profile design page for setting a profile page links colour. + $this->out->element('label', array('for' => 'swatch-5'), _('Links')); + $this->out->element('input', array('name' => 'design_links', + 'type' => 'text', + 'id' => 'swatch-5', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '')); + $this->out->elementEnd('li'); + + } catch (WebColorException $e) { + common_log(LOG_ERR, 'Bad color values in design ID: ' .$this->design->id); + } + + $this->out->elementEnd('ul'); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { - $this->out->submit('save', _('Save'), 'submit form_action-secondary', ++ // TRANS: Button text on profile design page to save settings. ++ $this->out->submit('save', _m('BUTTON','Save'), 'submit form_action-secondary', ++ // TRANS: Title for button on profile design page to save settings. + 'save', _('Save design')); + } +} diff --cc lib/designsettings.php index 58578f1886,90296a64da..d0601c5530 --- a/lib/designsettings.php +++ b/lib/designsettings.php @@@ -84,11 -82,197 +82,11 @@@ class DesignSettingsAction extends Acco * * @return nothing */ - function showDesignForm($design) { - $this->elementStart('form', array('method' => 'post', - 'enctype' => 'multipart/form-data', - 'id' => 'form_settings_design', - 'class' => 'form_settings', - 'action' => $this->submitaction)); - $this->elementStart('fieldset'); - $this->hidden('token', common_session_token()); - - $this->elementStart('fieldset', array('id' => - 'settings_design_background-image')); - // TRANS: Fieldset legend on profile design page. - $this->element('legend', null, _('Change background image')); - $this->elementStart('ul', 'form_data'); - $this->elementStart('li'); - $this->element('label', array('for' => 'design_background-image_file'), - // TRANS: Label in form on profile design page. - // TRANS: Field contains file name on user's computer that could be that user's custom profile background image. - _('Upload file')); - $this->element('input', array('name' => 'design_background-image_file', - 'type' => 'file', - 'id' => 'design_background-image_file')); - // TRANS: Instructions for form on profile design page. - $this->element('p', 'form_guide', _('You can upload your personal ' . - 'background image. The maximum file size is 2MB.')); - $this->element('input', array('name' => 'MAX_FILE_SIZE', - 'type' => 'hidden', - 'id' => 'MAX_FILE_SIZE', - 'value' => ImageFile::maxFileSizeInt())); - $this->elementEnd('li'); - - if (!empty($design->backgroundimage)) { - $this->elementStart('li', array('id' => - 'design_background-image_onoff')); - - $this->element('img', array('src' => - Design::url($design->backgroundimage))); - - $attrs = array('name' => 'design_background-image_onoff', - 'type' => 'radio', - 'id' => 'design_background-image_on', - 'class' => 'radio', - 'value' => 'on'); - - if ($design->disposition & BACKGROUND_ON) { - $attrs['checked'] = 'checked'; - } - - $this->element('input', $attrs); - - $this->element('label', array('for' => 'design_background-image_on', - 'class' => 'radio'), - // TRANS: Radio button on profile design page that will enable use of the uploaded profile image. - _m('RADIO','On')); - - $attrs = array('name' => 'design_background-image_onoff', - 'type' => 'radio', - 'id' => 'design_background-image_off', - 'class' => 'radio', - 'value' => 'off'); - - if ($design->disposition & BACKGROUND_OFF) { - $attrs['checked'] = 'checked'; - } - - $this->element('input', $attrs); - - $this->element('label', array('for' => 'design_background-image_off', - 'class' => 'radio'), - // TRANS: Radio button on profile design page that will disable use of the uploaded profile image. - _m('RADIO','Off')); - // TRANS: Form guide for a set of radio buttons on the profile design page that will enable or disable - // TRANS: use of the uploaded profile image. - $this->element('p', 'form_guide', _('Turn background image on or off.')); - $this->elementEnd('li'); - - $this->elementStart('li'); - $this->checkbox('design_background-image_repeat', - // TRANS: Checkbox label on profile design page that will cause the profile image to be tiled. - _('Tile background image'), - ($design->disposition & BACKGROUND_TILE) ? true : false); - $this->elementEnd('li'); - } - - $this->elementEnd('ul'); - $this->elementEnd('fieldset'); - - $this->elementStart('fieldset', array('id' => 'settings_design_color')); - // TRANS: Fieldset legend on profile design page to change profile page colours. - $this->element('legend', null, _('Change colours')); - $this->elementStart('ul', 'form_data'); - - try { - $bgcolor = new WebColor($design->backgroundcolor); - - $this->elementStart('li'); - // TRANS: Label on profile design page for setting a profile page background colour. - $this->element('label', array('for' => 'swatch-1'), _('Background')); - $this->element('input', array('name' => 'design_background', - 'type' => 'text', - 'id' => 'swatch-1', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '')); - $this->elementEnd('li'); - - $ccolor = new WebColor($design->contentcolor); - - $this->elementStart('li'); - // TRANS: Label on profile design page for setting a profile page content colour. - $this->element('label', array('for' => 'swatch-2'), _('Content')); - $this->element('input', array('name' => 'design_content', - 'type' => 'text', - 'id' => 'swatch-2', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '')); - $this->elementEnd('li'); - - $sbcolor = new WebColor($design->sidebarcolor); - - $this->elementStart('li'); - // TRANS: Label on profile design page for setting a profile page sidebar colour. - $this->element('label', array('for' => 'swatch-3'), _('Sidebar')); - $this->element('input', array('name' => 'design_sidebar', - 'type' => 'text', - 'id' => 'swatch-3', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '')); - $this->elementEnd('li'); - - $tcolor = new WebColor($design->textcolor); - - $this->elementStart('li'); - // TRANS: Label on profile design page for setting a profile page text colour. - $this->element('label', array('for' => 'swatch-4'), _('Text')); - $this->element('input', array('name' => 'design_text', - 'type' => 'text', - 'id' => 'swatch-4', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '')); - $this->elementEnd('li'); - - $lcolor = new WebColor($design->linkcolor); - - $this->elementStart('li'); - // TRANS: Label on profile design page for setting a profile page links colour. - $this->element('label', array('for' => 'swatch-5'), _('Links')); - $this->element('input', array('name' => 'design_links', - 'type' => 'text', - 'id' => 'swatch-5', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '')); - $this->elementEnd('li'); - - } catch (WebColorException $e) { - common_log(LOG_ERR, 'Bad color values in design ID: ' .$design->id); - } + $form = new DesignForm($this, $design, $this->selfUrl()); + $form->show(); + - $this->elementEnd('ul'); - $this->elementEnd('fieldset'); - - // TRANS: Button text on profile design page to immediately reset all colour settings to default. - $this->submit('defaults', _('Use defaults'), 'submit form_action-default', - // TRANS: Title for button on profile design page to reset all colour settings to default. - 'defaults', _('Restore default designs')); - - $this->element('input', array('id' => 'settings_design_reset', - 'type' => 'reset', - // TRANS: Button text on profile design page to reset all colour settings to default without saving. - 'value' => _m('BUTTON','Reset'), - 'class' => 'submit form_action-primary', - // TRANS: Title for button on profile design page to reset all colour settings to default without saving. - 'title' => _('Reset back to default'))); - - // TRANS: Button text on profile design page to save settings. - $this->submit('save', _m('BUTTON','Save'), 'submit form_action-secondary', - // TRANS: Title for button on profile design page to save settings. - 'save', _('Save design')); - - $this->elementEnd('fieldset'); - $this->elementEnd('form'); } /** diff --cc lib/framework.php index acfca9f0e8,0000000000..70987e086c mode 100644,000000..100644 --- a/lib/framework.php +++ b/lib/framework.php @@@ -1,143 -1,0 +1,154 @@@ +. + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } + +define('STATUSNET_VERSION', '0.9.6'); +define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility + +define('STATUSNET_CODENAME', 'Man on the Moon'); + +define('AVATAR_PROFILE_SIZE', 96); +define('AVATAR_STREAM_SIZE', 48); +define('AVATAR_MINI_SIZE', 24); + +define('NOTICES_PER_PAGE', 20); +define('PROFILES_PER_PAGE', 20); + +define('FOREIGN_NOTICE_SEND', 1); +define('FOREIGN_NOTICE_RECV', 2); +define('FOREIGN_NOTICE_SEND_REPLY', 4); + +define('FOREIGN_FRIEND_SEND', 1); +define('FOREIGN_FRIEND_RECV', 2); + +define('NOTICE_INBOX_SOURCE_SUB', 1); +define('NOTICE_INBOX_SOURCE_GROUP', 2); +define('NOTICE_INBOX_SOURCE_REPLY', 3); +define('NOTICE_INBOX_SOURCE_FORWARD', 4); +define('NOTICE_INBOX_SOURCE_GATEWAY', -1); + +# append our extlib dir as the last-resort place to find libs + +set_include_path(get_include_path() . PATH_SEPARATOR . INSTALLDIR . '/extlib/'); + +// To protect against upstream libraries which haven't updated +// for PHP 5.3 where dl() function may not be present... +if (!function_exists('dl')) { + // function_exists() returns false for things in disable_functions, + // but they still exist and we'll die if we try to redefine them. + // + // Fortunately trying to call the disabled one will only trigger + // a warning, not a fatal, so it's safe to leave it for our case. + // Callers will be suppressing warnings anyway. + $disabled = array_filter(array_map('trim', explode(',', ini_get('disable_functions')))); + if (!in_array('dl', $disabled)) { + function dl($library) { + return false; + } + } +} + +# global configuration object + +require_once('PEAR.php'); +require_once('PEAR/Exception.php'); +require_once('DB/DataObject.php'); +require_once('DB/DataObject/Cast.php'); # for dates + +require_once(INSTALLDIR.'/lib/language.php'); + +// This gets included before the config file, so that admin code and plugins +// can use it + +require_once(INSTALLDIR.'/lib/event.php'); +require_once(INSTALLDIR.'/lib/plugin.php'); + +function addPlugin($name, $attrs = null) +{ + return StatusNet::addPlugin($name, $attrs); +} + +function _have_config() +{ + return StatusNet::haveConfig(); +} + +function __autoload($cls) +{ + if (file_exists(INSTALLDIR.'/classes/' . $cls . '.php')) { + require_once(INSTALLDIR.'/classes/' . $cls . '.php'); + } else if (file_exists(INSTALLDIR.'/lib/' . strtolower($cls) . '.php')) { + require_once(INSTALLDIR.'/lib/' . strtolower($cls) . '.php'); + } else if (mb_substr($cls, -6) == 'Action' && + file_exists(INSTALLDIR.'/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php')) { + require_once(INSTALLDIR.'/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php'); + } else if ($cls == 'OAuthRequest') { + require_once('OAuth.php'); + } else { + Event::handle('Autoload', array(&$cls)); + } +} + +// XXX: how many of these could be auto-loaded on use? +// XXX: note that these files should not use config options +// at compile time since DB config options are not yet loaded. + +require_once 'Validate.php'; +require_once 'markdown.php'; + +// XXX: other formats here + ++/** ++ * Avoid the NICKNAME_FMT constant; use the Nickname class instead. ++ * ++ * Nickname::DISPLAY_FMT is more suitable for inserting into regexes; ++ * note that it includes the [] and repeating bits, so should be wrapped ++ * directly in a capture paren usually. ++ * ++ * For validation, use Nickname::normalize(), Nickname::isValid() etc. ++ * ++ * @deprecated ++ */ +define('NICKNAME_FMT', VALIDATE_NUM.VALIDATE_ALPHA_LOWER); + +require_once INSTALLDIR.'/lib/util.php'; +require_once INSTALLDIR.'/lib/action.php'; +require_once INSTALLDIR.'/lib/mail.php'; +require_once INSTALLDIR.'/lib/subs.php'; + +require_once INSTALLDIR.'/lib/clientexception.php'; +require_once INSTALLDIR.'/lib/serverexception.php'; + + +//set PEAR error handling to use regular PHP exceptions +function PEAR_ErrorToPEAR_Exception($err) +{ + //DB_DataObject throws error when an empty set would be returned + //That behavior is weird, and not how the rest of StatusNet works. + //So just ignore those errors. + if ($err->getCode() == DB_DATAOBJECT_ERROR_NODATA) { + return; + } + if ($err->getCode()) { + throw new PEAR_Exception($err->getMessage(), $err->getCode()); + } + throw new PEAR_Exception($err->getMessage()); +} +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'PEAR_ErrorToPEAR_Exception'); diff --cc lib/router.php index efead04ab3,eff88bb462..9dfa6e00b0 --- a/lib/router.php +++ b/lib/router.php @@@ -151,6 -222,8 +222,8 @@@ class Route array('action' => 'publicxrds')); $m->connect('.well-known/host-meta', array('action' => 'hostmeta')); - $m->connect('main/xrd', - array('action' => 'userxrd')); ++ $m->connect('main/xrd', ++ array('action' => 'userxrd')); // these take a code diff --cc lib/util.php index 1d4f5a5499,da36121ffd..3d4adcf4bf --- a/lib/util.php +++ b/lib/util.php @@@ -926,23 -994,27 +1010,39 @@@ function common_linkify($url) return XMLStringer::estring('a', $attrs, $url); } - function common_shorten_links($text, $always = false) + /** + * Find and shorten links in a given chunk of text if it's longer than the + * configured notice content limit (or unconditionally). + * + * Side effects: may save file and file_redirection records for referenced URLs. + * + * Pass the $user option or call $user->shortenLinks($text) to ensure the proper + * user's options are used; otherwise the current web session user's setitngs + * will be used or ur1.ca if there is no active web login. + * + * @param string $text + * @param boolean $always (optional) + * @param User $user (optional) + * + * @return string + */ + function common_shorten_links($text, $always = false, User $user=null) { - $maxLength = Notice::maxContent(); - if (!$always && ($maxLength == 0 || mb_strlen($text) <= $maxLength)) return $text; - return common_replace_urls_callback($text, array('File_redirection', 'makeShort'), $user); + common_debug("common_shorten_links() called"); + + $user = common_current_user(); + + $maxLength = User_urlshortener_prefs::maxNoticeLength($user); + + common_debug("maxLength = $maxLength"); + + if ($always || mb_strlen($text) > $maxLength) { + common_debug("Forcing shortening"); - return common_replace_urls_callback($text, array('File_redirection', 'forceShort')); ++ return common_replace_urls_callback($text, array('File_redirection', 'forceShort'), $user); + } else { + common_debug("Not forcing shortening"); - return common_replace_urls_callback($text, array('File_redirection', 'makeShort')); ++ return common_replace_urls_callback($text, array('File_redirection', 'makeShort'), $user); + } } /** @@@ -1921,42 -2055,33 +2053,40 @@@ function common_database_tablename($tab /** * Shorten a URL with the current user's configured shortening service, * or ur1.ca if configured, or not at all if no shortening is set up. - * Length is not considered. * - * @param string $long_url + * @param string $long_url original URL + * @param User $user to specify a particular user's options + * @param boolean $force Force shortening (used when notice is too long) - * * @return string may return the original URL if shortening failed * * @fixme provide a way to specify a particular shortener - * @fixme provide a way to specify to use a given user's shortening preferences */ - - function common_shorten_url($long_url, $force = false) -function common_shorten_url($long_url, User $user=null) ++function common_shorten_url($long_url, User $user=null, $force = false) { + common_debug("Shortening URL '$long_url' (force = $force)"); + $long_url = trim($long_url); - if (empty($user)) { - // Current web session - $user = common_current_user(); - } - if (empty($user)) { - // common current user does not find a user when called from the XMPP daemon - // therefore we'll set one here fix, so that XMPP given URLs may be shortened - $shortenerName = 'ur1.ca'; - } else { - $shortenerName = $user->urlshorteningservice; + + $user = common_current_user(); + + $maxUrlLength = User_urlshortener_prefs::maxUrlLength($user); + common_debug("maxUrlLength = $maxUrlLength"); + + // $force forces shortening even if it's not strictly needed + + if (mb_strlen($long_url) < $maxUrlLength && !$force) { + common_debug("Skipped shortening URL."); + return $long_url; } - if(Event::handle('StartShortenUrl', array($long_url,$shortenerName,&$shortenedUrl))){ + $shortenerName = User_urlshortener_prefs::urlShorteningService($user); + + common_debug("Shortener name = '$shortenerName'"); + + if (Event::handle('StartShortenUrl', array($long_url, $shortenerName, &$shortenedUrl))) { //URL wasn't shortened, so return the long url return $long_url; - }else{ + } else { //URL was shortened, so return the result return trim($shortenedUrl); } diff --cc plugins/OStatus/OStatusPlugin.php index e38d52d3d7,d0b64e8769..f846a2fc8b --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@@ -1010,11 -1008,43 +1008,43 @@@ class OStatusPlugin extends Plugi return true; } - function onStartHostMetaLinks(&$links) { - $url = common_local_url('userxrd'); - $url.= '?uri={uri}'; - $links[] = array('rel' => Discovery::LRDD_REL, - 'template' => $url, - 'title' => array('Resource Descriptor')); + function onEndXrdActionLinks(&$xrd, $user) + { - $xrd->links[] = array('rel' => Discovery::UPDATESFROM, ++ $xrd->links[] = array('rel' => Discovery::UPDATESFROM, + 'href' => common_local_url('ApiTimelineUser', + array('id' => $user->id, + 'format' => 'atom')), + 'type' => 'application/atom+xml'); + + // Salmon + $salmon_url = common_local_url('usersalmon', + array('id' => $user->id)); + + $xrd->links[] = array('rel' => Salmon::REL_SALMON, + 'href' => $salmon_url); + // XXX : Deprecated - to be removed. + $xrd->links[] = array('rel' => Salmon::NS_REPLIES, + 'href' => $salmon_url); + + $xrd->links[] = array('rel' => Salmon::NS_MENTIONS, + 'href' => $salmon_url); + + // Get this user's keypair + $magickey = Magicsig::staticGet('user_id', $user->id); + if (!$magickey) { + // No keypair yet, let's generate one. + $magickey = new Magicsig(); + $magickey->generate($user->id); + } + + $xrd->links[] = array('rel' => Magicsig::PUBLICKEYREL, + '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}'; + $xrd->links[] = array('rel' => 'http://ostatus.org/schema/1.0/subscribe', + 'template' => $url ); + - return true; ++ return true; } }