X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Frouter.php;h=e6b4c0fbc8a08dfb32456837303bba98fd131143;hb=c619a257fe04a5ad4cc670c14cc1eab2042b71d8;hp=b1cc8d52941347bec09400c38c7affdba68a1ed2;hpb=6c77d86b7f39c35eac0fcc3f13c0beba3e694318;p=quix0rs-gnu-social.git diff --git a/lib/router.php b/lib/router.php index b1cc8d5294..e6b4c0fbc8 100644 --- a/lib/router.php +++ b/lib/router.php @@ -33,14 +33,15 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { require_once 'Net/URL/Mapper.php'; -class StatusNet_URL_Mapper extends Net_URL_Mapper { - +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)) { @@ -54,10 +55,47 @@ class StatusNet_URL_Mapper extends Net_URL_Mapper { $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; + } } /** @@ -71,7 +109,6 @@ class StatusNet_URL_Mapper extends Net_URL_Mapper { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ - class Router { var $m = null; @@ -89,11 +126,43 @@ class Router function __construct() { - if (!$this->m) { - $this->m = $this->initialize(); + 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); + } + } } } + /** + * Create a unique hashkey for the router. + * + * The router's url map can change based on the version of the software + * 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 + * 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. + * + * @return string cache key string that should uniquely identify a router + */ + + static function cacheKey() + { + return Cache::codeKey('router'); + } + function initialize() { $m = StatusNet_URL_Mapper::getInstance(); @@ -130,7 +199,7 @@ class Router 'deleteuser', 'geocode', 'version', - ); + ); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); @@ -151,6 +220,10 @@ class Router $m->connect('main/xrds', array('action' => 'publicxrds')); + $m->connect('.well-known/host-meta', + array('action' => 'hostmeta')); + $m->connect('main/xrd', + array('action' => 'userxrd')); // these take a code @@ -175,19 +248,19 @@ class Router } $m->connect('settings/oauthapps/show/:id', - array('action' => 'showapplication'), - array('id' => '[0-9]+') + array('action' => 'showapplication'), + array('id' => '[0-9]+') ); $m->connect('settings/oauthapps/new', - array('action' => 'newapplication') + array('action' => 'newapplication') ); $m->connect('settings/oauthapps/edit/:id', - array('action' => 'editapplication'), - array('id' => '[0-9]+') + array('action' => 'editapplication'), + array('id' => '[0-9]+') ); $m->connect('settings/oauthapps/delete/:id', - array('action' => 'deleteapplication'), - array('id' => '[0-9]+') + array('action' => 'deleteapplication'), + array('id' => '[0-9]+') ); // search @@ -221,10 +294,10 @@ class Router $m->connect('notice/new', array('action' => 'newnotice')); $m->connect('notice/new?replyto=:replyto', array('action' => 'newnotice'), - array('replyto' => '[A-Za-z0-9_-]+')); + array('replyto' => Nickname::DISPLAY_FMT)); $m->connect('notice/new?replyto=:replyto&inreplyto=:inreplyto', array('action' => 'newnotice'), - array('replyto' => '[A-Za-z0-9_-]+'), + array('replyto' => Nickname::DISPLAY_FMT), array('inreplyto' => '[0-9]+')); $m->connect('notice/:notice/file', @@ -248,7 +321,7 @@ class Router array('id' => '[0-9]+')); $m->connect('message/new', array('action' => 'newmessage')); - $m->connect('message/new?to=:to', array('action' => 'newmessage'), array('to' => '[A-Za-z0-9_-]+')); + $m->connect('message/new?to=:to', array('action' => 'newmessage'), array('to' => Nickname::DISPLAY_FMT)); $m->connect('message/:message', array('action' => 'showmessage'), array('message' => '[0-9]+')); @@ -279,7 +352,7 @@ class Router foreach (array('edit', 'join', 'leave', 'delete') as $v) { $m->connect('group/:nickname/'.$v, array('action' => $v.'group'), - array('nickname' => '[a-zA-Z0-9]+')); + array('nickname' => Nickname::DISPLAY_FMT)); $m->connect('group/:id/id/'.$v, array('action' => $v.'group'), array('id' => '[0-9]+')); @@ -288,20 +361,20 @@ class Router foreach (array('members', 'logo', 'rss', 'designsettings') as $n) { $m->connect('group/:nickname/'.$n, array('action' => 'group'.$n), - array('nickname' => '[a-zA-Z0-9]+')); + array('nickname' => Nickname::DISPLAY_FMT)); } $m->connect('group/:nickname/foaf', array('action' => 'foafgroup'), - array('nickname' => '[a-zA-Z0-9]+')); + array('nickname' => Nickname::DISPLAY_FMT)); $m->connect('group/:nickname/blocked', array('action' => 'blockedfromgroup'), - array('nickname' => '[a-zA-Z0-9]+')); + array('nickname' => Nickname::DISPLAY_FMT)); $m->connect('group/:nickname/makeadmin', array('action' => 'makeadmin'), - array('nickname' => '[a-zA-Z0-9]+')); + array('nickname' => Nickname::DISPLAY_FMT)); $m->connect('group/:id/id', array('action' => 'groupbyid'), @@ -309,7 +382,7 @@ class Router $m->connect('group/:nickname', array('action' => 'showgroup'), - array('nickname' => '[a-zA-Z0-9]+')); + array('nickname' => Nickname::DISPLAY_FMT)); $m->connect('group/', array('action' => 'groups')); $m->connect('group', array('action' => 'groups')); @@ -330,7 +403,7 @@ class Router $m->connect('api/statuses/friends_timeline/:id.:format', array('action' => 'ApiTimelineFriends', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/home_timeline.:format', @@ -339,7 +412,7 @@ class Router $m->connect('api/statuses/home_timeline/:id.:format', array('action' => 'ApiTimelineHome', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/user_timeline.:format', @@ -348,7 +421,7 @@ class Router $m->connect('api/statuses/user_timeline/:id.:format', array('action' => 'ApiTimelineUser', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/mentions.:format', @@ -357,7 +430,7 @@ class Router $m->connect('api/statuses/mentions/:id.:format', array('action' => 'ApiTimelineMentions', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/replies.:format', @@ -366,7 +439,7 @@ class Router $m->connect('api/statuses/replies/:id.:format', array('action' => 'ApiTimelineMentions', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/retweeted_by_me.:format', @@ -387,7 +460,7 @@ class Router $m->connect('api/statuses/friends/:id.:format', array('action' => 'ApiUserFriends', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); $m->connect('api/statuses/followers.:format', @@ -396,17 +469,17 @@ class Router $m->connect('api/statuses/followers/:id.:format', array('action' => 'ApiUserFollowers', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); $m->connect('api/statuses/show.:format', array('action' => 'ApiStatusesShow', - 'format' => '(xml|json)')); + 'format' => '(xml|json|atom)')); $m->connect('api/statuses/show/:id.:format', array('action' => 'ApiStatusesShow', 'id' => '[0-9]+', - 'format' => '(xml|json)')); + 'format' => '(xml|json|atom)')); $m->connect('api/statuses/update.:format', array('action' => 'ApiStatusesUpdate', @@ -439,7 +512,7 @@ class Router $m->connect('api/users/show/:id.:format', array('action' => 'ApiUserShow', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); // direct messages @@ -477,12 +550,12 @@ class Router $m->connect('api/friendships/create/:id.:format', array('action' => 'ApiFriendshipsCreate', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); $m->connect('api/friendships/destroy/:id.:format', array('action' => 'ApiFriendshipsDestroy', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); // Social graph @@ -539,28 +612,36 @@ class Router $m->connect('api/favorites/:id.:format', array('action' => 'ApiTimelineFavorites', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json|rss|atom)')); $m->connect('api/favorites/create/:id.:format', array('action' => 'ApiFavoriteCreate', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); $m->connect('api/favorites/destroy/:id.:format', array('action' => 'ApiFavoriteDestroy', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); // blocks + $m->connect('api/blocks/create.:format', + array('action' => 'ApiBlockCreate', + 'format' => '(xml|json)')); + $m->connect('api/blocks/create/:id.:format', array('action' => 'ApiBlockCreate', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/blocks/destroy.:format', + array('action' => 'ApiBlockDestroy', 'format' => '(xml|json)')); $m->connect('api/blocks/destroy/:id.:format', array('action' => 'ApiBlockDestroy', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); // help @@ -596,7 +677,7 @@ class Router $m->connect('api/statusnet/groups/timeline/:id.:format', array('action' => 'ApiTimelineGroup', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json|rss|atom)')); $m->connect('api/statusnet/groups/show.:format', @@ -605,12 +686,12 @@ class Router $m->connect('api/statusnet/groups/show/:id.:format', array('action' => 'ApiGroupShow', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); $m->connect('api/statusnet/groups/join.:format', array('action' => 'ApiGroupJoin', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); $m->connect('api/statusnet/groups/join/:id.:format', @@ -619,7 +700,7 @@ class Router $m->connect('api/statusnet/groups/leave.:format', array('action' => 'ApiGroupLeave', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); $m->connect('api/statusnet/groups/leave/:id.:format', @@ -636,7 +717,7 @@ class Router $m->connect('api/statusnet/groups/list/:id.:format', array('action' => 'ApiGroupList', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json|rss|atom)')); $m->connect('api/statusnet/groups/list_all.:format', @@ -649,7 +730,7 @@ class Router $m->connect('api/statusnet/groups/membership/:id.:format', array('action' => 'ApiGroupMembership', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); $m->connect('api/statusnet/groups/create.:format', @@ -692,7 +773,6 @@ class Router $m->connect('admin/snapshot', array('action' => 'snapshotadminpanel')); $m->connect('admin/license', array('action' => 'licenseadminpanel')); - $m->connect('getfile/:filename', array('action' => 'getfile'), array('filename' => '[A-Za-z0-9._-]+')); @@ -701,16 +781,7 @@ class Router if (common_config('singleuser', 'enabled')) { - $user = User::siteOwner(); - - if (!empty($user)) { - $nickname = $user->nickname; - } else { - $nickname = common_config('singleuser', 'nickname'); - if (empty($nickname)) { - throw new ServerException(_("No single user defined for single-user mode.")); - } - } + $nickname = User::singleUserNickname(); foreach (array('subscriptions', 'subscribers', 'all', 'foaf', 'xrds', @@ -765,9 +836,7 @@ class Router $m->connect('', array('action' => 'showstream', 'nickname' => $nickname)); - } else { - $m->connect('', array('action' => 'public')); $m->connect('rss', array('action' => 'publicrss')); $m->connect('featuredrss', array('action' => 'featuredrss')); @@ -783,56 +852,74 @@ class Router 'replies', 'inbox', 'outbox', 'microsummary', 'hcard') as $a) { $m->connect(':nickname/'.$a, array('action' => $a), - array('nickname' => '[a-zA-Z0-9]{1,64}')); + array('nickname' => Nickname::DISPLAY_FMT)); } foreach (array('subscriptions', 'subscribers') as $a) { $m->connect(':nickname/'.$a.'/:tag', array('action' => $a), array('tag' => '[a-zA-Z0-9]+', - 'nickname' => '[a-zA-Z0-9]{1,64}')); + 'nickname' => Nickname::DISPLAY_FMT)); } foreach (array('rss', 'groups') as $a) { $m->connect(':nickname/'.$a, array('action' => 'user'.$a), - array('nickname' => '[a-zA-Z0-9]{1,64}')); + array('nickname' => Nickname::DISPLAY_FMT)); } foreach (array('all', 'replies', 'favorites') as $a) { $m->connect(':nickname/'.$a.'/rss', array('action' => $a.'rss'), - array('nickname' => '[a-zA-Z0-9]{1,64}')); + array('nickname' => Nickname::DISPLAY_FMT)); } $m->connect(':nickname/favorites', array('action' => 'showfavorites'), - array('nickname' => '[a-zA-Z0-9]{1,64}')); + array('nickname' => Nickname::DISPLAY_FMT)); $m->connect(':nickname/avatar/:size', array('action' => 'avatarbynickname'), array('size' => '(original|96|48|24)', - 'nickname' => '[a-zA-Z0-9]{1,64}')); + 'nickname' => Nickname::DISPLAY_FMT)); $m->connect(':nickname/tag/:tag/rss', array('action' => 'userrss'), - array('nickname' => '[a-zA-Z0-9]{1,64}'), + array('nickname' => Nickname::DISPLAY_FMT), array('tag' => '[\pL\pN_\-\.]{1,64}')); $m->connect(':nickname/tag/:tag', array('action' => 'showstream'), - array('nickname' => '[a-zA-Z0-9]{1,64}'), + array('nickname' => Nickname::DISPLAY_FMT), array('tag' => '[\pL\pN_\-\.]{1,64}')); $m->connect(':nickname/rsd.xml', array('action' => 'rsd'), - array('nickname' => '[a-zA-Z0-9]{1,64}')); + array('nickname' => Nickname::DISPLAY_FMT)); $m->connect(':nickname', array('action' => 'showstream'), - array('nickname' => '[a-zA-Z0-9]{1,64}')); + array('nickname' => Nickname::DISPLAY_FMT)); } + // AtomPub API + + $m->connect('api/statusnet/app/service/:id.xml', + array('action' => 'ApiAtomService', + 'id' => Nickname::DISPLAY_FMT)); + + $m->connect('api/statusnet/app/service.xml', + array('action' => 'ApiAtomService')); + + $m->connect('api/statusnet/app/subscriptions/:subscriber/:subscribed.atom', + array('action' => 'AtomPubShowSubscription'), + array('subscriber' => '[0-9]+', + 'subscribed' => '[0-9]+')); + + $m->connect('api/statusnet/app/subscriptions/:subscriber.atom', + array('action' => 'AtomPubSubscriptionFeed'), + array('subscriber' => '[0-9]+')); + // user stuff Event::handle('RouterInitialized', array($m)); @@ -848,7 +935,8 @@ class Router } catch (Net_URL_Mapper_InvalidException $e) { common_log(LOG_ERR, "Problem getting route for $path - " . $e->getMessage()); - $cac = new ClientErrorAction("Page not found.", 404); + // TRANS: Client error on action trying to visit a non-existing page. + $cac = new ClientErrorAction(_('Page not found.'), 404); $cac->showPage(); } @@ -874,8 +962,17 @@ class Router $qpos = strpos($url, '?'); if ($qpos !== false) { $url = substr($url, 0, $qpos+1) . - str_replace('?', '&', substr($url, $qpos+1)); + str_replace('?', '&', substr($url, $qpos+1)); + + // @fixme this is a hacky workaround for http_build_query in the + // lower-level code and bad configs that set the default separator + // to & instead of &. Encoded &s in parameters will not be + // affected. + $url = substr($url, 0, $qpos+1) . + str_replace('&', '&', substr($url, $qpos+1)); + } + return $url; } }