summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorBrion Vibber <brion@pobox.com>2010-10-07 13:30:34 -0700
committerBrion Vibber <brion@pobox.com>2010-10-07 13:30:34 -0700
commitfd0768be291c8c32ae5bfa434cfed4ed93548e49 (patch)
tree1dfd1ab41e9e25e062f40dcf8786ab82348830a3 /plugins
parent707b45097428b0dbcdbf9ae2590129080207f254 (diff)
parent06c4212bd4db8815b3f91e5eab3a079784738ae3 (diff)
Merge branch 'master' into 0.9.x
Diffstat (limited to 'plugins')
-rw-r--r--plugins/BitlyUrl/BitlyUrlPlugin.php206
-rw-r--r--plugins/BitlyUrl/README37
-rw-r--r--plugins/BitlyUrl/bitlyadminpanelaction.php238
-rw-r--r--plugins/OStatus/OStatusPlugin.php2
-rw-r--r--plugins/OStatus/scripts/fixup-shadow.php44
5 files changed, 519 insertions, 8 deletions
diff --git a/plugins/BitlyUrl/BitlyUrlPlugin.php b/plugins/BitlyUrl/BitlyUrlPlugin.php
index 10d99b358..93a35b3f3 100644
--- a/plugins/BitlyUrl/BitlyUrlPlugin.php
+++ b/plugins/BitlyUrl/BitlyUrlPlugin.php
@@ -2,7 +2,7 @@
/**
* StatusNet, the distributed open-source microblogging tool
*
- * Plugin to push RSS/Atom updates to a PubSubHubBub hub
+ * Plugin to use bit.ly URL shortening services.
*
* PHP version 5
*
@@ -22,7 +22,9 @@
* @category Plugin
* @package StatusNet
* @author Craig Andrews <candrews@integralblue.com>
+ * @author Brion Vibber <brion@status.net>
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
+ * @copyright 2010 StatusNet, Inc http://status.net/
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
@@ -35,26 +37,135 @@ require_once INSTALLDIR.'/plugins/UrlShortener/UrlShortenerPlugin.php';
class BitlyUrlPlugin extends UrlShortenerPlugin
{
- public $serviceUrl;
+ public $shortenerName = 'bit.ly';
+ public $serviceUrl = 'http://bit.ly/api?method=shorten&version=2.0.1&longUrl=%s';
+ public $login; // To set a site-default when admins or users don't override it.
+ public $apiKey;
function onInitializePlugin(){
parent::onInitializePlugin();
if(!isset($this->serviceUrl)){
- throw new Exception(_m("You must specify a serviceUrl."));
+ throw new Exception(_m("You must specify a serviceUrl for bit.ly shortening."));
}
}
+ /**
+ * Add bit.ly to the list of available URL shorteners if it's configured,
+ * otherwise leave it out.
+ *
+ * @param array $shorteners
+ * @return boolean hook return value
+ */
+ function onGetUrlShorteners(&$shorteners)
+ {
+ if ($this->getLogin() && $this->getApiKey()) {
+ return parent::onGetUrlShorteners($shorteners);
+ }
+ return true;
+ }
+
+ /**
+ * Short a URL
+ * @param url
+ * @return string shortened version of the url, or null if URL shortening failed
+ */
protected function shorten($url) {
- $response = $this->http_get($url);
- if(!$response) return;
- return current(json_decode($response)->results)->hashUrl;
+ $response = $this->query($url);
+ if ($this->isOk($url, $response)) {
+ return $this->decode($url, $response->getBody());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the user's or site-wide default bit.ly login name.
+ *
+ * @return string
+ */
+ protected function getLogin()
+ {
+ $login = common_config('bitly', 'default_login');
+ if (!$login) {
+ $login = $this->login;
+ }
+ return $login;
+ }
+
+ /**
+ * Get the user's or site-wide default bit.ly API key.
+ *
+ * @return string
+ */
+ protected function getApiKey()
+ {
+ $key = common_config('bitly', 'default_apikey');
+ if (!$key) {
+ $key = $this->apiKey;
+ }
+ return $key;
+ }
+
+ /**
+ * Inject API key into query before sending out...
+ *
+ * @param string $url
+ * @return HTTPResponse
+ */
+ protected function query($url)
+ {
+ // http://code.google.com/p/bitly-api/wiki/ApiDocumentation#/shorten
+ $params = http_build_query(array(
+ 'login' => $this->getLogin(),
+ 'apiKey' => $this->getApiKey()), '', '&');
+ $serviceUrl = sprintf($this->serviceUrl, $url) . '&' . $params;
+
+ $request = HTTPClient::start();
+ return $request->get($serviceUrl);
+ }
+
+ /**
+ * JSON decode for API result
+ */
+ protected function decode($url, $body)
+ {
+ $json = json_decode($body, true);
+ return $json['results'][$url]['shortUrl'];
+ }
+
+ /**
+ * JSON decode for API result
+ */
+ protected function isOk($url, $response)
+ {
+ $code = 'unknown';
+ $msg = '';
+ if ($response->isOk()) {
+ $body = $response->getBody();
+ common_log(LOG_INFO, $body);
+ $json = json_decode($body, true);
+ if ($json['statusCode'] == 'OK') {
+ $data = $json['results'][$url];
+ if (isset($data['shortUrl'])) {
+ return true;
+ } else if (isset($data['statusCode']) && $data['statusCode'] == 'ERROR') {
+ $code = $data['errorCode'];
+ $msg = $data['errorMessage'];
+ }
+ } else if ($json['statusCode'] == 'ERROR') {
+ $code = $json['errorCode'];
+ $msg = $json['errorMessage'];
+ }
+ common_log(LOG_ERR, "bit.ly returned error $code $msg for $url");
+ }
+ return false;
}
function onPluginVersion(&$versions)
{
$versions[] = array('name' => sprintf('BitlyUrl (%s)', $this->shortenerName),
'version' => STATUSNET_VERSION,
- 'author' => 'Craig Andrews',
+ 'author' => 'Craig Andrews, Brion Vibber',
'homepage' => 'http://status.net/wiki/Plugin:BitlyUrl',
'rawdescription' =>
sprintf(_m('Uses <a href="http://%1$s/">%1$s</a> URL-shortener service.'),
@@ -62,4 +173,85 @@ class BitlyUrlPlugin extends UrlShortenerPlugin
return true;
}
+
+ /**
+ * Hook for RouterInitialized event.
+ *
+ * @param Net_URL_Mapper $m path-to-action mapper
+ * @return boolean hook return
+ */
+ function onRouterInitialized($m)
+ {
+ $m->connect('admin/bitly',
+ array('action' => 'bitlyadminpanel'));
+ return true;
+ }
+
+ /**
+ * If the plugin's installed, this should be accessible to admins.
+ */
+ function onAdminPanelCheck($name, &$isOK)
+ {
+ if ($name == 'bitly') {
+ $isOK = true;
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Add the bit.ly admin panel to the list...
+ */
+ function onEndAdminPanelNav($nav)
+ {
+ if (AdminPanelAction::canAdmin('bitly')) {
+ $action_name = $nav->action->trimmed('action');
+
+ $nav->out->menuItem(common_local_url('bitlyadminpanel'),
+ _m('bit.ly'),
+ _m('bit.ly URL shortening'),
+ $action_name == 'bitlyadminpanel',
+ 'nav_bitly_admin_panel');
+ }
+
+ return true;
+ }
+
+ /**
+ * Automatically load the actions and libraries used by the plugin
+ *
+ * @param Class $cls the class
+ *
+ * @return boolean hook return
+ *
+ */
+ function onAutoload($cls)
+ {
+ $base = dirname(__FILE__);
+ $lower = strtolower($cls);
+ switch ($lower) {
+ case 'bitlyadminpanelaction':
+ require_once "$base/$lower.php";
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ /**
+ * Internal hook point to check the default global credentials so
+ * the admin form knows if we have a fallback or not.
+ *
+ * @param string $login
+ * @param string $apiKey
+ * @return boolean hook return value
+ */
+ function onBitlyDefaultCredentials(&$login, &$apiKey)
+ {
+ $login = $this->login;
+ $apiKey = $this->apiKey;
+ return false;
+ }
+
}
diff --git a/plugins/BitlyUrl/README b/plugins/BitlyUrl/README
new file mode 100644
index 000000000..0b3af1dd6
--- /dev/null
+++ b/plugins/BitlyUrl/README
@@ -0,0 +1,37 @@
+bit.ly URL shortening requires the login name and API key for a bit.ly account.
+Register for an account or set up your API key here:
+
+ http://bit.ly/a/your_api_key
+
+Administrators can configure a login and API key to use through the admin panels
+on the site; these credentials will then be used for all users.
+
+(In the future, options will be added for individual users to override the keys
+with their own login for URLs they post.)
+
+If the login and API key are left empty in the admin panel, then bit.ly will be
+disabled and hidden from the list of available URL shorteners unless a global
+default was provided in the plugin configuration.
+
+
+To enable bit.ly with no default credentials, simply slip into your config.php:
+
+ addPlugin('BitlyUrl');
+
+To provide default credentials, add them as parameters:
+
+ addPlugin('BitlyUrl', array(
+ 'login' => 'myname',
+ 'apiKey' => '############################'
+ ));
+
+These settings will not be individually exposed to the admin panels, but the
+panel will indicate whether or not the global default settings are available;
+this makes it suitable as a global default for multi-site hosting, where admins
+on individual sites can change to use their own settings.
+
+
+If you're using a bit.ly pro account with a custom domain etc, it should all
+"just work" as long as you use the correct login name and API key for your
+account.
+
diff --git a/plugins/BitlyUrl/bitlyadminpanelaction.php b/plugins/BitlyUrl/bitlyadminpanelaction.php
new file mode 100644
index 000000000..05b8e8326
--- /dev/null
+++ b/plugins/BitlyUrl/bitlyadminpanelaction.php
@@ -0,0 +1,238 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Admin panel for plugin to use bit.ly URL shortening services.
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 Settings
+ * @package StatusNet
+ * @author Brion Vibber <brion@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * Administer global bit.ly URL shortener settings
+ *
+ * @category Admin
+ * @package StatusNet
+ * @author Brion Vibber <brion@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class BitlyadminpanelAction extends AdminPanelAction
+{
+ /**
+ * Returns the page title
+ *
+ * @return string page title
+ */
+
+ function title()
+ {
+ return _m('bit.ly URL shortening');
+ }
+
+ /**
+ * Instructions for using this form.
+ *
+ * @return string instructions
+ */
+
+ function getInstructions()
+ {
+ return _m('URL shortening with bit.ly requires ' .
+ '[a bit.ly account and API key](http://bit.ly/a/your_api_key). ' .
+ 'This verifies that this is an authorized account, and ' .
+ 'allow you to use bit.ly\'s tracking features and custom domains.');
+ }
+
+ /**
+ * Show the bit.ly admin panel form
+ *
+ * @return void
+ */
+
+ function showForm()
+ {
+ $form = new BitlyAdminPanelForm($this);
+ $form->show();
+ return;
+ }
+
+ /**
+ * Save settings from the form
+ *
+ * @return void
+ */
+
+ function saveSettings()
+ {
+ static $settings = array(
+ 'bitly' => array('default_login', 'default_apikey')
+ );
+
+ $values = array();
+
+ foreach ($settings as $section => $parts) {
+ foreach ($parts as $setting) {
+ $values[$section][$setting]
+ = $this->trimmed($setting);
+ }
+ }
+
+ // This throws an exception on validation errors
+
+ $this->validate($values);
+
+ // assert(all values are valid);
+
+ $config = new Config();
+
+ $config->query('BEGIN');
+
+ foreach ($settings as $section => $parts) {
+ foreach ($parts as $setting) {
+ Config::save($section, $setting, $values[$section][$setting]);
+ }
+ }
+
+ $config->query('COMMIT');
+
+ return;
+ }
+
+ function validate(&$values)
+ {
+ // Validate consumer key and secret (can't be too long)
+
+ if (mb_strlen($values['bitly']['default_apikey']) > 255) {
+ $this->clientError(
+ _m("Invalid login. Max length is 255 characters.")
+ );
+ }
+
+ if (mb_strlen($values['bitly']['default_apikey']) > 255) {
+ $this->clientError(
+ _m("Invalid API key. Max length is 255 characters.")
+ );
+ }
+ }
+}
+
+class BitlyAdminPanelForm extends AdminForm
+{
+ /**
+ * ID of the form
+ *
+ * @return int ID of the form
+ */
+
+ function id()
+ {
+ return 'bitlyadminpanel';
+ }
+
+ /**
+ * class of the form
+ *
+ * @return string class of the form
+ */
+
+ function formClass()
+ {
+ return 'form_settings';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+
+ function action()
+ {
+ return common_local_url('bitlyadminpanel');
+ }
+
+ /**
+ * Data elements of the form
+ *
+ * @return void
+ */
+
+ function formData()
+ {
+ $this->out->elementStart(
+ 'fieldset',
+ array('id' => 'settings_bitly')
+ );
+ $this->out->element('legend', null, _m('Credentials'));
+
+ // Do we have global defaults to fall back on?
+ $login = $apiKey = false;
+ Event::handle('BitlyDefaultCredentials', array(&$login, &$apiKey));
+ $haveGlobalDefaults = ($login && $apiKey);
+ if ($login && $apiKey) {
+ $this->out->element('p', 'form_guide',
+ _m('Leave these empty to use global default credentials.'));
+ } else {
+ $this->out->element('p', 'form_guide',
+ _m('If you leave these empty, bit.ly will be unavailable to users.'));
+ }
+ $this->out->elementStart('ul', 'form_data');
+
+ $this->li();
+ $this->input(
+ 'default_login',
+ _m('Login name'),
+ null,
+ 'bitly'
+ );
+ $this->unli();
+
+ $this->li();
+ $this->input(
+ 'default_apikey',
+ _m('API key'),
+ null,
+ 'bitly'
+ );
+ $this->unli();
+
+ $this->out->elementEnd('ul');
+ $this->out->elementEnd('fieldset');
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+
+ function formActions()
+ {
+ $this->out->submit('submit', _('Save'), 'submit', null, _m('Save bit.ly settings'));
+ }
+}
diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php
index 3cd29aff7..9c6696439 100644
--- a/plugins/OStatus/OStatusPlugin.php
+++ b/plugins/OStatus/OStatusPlugin.php
@@ -966,7 +966,7 @@ class OStatusPlugin extends Plugin
{
$group = User_group::staticGet('uri', $url);
if ($group) {
- $local = Local_group::staticGet('id', $group->id);
+ $local = Local_group::staticGet('group_id', $group->id);
if ($local) {
return $group->id;
}
diff --git a/plugins/OStatus/scripts/fixup-shadow.php b/plugins/OStatus/scripts/fixup-shadow.php
index 3e2c18e02..18df2995f 100644
--- a/plugins/OStatus/scripts/fixup-shadow.php
+++ b/plugins/OStatus/scripts/fixup-shadow.php
@@ -84,6 +84,50 @@ while ($group->fetch()) {
}
echo "\n";
+// And there may be user_group entries remaining where we've already killed
+// the ostatus_profile. These were "harmless" until our lookup started actually
+// using the uri field, at which point we can clearly see it breaks stuff.
+echo "Checking for leftover bogus user_group.uri entries obscuring local_group entries...\n";
+
+$group = new User_group();
+$group->joinAdd(array('id', 'local_group:group_id'), 'LEFT');
+$group->whereAdd('group_id IS NULL');
+
+
+$marker = mt_rand(31337, 31337000);
+$groupTemplate = common_local_url('groupbyid', array('id' => $marker));
+$encGroup = $group->escape($groupTemplate, true);
+$encGroup = str_replace($marker, '%', $encGroup);
+echo " LIKE '$encGroup'\n";
+$group->whereAdd("uri LIKE '$encGroup'");
+
+$group->find();
+$count = $group->N;
+echo "Found $count...\n";
+
+while ($group->fetch()) {
+ $uri = $group->uri;
+ if (preg_match('!/group/(\d+)/id!', $uri, $matches)) {
+ $id = intval($matches[1]);
+ $local = Local_group::staticGet('group_id', $id);
+ if ($local) {
+ $nick = $local->nickname;
+ } else {
+ $nick = '<deleted>';
+ }
+ echo "local group $id ($local->nickname) hidden by $uri (bogus group id $group->id)";
+ if ($dry) {
+ echo " - skipping\n";
+ } else {
+ echo " - removing bogus user_group entry...";
+ $evil = User_group::staticGet('id', $group->id);
+ $evil->delete();
+ echo " ok\n";
+ }
+ }
+}
+echo "\n";
+
// Fallback?
echo "Checking for bogus profiles blocking local users/groups by URI pattern match...\n";