X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Frouter.php;h=6533e24e57ff672b578e23057e9bfdda775e4f53;hb=8aacc4b84af5154749f4b0758f41cb705350f704;hp=ff1b27925512e339868a8f08a02847323e91b5a4;hpb=648f79be10c1f62eb649563aa4f1cd5c51ddb19f;p=quix0rs-gnu-social.git diff --git a/lib/router.php b/lib/router.php index ff1b279255..6533e24e57 100644 --- a/lib/router.php +++ b/lib/router.php @@ -33,8 +33,10 @@ 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() { @@ -53,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; + } } /** @@ -77,6 +116,8 @@ class Router static $bare = array('requesttoken', 'accesstoken', 'userauthorization', 'postnotice', 'updateprofile', 'finishremotesubscribe'); + const REGEX_TAG = '[^\/]+'; // [\pL\pN_\-\.]{1,64} better if we can do unicode regexes + static function get() { if (!Router::$inst) { @@ -87,11 +128,52 @@ 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() + { + $parts = array('router'); + + // Many router paths depend on this setting. + if (common_config('singleuser', 'enabled')) { + $parts[] = '1user'; + } else { + $parts[] = 'multi'; + } + + return Cache::codeKey(implode(':', $parts)); + } + function initialize() { $m = StatusNet_URL_Mapper::getInstance(); @@ -117,7 +199,8 @@ class Router // main stuff is repetitive $main = array('login', 'logout', 'register', 'subscribe', - 'unsubscribe', 'confirmaddress', 'recoverpassword', + 'unsubscribe', 'cancelsubscription', 'approvesub', + 'confirmaddress', 'recoverpassword', 'invite', 'favor', 'disfavor', 'sup', 'block', 'unblock', 'subedit', 'groupblock', 'groupunblock', @@ -128,7 +211,10 @@ class Router 'deleteuser', 'geocode', 'version', - ); + 'backupaccount', + 'deleteaccount', + 'restoreaccount', + ); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); @@ -149,6 +235,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 @@ -168,24 +258,24 @@ class Router // settings foreach (array('profile', 'avatar', 'password', 'im', 'oauthconnections', - 'oauthapps', 'email', 'sms', 'userdesign', 'other') as $s) { + 'oauthapps', 'email', 'sms', 'userdesign', 'url') as $s) { $m->connect('settings/'.$s, array('action' => $s.'settings')); } $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 @@ -219,10 +309,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', @@ -244,9 +334,12 @@ class Router $m->connect('conversation/:id', array('action' => 'conversation'), array('id' => '[0-9]+')); + $m->connect('conversation/:id/replies', + array('action' => 'conversationreplies'), + 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]+')); @@ -261,23 +354,23 @@ class Router $m->connect('tag', array('action' => 'publictagcloud')); $m->connect('tag/:tag/rss', array('action' => 'tagrss'), - array('tag' => '[\pL\pN_\-\.]{1,64}')); + array('tag' => self::REGEX_TAG)); $m->connect('tag/:tag', array('action' => 'tag'), - array('tag' => '[\pL\pN_\-\.]{1,64}')); + array('tag' => self::REGEX_TAG)); $m->connect('peopletag/:tag', array('action' => 'peopletag'), - array('tag' => '[a-zA-Z0-9]+')); + array('tag' => self::REGEX_TAG)); // groups $m->connect('group/new', array('action' => 'newgroup')); - foreach (array('edit', 'join', 'leave', 'delete') as $v) { + foreach (array('edit', 'join', 'leave', 'delete', 'cancel', 'approve') 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]+')); @@ -286,20 +379,24 @@ 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/:nickname/members/pending', + array('action' => 'groupqueue'), + array('nickname' => Nickname::DISPLAY_FMT)); $m->connect('group/:id/id', array('action' => 'groupbyid'), @@ -307,7 +404,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')); @@ -318,66 +415,71 @@ class Router // statuses API + $m->connect('api', + array('action' => 'Redirect', + 'nextAction' => 'doc', + 'args' => array('title' => 'api'))); + $m->connect('api/statuses/public_timeline.:format', array('action' => 'ApiTimelinePublic', - 'format' => '(xml|json|rss|atom)')); + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/friends_timeline.:format', array('action' => 'ApiTimelineFriends', - 'format' => '(xml|json|rss|atom)')); + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/friends_timeline/:id.:format', array('action' => 'ApiTimelineFriends', - 'id' => '[a-zA-Z0-9]+', - 'format' => '(xml|json|rss|atom)')); + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/home_timeline.:format', array('action' => 'ApiTimelineHome', - 'format' => '(xml|json|rss|atom)')); + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/home_timeline/:id.:format', array('action' => 'ApiTimelineHome', - 'id' => '[a-zA-Z0-9]+', - 'format' => '(xml|json|rss|atom)')); + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/user_timeline.:format', array('action' => 'ApiTimelineUser', - 'format' => '(xml|json|rss|atom)')); + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/user_timeline/:id.:format', array('action' => 'ApiTimelineUser', - 'id' => '[a-zA-Z0-9]+', - 'format' => '(xml|json|rss|atom)')); + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/mentions.:format', array('action' => 'ApiTimelineMentions', - 'format' => '(xml|json|rss|atom)')); + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/mentions/:id.:format', array('action' => 'ApiTimelineMentions', - 'id' => '[a-zA-Z0-9]+', - 'format' => '(xml|json|rss|atom)')); + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/replies.:format', array('action' => 'ApiTimelineMentions', - 'format' => '(xml|json|rss|atom)')); + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/replies/:id.:format', array('action' => 'ApiTimelineMentions', - 'id' => '[a-zA-Z0-9]+', - 'format' => '(xml|json|rss|atom)')); + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statuses/retweeted_by_me.:format', array('action' => 'ApiTimelineRetweetedByMe', - 'format' => '(xml|json|atom)')); + 'format' => '(xml|json|atom|as)')); $m->connect('api/statuses/retweeted_to_me.:format', array('action' => 'ApiTimelineRetweetedToMe', - 'format' => '(xml|json|atom)')); + 'format' => '(xml|json|atom|as)')); $m->connect('api/statuses/retweets_of_me.:format', array('action' => 'ApiTimelineRetweetsOfMe', - 'format' => '(xml|json|atom)')); + 'format' => '(xml|json|atom|as)')); $m->connect('api/statuses/friends.:format', array('action' => 'ApiUserFriends', @@ -385,7 +487,7 @@ class Router $m->connect('api/statuses/friends/:id.:format', array('action' => 'ApiUserFriends', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_FMT, 'format' => '(xml|json)')); $m->connect('api/statuses/followers.:format', @@ -394,17 +496,17 @@ class Router $m->connect('api/statuses/followers/:id.:format', array('action' => 'ApiUserFollowers', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_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', @@ -437,7 +539,12 @@ class Router $m->connect('api/users/show/:id.:format', array('action' => 'ApiUserShow', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/users/profile_image/:screen_name.:format', + array('action' => 'ApiUserProfileImage', + 'screen_name' => Nickname::DISPLAY_FMT, 'format' => '(xml|json)')); // direct messages @@ -475,12 +582,12 @@ class Router $m->connect('api/friendships/create/:id.:format', array('action' => 'ApiFriendshipsCreate', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_FMT, 'format' => '(xml|json)')); $m->connect('api/friendships/destroy/:id.:format', array('action' => 'ApiFriendshipsDestroy', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_FMT, 'format' => '(xml|json)')); // Social graph @@ -533,32 +640,40 @@ class Router $m->connect('api/favorites.:format', array('action' => 'ApiTimelineFavorites', - 'format' => '(xml|json|rss|atom)')); + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/favorites/:id.:format', array('action' => 'ApiTimelineFavorites', - 'id' => '[a-zA-Z0-9]+', - 'format' => '(xml|json|rss|atom)')); + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/favorites/create/:id.:format', array('action' => 'ApiFavoriteCreate', - 'id' => '[a-zA-Z0-9]+', + 'id' => '[0-9]+', 'format' => '(xml|json)')); $m->connect('api/favorites/destroy/:id.:format', array('action' => 'ApiFavoriteDestroy', - 'id' => '[a-zA-Z0-9]+', + 'id' => '[0-9]+', '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::INPUT_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::INPUT_FMT, 'format' => '(xml|json)')); // help @@ -594,8 +709,8 @@ class Router $m->connect('api/statusnet/groups/timeline/:id.:format', array('action' => 'ApiTimelineGroup', - 'id' => '[a-zA-Z0-9]+', - 'format' => '(xml|json|rss|atom)')); + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); $m->connect('api/statusnet/groups/show.:format', array('action' => 'ApiGroupShow', @@ -603,12 +718,12 @@ class Router $m->connect('api/statusnet/groups/show/:id.:format', array('action' => 'ApiGroupShow', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_FMT, 'format' => '(xml|json)')); $m->connect('api/statusnet/groups/join.:format', array('action' => 'ApiGroupJoin', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_FMT, 'format' => '(xml|json)')); $m->connect('api/statusnet/groups/join/:id.:format', @@ -617,7 +732,7 @@ class Router $m->connect('api/statusnet/groups/leave.:format', array('action' => 'ApiGroupLeave', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_FMT, 'format' => '(xml|json)')); $m->connect('api/statusnet/groups/leave/:id.:format', @@ -634,7 +749,7 @@ class Router $m->connect('api/statusnet/groups/list/:id.:format', array('action' => 'ApiGroupList', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_FMT, 'format' => '(xml|json|rss|atom)')); $m->connect('api/statusnet/groups/list_all.:format', @@ -647,16 +762,22 @@ class Router $m->connect('api/statusnet/groups/membership/:id.:format', array('action' => 'ApiGroupMembership', - 'id' => '[a-zA-Z0-9]+', + 'id' => Nickname::INPUT_FMT, 'format' => '(xml|json)')); $m->connect('api/statusnet/groups/create.:format', array('action' => 'ApiGroupCreate', 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/update/:id.:format', + array('action' => 'ApiGroupProfileUpdate', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + // Tags $m->connect('api/statusnet/tags/timeline/:tag.:format', array('action' => 'ApiTimelineTag', - 'format' => '(xml|json|rss|atom)')); + 'format' => '(xml|json|rss|atom|as)')); // media related $m->connect( @@ -676,19 +797,27 @@ class Router array('action' => 'ApiOauthAccessToken')); $m->connect('api/oauth/authorize', - array('action' => 'apioauthauthorize')); + array('action' => 'ApiOauthAuthorize')); // Admin - $m->connect('admin/site', array('action' => 'siteadminpanel')); - $m->connect('admin/design', array('action' => 'designadminpanel')); - $m->connect('admin/user', array('action' => 'useradminpanel')); - $m->connect('admin/access', array('action' => 'accessadminpanel')); - $m->connect('admin/paths', array('action' => 'pathsadminpanel')); - $m->connect('admin/sessions', array('action' => 'sessionsadminpanel')); - $m->connect('admin/sitenotice', array('action' => 'sitenoticeadminpanel')); - $m->connect('admin/snapshot', array('action' => 'snapshotadminpanel')); - $m->connect('admin/license', array('action' => 'licenseadminpanel')); + $m->connect('panel/site', array('action' => 'siteadminpanel')); + $m->connect('panel/design', array('action' => 'designadminpanel')); + $m->connect('panel/user', array('action' => 'useradminpanel')); + $m->connect('panel/access', array('action' => 'accessadminpanel')); + $m->connect('panel/paths', array('action' => 'pathsadminpanel')); + $m->connect('panel/sessions', array('action' => 'sessionsadminpanel')); + $m->connect('panel/sitenotice', array('action' => 'sitenoticeadminpanel')); + $m->connect('panel/snapshot', array('action' => 'snapshotadminpanel')); + $m->connect('panel/license', array('action' => 'licenseadminpanel')); + + $m->connect('panel/plugins', array('action' => 'pluginsadminpanel')); + $m->connect('panel/plugins/enable/:plugin', + array('action' => 'pluginenable'), + array('plugin' => '[A-Za-z0-9_]+')); + $m->connect('panel/plugins/disable/:plugin', + array('action' => 'plugindisable'), + array('plugin' => '[A-Za-z0-9_]+')); $m->connect('getfile/:filename', array('action' => 'getfile'), @@ -698,8 +827,7 @@ class Router if (common_config('singleuser', 'enabled')) { - $user = User::singleUser(); - $nickname = $user->nickname; + $nickname = User::singleUserNickname(); foreach (array('subscriptions', 'subscribers', 'all', 'foaf', 'xrds', @@ -713,9 +841,13 @@ class Router $m->connect($a.'/:tag', array('action' => $a, 'nickname' => $nickname), - array('tag' => '[a-zA-Z0-9]+')); + array('tag' => self::REGEX_TAG)); } + $m->connect('subscribers/pending', + array('action' => 'subqueue', + 'nickname' => $nickname)); + foreach (array('rss', 'groups') as $a) { $m->connect($a, array('action' => 'user'.$a, @@ -740,12 +872,12 @@ class Router $m->connect('tag/:tag/rss', array('action' => 'userrss', 'nickname' => $nickname), - array('tag' => '[\pL\pN_\-\.]{1,64}')); + array('tag' => self::REGEX_TAG)); $m->connect('tag/:tag', array('action' => 'showstream', 'nickname' => $nickname), - array('tag' => '[\pL\pN_\-\.]{1,64}')); + array('tag' => self::REGEX_TAG)); $m->connect('rsd.xml', array('action' => 'rsd', @@ -770,56 +902,101 @@ 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)); } + $m->connect(':nickname/subscribers/pending', + array('action' => 'subqueue'), + 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}')); + array('tag' => self::REGEX_TAG, + '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('tag' => '[\pL\pN_\-\.]{1,64}')); + array('nickname' => Nickname::DISPLAY_FMT), + array('tag' => self::REGEX_TAG)); $m->connect(':nickname/tag/:tag', array('action' => 'showstream'), - array('nickname' => '[a-zA-Z0-9]{1,64}'), - array('tag' => '[\pL\pN_\-\.]{1,64}')); + array('nickname' => Nickname::DISPLAY_FMT), + array('tag' => self::REGEX_TAG)); $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'), + array('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]+')); + + $m->connect('api/statusnet/app/favorites/:profile/:notice.atom', + array('action' => 'AtomPubShowFavorite'), + array('profile' => '[0-9]+', + 'notice' => '[0-9]+')); + + $m->connect('api/statusnet/app/favorites/:profile.atom', + array('action' => 'AtomPubFavoriteFeed'), + array('profile' => '[0-9]+')); + + $m->connect('api/statusnet/app/memberships/:profile/:group.atom', + array('action' => 'AtomPubShowMembership'), + array('profile' => '[0-9]+', + 'group' => '[0-9]+')); + + $m->connect('api/statusnet/app/memberships/:profile.atom', + array('action' => 'AtomPubMembershipFeed'), + array('profile' => '[0-9]+')); + + // URL shortening + + $m->connect('url/:id', + array('action' => 'redirecturl', + 'id' => '[0-9]+')); + // user stuff Event::handle('RouterInitialized', array($m)); @@ -862,8 +1039,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; } }