Merge branch 'testing' of git@gitorious.org:statusnet/mainline into testing
This commit is contained in:
		@@ -294,6 +294,9 @@ class NewnoticeAction extends Action
 | 
			
		||||
            if ($profile) {
 | 
			
		||||
                $content = '@' . $profile->nickname . ' ';
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // @fixme most of these bits above aren't being passed on above
 | 
			
		||||
            $inreplyto = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $notice_form = new NoticeForm($this, '', $content, null, $inreplyto);
 | 
			
		||||
 
 | 
			
		||||
@@ -425,8 +425,6 @@ class Action extends HTMLOutputter // lawsuit
 | 
			
		||||
            $connect = 'imsettings';
 | 
			
		||||
        } else if (common_config('sms', 'enabled')) {
 | 
			
		||||
            $connect = 'smssettings';
 | 
			
		||||
        } else if (common_config('twitter', 'enabled')) {
 | 
			
		||||
            $connect = 'twittersettings';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->elementStart('dl', array('id' => 'site_nav_global_primary'));
 | 
			
		||||
 
 | 
			
		||||
@@ -177,8 +177,8 @@ $default =
 | 
			
		||||
        array('source' => 'StatusNet', # source attribute for Twitter
 | 
			
		||||
              'taguri' => null), # base for tag URIs
 | 
			
		||||
        'twitter' =>
 | 
			
		||||
        array('enabled'       => true,
 | 
			
		||||
              'consumer_key'    => null,
 | 
			
		||||
        array('signin' => true,
 | 
			
		||||
              'consumer_key' => null,
 | 
			
		||||
              'consumer_secret' => null),
 | 
			
		||||
        'cache' =>
 | 
			
		||||
        array('base' => null),
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								lib/util.php
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								lib/util.php
									
									
									
									
									
								
							@@ -809,8 +809,28 @@ function common_shorten_links($text)
 | 
			
		||||
 | 
			
		||||
function common_xml_safe_str($str)
 | 
			
		||||
{
 | 
			
		||||
    // Neutralize control codes and surrogates
 | 
			
		||||
	return preg_replace('/[\p{Cc}\p{Cs}]/u', '*', $str);
 | 
			
		||||
    // Replace common eol and extra whitespace input chars
 | 
			
		||||
    $unWelcome = array(
 | 
			
		||||
        "\t",  // tab
 | 
			
		||||
        "\n",  // newline
 | 
			
		||||
        "\r",  // cr
 | 
			
		||||
        "\0",  // null byte eos
 | 
			
		||||
        "\x0B" // vertical tab
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    $replacement = array(
 | 
			
		||||
        ' ', // single space
 | 
			
		||||
        ' ',
 | 
			
		||||
        '',  // nothing
 | 
			
		||||
        '',
 | 
			
		||||
        ' '
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    $str = str_replace($unWelcome, $replacement, $str);
 | 
			
		||||
 | 
			
		||||
    // Neutralize any additional control codes and UTF-16 surrogates
 | 
			
		||||
    // (Twitter uses '*')
 | 
			
		||||
    return preg_replace('/[\p{Cc}\p{Cs}]/u', '*', $str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function common_tag_link($tag)
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@
 | 
			
		||||
 * @category  Plugin
 | 
			
		||||
 * @package   StatusNet
 | 
			
		||||
 * @author    Zach Copley <zach@status.net>
 | 
			
		||||
 * @copyright 2009 StatusNet, Inc.
 | 
			
		||||
 * @copyright 2009-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/
 | 
			
		||||
 */
 | 
			
		||||
@@ -32,12 +32,12 @@ if (!defined('STATUSNET')) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
define("FACEBOOK_CONNECT_SERVICE", 3);
 | 
			
		||||
define('FACEBOOKPLUGIN_VERSION', '0.9');
 | 
			
		||||
 | 
			
		||||
require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Facebook plugin to add a StatusNet Facebook application
 | 
			
		||||
 * Facebook plugin to add a StatusNet Facebook canvas application
 | 
			
		||||
 * and allow registration and authentication via Facebook Connect
 | 
			
		||||
 *
 | 
			
		||||
 * @category Plugin
 | 
			
		||||
 * @package  StatusNet
 | 
			
		||||
@@ -49,6 +49,36 @@ require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php';
 | 
			
		||||
class FacebookPlugin extends Plugin
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    const VERSION = STATUSNET_VERSION;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializer for the plugin.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function initialize()
 | 
			
		||||
    {
 | 
			
		||||
        // Allow the key and secret to be passed in
 | 
			
		||||
        // Control panel will override
 | 
			
		||||
 | 
			
		||||
        if (isset($this->apikey)) {
 | 
			
		||||
            $key = common_config('facebook', 'apikey');
 | 
			
		||||
            if (empty($key)) {
 | 
			
		||||
                Config::save('facebook', 'apikey', $this->apikey);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isset($this->secret)) {
 | 
			
		||||
            $secret = common_config('facebook', 'secret');
 | 
			
		||||
            if (empty($secret)) {
 | 
			
		||||
                Config::save(
 | 
			
		||||
                    'facebook',
 | 
			
		||||
                    'secret',
 | 
			
		||||
                    $this->secret
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Add Facebook app actions to the router table
 | 
			
		||||
     *
 | 
			
		||||
@@ -70,6 +100,7 @@ class FacebookPlugin extends Plugin
 | 
			
		||||
                    array('action' => 'facebooksettings'));
 | 
			
		||||
        $m->connect('facebook/app/invite.php', array('action' => 'facebookinvite'));
 | 
			
		||||
        $m->connect('facebook/app/remove', array('action' => 'facebookremove'));
 | 
			
		||||
        $m->connect('admin/facebook', array('action' => 'facebookadminpanel'));
 | 
			
		||||
 | 
			
		||||
        // Facebook Connect stuff
 | 
			
		||||
 | 
			
		||||
@@ -98,6 +129,7 @@ class FacebookPlugin extends Plugin
 | 
			
		||||
        case 'FacebookinviteAction':
 | 
			
		||||
        case 'FacebookremoveAction':
 | 
			
		||||
        case 'FacebooksettingsAction':
 | 
			
		||||
        case 'FacebookadminpanelAction':
 | 
			
		||||
            include_once INSTALLDIR . '/plugins/Facebook/' .
 | 
			
		||||
              strtolower(mb_substr($cls, 0, -6)) . '.php';
 | 
			
		||||
            return false;
 | 
			
		||||
@@ -122,6 +154,32 @@ class FacebookPlugin extends Plugin
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Add a Facebook tab to the admin panels
 | 
			
		||||
     *
 | 
			
		||||
     * @param Widget $nav Admin panel nav
 | 
			
		||||
     *
 | 
			
		||||
     * @return boolean hook value
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function onEndAdminPanelNav($nav)
 | 
			
		||||
    {
 | 
			
		||||
        if (AdminPanelAction::canAdmin('facebook')) {
 | 
			
		||||
 | 
			
		||||
            $action_name = $nav->action->trimmed('action');
 | 
			
		||||
 | 
			
		||||
            $nav->out->menuItem(
 | 
			
		||||
                common_local_url('facebookadminpanel'),
 | 
			
		||||
                _m('Facebook'),
 | 
			
		||||
                _m('Facebook integration configuration'),
 | 
			
		||||
                $action_name == 'facebookadminpanel',
 | 
			
		||||
                'nav_facebook_admin_panel'
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Override normal HTML output to force the content type to
 | 
			
		||||
     * text/html and add in xmlns:fb
 | 
			
		||||
@@ -359,8 +417,6 @@ class FacebookPlugin extends Plugin
 | 
			
		||||
            $connect = 'imsettings';
 | 
			
		||||
        } else if (common_config('sms', 'enabled')) {
 | 
			
		||||
            $connect = 'smssettings';
 | 
			
		||||
        } else if (common_config('twitter', 'enabled')) {
 | 
			
		||||
            $connect = 'twittersettings';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!empty($user)) {
 | 
			
		||||
@@ -525,15 +581,18 @@ class FacebookPlugin extends Plugin
 | 
			
		||||
 | 
			
		||||
    function onPluginVersion(&$versions)
 | 
			
		||||
    {
 | 
			
		||||
        $versions[] = array('name' => 'Facebook',
 | 
			
		||||
                            'version' => FACEBOOKPLUGIN_VERSION,
 | 
			
		||||
                            'author' => 'Zach Copley',
 | 
			
		||||
                            'homepage' => 'http://status.net/wiki/Plugin:Facebook',
 | 
			
		||||
                            'rawdescription' =>
 | 
			
		||||
                            _m('The Facebook plugin allows you to integrate ' .
 | 
			
		||||
                               'your StatusNet instance with ' .
 | 
			
		||||
                               '<a href="http://facebook.com/">Facebook</a> ' .
 | 
			
		||||
                               'and Facebook Connect.'));
 | 
			
		||||
        $versions[] = array(
 | 
			
		||||
            'name' => 'Facebook',
 | 
			
		||||
            'version' => self::VERSION,
 | 
			
		||||
            'author' => 'Zach Copley',
 | 
			
		||||
            'homepage' => 'http://status.net/wiki/Plugin:Facebook',
 | 
			
		||||
            'rawdescription' => _m(
 | 
			
		||||
                'The Facebook plugin allows you to integrate ' .
 | 
			
		||||
                'your StatusNet instance with ' .
 | 
			
		||||
                '<a href="http://facebook.com/">Facebook</a> ' .
 | 
			
		||||
                'and Facebook Connect.'
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										223
									
								
								plugins/Facebook/facebookadminpanel.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								plugins/Facebook/facebookadminpanel.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,223 @@
 | 
			
		||||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * StatusNet, the distributed open-source microblogging tool
 | 
			
		||||
 *
 | 
			
		||||
 * Facebook integration administration panel
 | 
			
		||||
 *
 | 
			
		||||
 * 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    Zach Copley <zach@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 Facebook integration settings
 | 
			
		||||
 *
 | 
			
		||||
 * @category Admin
 | 
			
		||||
 * @package  StatusNet
 | 
			
		||||
 * @author   Zach Copley <zach@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 FacebookadminpanelAction extends AdminPanelAction
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the page title
 | 
			
		||||
     *
 | 
			
		||||
     * @return string page title
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function title()
 | 
			
		||||
    {
 | 
			
		||||
        return _m('Facebook');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Instructions for using this form.
 | 
			
		||||
     *
 | 
			
		||||
     * @return string instructions
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function getInstructions()
 | 
			
		||||
    {
 | 
			
		||||
        return _m('Facebook integration settings');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Show the Facebook admin panel form
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function showForm()
 | 
			
		||||
    {
 | 
			
		||||
        $form = new FacebookAdminPanelForm($this);
 | 
			
		||||
        $form->show();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Save settings from the form
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function saveSettings()
 | 
			
		||||
    {
 | 
			
		||||
        static $settings = array(
 | 
			
		||||
            'facebook'     => array('apikey', 'secret'),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $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['facebook']['apikey']) > 255) {
 | 
			
		||||
            $this->clientError(
 | 
			
		||||
                _m("Invalid Facebook API key. Max length is 255 characters.")
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mb_strlen($values['facebook']['secret']) > 255) {
 | 
			
		||||
            $this->clientError(
 | 
			
		||||
                _m("Invalid Facebook API secret. Max length is 255 characters.")
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FacebookAdminPanelForm extends AdminForm
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * ID of the form
 | 
			
		||||
     *
 | 
			
		||||
     * @return int ID of the form
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function id()
 | 
			
		||||
    {
 | 
			
		||||
        return 'facebookadminpanel';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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('facebookadminpanel');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Data elements of the form
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function formData()
 | 
			
		||||
    {
 | 
			
		||||
        $this->out->elementStart(
 | 
			
		||||
            'fieldset',
 | 
			
		||||
            array('id' => 'settings_facebook-application')
 | 
			
		||||
        );
 | 
			
		||||
        $this->out->element('legend', null, _m('Facebook application settings'));
 | 
			
		||||
        $this->out->elementStart('ul', 'form_data');
 | 
			
		||||
 | 
			
		||||
        $this->li();
 | 
			
		||||
        $this->input(
 | 
			
		||||
            'apikey',
 | 
			
		||||
            _m('API key'),
 | 
			
		||||
            _m('API key provided by Facebook'),
 | 
			
		||||
            'facebook'
 | 
			
		||||
        );
 | 
			
		||||
        $this->unli();
 | 
			
		||||
 | 
			
		||||
        $this->li();
 | 
			
		||||
        $this->input(
 | 
			
		||||
            'secret',
 | 
			
		||||
             _m('Secret'),
 | 
			
		||||
            _m('API secret provided by Facebook'),
 | 
			
		||||
            'facebook'
 | 
			
		||||
        );
 | 
			
		||||
        $this->unli();
 | 
			
		||||
 | 
			
		||||
        $this->out->elementEnd('ul');
 | 
			
		||||
        $this->out->elementEnd('fieldset');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Action elements
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function formActions()
 | 
			
		||||
    {
 | 
			
		||||
        $this->out->submit('submit', _('Save'), 'submit', null, _('Save Facebook settings'));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -312,8 +312,6 @@ class MobileProfilePlugin extends WAP20Plugin
 | 
			
		||||
            $connect = 'imsettings';
 | 
			
		||||
        } else if (common_config('sms', 'enabled')) {
 | 
			
		||||
            $connect = 'smssettings';
 | 
			
		||||
        } else if (common_config('twitter', 'enabled')) {
 | 
			
		||||
            $connect = 'twittersettings';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $action->elementStart('ul', array('id' => 'site_nav_global_primary'));
 | 
			
		||||
 
 | 
			
		||||
@@ -222,31 +222,62 @@ class OStatusPlugin extends Plugin
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     * Find any explicit remote mentions. Accepted forms:
 | 
			
		||||
     *   Webfinger: @user@example.com
 | 
			
		||||
     *   Profile link: @example.com/mublog/user
 | 
			
		||||
     * @param Profile $sender (os user?)
 | 
			
		||||
     * @param string $text input markup text
 | 
			
		||||
     * @param array &$mention in/out param: set of found mentions
 | 
			
		||||
     * @return boolean hook return value
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function onEndFindMentions($sender, $text, &$mentions)
 | 
			
		||||
    {
 | 
			
		||||
        preg_match_all('/(?:^|\s+)@((?:\w+\.)*\w+@(?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+)/',
 | 
			
		||||
        preg_match_all('!(?:^|\s+)
 | 
			
		||||
                        @(                                # Webfinger:
 | 
			
		||||
                          (?:\w+\.)*\w+                   #   user
 | 
			
		||||
                          @                               #   @
 | 
			
		||||
                          (?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+ #   domain
 | 
			
		||||
                         |                                # Profile:
 | 
			
		||||
                          (?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+ #   domain
 | 
			
		||||
                          (?:/\w+)+                       #   /path1(/path2...)
 | 
			
		||||
                         )!x',
 | 
			
		||||
                       $text,
 | 
			
		||||
                       $wmatches,
 | 
			
		||||
                       PREG_OFFSET_CAPTURE);
 | 
			
		||||
 | 
			
		||||
        foreach ($wmatches[1] as $wmatch) {
 | 
			
		||||
            $target = $wmatch[0];
 | 
			
		||||
            $oprofile = null;
 | 
			
		||||
 | 
			
		||||
            $webfinger = $wmatch[0];
 | 
			
		||||
 | 
			
		||||
            $this->log(LOG_INFO, "Checking Webfinger for address '$webfinger'");
 | 
			
		||||
 | 
			
		||||
            $oprofile = Ostatus_profile::ensureWebfinger($webfinger);
 | 
			
		||||
            if (strpos($target, '/') === false) {
 | 
			
		||||
                $this->log(LOG_INFO, "Checking Webfinger for address '$target'");
 | 
			
		||||
                try {
 | 
			
		||||
                    $oprofile = Ostatus_profile::ensureWebfinger($target);
 | 
			
		||||
                } catch (Exception $e) {
 | 
			
		||||
                    $this->log(LOG_ERR, "Webfinger check failed: " . $e->getMessage());
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                $schemes = array('https', 'http');
 | 
			
		||||
                foreach ($schemes as $scheme) {
 | 
			
		||||
                    $url = "$scheme://$target";
 | 
			
		||||
                    $this->log(LOG_INFO, "Checking profile address '$url'");
 | 
			
		||||
                    try {
 | 
			
		||||
                        $oprofile = Ostatus_profile::ensureProfile($url);
 | 
			
		||||
                        if ($oprofile) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                    } catch (Exception $e) {
 | 
			
		||||
                        $this->log(LOG_ERR, "Profile check failed: " . $e->getMessage());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (empty($oprofile)) {
 | 
			
		||||
 | 
			
		||||
                $this->log(LOG_INFO, "No Ostatus_profile found for address '$webfinger'");
 | 
			
		||||
 | 
			
		||||
                $this->log(LOG_INFO, "No Ostatus_profile found for address '$target'");
 | 
			
		||||
            } else {
 | 
			
		||||
 | 
			
		||||
                $this->log(LOG_INFO, "Ostatus_profile found for address '$webfinger'");
 | 
			
		||||
                $this->log(LOG_INFO, "Ostatus_profile found for address '$target'");
 | 
			
		||||
 | 
			
		||||
                if ($oprofile->isGroup()) {
 | 
			
		||||
                    continue;
 | 
			
		||||
@@ -261,7 +292,7 @@ class OStatusPlugin extends Plugin
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                $mentions[] = array('mentioned' => array($profile),
 | 
			
		||||
                                    'text' => $wmatch[0],
 | 
			
		||||
                                    'text' => $target,
 | 
			
		||||
                                    'position' => $pos,
 | 
			
		||||
                                    'url' => $profile->profileurl);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -104,7 +104,7 @@ class PushHubAction extends Action
 | 
			
		||||
            throw new ClientException("Invalid hub.secret $secret; must be under 200 bytes.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $sub = HubSub::staticGet($sub->topic, $sub->callback);
 | 
			
		||||
        $sub = HubSub::staticGet($topic, $callback);
 | 
			
		||||
        if (!$sub) {
 | 
			
		||||
            // Creating a new one!
 | 
			
		||||
            $sub = new HubSub();
 | 
			
		||||
 
 | 
			
		||||
@@ -260,9 +260,15 @@ class HubSub extends Memcached_DataObject
 | 
			
		||||
            $retries = intval(common_config('ostatus', 'hub_retries'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $data = array('sub' => clone($this),
 | 
			
		||||
        // We dare not clone() as when the clone is discarded it'll
 | 
			
		||||
        // destroy the result data for the parent query.
 | 
			
		||||
        // @fixme use clone() again when it's safe to copy an
 | 
			
		||||
        // individual item from a multi-item query again.
 | 
			
		||||
        $sub = HubSub::staticGet($this->topic, $this->callback);
 | 
			
		||||
        $data = array('sub' => $sub,
 | 
			
		||||
                      'atom' => $atom,
 | 
			
		||||
                      'retries' => $retries);
 | 
			
		||||
        common_log(LOG_INFO, "Queuing PuSH: $this->topic to $this->callback");
 | 
			
		||||
        $qm = QueueManager::get();
 | 
			
		||||
        $qm->enqueue($data, 'hubout');
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -146,8 +146,10 @@ class Magicsig extends Memcached_DataObject
 | 
			
		||||
        
 | 
			
		||||
        $mod = base64_url_decode($matches[1]);
 | 
			
		||||
        $exp = base64_url_decode($matches[2]);
 | 
			
		||||
        if ($matches[4]) {
 | 
			
		||||
        if (!empty($matches[4])) {
 | 
			
		||||
            $private_exp = base64_url_decode($matches[4]);
 | 
			
		||||
        } else {
 | 
			
		||||
            $private_exp = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $params['public_key'] = new Crypt_RSA_KEY($mod, $exp, 'public');
 | 
			
		||||
 
 | 
			
		||||
@@ -698,7 +698,7 @@ class Ostatus_profile extends Memcached_DataObject
 | 
			
		||||
    {
 | 
			
		||||
        // Get the canonical feed URI and check it
 | 
			
		||||
        $discover = new FeedDiscovery();
 | 
			
		||||
        if ($hints['feedurl']) {
 | 
			
		||||
        if (isset($hints['feedurl'])) {
 | 
			
		||||
            $feeduri = $hints['feedurl'];
 | 
			
		||||
            $feeduri = $discover->discoverFromFeedURL($feeduri);
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -1145,7 +1145,7 @@ class Ostatus_profile extends Memcached_DataObject
 | 
			
		||||
 | 
			
		||||
        if (!empty($poco)) {
 | 
			
		||||
            $url = $poco->getPrimaryURL();
 | 
			
		||||
            if ($url->type == 'homepage') {
 | 
			
		||||
            if ($url && $url->type == 'homepage') {
 | 
			
		||||
                $homepage = $url->value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -94,7 +94,7 @@ class Discovery
 | 
			
		||||
            $links = call_user_func(array($class, 'discover'), $uri);
 | 
			
		||||
            if ($link = Discovery::getService($links, Discovery::LRDD_REL)) {
 | 
			
		||||
                // Load the LRDD XRD
 | 
			
		||||
                if ($link['template']) {
 | 
			
		||||
                if (!empty($link['template'])) {
 | 
			
		||||
                    $xrd_uri = Discovery::applyTemplate($link['template'], $uri);
 | 
			
		||||
                } else {
 | 
			
		||||
                    $xrd_uri = $link['href'];
 | 
			
		||||
 
 | 
			
		||||
@@ -53,17 +53,22 @@ class XRD
 | 
			
		||||
        $xrd = new XRD();
 | 
			
		||||
 | 
			
		||||
        $dom = new DOMDocument();
 | 
			
		||||
        $dom->loadXML($xml);
 | 
			
		||||
        if (!$dom->loadXML($xml)) {
 | 
			
		||||
            throw new Exception("Invalid XML");
 | 
			
		||||
        }
 | 
			
		||||
        $xrd_element = $dom->getElementsByTagName('XRD')->item(0);
 | 
			
		||||
 | 
			
		||||
        // Check for host-meta host
 | 
			
		||||
        $host = $xrd_element->getElementsByTagName('Host')->item(0)->nodeValue;
 | 
			
		||||
        $host = $xrd_element->getElementsByTagName('Host')->item(0);
 | 
			
		||||
        if ($host) {
 | 
			
		||||
            $xrd->host = $host;
 | 
			
		||||
            $xrd->host = $host->nodeValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Loop through other elements
 | 
			
		||||
        foreach ($xrd_element->childNodes as $node) {
 | 
			
		||||
            if (!($node instanceof DOMElement)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            switch ($node->tagName) {
 | 
			
		||||
            case 'Expires':
 | 
			
		||||
                $xrd->expires = $node->nodeValue;
 | 
			
		||||
@@ -156,20 +161,20 @@ class XRD
 | 
			
		||||
    function saveLink($doc, $link)
 | 
			
		||||
    {
 | 
			
		||||
        $link_element = $doc->createElement('Link');
 | 
			
		||||
        if ($link['rel']) {
 | 
			
		||||
        if (!empty($link['rel'])) {
 | 
			
		||||
            $link_element->setAttribute('rel', $link['rel']);
 | 
			
		||||
        }
 | 
			
		||||
        if ($link['type']) {
 | 
			
		||||
        if (!empty($link['type'])) {
 | 
			
		||||
            $link_element->setAttribute('type', $link['type']);
 | 
			
		||||
        }
 | 
			
		||||
        if ($link['href']) {
 | 
			
		||||
        if (!empty($link['href'])) {
 | 
			
		||||
            $link_element->setAttribute('href', $link['href']);
 | 
			
		||||
        }
 | 
			
		||||
        if ($link['template']) {
 | 
			
		||||
        if (!empty($link['template'])) {
 | 
			
		||||
            $link_element->setAttribute('template', $link['template']);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (is_array($link['title'])) {
 | 
			
		||||
        if (!empty($link['title']) && is_array($link['title'])) {
 | 
			
		||||
            foreach($link['title'] as $title) {
 | 
			
		||||
                $title = $doc->createElement('Title', $title);
 | 
			
		||||
                $link_element->appendChild($title);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,47 +1,89 @@
 | 
			
		||||
Twitter Bridge Plugin
 | 
			
		||||
=====================
 | 
			
		||||
 | 
			
		||||
This Twitter "bridge" plugin allows you to integrate your StatusNet
 | 
			
		||||
instance with Twitter.  Installing it will allow your users to:
 | 
			
		||||
 | 
			
		||||
    - automatically post notices to thier Twitter accounts
 | 
			
		||||
    - automatically post notices to their Twitter accounts
 | 
			
		||||
    - automatically subscribe to other Twitter users who are also using
 | 
			
		||||
      your StatusNet install, if possible (requires running a daemon)
 | 
			
		||||
    - import their Twitter friends' tweets (requires running a daemon)
 | 
			
		||||
    - allow users to authenticate using Twitter ('Sign in with Twitter')
 | 
			
		||||
 | 
			
		||||
Installation
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
To enable the plugin, add the following to your config.php:
 | 
			
		||||
 | 
			
		||||
    addPlugin("TwitterBridge");
 | 
			
		||||
 | 
			
		||||
OAuth is used to to access protected resources on Twitter (as opposed to
 | 
			
		||||
HTTP Basic Auth)*.  To use Twitter bridging you will need to register
 | 
			
		||||
your instance of StatusNet as an application on Twitter
 | 
			
		||||
(http://twitter.com/apps), and update the following variables in your
 | 
			
		||||
config.php with the consumer key and secret Twitter generates for you:
 | 
			
		||||
 | 
			
		||||
    $config['twitter']['consumer_key']    = 'YOURKEY';
 | 
			
		||||
    $config['twitter']['consumer_secret'] = 'YOURSECRET';
 | 
			
		||||
OAuth 1.0a (http://oauth.net) is used to to access protected resources
 | 
			
		||||
on Twitter (as opposed to HTTP Basic Auth)*.  To use Twitter bridging
 | 
			
		||||
you will need to register your instance of StatusNet as an application
 | 
			
		||||
on Twitter (http://twitter.com/apps).  During the application
 | 
			
		||||
registration process your application will be assigned a "consumer" key
 | 
			
		||||
and secret, which the plugin will use to make OAuth requests to Twitter.
 | 
			
		||||
You can either pass the consumer key and secret in when you enable the
 | 
			
		||||
plugin, or set it using the Twitter administration panel.
 | 
			
		||||
 | 
			
		||||
When registering your application with Twitter set the type to "Browser"
 | 
			
		||||
and your Callback URL to:
 | 
			
		||||
 | 
			
		||||
    http://example.org/mublog/twitter/authorization
 | 
			
		||||
 | 
			
		||||
The default access type should be, "Read & Write".
 | 
			
		||||
(Change "example.org" to your site domain and "mublog" to your site
 | 
			
		||||
path.)
 | 
			
		||||
 | 
			
		||||
The default access type should be "Read & Write".
 | 
			
		||||
 | 
			
		||||
To enable the plugin, add the following to your config.php:
 | 
			
		||||
 | 
			
		||||
    addPlugin(
 | 
			
		||||
        'TwitterBridge',
 | 
			
		||||
        array(
 | 
			
		||||
            'consumer_key'    => 'YOUR_CONSUMER_KEY',
 | 
			
		||||
            'consumer_secret' => 'YOUR_CONSUMER_SECRET'
 | 
			
		||||
        )
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
* Note: The plugin will still push notices to Twitter for users who
 | 
			
		||||
  have previously setup the Twitter bridge using their Twitter name and
 | 
			
		||||
  password under an older versions of StatusNet, but all new Twitter
 | 
			
		||||
  have previously set up the Twitter bridge using their Twitter name and
 | 
			
		||||
  password under an older version of StatusNet, but all new Twitter
 | 
			
		||||
  bridge connections will use OAuth.
 | 
			
		||||
 | 
			
		||||
Deamons
 | 
			
		||||
Administration panel
 | 
			
		||||
--------------------
 | 
			
		||||
 | 
			
		||||
As of StatusNet 0.9.0 there is a new administration panel that allows
 | 
			
		||||
you to configure Twitter bridge settings within StatusNet itself,
 | 
			
		||||
instead of having to specify them manually in your config.php.  To enable
 | 
			
		||||
the administration panel, you will need to add it to the list of active
 | 
			
		||||
administration panels.  You can do this via your config.php. E.g.:
 | 
			
		||||
 | 
			
		||||
    $config['admin']['panels'][] = 'twitter';
 | 
			
		||||
 | 
			
		||||
And to access it, you'll need to use a user with the "administrator"
 | 
			
		||||
role (see: scripts/userrole.php).
 | 
			
		||||
 | 
			
		||||
Sign in with Twitter
 | 
			
		||||
--------------------
 | 
			
		||||
 | 
			
		||||
With 0.9.0, StatusNet optionally allows users to register and
 | 
			
		||||
authenticate using their Twitter credentials via the "Sign in with
 | 
			
		||||
Twitter" pattern described here:
 | 
			
		||||
 | 
			
		||||
    http://apiwiki.twitter.com/Sign-in-with-Twitter
 | 
			
		||||
 | 
			
		||||
The option is _on_ by default when you install the plugin, but it can
 | 
			
		||||
disabled via the Twitter bridge administration panel, or by adding the
 | 
			
		||||
following line to your config.php:
 | 
			
		||||
 | 
			
		||||
    $config['twitter']['signin'] = false;
 | 
			
		||||
 | 
			
		||||
Daemons
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
For friend syncing and importing notices running two additional daemon
 | 
			
		||||
scripts is necessary (synctwitterfriends.php and
 | 
			
		||||
twitterstatusfetcher.php).
 | 
			
		||||
For friend syncing and importing Twitter tweets, running two
 | 
			
		||||
additional daemon scripts is necessary: synctwitterfriends.php and
 | 
			
		||||
twitterstatusfetcher.php.
 | 
			
		||||
 | 
			
		||||
In the daemons subidrectory of the plugin are three scripts:
 | 
			
		||||
In the daemons subdirectory of the plugin are three scripts:
 | 
			
		||||
 | 
			
		||||
* Twitter Friends Syncing (daemons/synctwitterfriends.php)
 | 
			
		||||
 | 
			
		||||
@@ -51,13 +93,13 @@ subscribe to "friends" (people they "follow") on Twitter who also have
 | 
			
		||||
accounts on your StatusNet system, and who have previously set up a link
 | 
			
		||||
for automatically posting notices to Twitter.
 | 
			
		||||
 | 
			
		||||
The plugin will try to start this daemon when you run
 | 
			
		||||
scripts/startdaemons.sh.
 | 
			
		||||
The plugin will start this daemon when you run scripts/startdaemons.sh.
 | 
			
		||||
 | 
			
		||||
* Importing statuses from Twitter (daemons/twitterstatusfetcher.php)
 | 
			
		||||
 | 
			
		||||
To allow your users to import their friends' Twitter statuses, you will
 | 
			
		||||
need to enable the bidirectional Twitter bridge in your config.php:
 | 
			
		||||
You can allow uses to enable importing of your friends' Twitter
 | 
			
		||||
timelines either in the Twitter bridge administration panel or in your
 | 
			
		||||
config.php using the following configuration line:
 | 
			
		||||
 | 
			
		||||
    $config['twitterimport']['enabled'] = true;
 | 
			
		||||
 | 
			
		||||
@@ -66,8 +108,9 @@ other daemons when you run scripts/startdaemons.sh.
 | 
			
		||||
 | 
			
		||||
Additionally, you will want to set the integration source variable,
 | 
			
		||||
which will keep notices posted to Twitter via StatusNet from looping
 | 
			
		||||
back.  The integration source should be set to the name of your
 | 
			
		||||
application, exactly as you specified it on the settings page for your
 | 
			
		||||
back.  You can do this in the Twitter bridge administration panel, or
 | 
			
		||||
via config.php. The integration source should be set to the name of your
 | 
			
		||||
application _exactly_ as you specified it on the settings page for your
 | 
			
		||||
StatusNet application on Twitter, e.g.:
 | 
			
		||||
 | 
			
		||||
    $config['integration']['source'] = 'YourApp';
 | 
			
		||||
@@ -79,7 +122,9 @@ set up Twitter bridging.
 | 
			
		||||
 | 
			
		||||
It's not strictly necessary to run this queue handler, and sites that
 | 
			
		||||
haven't enabled queuing are still able to push notices to Twitter, but
 | 
			
		||||
for larger sites and sites that wish to improve performance, this
 | 
			
		||||
script allows notices to be sent "offline" via a separate process.
 | 
			
		||||
for larger sites and sites that wish to improve performance the script
 | 
			
		||||
allows notices to be sent "offline" via a separate process.
 | 
			
		||||
 | 
			
		||||
The plugin will start this script when you run scripts/startdaemons.sh.
 | 
			
		||||
StatusNet will automatically use the TwitterQueueHandler if you have
 | 
			
		||||
enabled the queuing subsystem.  See the "Queues and daemons" section of
 | 
			
		||||
the main README file for more information about how to do that.
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
 * @author    Julien C <chaumond@gmail.com>
 | 
			
		||||
 * @copyright 2009-2010 Control Yourself, Inc.
 | 
			
		||||
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
			
		||||
 * @link      http://laconi.ca/
 | 
			
		||||
 * @link      http://status.net/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
if (!defined('STATUSNET')) {
 | 
			
		||||
@@ -32,8 +32,6 @@ if (!defined('STATUSNET')) {
 | 
			
		||||
 | 
			
		||||
require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php';
 | 
			
		||||
 | 
			
		||||
define('TWITTERBRIDGEPLUGIN_VERSION', '0.9');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Plugin for sending and importing Twitter statuses
 | 
			
		||||
 *
 | 
			
		||||
@@ -44,19 +42,41 @@ define('TWITTERBRIDGEPLUGIN_VERSION', '0.9');
 | 
			
		||||
 * @author   Zach Copley <zach@status.net>
 | 
			
		||||
 * @author   Julien C <chaumond@gmail.com>
 | 
			
		||||
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
			
		||||
 * @link     http://laconi.ca/
 | 
			
		||||
 * @link     http://status.net/
 | 
			
		||||
 * @link     http://twitter.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
class TwitterBridgePlugin extends Plugin
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    const VERSION = STATUSNET_VERSION;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializer for the plugin.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function __construct()
 | 
			
		||||
    function initialize()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
        // Allow the key and secret to be passed in
 | 
			
		||||
        // Control panel will override
 | 
			
		||||
 | 
			
		||||
        if (isset($this->consumer_key)) {
 | 
			
		||||
            $key = common_config('twitter', 'consumer_key');
 | 
			
		||||
            if (empty($key)) {
 | 
			
		||||
                Config::save('twitter', 'consumer_key', $this->consumer_key);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isset($this->consumer_secret)) {
 | 
			
		||||
            $secret = common_config('twitter', 'consumer_secret');
 | 
			
		||||
            if (empty($secret)) {
 | 
			
		||||
                Config::save(
 | 
			
		||||
                    'twitter',
 | 
			
		||||
                    'consumer_secret',
 | 
			
		||||
                    $this->consumer_secret
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -71,10 +91,17 @@ class TwitterBridgePlugin extends Plugin
 | 
			
		||||
 | 
			
		||||
    function onRouterInitialized($m)
 | 
			
		||||
    {
 | 
			
		||||
        $m->connect('twitter/authorization',
 | 
			
		||||
                    array('action' => 'twitterauthorization'));
 | 
			
		||||
        $m->connect(
 | 
			
		||||
            'twitter/authorization',
 | 
			
		||||
            array('action' => 'twitterauthorization')
 | 
			
		||||
        );
 | 
			
		||||
        $m->connect('settings/twitter', array('action' => 'twittersettings'));
 | 
			
		||||
        $m->connect('main/twitterlogin', array('action' => 'twitterlogin'));
 | 
			
		||||
 | 
			
		||||
        if (common_config('twitter', 'signin')) {
 | 
			
		||||
            $m->connect('main/twitterlogin', array('action' => 'twitterlogin'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $m->connect('admin/twitter', array('action' => 'twitteradminpanel'));
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
@@ -88,13 +115,16 @@ class TwitterBridgePlugin extends Plugin
 | 
			
		||||
     */
 | 
			
		||||
    function onEndLoginGroupNav(&$action)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $action_name = $action->trimmed('action');
 | 
			
		||||
 | 
			
		||||
        $action->menuItem(common_local_url('twitterlogin'),
 | 
			
		||||
                                           _('Twitter'),
 | 
			
		||||
                                           _('Login or register using Twitter'),
 | 
			
		||||
                                             'twitterlogin' === $action_name);
 | 
			
		||||
        if (common_config('twitter', 'signin')) {
 | 
			
		||||
            $action->menuItem(
 | 
			
		||||
                common_local_url('twitterlogin'),
 | 
			
		||||
                _m('Twitter'),
 | 
			
		||||
                _m('Login or register using Twitter'),
 | 
			
		||||
                'twitterlogin' === $action_name
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
@@ -110,10 +140,12 @@ class TwitterBridgePlugin extends Plugin
 | 
			
		||||
    {
 | 
			
		||||
        $action_name = $action->trimmed('action');
 | 
			
		||||
 | 
			
		||||
        $action->menuItem(common_local_url('twittersettings'),
 | 
			
		||||
                          _m('Twitter'),
 | 
			
		||||
                          _m('Twitter integration options'),
 | 
			
		||||
                          $action_name === 'twittersettings');
 | 
			
		||||
        $action->menuItem(
 | 
			
		||||
            common_local_url('twittersettings'),
 | 
			
		||||
            _m('Twitter'),
 | 
			
		||||
            _m('Twitter integration options'),
 | 
			
		||||
            $action_name === 'twittersettings'
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
@@ -132,6 +164,7 @@ class TwitterBridgePlugin extends Plugin
 | 
			
		||||
        case 'TwittersettingsAction':
 | 
			
		||||
        case 'TwitterauthorizationAction':
 | 
			
		||||
        case 'TwitterloginAction':
 | 
			
		||||
        case 'TwitteradminpanelAction':
 | 
			
		||||
            include_once INSTALLDIR . '/plugins/TwitterBridge/' .
 | 
			
		||||
              strtolower(mb_substr($cls, 0, -6)) . '.php';
 | 
			
		||||
            return false;
 | 
			
		||||
@@ -173,12 +206,18 @@ class TwitterBridgePlugin extends Plugin
 | 
			
		||||
     */
 | 
			
		||||
    function onGetValidDaemons($daemons)
 | 
			
		||||
    {
 | 
			
		||||
        array_push($daemons, INSTALLDIR .
 | 
			
		||||
                   '/plugins/TwitterBridge/daemons/synctwitterfriends.php');
 | 
			
		||||
        array_push(
 | 
			
		||||
            $daemons,
 | 
			
		||||
            INSTALLDIR
 | 
			
		||||
            . '/plugins/TwitterBridge/daemons/synctwitterfriends.php'
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (common_config('twitterimport', 'enabled')) {
 | 
			
		||||
            array_push($daemons, INSTALLDIR
 | 
			
		||||
                . '/plugins/TwitterBridge/daemons/twitterstatusfetcher.php');
 | 
			
		||||
            array_push(
 | 
			
		||||
                $daemons,
 | 
			
		||||
                INSTALLDIR
 | 
			
		||||
                . '/plugins/TwitterBridge/daemons/twitterstatusfetcher.php'
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
@@ -197,17 +236,55 @@ class TwitterBridgePlugin extends Plugin
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Add a Twitter tab to the admin panel
 | 
			
		||||
     *
 | 
			
		||||
     * @param Widget $nav Admin panel nav
 | 
			
		||||
     *
 | 
			
		||||
     * @return boolean hook value
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function onEndAdminPanelNav($nav)
 | 
			
		||||
    {
 | 
			
		||||
        if (AdminPanelAction::canAdmin('twitter')) {
 | 
			
		||||
 | 
			
		||||
            $action_name = $nav->action->trimmed('action');
 | 
			
		||||
 | 
			
		||||
            $nav->out->menuItem(
 | 
			
		||||
                common_local_url('twitteradminpanel'),
 | 
			
		||||
                _m('Twitter'),
 | 
			
		||||
                _m('Twitter bridge configuration'),
 | 
			
		||||
                $action_name == 'twitteradminpanel',
 | 
			
		||||
                'nav_twitter_admin_panel'
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Plugin version data
 | 
			
		||||
     *
 | 
			
		||||
     * @param array &$versions array of version blocks
 | 
			
		||||
     *
 | 
			
		||||
     * @return boolean hook value
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function onPluginVersion(&$versions)
 | 
			
		||||
    {
 | 
			
		||||
        $versions[] = array('name' => 'TwitterBridge',
 | 
			
		||||
                            'version' => TWITTERBRIDGEPLUGIN_VERSION,
 | 
			
		||||
                            'author' => 'Zach Copley',
 | 
			
		||||
                            'homepage' => 'http://status.net/wiki/Plugin:TwitterBridge',
 | 
			
		||||
                            'rawdescription' =>
 | 
			
		||||
                            _m('The Twitter "bridge" plugin allows you to integrate ' .
 | 
			
		||||
                               'your StatusNet instance with ' .
 | 
			
		||||
                               '<a href="http://twitter.com/">Twitter</a>.'));
 | 
			
		||||
        $versions[] = array(
 | 
			
		||||
            'name' => 'TwitterBridge',
 | 
			
		||||
            'version' => self::VERSION,
 | 
			
		||||
            'author' => 'Zach Copley, Julien C',
 | 
			
		||||
            'homepage' => 'http://status.net/wiki/Plugin:TwitterBridge',
 | 
			
		||||
            'rawdescription' => _m(
 | 
			
		||||
                'The Twitter "bridge" plugin allows you to integrate ' .
 | 
			
		||||
                'your StatusNet instance with ' .
 | 
			
		||||
                '<a href="http://twitter.com/">Twitter</a>.'
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										280
									
								
								plugins/TwitterBridge/twitteradminpanel.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								plugins/TwitterBridge/twitteradminpanel.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,280 @@
 | 
			
		||||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * StatusNet, the distributed open-source microblogging tool
 | 
			
		||||
 *
 | 
			
		||||
 * Twitter bridge administration panel
 | 
			
		||||
 *
 | 
			
		||||
 * 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    Zach Copley <zach@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 Twitter bridge settings
 | 
			
		||||
 *
 | 
			
		||||
 * @category Admin
 | 
			
		||||
 * @package  StatusNet
 | 
			
		||||
 * @author   Zach Copley <zach@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 TwitteradminpanelAction extends AdminPanelAction
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the page title
 | 
			
		||||
     *
 | 
			
		||||
     * @return string page title
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function title()
 | 
			
		||||
    {
 | 
			
		||||
        return _m('Twitter');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Instructions for using this form.
 | 
			
		||||
     *
 | 
			
		||||
     * @return string instructions
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function getInstructions()
 | 
			
		||||
    {
 | 
			
		||||
        return _m('Twitter bridge settings');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Show the Twitter admin panel form
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function showForm()
 | 
			
		||||
    {
 | 
			
		||||
        $form = new TwitterAdminPanelForm($this);
 | 
			
		||||
        $form->show();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Save settings from the form
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function saveSettings()
 | 
			
		||||
    {
 | 
			
		||||
        static $settings = array(
 | 
			
		||||
            'twitter'     => array('consumer_key', 'consumer_secret'),
 | 
			
		||||
            'integration' => array('source')
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        static $booleans = array(
 | 
			
		||||
            'twitter'       => array('signin'),
 | 
			
		||||
            'twitterimport' => array('enabled')
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $values = array();
 | 
			
		||||
 | 
			
		||||
        foreach ($settings as $section => $parts) {
 | 
			
		||||
            foreach ($parts as $setting) {
 | 
			
		||||
                $values[$section][$setting]
 | 
			
		||||
                    = $this->trimmed($setting);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($booleans as $section => $parts) {
 | 
			
		||||
            foreach ($parts as $setting) {
 | 
			
		||||
                $values[$section][$setting]
 | 
			
		||||
                    = ($this->boolean($setting)) ? 1 : 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($booleans 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['twitter']['consumer_key']) > 255) {
 | 
			
		||||
            $this->clientError(
 | 
			
		||||
                _m("Invalid consumer key. Max length is 255 characters.")
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mb_strlen($values['twitter']['consumer_secret']) > 255) {
 | 
			
		||||
            $this->clientError(
 | 
			
		||||
                _m("Invalid consumer secret. Max length is 255 characters.")
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class TwitterAdminPanelForm extends AdminForm
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * ID of the form
 | 
			
		||||
     *
 | 
			
		||||
     * @return int ID of the form
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function id()
 | 
			
		||||
    {
 | 
			
		||||
        return 'twitteradminpanel';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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('twitteradminpanel');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Data elements of the form
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function formData()
 | 
			
		||||
    {
 | 
			
		||||
        $this->out->elementStart(
 | 
			
		||||
            'fieldset',
 | 
			
		||||
            array('id' => 'settings_twitter-application')
 | 
			
		||||
        );
 | 
			
		||||
        $this->out->element('legend', null, _m('Twitter application settings'));
 | 
			
		||||
        $this->out->elementStart('ul', 'form_data');
 | 
			
		||||
 | 
			
		||||
        $this->li();
 | 
			
		||||
        $this->input(
 | 
			
		||||
            'consumer_key',
 | 
			
		||||
            _m('Consumer key'),
 | 
			
		||||
            _m('Consumer key assigned by Twitter'),
 | 
			
		||||
            'twitter'
 | 
			
		||||
        );
 | 
			
		||||
        $this->unli();
 | 
			
		||||
 | 
			
		||||
        $this->li();
 | 
			
		||||
        $this->input(
 | 
			
		||||
            'consumer_secret',
 | 
			
		||||
             _m('Consumer secret'),
 | 
			
		||||
            _m('Consumer secret assigned by Twitter'),
 | 
			
		||||
            'twitter'
 | 
			
		||||
        );
 | 
			
		||||
        $this->unli();
 | 
			
		||||
 | 
			
		||||
        $this->li();
 | 
			
		||||
        $this->input(
 | 
			
		||||
            'source',
 | 
			
		||||
             _m('Integration source'),
 | 
			
		||||
            _m('Name of your Twitter application'),
 | 
			
		||||
            'integration'
 | 
			
		||||
        );
 | 
			
		||||
        $this->unli();
 | 
			
		||||
 | 
			
		||||
        $this->out->elementEnd('ul');
 | 
			
		||||
        $this->out->elementEnd('fieldset');
 | 
			
		||||
 | 
			
		||||
        $this->out->elementStart(
 | 
			
		||||
            'fieldset',
 | 
			
		||||
            array('id' => 'settings_twitter-options')
 | 
			
		||||
        );
 | 
			
		||||
        $this->out->element('legend', null, _m('Options'));
 | 
			
		||||
 | 
			
		||||
        $this->out->elementStart('ul', 'form_data');
 | 
			
		||||
 | 
			
		||||
        $this->li();
 | 
			
		||||
 | 
			
		||||
        $this->out->checkbox(
 | 
			
		||||
            'signin', _m('Enable "Sign-in with Twitter"'),
 | 
			
		||||
            (bool) $this->value('signin', 'twitter'),
 | 
			
		||||
            _m('Allow users to login with their Twitter credentials')
 | 
			
		||||
        );
 | 
			
		||||
        $this->unli();
 | 
			
		||||
 | 
			
		||||
        $this->li();
 | 
			
		||||
        $this->out->checkbox(
 | 
			
		||||
            'enabled', _m('Enable Twitter import'),
 | 
			
		||||
            (bool) $this->value('enabled', 'twitterimport'),
 | 
			
		||||
            _m('Allow users to import their Twitter friends\' timelines')
 | 
			
		||||
        );
 | 
			
		||||
        $this->unli();
 | 
			
		||||
 | 
			
		||||
        $this->out->elementEnd('ul');
 | 
			
		||||
 | 
			
		||||
        $this->out->elementEnd('fieldset');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Action elements
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function formActions()
 | 
			
		||||
    {
 | 
			
		||||
        $this->out->submit('submit', _('Save'), 'submit', null, _('Save Twitter settings'));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -47,7 +47,7 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php';
 | 
			
		||||
 * @author   Zach Copley <zach@status.net>
 | 
			
		||||
 * @author   Julien C <chaumond@gmail.com>
 | 
			
		||||
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
			
		||||
 * @link     http://laconi.ca/
 | 
			
		||||
 * @link     http://status.net/
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class TwitterauthorizationAction extends Action
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user