From 7e173f5db80b348d01375a1e53b8ac050c082dea Mon Sep 17 00:00:00 2001 From: Jeroen De Dauw Date: Sat, 20 Nov 2010 15:14:12 +0100 Subject: [PATCH 01/10] Added Awesomeness extension --- plugins/Awesomeness/AwesomenessPlugin.php | 111 ++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 plugins/Awesomeness/AwesomenessPlugin.php diff --git a/plugins/Awesomeness/AwesomenessPlugin.php b/plugins/Awesomeness/AwesomenessPlugin.php new file mode 100644 index 0000000000..0d7900064d --- /dev/null +++ b/plugins/Awesomeness/AwesomenessPlugin.php @@ -0,0 +1,111 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Jeroen De Dauw + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Facebook plugin to add a StatusNet Facebook canvas application + * and allow registration and authentication via Facebook Connect + * + * @category Plugin + * @package StatusNet + * @author Jeroen De Dauw + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class AwesomenessPlugin extends Plugin +{ + + const VERSION = '0.0.42'; + + public function onPluginVersion(&$versions) + { + $versions[] = array( + 'name' => 'Awesomeness', + 'version' => self::VERSION, + 'author' => 'Jeroen De Dauw', + 'homepage' => 'http://status.net/wiki/Plugin:Awesomeness', + 'rawdescription' => _m( + 'The Awesomeness plugin adds adittional awesomeness ' . + 'to your StatusNet install. ' + ) + ); + return true; + } + + /** + * Add the conrnify button + * + * @param Action $action the current action + * + * @return void + */ + + function onEndShowSections(Action $action) + { + $action->elementStart('div', array('id' => 'cornify_section', + 'class' => 'section')); + + $action->raw( + << + Cornify + + +EOT + ); + + $action->elementEnd('div'); + } + + /** + * Hook for new-notice form processing to take our HTML goodies; + * won't affect API posting etc. + * + * @param NewNoticeAction $action + * @param User $user + * @param string $content + * @param array $options + * @return boolean hook return + */ + function onStartSaveNewNoticeWeb($action, $user, &$content, &$options) + { + $content = htmlspecialchars($content); + $options['rendered'] = preg_replace("/(^|\s|-)(awesome|awesomeness[\?!\.\,]?)(\s|$)/i", " $2 ", $content); + } + +} \ No newline at end of file From 5ad06e80b654d8a6a6e5487349e659d8ee46d471 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 22 Nov 2010 12:38:47 -0800 Subject: [PATCH 02/10] Tweak regex in Awesomeness plugin --- plugins/Awesomeness/AwesomenessPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Awesomeness/AwesomenessPlugin.php b/plugins/Awesomeness/AwesomenessPlugin.php index 0d7900064d..c182264b7f 100644 --- a/plugins/Awesomeness/AwesomenessPlugin.php +++ b/plugins/Awesomeness/AwesomenessPlugin.php @@ -105,7 +105,7 @@ EOT function onStartSaveNewNoticeWeb($action, $user, &$content, &$options) { $content = htmlspecialchars($content); - $options['rendered'] = preg_replace("/(^|\s|-)(awesome|awesomeness[\?!\.\,]?)(\s|$)/i", " $2 ", $content); + $options['rendered'] = preg_replace("/(^|\s|-)((?:awesome|awesomeness)[\?!\.\,]?)(\s|$)/i", " $2 ", $content); } } \ No newline at end of file From c0ce953288db5a3c632184f68f81db135eff0250 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 22 Nov 2010 12:39:38 -0800 Subject: [PATCH 03/10] Update doc comment for Awesomeness plugin --- plugins/Awesomeness/AwesomenessPlugin.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/Awesomeness/AwesomenessPlugin.php b/plugins/Awesomeness/AwesomenessPlugin.php index c182264b7f..294f094389 100644 --- a/plugins/Awesomeness/AwesomenessPlugin.php +++ b/plugins/Awesomeness/AwesomenessPlugin.php @@ -31,8 +31,7 @@ if (!defined('STATUSNET')) { } /** - * Facebook plugin to add a StatusNet Facebook canvas application - * and allow registration and authentication via Facebook Connect + * Fun sample plugin: tweaks input data and adds a 'Cornify' widget to sidebar. * * @category Plugin * @package StatusNet From 806832e3392d6f2a824bc368dae4bc2831da39fa Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 26 Nov 2010 11:18:41 -0500 Subject: [PATCH 04/10] Revert "Ticket #2796: don't allow arbitrary overriding of the 'action' class and other parameters pulled from the URL mapper." This reverts commit 4193a826d3500c1c8771e2a55ca197011fe637c8. --- index.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/index.php b/index.php index 6079d1f2c4..9501e2275d 100644 --- a/index.php +++ b/index.php @@ -272,11 +272,7 @@ function main() return; } - // Note the order here: arguments from the URL mapper will - // override request params that have been sent. This ensures - // that for instance an action parameter can't be overridden - // with an arbitrary action class. - $args = array_merge($_REQUEST, $args); + $args = array_merge($args, $_REQUEST); Event::handle('ArgsInitialize', array(&$args)); From f5c854906850f37a5b9f4816fe2b28de14353859 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 30 Nov 2010 09:57:02 -0500 Subject: [PATCH 05/10] Squashed commit of the following: commit 39fdd181d95d2c39a3ea1ca330b10a99a92b961f Author: Evan Prodromou Date: Mon Nov 29 10:37:49 2010 -0500 use cache key prefix for router cache key commit 4cb9e56941922489b83d6425c059cf770991e68f Author: Evan Prodromou Date: Mon Nov 29 10:31:21 2010 -0500 use a unique hashkey based on the software version and loaded plugins commit 44458b48aef719543e11f83b41fded65cbcb8be9 Author: Evan Prodromou Date: Sat Nov 27 17:04:15 2010 -0500 cache the NUM object commit 809c188307a9b4ada15f3d7fa573a6034341efef Author: Evan Prodromou Date: Sat Nov 27 15:44:12 2010 -0500 accelerate routing by pivoting paths on actions --- lib/router.php | 84 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/lib/router.php b/lib/router.php index 9aaac7dfe3..3ea93b7081 100644 --- a/lib/router.php +++ b/lib/router.php @@ -33,13 +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)) { @@ -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; + } } /** @@ -87,11 +126,48 @@ class Router function __construct() { - if (!$this->m) { - $this->m = $this->initialize(); + if (empty($this->m)) { + $k = self::cacheKey(); + $m = Cache::get($k); + if (!empty($m)) { + $this->m = $m; + } else { + $this->m = $this->initialize(); + Cache::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() + { + $plugins = StatusNet::getActivePlugins(); + $names = array(); + + foreach ($plugins as $plugin) { + $names[] = $plugin[0]; + } + + $names = array_unique($names); + asort($names); + + return Cache::key('router:'.STATUSNET_VERSION.':'.implode(',', $names)); + } + function initialize() { $m = StatusNet_URL_Mapper::getInstance(); From c86dff990196f0a9a5cd2eb5a7183c39ea851446 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 30 Nov 2010 10:11:39 -0500 Subject: [PATCH 06/10] use a CRC32 of the plugin names rather than actual names --- lib/router.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/router.php b/lib/router.php index 3ea93b7081..1cd66ca79d 100644 --- a/lib/router.php +++ b/lib/router.php @@ -164,8 +164,12 @@ class Router $names = array_unique($names); asort($names); + + // Unique enough. - return Cache::key('router:'.STATUSNET_VERSION.':'.implode(',', $names)); + $uniq = crc32(implode(',', $names)); + + return Cache::key('router:'.STATUSNET_VERSION.':'.$uniq); } function initialize() From 0d99a01d7412be761a7888132573c2bc40848456 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 30 Nov 2010 10:27:32 -0500 Subject: [PATCH 07/10] a quick script to flush the router from cache if needed --- scripts/flushrouter.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 scripts/flushrouter.php diff --git a/scripts/flushrouter.php b/scripts/flushrouter.php new file mode 100644 index 0000000000..79493eae49 --- /dev/null +++ b/scripts/flushrouter.php @@ -0,0 +1,33 @@ +#!/usr/bin/env php +. + */ + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); + +$helptext = << +Flush the url router from cache. + +END_OF_FLUSHROUTER_HELP; + +require_once INSTALLDIR.'/scripts/commandline.inc'; + +Cache::delete(Router::cacheKey()); + +print "OK.\n"; \ No newline at end of file From af31767b637849f4cc904a89e30ccc81b4f4df66 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 30 Nov 2010 14:44:16 -0500 Subject: [PATCH 08/10] was using Cache::get() and ::set() wrong --- lib/router.php | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/router.php b/lib/router.php index 1cd66ca79d..7272a96904 100644 --- a/lib/router.php +++ b/lib/router.php @@ -128,12 +128,13 @@ class Router { if (empty($this->m)) { $k = self::cacheKey(); - $m = Cache::get($k); + $c = Cache::instance(); + $m = $c->get($k); if (!empty($m)) { $this->m = $m; } else { $this->m = $this->initialize(); - Cache::set($k, $this->m); + $c->set($k, $this->m); } } } @@ -156,18 +157,18 @@ class Router static function cacheKey() { $plugins = StatusNet::getActivePlugins(); - $names = array(); + $names = array(); - foreach ($plugins as $plugin) { - $names[] = $plugin[0]; - } + foreach ($plugins as $plugin) { + $names[] = $plugin[0]; + } - $names = array_unique($names); - asort($names); + $names = array_unique($names); + asort($names); - // Unique enough. + // Unique enough. - $uniq = crc32(implode(',', $names)); + $uniq = crc32(implode(',', $names)); return Cache::key('router:'.STATUSNET_VERSION.':'.$uniq); } From bcccbd6d8afb8b022d80ca7fa558ac4dbb31d38b Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 30 Nov 2010 12:40:23 -0800 Subject: [PATCH 09/10] BitlyPlugin: fix for shortening URLs containing ampersand (&) --- plugins/BitlyUrl/BitlyUrlPlugin.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/BitlyUrl/BitlyUrlPlugin.php b/plugins/BitlyUrl/BitlyUrlPlugin.php index 93a35b3f38..b4f80a50a4 100644 --- a/plugins/BitlyUrl/BitlyUrlPlugin.php +++ b/plugins/BitlyUrl/BitlyUrlPlugin.php @@ -118,7 +118,7 @@ class BitlyUrlPlugin extends UrlShortenerPlugin $params = http_build_query(array( 'login' => $this->getLogin(), 'apiKey' => $this->getApiKey()), '', '&'); - $serviceUrl = sprintf($this->serviceUrl, $url) . '&' . $params; + $serviceUrl = sprintf($this->serviceUrl, urlencode($url)) . '&' . $params; $request = HTTPClient::start(); return $request->get($serviceUrl); @@ -145,6 +145,10 @@ class BitlyUrlPlugin extends UrlShortenerPlugin common_log(LOG_INFO, $body); $json = json_decode($body, true); if ($json['statusCode'] == 'OK') { + if (!isset($json['results'][$url])) { + common_log(LOG_ERR, "bit.ly returned OK response, but didn't find expected URL $url in $body"); + return false; + } $data = $json['results'][$url]; if (isset($data['shortUrl'])) { return true; From b4fc54c308936477706acb5cc3c4acae4c3f3a4d Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 30 Nov 2010 12:46:33 -0800 Subject: [PATCH 10/10] Flush router cache when saving Twitter admin settings: adding/removing keys can enable/disable some actions. This avoids having users' Twitter settings unreachable after adding your keys to an installation with TwitterBridge on but not pre-configured. --- plugins/TwitterBridge/twitteradminpanel.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/TwitterBridge/twitteradminpanel.php b/plugins/TwitterBridge/twitteradminpanel.php index d05a2c6b3e..1a83b47d56 100644 --- a/plugins/TwitterBridge/twitteradminpanel.php +++ b/plugins/TwitterBridge/twitteradminpanel.php @@ -133,6 +133,11 @@ class TwitteradminpanelAction extends AdminPanelAction $config->query('COMMIT'); + // Flush the router cache: we may have enabled/disabled bridging, + // which will add or remove some actions. + $cache = Cache::instance(); + $cache->delete(Router::cacheKey()); + return; }