Merge branch '1.0.x' of gitorious.org:statusnet/mainline into 1.0.x

* '1.0.x' of gitorious.org:statusnet/mainline: (24 commits)
  Change time format to work with older PHP (before 5.3)
  move OMB-specific remote login button to OMB Plugin
  use correct redirect on logout of single-user site
  disable routes that aren't available in single-user mode
  upgrade to beta4
  Better error handling when the email subsystem isn't working. The installer was dying trying to send a confirmation email to the initial user.
  Store a list of all paths the router knows about (backward compatibility with Net_URL_Mapper)
  Upgrade 0.9.x bookmarks to 1.0.x
  add hooks for upgrades
  include q as param, not arg for search sub menu
  exact match for paths
  change category on urlmapper.php
  Fix undefined variable
  don't forget to add qstring to static paths
  with new URLMapper, cached router takes more memory, time than re-generating
  Deal with default param patterns more effectively
  two useful functions for profiling
  Remove unused xrds stuff from profile (replace in OMB please)
  add default groupdirectory route
  new URLMapper without Net_URL_Mapper
  ...
This commit is contained in:
Zach Copley 2011-09-17 13:30:40 -07:00
commit c5b731883b
27 changed files with 507 additions and 1734 deletions

View File

@ -1418,3 +1418,7 @@ StartShowInvitationSuccess: Right before showing invitations success msg
EndShowInvitationSuccess: After showing invitations success msg
- $action: invitation action
StartUpgrade: when starting a site upgrade
EndUpgrade: when ending a site upgrade; good place to do your own upgrades

4
README
View File

@ -2,8 +2,8 @@
README
------
StatusNet 1.0.0beta3
27 August 2011
StatusNet 1.0.0beta4
16 September 2011
This is the README file for StatusNet, the Open Source social
networking platform. It includes installation instructions,

View File

@ -73,7 +73,13 @@ class LogoutAction extends Action
}
Event::handle('EndLogout', array($this));
common_redirect(common_local_url('public'), 303);
if (common_config('singleuser', 'enabled')) {
$user = User::singleUser();
common_redirect(common_local_url('showstream',
array('nickname' => $user->nickname)));
} else {
common_redirect(common_local_url('public'), 303);
}
}
}

View File

@ -92,9 +92,6 @@ class ShowstreamAction extends ProfileAction
// For YADIS discovery, we also have a <meta> tag
header('X-XRDS-Location: '. common_local_url('xrds', array('nickname' =>
$this->user->nickname)));
$this->showPage();
}
@ -171,11 +168,6 @@ class ShowstreamAction extends ProfileAction
function extraHead()
{
// for remote subscriptions etc.
$this->element('meta', array('http-equiv' => 'X-XRDS-Location',
'content' => common_local_url('xrds', array('nickname' =>
$this->user->nickname))));
if ($this->profile->bio) {
$this->element('meta', array('name' => 'description',
'content' => $this->profile->bio));

View File

@ -203,14 +203,14 @@ class Group_member extends Managed_DataObject
if (!empty($this->uri)) {
return $this->uri;
} else {
return self::newURI($this->member_id, $this->group_id, $this->created);
return self::newURI($this->profile_id, $this->group_id, $this->created);
}
}
static function newURI($member_id, $group_id, $created)
static function newURI($profile_id, $group_id, $created)
{
return TagURI::mint('join:%d:%d:%s',
$member_id,
$profile_id,
$group_id,
common_date_iso8601($created));
}

View File

@ -1,324 +0,0 @@
<?php
/**
* URL parser and mapper
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Net
* @package Net_URL_Mapper
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id: Mapper.php 232857 2007-03-28 10:23:04Z mansion $
* @link http://pear.php.net/package/Net_URL_Mapper
*/
require_once 'Net/URL/Mapper/Path.php';
require_once 'Net/URL/Mapper/Exception.php';
/**
* URL parser and mapper class
*
* This class takes an URL and a configuration and returns formatted data
* about the request according to a configuration parameter
*
* @category Net
* @package Net_URL_Mapper
* @author Bertrand Mansion <golgote@mamasam.com>
* @version Release: @package_version@
*/
class Net_URL_Mapper
{
/**
* Array of Net_URL_Mapper instances
* @var array
*/
private static $instances = array();
/**
* Mapped paths collection
* @var array
*/
protected $paths = array();
/**
* Prefix used for url mapping
* @var string
*/
protected $prefix = '';
/**
* Optional scriptname if mod_rewrite is not available
* @var string
*/
protected $scriptname = '';
/**
* Mapper instance id
* @var string
*/
protected $id = '__default__';
/**
* Class constructor
* Constructor is private, you should use getInstance() instead.
*/
private function __construct() { }
/**
* Returns a singleton object corresponding to the requested instance id
* @param string Requested instance name
* @return Object Net_URL_Mapper Singleton
*/
public static function getInstance($id = '__default__')
{
if (!isset(self::$instances[$id])) {
$m = new Net_URL_Mapper();
$m->id = $id;
self::$instances[$id] = $m;
}
return self::$instances[$id];
}
/**
* Returns the instance id
* @return string Mapper instance id
*/
public function getId()
{
return $this->id;
}
/**
* Parses a path and creates a connection
* @param string The path to connect
* @param array Default values for path parts
* @param array Regular expressions for path parts
* @return object Net_URL_Mapper_Path
*/
public function connect($path, $defaults = array(), $rules = array())
{
$pathObj = new Net_URL_Mapper_Path($path, $defaults, $rules);
$this->addPath($pathObj);
return $pathObj;
}
/**
* Set the url prefix if needed
*
* Example: using the prefix to differenciate mapper instances
* <code>
* $fr = Net_URL_Mapper::getInstance('fr');
* $fr->setPrefix('/fr');
* $en = Net_URL_Mapper::getInstance('en');
* $en->setPrefix('/en');
* </code>
*
* @param string URL prefix
*/
public function setPrefix($prefix)
{
$this->prefix = '/'.trim($prefix, '/');
}
/**
* Set the scriptname if mod_rewrite not available
*
* Example: will match and generate url like
* - index.php/view/product/1
* <code>
* $m = Net_URL_Mapper::getInstance();
* $m->setScriptname('index.php');
* </code>
* @param string URL prefix
*/
public function setScriptname($scriptname)
{
$this->scriptname = $scriptname;
}
/**
* Will attempt to match an url with a defined path
*
* If an url corresponds to a path, the resulting values are returned
* in an array. If none is found, null is returned. In case an url is
* matched but its content doesn't validate the path rules, an exception is
* thrown.
*
* @param string URL
* @return array|null array if match found, null otherwise
* @throws Net_URL_Mapper_InvalidException
*/
public function match($url)
{
$nurl = '/'.trim($url, '/');
// Remove scriptname if needed
if (!empty($this->scriptname) &&
strpos($nurl, $this->scriptname) === 0) {
$nurl = substr($nurl, strlen($this->scriptname));
if (empty($nurl)) {
$nurl = '/';
}
}
// Remove prefix
if (!empty($this->prefix)) {
if (strpos($nurl, $this->prefix) !== 0) {
return null;
}
$nurl = substr($nurl, strlen($this->prefix));
if (empty($nurl)) {
$nurl = '/';
}
}
// Remove query string
if (($pos = strpos($nurl, '?')) !== false) {
$nurl = substr($nurl, 0, $pos);
}
$paths = array();
$values = null;
// Make a list of paths that conform to route format
foreach ($this->paths as $path) {
$regex = $path->getFormat();
if (preg_match($regex, $nurl)) {
$paths[] = $path;
}
}
// Make sure one of the paths found is valid
foreach ($paths as $path) {
$regex = $path->getRule();
if (preg_match($regex, $nurl, $matches)) {
$values = $path->getDefaults();
array_shift($matches);
$clean = array();
foreach ($matches as $k => $v) {
$v = trim($v, '/');
if (!is_int($k) && $v !== '') {
$values[$k] = $v;
}
}
break;
}
}
// A path conforms but does not validate
if (is_null($values) && !empty($paths)) {
$e = new Net_URL_Mapper_InvalidException('A path was found but is invalid.');
$e->setPath($paths[0]);
$e->setUrl($url);
throw $e;
}
return $values;
}
/**
* Generate an url based on given parameters
*
* Will attempt to find a path definition that matches the given parameters and
* will generate an url based on this path.
*
* @param array Values to be used for the url generation
* @param array Key/value pairs for query string if needed
* @param string Anchor (fragment) if needed
* @return string|false String if a rule was found, false otherwise
*/
public function generate($values = array(), $qstring = array(), $anchor = '')
{
// Use root path if any
if (empty($values) && isset($this->paths['/'])) {
return $this->scriptname.$this->prefix.$this->paths['/']->generate($values, $qstring, $anchor);
}
foreach ($this->paths as $path) {
$set = array();
foreach ($values as $k => $v) {
if ($path->hasKey($k, $v)) {
$set[$k] = $v;
}
}
if (count($set) == count($values) &&
count($set) <= $path->getMaxKeys()) {
$req = $path->getRequired();
if (count(array_intersect(array_keys($set), $req)) != count($req)) {
continue;
}
$gen = $path->generate($set, $qstring, $anchor);
return $this->scriptname.$this->prefix.$gen;
}
}
return false;
}
/**
* Returns defined paths
* @return array Array of paths
*/
public function getPaths()
{
return $this->paths;
}
/**
* Reset all paths
* This is probably only useful for testing
*/
public function reset()
{
$this->paths = array();
$this->prefix = '';
}
/**
* Add a new path to the mapper
* @param object Net_URL_Mapper_Path object
*/
public function addPath(Net_URL_Mapper_Path $path)
{
$this->paths[$path->getPath()] = $path;
}
}
?>

View File

@ -1,104 +0,0 @@
<?php
/**
* Exception classes for Net_URL_Mapper
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Net
* @package Net_URL_Mapper
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id: Exception.php 232857 2007-03-28 10:23:04Z mansion $
* @link http://pear.php.net/package/Net_URL_Mapper
*/
/**
* Base class for exceptions in PEAR
*/
require_once 'PEAR/Exception.php';
/**
* Base class for exceptions in Net_URL_Mapper package
*
* Such a base class is required by the Exception RFC:
* http://pear.php.net/pepr/pepr-proposal-show.php?id=132
* It will rarely be thrown directly, its specialized subclasses will be
* thrown most of the time.
*
* @category Net
* @package Net_URL_Mapper
* @version Release: @package_version@
*/
class Net_URL_Mapper_Exception extends PEAR_Exception
{
}
/**
* Exception thrown when a path is invalid
*
* A path can conform to a given structure, but contain invalid parameters.
* <code>
* $m = Net_URL_Mapper::getInstance();
* $m->connect('hi/:name', null, array('name'=>'[a-z]+'));
* $m->match('/hi/FOXY'); // Will throw the exception
* </code>
*
* @category Net
* @package Net_URL_Mapper
* @version Release: @package_version@
*/
class Net_URL_Mapper_InvalidException extends Net_URL_Mapper_Exception
{
protected $path;
protected $url;
public function setPath($path)
{
$this->path = $path;
}
public function getPath()
{
return $this->path;
}
public function setUrl($url)
{
$this->url = $url;
}
public function getUrl()
{
return $this->url;
}
}
?>

View File

@ -1,142 +0,0 @@
<?php
/**
* URL parser and mapper
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Net
* @package Net_URL_Mapper
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id: Part.php 232857 2007-03-28 10:23:04Z mansion $
* @link http://pear.php.net/package/Net_URL_Mapper
*/
abstract class Net_URL_Mapper_Part
{
protected $defaults;
protected $rule;
protected $public;
protected $type;
protected $required = false;
/**
* Part name if dynamic or content, generated from path
* @var string
*/
public $content;
const DYNAMIC = 1;
const WILDCARD = 2;
const FIXED = 3;
public function __construct($content, $path)
{
$this->content = $content;
$this->path = $path;
}
public function setRule($rule)
{
$this->rule = $rule;
}
abstract public function getFormat();
abstract public function getRule();
public function addSlash($str)
{
$str = trim($str, '/');
if (($pos = strpos($this->path, '/')) !== false) {
if ($pos == 0) {
$str = '/'.$str;
} else {
$str .= '/';
}
}
return $str;
}
public function addSlashRegex($str)
{
$str = trim($str, '/');
if (($pos = strpos($this->path, '/')) !== false) {
if ($pos == 0) {
$str = '\/'.$str;
} else {
$str .= '\/';
}
}
if (!$this->isRequired()) {
$str = '('.$str.'|)';
}
return $str;
}
public function setDefaults($defaults)
{
$this->defaults = (string)$defaults;
}
public function getType()
{
return $this->type;
}
public function accept($visitor, $method = null)
{
$args = func_get_args();
$visitor->$method($this, $args);
}
public function setRequired($required)
{
$this->required = $required;
}
public function isRequired()
{
return $this->required;
}
abstract public function generate($value = null);
public function match($value)
{
$rule = $this->getRule();
return preg_match('/^'.$rule.'$/', $this->addSlash($value));
}
}
?>

View File

@ -1,81 +0,0 @@
<?php
/**
* URL parser and mapper
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Net
* @package Net_URL_Mapper
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id: Dynamic.php 232857 2007-03-28 10:23:04Z mansion $
* @link http://pear.php.net/package/Net_URL_Mapper
*/
require_once 'Net/URL/Mapper/Part.php';
class Net_URL_Mapper_Part_Dynamic extends Net_URL_Mapper_Part
{
public function __construct($content, $path)
{
$this->type = Net_URL_Mapper_Part::DYNAMIC;
$this->setRequired(true);
parent::__construct($content, $path);
}
public function getFormat()
{
return $this->addSlashRegex('[^\/]+');
}
public function getRule()
{
if (!empty($this->rule)) {
return '(?P<'.$this->content.'>'.$this->addSlashRegex($this->rule).')';
}
return '(?P<'.$this->content.'>'.$this->addSlashRegex('[^\/]+').')';
}
public function generate($value = null)
{
if (is_array($value) && isset($value[$this->content])) {
$val = $value[$this->content];
} elseif (!is_array($value) && !is_null($value)) {
$val = $value;
} else {
$val = $this->defaults;
}
return $this->addSlash(urlencode($val));
}
}
?>

View File

@ -1,70 +0,0 @@
<?php
/**
* URL parser and mapper
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Net
* @package Net_URL_Mapper
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id: Fixed.php 232857 2007-03-28 10:23:04Z mansion $
* @link http://pear.php.net/package/Net_URL_Mapper
*/
require_once 'Net/URL/Mapper/Part.php';
class Net_URL_Mapper_Part_Fixed extends Net_URL_Mapper_Part
{
public function __construct($content, $path)
{
$this->type = Net_URL_Mapper_Part::FIXED;
parent::__construct($content, $path);
}
public function getFormat()
{
return $this->getRule();
}
public function getRule()
{
return preg_quote($this->path, '/');
}
public function generate($value = null)
{
return $this->path;
}
}
?>

View File

@ -1,80 +0,0 @@
<?php
/**
* URL parser and mapper
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Net
* @package Net_URL_Mapper
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id: Wildcard.php 232857 2007-03-28 10:23:04Z mansion $
* @link http://pear.php.net/package/Net_URL_Mapper
*/
require_once 'Net/URL/Mapper/Part.php';
class Net_URL_Mapper_Part_Wildcard extends Net_URL_Mapper_Part
{
public function __construct($content, $path)
{
$this->type = Net_URL_Mapper_Part::WILDCARD;
$this->setRequired(true);
parent::__construct($content, $path);
}
public function getFormat()
{
return $this->addSlashRegex('.*');;
}
public function getRule()
{
return '(?P<'.$this->content.'>'.$this->addSlashRegex('.*').')';
}
public function generate($value = null)
{
if (is_array($value) && isset($value[$this->content])) {
$val = $value[$this->content];
} elseif (!is_array($value) && !is_null($value)) {
$val = $value;
} else {
$val = $this->defaults;
}
return $this->addSlash(str_replace(
array('%2F', '%23'),
array('/', '#'), urlencode($val)));
}
}
?>

View File

@ -1,451 +0,0 @@
<?php
/**
* URL parser and mapper
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Net
* @package Net_URL_Mapper
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id: Path.php 296456 2010-03-20 00:41:08Z kguest $
* @link http://pear.php.net/package/Net_URL_Mapper
*/
require_once 'Net/URL.php';
require_once 'Net/URL/Mapper/Part/Dynamic.php';
require_once 'Net/URL/Mapper/Part/Wildcard.php';
require_once 'Net/URL/Mapper/Part/Fixed.php';
class Net_URL_Mapper_Path
{
private $path = '';
private $N = 0;
public $token;
public $value;
private $line = 1;
private $state = 1;
protected $alias;
protected $rules = array();
protected $defaults = array();
protected $parts = array();
protected $rule;
protected $format;
protected $minKeys;
protected $maxKeys;
protected $fixed = true;
protected $required;
public function __construct($path = '', $defaults = array(), $rules = array())
{
$this->path = '/'.trim(Net_URL::resolvePath($path), '/');
$this->setDefaults($defaults);
$this->setRules($rules);
try {
$this->parsePath();
} catch (Exception $e) {
// The path could not be parsed correctly, treat it as fixed
$this->fixed = true;
$part = self::createPart(Net_URL_Mapper_Part::FIXED, $this->path, $this->path);
$this->parts = array($part);
}
$this->getRequired();
}
/**
* Called when the object is serialized
* Make sure we do not store too much info when the object is serialized
* and call the regular expressions generator functions so that they will
* not need to be generated again on wakeup.
*
* @return array Name of properties to store when serialized
*/
public function __sleep()
{
$this->getFormat();
$this->getRule();
return array('alias', 'path', 'defaults', 'rule', 'format',
'parts', 'minKeys', 'maxKeys', 'fixed', 'required');
}
public function getPath()
{
return $this->path;
}
protected function parsePath()
{
while ($this->yylex()) { }
}
/**
* Get the path alias
* Path aliases can be used instead of full path
* @return null|string
*/
public function getAlias()
{
return $this->alias;
}
/**
* Set the path name
* @param string Set the path name
* @see getAlias()
*/
public function setAlias($alias)
{
$this->alias = $alias;
return $this;
}
/**
* Get the path parts default values
* @return null|array
*/
public function getDefaults()
{
return $this->defaults;
}
/**
* Set the path parts default values
* @param array Associative array with format partname => value
*/
public function setDefaults($defaults)
{
if (is_array($defaults)) {
$this->defaults = $defaults;
} else {
$this->defaults = array();
}
}
/**
* Set the path parts default values
* @param array Associative array with format partname => value
*/
public function setRules($rules)
{
if (is_array($rules)) {
$this->rules = $rules;
} else {
$this->rules = array();
}
}
/**
* Returns the regular expression used to match this path
* @return string PERL Regular expression
*/
public function getRule()
{
if (is_null($this->rule)) {
$this->rule = '/^';
foreach ($this->parts as $path => $part) {
$this->rule .= $part->getRule();
}
$this->rule .= '$/';
}
return $this->rule;
}
public function getFormat()
{
if (is_null($this->format)) {
$this->format = '/^';
foreach ($this->parts as $path => $part) {
$this->format .= $part->getFormat();
}
$this->format .= '$/';
}
return $this->format;
}
protected function addPart($part)
{
if (array_key_exists($part->content, $this->defaults)) {
$part->setRequired(false);
$part->setDefaults($this->defaults[$part->content]);
}
if (isset($this->rules[$part->content])) {
$part->setRule($this->rules[$part->content]);
}
$this->rule = null;
if ($part->getType() != Net_URL_Mapper_Part::FIXED) {
$this->fixed = false;
$this->parts[$part->content] = $part;
} else {
$this->parts[] = $part;
}
return $part;
}
public static function createPart($type, $content, $path)
{
switch ($type) {
case Net_URL_Mapper_Part::DYNAMIC:
return new Net_URL_Mapper_Part_Dynamic($content, $path);
break;
case Net_URL_Mapper_Part::WILDCARD:
return new Net_URL_Mapper_Part_Wildcard($content, $path);
break;
default:
return new Net_URL_Mapper_Part_Fixed($content, $path);
}
}
/**
* Checks whether the path contains the given part by name
* If value parameter is given, the part also checks if the
* given value conforms to the part rule.
* @param string Part name
* @param mixed The value to check against
*/
public function hasKey($partName, $value = null)
{
if (array_key_exists($partName, $this->parts)) {
if (!is_null($value) && $value !== false) {
return $this->parts[$partName]->match($value);
} else {
return true;
}
} elseif (array_key_exists($partName, $this->defaults) &&
$value == $this->defaults[$partName]) {
return true;
}
return false;
}
public function generate($values = array(), $qstring = array(), $anchor = '')
{
$path = '';
foreach ($this->parts as $part) {
$path .= $part->generate($values);
}
$path = '/'.trim(Net_URL::resolvePath($path), '/');
if (!empty($qstring)) {
if(strpos($path, '?') === false) {
$path .= '?';
} else {
$path .= '&';
}
$path .= http_build_query($qstring);
}
if (!empty($anchor)) {
$path .= '#'.ltrim($anchor, '#');
}
return $path;
}
public function getRequired()
{
if (!isset($this->required)) {
$req = array();
foreach ($this->parts as $part) {
if ($part->isRequired()) {
$req[] = $part->content;
}
}
$this->required = $req;
}
return $this->required;
}
public function getMaxKeys()
{
if (is_null($this->maxKeys)) {
$this->maxKeys = count($this->required);
$this->maxKeys += count($this->defaults);
}
return $this->maxKeys;
}
private $_yy_state = 1;
private $_yy_stack = array();
function yylex()
{
return $this->{'yylex' . $this->_yy_state}();
}
function yypushstate($state)
{
array_push($this->_yy_stack, $this->_yy_state);
$this->_yy_state = $state;
}
function yypopstate()
{
$this->_yy_state = array_pop($this->_yy_stack);
}
function yybegin($state)
{
$this->_yy_state = $state;
}
function yylex1()
{
$tokenMap = array (
1 => 1,
3 => 1,
5 => 1,
7 => 1,
9 => 1,
);
if ($this->N >= strlen($this->path)) {
return false; // end of input
}
$yy_global_pattern = "/^(\/?:\/?\\(([a-zA-Z0-9_]+)\\))|^(\/?\\*\/?\\(([a-zA-Z0-9_]+)\\))|^(\/?:([a-zA-Z0-9_]+))|^(\/?\\*([a-zA-Z0-9_]+))|^(\/?([^\/:*]+))/";
do {
if (preg_match($yy_global_pattern, substr($this->path, $this->N), $yymatches)) {
$yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if (!count($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
'an empty string. Input "' . substr($this->path,
$this->N, 5) . '... state START');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value
$r = $this->{'yy_r1_' . $this->token}($yysubmatches);
if ($r === null) {
$this->N += strlen($this->value);
$this->line += substr_count("\n", $this->value);
// accept this token
return true;
} elseif ($r === true) {
// we have changed state
// process this token in the new state
return $this->yylex();
} elseif ($r === false) {
$this->N += strlen($this->value);
$this->line += substr_count("\n", $this->value);
if ($this->N >= strlen($this->path)) {
return false; // end of input
}
// skip this token
continue;
} else { $yy_yymore_patterns = array(
1 => "^(\/?\\*\/?\\(([a-zA-Z0-9_]+)\\))|^(\/?:([a-zA-Z0-9_]+))|^(\/?\\*([a-zA-Z0-9_]+))|^(\/?([^\/:*]+))",
3 => "^(\/?:([a-zA-Z0-9_]+))|^(\/?\\*([a-zA-Z0-9_]+))|^(\/?([^\/:*]+))",
5 => "^(\/?\\*([a-zA-Z0-9_]+))|^(\/?([^\/:*]+))",
7 => "^(\/?([^\/:*]+))",
9 => "",
);
// yymore is needed
do {
if (!strlen($yy_yymore_patterns[$this->token])) {
throw new Exception('cannot do yymore for the last token');
}
if (preg_match($yy_yymore_patterns[$this->token],
substr($this->path, $this->N), $yymatches)) {
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
$this->value = current($yymatches); // token value
$this->line = substr_count("\n", $this->value);
}
} while ($this->{'yy_r1_' . $this->token}() !== null);
// accept
$this->N += strlen($this->value);
$this->line += substr_count("\n", $this->value);
return true;
}
} else {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->path[$this->N]);
}
break;
} while (true);
} // end function
const START = 1;
function yy_r1_1($yy_subpatterns)
{
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::DYNAMIC, $c, $this->value);
$this->addPart($part);
}
function yy_r1_3($yy_subpatterns)
{
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::WILDCARD, $c, $this->value);
$this->addPart($part);
}
function yy_r1_5($yy_subpatterns)
{
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::DYNAMIC, $c, $this->value);
$this->addPart($part);
}
function yy_r1_7($yy_subpatterns)
{
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::WILDCARD, $c, $this->value);
$this->addPart($part);
}
function yy_r1_9($yy_subpatterns)
{
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::FIXED, $c, $this->value);
$this->addPart($part);
}
}
?>

View File

@ -1,334 +0,0 @@
<?php
/**
* URL parser and mapper
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Net
* @package Net_URL_Mapper
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id: Path.plex 283937 2009-07-12 11:37:21Z mansion $
* @link http://pear.php.net/package/Net_URL_Mapper
*/
require_once 'Net/URL/Mapper/Part/Dynamic.php';
require_once 'Net/URL/Mapper/Part/Wildcard.php';
require_once 'Net/URL/Mapper/Part/Fixed.php';
class Net_URL_Mapper_Path
{
private $path = '';
private $N = 0;
public $token;
public $value;
private $line = 1;
private $state = 1;
protected $alias;
protected $rules = array();
protected $defaults = array();
protected $parts = array();
protected $rule;
protected $format;
protected $minKeys;
protected $maxKeys;
protected $fixed = true;
protected $required;
public function __construct($path = '', $defaults = array(), $rules = array())
{
$this->path = '/'.trim(Net_URL::resolvePath($path), '/');
$this->setDefaults($defaults);
$this->setRules($rules);
try {
$this->parsePath();
} catch (Exception $e) {
// The path could not be parsed correctly, treat it as fixed
$this->fixed = true;
$part = self::createPart(Net_URL_Mapper_Part::FIXED, $this->path, $this->path);
$this->parts = array($part);
}
$this->getRequired();
}
/**
* Called when the object is serialized
* Make sure we do not store too much info when the object is serialized
* and call the regular expressions generator functions so that they will
* not need to be generated again on wakeup.
*
* @return array Name of properties to store when serialized
*/
public function __sleep()
{
$this->getFormat();
$this->getRule();
return array('alias', 'path', 'defaults', 'rule', 'format',
'parts', 'minKeys', 'maxKeys', 'fixed', 'required');
}
public function getPath()
{
return $this->path;
}
protected function parsePath()
{
while ($this->yylex()) { }
}
/**
* Get the path alias
* Path aliases can be used instead of full path
* @return null|string
*/
public function getAlias()
{
return $this->alias;
}
/**
* Set the path name
* @param string Set the path name
* @see getAlias()
*/
public function setAlias($alias)
{
$this->alias = $alias;
return $this;
}
/**
* Get the path parts default values
* @return null|array
*/
public function getDefaults()
{
return $this->defaults;
}
/**
* Set the path parts default values
* @param array Associative array with format partname => value
*/
public function setDefaults($defaults)
{
if (is_array($defaults)) {
$this->defaults = $defaults;
} else {
$this->defaults = array();
}
}
/**
* Set the path parts default values
* @param array Associative array with format partname => value
*/
public function setRules($rules)
{
if (is_array($rules)) {
$this->rules = $rules;
} else {
$this->rules = array();
}
}
/**
* Returns the regular expression used to match this path
* @return string PERL Regular expression
*/
public function getRule()
{
if (is_null($this->rule)) {
$this->rule = '/^';
foreach ($this->parts as $path => $part) {
$this->rule .= $part->getRule();
}
$this->rule .= '$/';
}
return $this->rule;
}
public function getFormat()
{
if (is_null($this->format)) {
$this->format = '/^';
foreach ($this->parts as $path => $part) {
$this->format .= $part->getFormat();
}
$this->format .= '$/';
}
return $this->format;
}
protected function addPart($part)
{
if (array_key_exists($part->content, $this->defaults)) {
$part->setRequired(false);
$part->setDefaults($this->defaults[$part->content]);
}
if (isset($this->rules[$part->content])) {
$part->setRule($this->rules[$part->content]);
}
$this->rule = null;
if ($part->getType() != Net_URL_Mapper_Part::FIXED) {
$this->fixed = false;
$this->parts[$part->content] = $part;
} else {
$this->parts[] = $part;
}
return $part;
}
public static function createPart($type, $content, $path)
{
switch ($type) {
case Net_URL_Mapper_Part::DYNAMIC:
return new Net_URL_Mapper_Part_Dynamic($content, $path);
break;
case Net_URL_Mapper_Part::WILDCARD:
return new Net_URL_Mapper_Part_Wildcard($content, $path);
break;
default:
return new Net_URL_Mapper_Part_Fixed($content, $path);
}
}
/**
* Checks whether the path contains the given part by name
* If value parameter is given, the part also checks if the
* given value conforms to the part rule.
* @param string Part name
* @param mixed The value to check against
*/
public function hasKey($partName, $value = null)
{
if (array_key_exists($partName, $this->parts)) {
if (!is_null($value) && $value !== false) {
return $this->parts[$partName]->match($value);
} else {
return true;
}
} elseif (array_key_exists($partName, $this->defaults) &&
$value == $this->defaults[$partName]) {
return true;
}
return false;
}
public function generate($values = array(), $qstring = array(), $anchor = '')
{
$path = '';
foreach ($this->parts as $part) {
$path .= $part->generate($values);
}
$path = '/'.trim(Net_URL::resolvePath($path), '/');
if (!empty($qstring)) {
$path .= '?'.http_build_query($qstring);
}
if (!empty($anchor)) {
$path .= '#'.ltrim($anchor, '#');
}
return $path;
}
public function getRequired()
{
if (!isset($this->required)) {
$req = array();
foreach ($this->parts as $part) {
if ($part->isRequired()) {
$req[] = $part->content;
}
}
$this->required = $req;
}
return $this->required;
}
public function getMaxKeys()
{
if (is_null($this->maxKeys)) {
$this->maxKeys = count($this->required);
$this->maxKeys += count($this->defaults);
}
return $this->maxKeys;
}
/*!lex2php
%input $this->path
%counter $this->N
%token $this->token
%value $this->value
%line $this->line
static = /\/?([^\/:\*]+)/
variable = /([a-zA-Z0-9_]+)/
dynamic = /\/?:/
wildcard = @/?\*@
grouping = /\/?\(([a-zA-Z0-9_]+)\)/
*/
/*!lex2php
%statename START
dynamic grouping {
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::DYNAMIC, $c, $this->value);
$this->addPart($part);
}
wildcard grouping {
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::WILDCARD, $c, $this->value);
$this->addPart($part);
}
dynamic variable {
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::DYNAMIC, $c, $this->value);
$this->addPart($part);
}
wildcard variable {
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::WILDCARD, $c, $this->value);
$this->addPart($part);
}
static {
$c = $yy_subpatterns[0];
$part = self::createPart(Net_URL_Mapper_Part::FIXED, $c, $this->value);
$this->addPart($part);
}
*/
}
?>

View File

@ -138,9 +138,6 @@ class AccountProfileBlock extends ProfileBlock
if (Event::handle('StartProfilePageActionsElements', array($this->out, $this->profile))) {
if (empty($cur)) { // not logged in
if (Event::handle('StartProfileRemoteSubscribe', array($this->out, $this->profile))) {
$this->out->elementStart('li', 'entity_subscribe');
$this->showRemoteSubscribeLink();
$this->out->elementEnd('li');
Event::handle('EndProfileRemoteSubscribe', array($this->out, $this->profile));
}
} else {
@ -298,16 +295,6 @@ class AccountProfileBlock extends ProfileBlock
$this->out->elementEnd('li');
}
function showRemoteSubscribeLink()
{
$url = common_local_url('remotesubscribe',
array('nickname' => $this->profile->nickname));
$this->out->element('a', array('href' => $url,
'class' => 'entity_remote_subscribe'),
// TRANS: Link text for link that will subscribe to a remote profile.
_m('BUTTON','Subscribe'));
}
function show()
{
$this->out->elementStart('div', 'profile_block account_profile_block section');

View File

@ -324,8 +324,12 @@ class Action extends HTMLOutputter // lawsuit
$this->script('xbImportNode.js');
$this->script('geometa.js');
}
$this->inlineScript('var _peopletagAC = "' .
common_local_url('peopletagautocomplete') . '";');
// This route isn't available in single-user mode.
// Not sure why, but it causes errors here.
if (!common_config('singleuser', 'enabled')) {
$this->inlineScript('var _peopletagAC = "' .
common_local_url('peopletagautocomplete') . '";');
}
$this->showScriptMessages();
// Anti-framing code to avoid clickjacking attacks in older browsers.
// This will show a blank page if the page is being framed, which is

View File

@ -20,7 +20,7 @@
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
define('STATUSNET_BASE_VERSION', '1.0.0');
define('STATUSNET_LIFECYCLE', 'beta3'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release'
define('STATUSNET_LIFECYCLE', 'beta4'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release'
define('STATUSNET_VERSION', STATUSNET_BASE_VERSION . STATUSNET_LIFECYCLE);
define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility

View File

@ -71,18 +71,25 @@ function mail_backend()
*/
function mail_send($recipients, $headers, $body)
{
// XXX: use Mail_Queue... maybe
$backend = mail_backend();
if (!isset($headers['Content-Type'])) {
$headers['Content-Type'] = 'text/plain; charset=UTF-8';
}
assert($backend); // throws an error if it's bad
$sent = $backend->send($recipients, $headers, $body);
if (PEAR::isError($sent)) {
common_log(LOG_ERR, 'Email error: ' . $sent->getMessage());
try {
// XXX: use Mail_Queue... maybe
$backend = mail_backend();
if (!isset($headers['Content-Type'])) {
$headers['Content-Type'] = 'text/plain; charset=UTF-8';
}
assert($backend); // throws an error if it's bad
$sent = $backend->send($recipients, $headers, $body);
return true;
} catch (PEAR_Exception $e) {
common_log(
LOG_ERR,
"Unable to send email - '{$e->getMessage()}'. "
. 'Is your mail subsystem set up correctly?'
);
return false;
}
return true;
}
/**

View File

@ -62,10 +62,12 @@ class PublicGroupNav extends Menu
$this->action->elementStart('ul', array('class' => 'nav'));
if (Event::handle('StartPublicGroupNav', array($this))) {
// TRANS: Menu item in search group navigation panel.
$this->out->menuItem(common_local_url('public'), _m('MENU','Public'),
// TRANS: Menu item title in search group navigation panel.
_('Public timeline'), $this->actionName == 'public', 'nav_timeline_public');
if (!common_config('singleuser', 'enabled')) {
// TRANS: Menu item in search group navigation panel.
$this->out->menuItem(common_local_url('public'), _m('MENU','Public'),
// TRANS: Menu item title in search group navigation panel.
_('Public timeline'), $this->actionName == 'public', 'nav_timeline_public');
}
// TRANS: Menu item in search group navigation panel.
$this->out->menuItem(common_local_url('groups'), _m('MENU','Groups'),
@ -84,10 +86,12 @@ class PublicGroupNav extends Menu
_('Featured users'), $this->actionName == 'featured', 'nav_featured');
}
// TRANS: Menu item in search group navigation panel.
$this->out->menuItem(common_local_url('favorited'), _m('MENU','Popular'),
// TRANS: Menu item title in search group navigation panel.
_('Popular notices'), $this->actionName == 'favorited', 'nav_timeline_favorited');
if (!common_config('singleuser', 'enabled')) {
// TRANS: Menu item in search group navigation panel.
$this->out->menuItem(common_local_url('favorited'), _m('MENU','Popular'),
// TRANS: Menu item title in search group navigation panel.
_('Popular notices'), $this->actionName == 'favorited', 'nav_timeline_favorited');
}
Event::handle('EndPublicGroupNav', array($this));
}

View File

@ -31,73 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once 'Net/URL/Mapper.php';
class StatusNet_URL_Mapper extends Net_URL_Mapper
{
private static $_singleton = null;
private $_actionToPath = array();
private function __construct()
{
}
public static function getInstance($id = '__default__')
{
if (empty(self::$_singleton)) {
self::$_singleton = new StatusNet_URL_Mapper();
}
return self::$_singleton;
}
public function connect($path, $defaults = array(), $rules = array())
{
$result = null;
if (Event::handle('StartConnectPath', array(&$path, &$defaults, &$rules, &$result))) {
$result = parent::connect($path, $defaults, $rules);
if (array_key_exists('action', $defaults)) {
$action = $defaults['action'];
} elseif (array_key_exists('action', $rules)) {
$action = $rules['action'];
} else {
$action = null;
}
$this->_mapAction($action, $result);
Event::handle('EndConnectPath', array($path, $defaults, $rules, $result));
}
return $result;
}
protected function _mapAction($action, $path)
{
if (!array_key_exists($action, $this->_actionToPath)) {
$this->_actionToPath[$action] = array();
}
$this->_actionToPath[$action][] = $path;
return;
}
public function generate($values = array(), $qstring = array(), $anchor = '')
{
if (!array_key_exists('action', $values)) {
return parent::generate($values, $qstring, $anchor);
}
$action = $values['action'];
if (!array_key_exists($action, $this->_actionToPath)) {
return parent::generate($values, $qstring, $anchor);
}
$oldPaths = $this->paths;
$this->paths = $this->_actionToPath[$action];
$result = parent::generate($values, $qstring, $anchor);
$this->paths = $oldPaths;
return $result;
}
}
/**
* URL Router
*
@ -136,19 +69,7 @@ class Router
function __construct()
{
if (empty($this->m)) {
if (!common_config('router', 'cache')) {
$this->m = $this->initialize();
} else {
$k = self::cacheKey();
$c = Cache::instance();
$m = $c->get($k);
if (!empty($m)) {
$this->m = $m;
} else {
$this->m = $this->initialize();
$c->set($k, $this->m);
}
}
$this->m = $this->initialize();
}
}
@ -159,8 +80,8 @@ class Router
* you're running and the plugins that are enabled. To avoid having bad routes
* get stuck in the cache, the key includes a list of plugins and the software
* version.
*
* There can still be problems with a) differences in versions of the plugins and
*
* There can still be problems with a) differences in versions of the plugins and
* b) people running code between official versions, but these tend to be more
* sophisticated users who can grok what's going on and clear their caches.
*
@ -183,7 +104,7 @@ class Router
function initialize()
{
$m = StatusNet_URL_Mapper::getInstance();
$m = new URLMapper();
if (Event::handle('StartInitializeRouter', array(&$m))) {
@ -1139,7 +1060,7 @@ class Router
{
try {
$match = $this->m->match($path);
} catch (Net_URL_Mapper_InvalidException $e) {
} catch (Exception $e) {
common_log(LOG_ERR, "Problem getting route for $path - " .
$e->getMessage());
// TRANS: Client error on action trying to visit a non-existing page.
@ -1161,7 +1082,6 @@ class Router
}
$url = $this->m->generate($args, $params, $fragment);
// Due to a bug in the Net_URL_Mapper code, the returned URL may
// contain a malformed query of the form ?p1=v1?p2=v2?p3=v3. We
// repair that here rather than modifying the upstream code...

257
lib/urlmapper.php Normal file
View File

@ -0,0 +1,257 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* URL mapper
*
* PHP version 5
*
* 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 <http://www.gnu.org/licenses/>.
*
* @category URL
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 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);
}
/**
* URL mapper
*
* Converts a path into a set of parameters, and vice versa
*
* We used to use Net_URL_Mapper, so there's a wrapper class at Router, q.v.
*
* NUM's vagaries are the main reason we have weirdnesses here.
*
* @category URL
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class URLMapper
{
const ACTION = 'action';
protected $statics = array();
protected $variables = array();
protected $reverse = array();
protected $allpaths = array();
function connect($path, $args, $paramPatterns=array())
{
if (!array_key_exists(self::ACTION, $args)) {
throw new Exception(sprintf("Can't connect %s; path has no action.", $path));
}
$allpaths[] = $path;
$action = $args[self::ACTION];
$paramNames = $this->getParamNames($path);
if (empty($paramNames)) {
$this->statics[$path] = $args;
if (array_key_exists($action, $this->reverse)) {
$this->reverse[$args[self::ACTION]][] = array($args, $path);
} else {
$this->reverse[$args[self::ACTION]] = array(array($args, $path));
}
} else {
// Eff if I understand why some go here and some go there.
// Anyways, fixup my preconceptions
foreach ($paramNames as $name) {
if (!array_key_exists($name, $paramPatterns) &&
array_key_exists($name, $args)) {
$paramPatterns[$name] = $args[$name];
unset($args[$name]);
}
}
$regex = $this->makeRegex($path, $paramPatterns);
$this->variables[] = array($args, $regex, $paramNames);
$format = $this->makeFormat($path, $paramPatterns);
if (array_key_exists($action, $this->reverse)) {
$this->reverse[$args[self::ACTION]][] = array($args, $format, $paramNames);
} else {
$this->reverse[$args[self::ACTION]] = array(array($args, $format, $paramNames));
}
}
}
function match($path)
{
if (array_key_exists($path, $this->statics)) {
return $this->statics[$path];
}
foreach ($this->variables as $pattern) {
list($args, $regex, $paramNames) = $pattern;
if (preg_match($regex, $path, $match)) {
$results = $args;
foreach ($paramNames as $name) {
$results[$name] = $match[$name];
}
return $results;
}
}
throw new Exception(sprintf('No match for path "%s"', $path));
}
function generate($args, $qstring, $fragment)
{
if (!array_key_exists(self::ACTION, $args)) {
throw new Exception("Every path needs an action.");
}
$action = $args[self::ACTION];
if (!array_key_exists($action, $this->reverse)) {
throw new Exception(sprintf('No candidate paths for action "%s"', $action));
}
$candidates = $this->reverse[$action];
foreach ($candidates as $candidate) {
if (count($candidate) == 2) { // static
list($tryArgs, $tryPath) = $candidate;
foreach ($tryArgs as $key => $value) {
if (!array_key_exists($key, $args) || $args[$key] != $value) {
// next candidate
continue 2;
}
}
// success
$path = $tryPath;
} else {
list($tryArgs, $format, $paramNames) = $candidate;
foreach ($tryArgs as $key => $value) {
if (!array_key_exists($key, $args) || $args[$key] != $value) {
// next candidate
continue 2;
}
}
// success
$toFormat = array();
foreach ($paramNames as $name) {
if (!array_key_exists($name, $args)) {
// next candidate
continue 2;
}
$toFormat[] = $args[$name];
}
$path = vsprintf($format, $toFormat);
}
if (!empty($qstring)) {
$formatted = http_build_query($qstring);
$path .= '?' . $formatted;
}
return $path;
}
// failure; some reporting twiddles
unset($args['action']);
if (empty($args)) {
throw new Exception(sprintf('No matches for action "%s"', $action));
}
$argstring = '';
foreach ($args as $key => $value) {
$argstring .= "$key=$value ";
}
throw new Exception(sprintf('No matches for action "%s" with arguments "%s"', $action, $argstring));
}
protected function getParamNames($path)
{
preg_match_all('/:(?P<name>\w+)/', $path, $match);
return $match['name'];
}
protected function makeRegex($path, $paramPatterns)
{
$pr = new PatternReplacer($paramPatterns);
$regex = preg_replace_callback('/:(\w+)/',
array($pr, 'toPattern'),
$path);
$regex = '#^' . str_replace('#', '\#', $regex) . '$#';
return $regex;
}
protected function makeFormat($path, $paramPatterns)
{
$format = preg_replace('/(:\w+)/', '%s', $path);
return $format;
}
public function getPaths()
{
return $this->allpaths;
}
}
class PatternReplacer
{
private $patterns;
function __construct($patterns)
{
$this->patterns = $patterns;
}
function toPattern($matches)
{
// trim out the :
$name = $matches[1];
if (array_key_exists($name, $this->patterns)) {
$pattern = $this->patterns[$name];
} else {
// ???
$pattern = '\w+';
}
return '(?P<'.$name.'>'.$pattern.')';
}
}

View File

@ -1237,12 +1237,12 @@ function common_local_url($action, $args=null, $params=null, $fragment=null, $ad
$ssl = common_is_sensitive($action);
if (common_config('site','fancy')) {
$url = common_path(mb_substr($path, 1), $ssl, $addSession);
$url = common_path($path, $ssl, $addSession);
} else {
if (mb_strpos($path, '/index.php') === 0) {
$url = common_path(mb_substr($path, 1), $ssl, $addSession);
$url = common_path($path, $ssl, $addSession);
} else {
$url = common_path('index.php'.$path, $ssl, $addSession);
$url = common_path('index.php/'.$path, $ssl, $addSession);
}
}
Event::handle('EndLocalURL', array(&$action, &$params, &$fragment, &$addSession, &$url));
@ -2312,3 +2312,31 @@ function common_is_email($str)
{
return (strpos($str, '@') !== false);
}
function common_init_stats()
{
global $_mem, $_ts;
$_mem = memory_get_usage(true);
$_ts = microtime(true);
}
function common_log_delta($comment=null)
{
global $_mem, $_ts;
$mold = $_mem;
$told = $_ts;
$_mem = memory_get_usage(true);
$_ts = microtime(true);
$mtotal = $_mem - $mold;
$ttotal = $_ts - $told;
if (empty($comment)) {
$comment = 'Delta';
}
common_debug(sprintf("%s: %d %d", $comment, $mtotal, round($ttotal * 1000000)));
}

View File

@ -551,4 +551,25 @@ class BookmarkPlugin extends MicroAppPlugin
// TRANS: Application title.
return _m('TITLE','Bookmark');
}
function onEndUpgrade()
{
// Version 0.9.x of the plugin didn't stamp notices
// with verb and object-type (for obvious reasons). Update
// those notices here.
$notice = new Notice();
$notice->whereAdd('exists (select uri from bookmark where bookmark.uri = notice.uri)');
$notice->whereAdd('((object_type is null) or (object_type = "' .ActivityObject::NOTE.'"))');
$notice->find();
while ($notice->fetch()) {
$original = clone($notice);
$notice->verb = ActivityVerb::POST;
$notice->object_type = ActivityObject::BOOKMARK;
$notice->update($original);
}
}
}

View File

@ -132,6 +132,11 @@ class DirectoryPlugin extends Plugin
array('filter' => '([0-9a-zA-Z_]{1,64}|0-9)')
);
$m->connect(
'groups',
array('action' => 'groupdirectory')
);
return true;
}

View File

@ -124,7 +124,7 @@ class EventForm extends Form
$this->li();
$times = EventTimeList::getTimes($today->format('m/d/Y 12:00') . ' am ' . $today->format('T'));
$start = EventTimeList::nearestHalfHour('@' . $today->getTimestamp());
$start = EventTimeList::nearestHalfHour($today->format('c'));
$start->setTimezone(new DateTimeZone(common_timezone()));
$this->out->dropdown(
@ -160,7 +160,7 @@ class EventForm extends Form
'event-endtime',
// TRANS: Field label on event form.
_m('LABEL','End time'),
EventTimeList::getTimes('@' . $start->getTimestamp(), true),
EventTimeList::getTimes($start->format('c'), true),
// TRANS: Field title on event form.
_m('Time the event ends.'),
false,

View File

@ -377,6 +377,20 @@ class OMBPlugin extends Plugin
return true;
}
function onStartProfileRemoteSubscribe($out, $profile)
{
$out->elementStart('li', 'entity_subscribe');
$url = common_local_url('remotesubscribe',
array('nickname' => $this->profile->nickname));
$out->element('a', array('href' => $url,
'class' => 'entity_remote_subscribe'),
// TRANS: Link text for link that will subscribe to a remote profile.
_m('BUTTON','Subscribe'));
$out->elementEnd('li');
return false;
}
/**
* Plugin version info
*

View File

@ -85,4 +85,23 @@ class SearchSubMenu extends MoreMenu
return $items;
}
function item($actionName, $args, $label, $description, $id=null, $cls=null)
{
if (empty($id)) {
$id = $this->menuItemID($actionName, $args);
}
// Add 'q' as a search param, not part of the url path
$url = common_local_url($actionName, array(), $args);
$this->out->menuItem($url,
$label,
$description,
$this->isCurrent($actionName, $args),
$id,
$cls);
}
}

View File

@ -33,18 +33,27 @@ require_once INSTALLDIR.'/scripts/commandline.inc';
function main()
{
updateSchemaCore();
updateSchemaPlugins();
if (Event::handle('StartUpgrade')) {
updateSchemaCore();
updateSchemaPlugins();
// These replace old "fixup_*" scripts
// These replace old "fixup_*" scripts
fixupNoticeRendered();
fixupNoticeConversation();
initConversation();
initInbox();
fixupGroupURI();
initLocalGroup();
initNoticeReshare();
fixupNoticeRendered();
fixupNoticeConversation();
initConversation();
initInbox();
fixupGroupURI();
initLocalGroup();
initNoticeReshare();
initFaveURI();
initSubscriptionURI();
initGroupMemberURI();
Event::handle('EndUpgrade');
}
}
function tableDefs()
@ -283,4 +292,86 @@ function initNoticeReshare()
printfnq("DONE.\n");
}
function initFaveURI()
{
printfnq("Ensuring all faves have a URI...");
$fave = new Fave();
$fave->whereAdd('uri IS NULL');
if ($fave->find()) {
while ($fave->fetch()) {
try {
$fave->decache();
$fave->query(sprintf('update fave '.
'set uri = "%s", '.
' modified = "%s" '.
'where user_id = %d '.
'and notice_id = %d',
Fave::newURI($fave->user_id, $fave->notice_id, $fave->modified),
common_sql_date(strtotime($fave->modified)),
$fave->user_id,
$fave->notice_id));
} catch (Exception $e) {
common_log(LOG_ERR, "Error updated fave URI: " . $e->getMessage());
}
}
}
printfnq("DONE.\n");
}
function initSubscriptionURI()
{
printfnq("Ensuring all subscriptions have a URI...");
$sub = new Subscription();
$sub->whereAdd('uri IS NULL');
if ($sub->find()) {
while ($sub->fetch()) {
try {
$sub->decache();
$sub->query(sprintf('update subscription '.
'set uri = "%s" '.
'where subscriber = %d '.
'and subscribed = %d',
Subscription::newURI($sub->subscriber, $sub->subscribed, $sub->created),
$sub->subscriber,
$sub->subscribed));
} catch (Exception $e) {
common_log(LOG_ERR, "Error updated subscription URI: " . $e->getMessage());
}
}
}
printfnq("DONE.\n");
}
function initGroupMemberURI()
{
printfnq("Ensuring all group memberships have a URI...");
$mem = new Group_member();
$mem->whereAdd('uri IS NULL');
if ($mem->find()) {
while ($mem->fetch()) {
try {
$mem->decache();
$mem->query(sprintf('update group_member set uri = "%s" '.
'where profile_id = %d ' .
'and group_id = %d ',
Group_member::newURI($mem->profile_id, $mem->group_id, $mem->created),
$mem->profile_id,
$mem->group_id));
} catch (Exception $e) {
common_log(LOG_ERR, "Error updated membership URI: " . $e->getMessage());
}
}
}
printfnq("DONE.\n");
}
main();