Merge branch '0.9.x' of git@gitorious.org:statusnet/mainline into 0.9.x
@ -247,3 +247,10 @@ StartLoadDoc: before loading a help doc (hook this to show your own documentatio
|
||||
EndLoadDoc: after loading a help doc (hook this to modify other documentation)
|
||||
- $title: title of the document
|
||||
- $output: HTML output to show
|
||||
|
||||
StartApiRss: after the rss <channel> element is started
|
||||
- $action: action object being shown
|
||||
|
||||
StartApiAtom: after the <feed> element is started
|
||||
- $action: action object being shown
|
||||
|
||||
|
1
README
@ -146,6 +146,7 @@ Your PHP installation must include the following PHP extensions:
|
||||
- GD. For scaling down avatar images.
|
||||
- mbstring. For handling Unicode (UTF-8) encoded strings.
|
||||
- gettext. For multiple languages. Default on many PHP installs.
|
||||
- tidy. Used to clean up HTML/URLs for the URL shortener to consume.
|
||||
|
||||
For some functionality, you will also need the following extensions:
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
/**
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2008, 2009, StatusNet, Inc.
|
||||
*
|
||||
@ -15,9 +15,29 @@
|
||||
*
|
||||
* 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 Actions
|
||||
* @package Actions
|
||||
* @author Evan Prodromou <evan@prodromou.name>
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @author Adrian Lang <mail@adrianlang.de>
|
||||
* @author Meitar Moscovitz <meitarm@gmail.com>
|
||||
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Evan Prodromou <evan@controlezvous.ca>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @author csarven <csarven@controlyourself.ca>
|
||||
* @license GNU Affero General Public License http://www.gnu.org/licenses/
|
||||
* @link http://status.net
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/personalgroupnav.php';
|
||||
require_once INSTALLDIR.'/lib/noticelist.php';
|
||||
@ -43,8 +63,8 @@ class AllAction extends ProfileAction
|
||||
$this->notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
|
||||
}
|
||||
|
||||
if($this->page > 1 && $this->notice->N == 0){
|
||||
$this->serverError(_('No such page'),$code=404);
|
||||
if ($this->page > 1 && $this->notice->N == 0) {
|
||||
$this->serverError(_('No such page'), $code = 404);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -73,20 +93,33 @@ class AllAction extends ProfileAction
|
||||
|
||||
function getFeeds()
|
||||
{
|
||||
return array(new Feed(Feed::RSS1,
|
||||
common_local_url('allrss', array('nickname' =>
|
||||
$this->user->nickname)),
|
||||
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
|
||||
new Feed(Feed::RSS2,
|
||||
common_local_url('api', array('apiaction' => 'statuses',
|
||||
'method' => 'friends_timeline',
|
||||
'argument' => $this->user->nickname.'.rss')),
|
||||
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
|
||||
new Feed(Feed::ATOM,
|
||||
common_local_url('api', array('apiaction' => 'statuses',
|
||||
'method' => 'friends_timeline',
|
||||
'argument' => $this->user->nickname.'.atom')),
|
||||
sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname)));
|
||||
return array(
|
||||
new Feed(Feed::RSS1,
|
||||
common_local_url(
|
||||
'allrss', array(
|
||||
'nickname' =>
|
||||
$this->user->nickname)
|
||||
),
|
||||
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
|
||||
new Feed(Feed::RSS2,
|
||||
common_local_url(
|
||||
'api', array(
|
||||
'apiaction' => 'statuses',
|
||||
'method' => 'friends_timeline',
|
||||
'argument' => $this->user->nickname.'.rss'
|
||||
)
|
||||
),
|
||||
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
|
||||
new Feed(Feed::ATOM,
|
||||
common_local_url(
|
||||
'api', array(
|
||||
'apiaction' => 'statuses',
|
||||
'method' => 'friends_timeline',
|
||||
'argument' => $this->user->nickname.'.atom'
|
||||
)
|
||||
),
|
||||
sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname))
|
||||
);
|
||||
}
|
||||
|
||||
function showLocalNav()
|
||||
@ -106,8 +139,7 @@ class AllAction extends ProfileAction
|
||||
} else {
|
||||
$message .= sprintf(_('You can try to [nudge %s](../%s) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname);
|
||||
}
|
||||
|
||||
@ -126,17 +158,19 @@ class AllAction extends ProfileAction
|
||||
$this->showEmptyListMessage();
|
||||
}
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'all', array('nickname' => $this->user->nickname));
|
||||
$this->pagination(
|
||||
$this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'all', array('nickname' => $this->user->nickname)
|
||||
);
|
||||
}
|
||||
|
||||
function showPageTitle()
|
||||
{
|
||||
$user =& common_current_user();
|
||||
if ($user && ($user->id == $this->user->id)) {
|
||||
$this->element('h1', NULL, _("You and friends"));
|
||||
$this->element('h1', null, _("You and friends"));
|
||||
} else {
|
||||
$this->element('h1', NULL, sprintf(_('%s and friends'), $this->user->nickname));
|
||||
$this->element('h1', null, sprintf(_('%s and friends'), $this->user->nickname));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
/**
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2008, 2009, StatusNet, Inc.
|
||||
*
|
||||
@ -15,9 +15,30 @@
|
||||
*
|
||||
* 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 Actions
|
||||
* @package Actions
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @author Evan Prodromou <evan@prodromou.name>
|
||||
* @author Brenda Wallace <shiny@cpan.org>
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @author Tom Adams <tom@holizz.com>
|
||||
* @author Christopher Vollick <psycotica0@gmail.com>
|
||||
* @author CiaranG <ciaran@ciarang.com>
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Evan Prodromou <evan@controlezvous.ca>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Gina Haeussge <osd@foosel.net>
|
||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
||||
* @license GNU Affero General Public License http://www.gnu.org/licenses/
|
||||
* @link http://status.net
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class ApiAction extends Action
|
||||
{
|
||||
@ -27,6 +48,8 @@ class ApiAction extends Action
|
||||
var $api_arg;
|
||||
var $api_method;
|
||||
var $api_action;
|
||||
var $auth_user;
|
||||
var $auth_pw;
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
@ -35,6 +58,7 @@ class ApiAction extends Action
|
||||
$this->api_action = $this->arg('apiaction');
|
||||
$method = $this->arg('method');
|
||||
$argument = $this->arg('argument');
|
||||
$this->basic_auth_process_header();
|
||||
|
||||
if (isset($argument)) {
|
||||
$cmdext = explode('.', $argument);
|
||||
@ -43,30 +67,30 @@ class ApiAction extends Action
|
||||
$this->content_type = strtolower($cmdext[1]);
|
||||
} else {
|
||||
|
||||
# Requested format / content-type will be an extension on the method
|
||||
//Requested format / content-type will be an extension on the method
|
||||
$cmdext = explode('.', $method);
|
||||
$this->api_method = $cmdext[0];
|
||||
$this->content_type = strtolower($cmdext[1]);
|
||||
}
|
||||
|
||||
if ($this->requires_auth()) {
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
if (!isset($this->auth_user)) {
|
||||
|
||||
# This header makes basic auth go
|
||||
//This header makes basic auth go
|
||||
header('WWW-Authenticate: Basic realm="StatusNet API"');
|
||||
|
||||
# If the user hits cancel -- bam!
|
||||
//If the user hits cancel -- bam!
|
||||
$this->show_basic_auth_error();
|
||||
} else {
|
||||
$nickname = $_SERVER['PHP_AUTH_USER'];
|
||||
$password = $_SERVER['PHP_AUTH_PW'];
|
||||
$nickname = $this->auth_user;
|
||||
$password = $this->auth_pw;
|
||||
$user = common_check_user($nickname, $password);
|
||||
|
||||
if ($user) {
|
||||
$this->user = $user;
|
||||
$this->process_command();
|
||||
} else {
|
||||
# basic authentication failed
|
||||
//basic authentication failed
|
||||
list($proxy, $ip) = common_client_ip();
|
||||
|
||||
common_log(LOG_WARNING, "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip.");
|
||||
@ -76,12 +100,12 @@ class ApiAction extends Action
|
||||
} else {
|
||||
|
||||
// Caller might give us a username even if not required
|
||||
if (isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
$user = User::staticGet('nickname', $_SERVER['PHP_AUTH_USER']);
|
||||
if (isset($this->auth_user)) {
|
||||
$user = User::staticGet('nickname', $this->auth_user);
|
||||
if ($user) {
|
||||
$this->user = $user;
|
||||
}
|
||||
# Twitter doesn't throw an error if the user isn't found
|
||||
//Twitter doesn't throw an error if the user isn't found
|
||||
}
|
||||
|
||||
$this->process_command();
|
||||
@ -94,7 +118,7 @@ class ApiAction extends Action
|
||||
$actionfile = INSTALLDIR."/actions/$action.php";
|
||||
|
||||
if (file_exists($actionfile)) {
|
||||
require_once($actionfile);
|
||||
include_once $actionfile;
|
||||
$action_class = ucfirst($action)."Action";
|
||||
$action_obj = new $action_class();
|
||||
|
||||
@ -110,10 +134,10 @@ class ApiAction extends Action
|
||||
|
||||
call_user_func(array($action_obj, $this->api_method), $_REQUEST, $apidata);
|
||||
} else {
|
||||
$this->clientError("API method not found!", $code=404);
|
||||
$this->clientError("API method not found!", $code = 404);
|
||||
}
|
||||
} else {
|
||||
$this->clientError("API method not found!", $code=404);
|
||||
$this->clientError("API method not found!", $code = 404);
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,6 +157,8 @@ class ApiAction extends Action
|
||||
'groups/show',
|
||||
'groups/timeline',
|
||||
'groups/list_all',
|
||||
'groups/membership',
|
||||
'groups/is_member',
|
||||
'groups/timeline');
|
||||
|
||||
static $bareauth = array('statuses/user_timeline',
|
||||
@ -179,10 +205,11 @@ class ApiAction extends Action
|
||||
$user_id = $this->arg('user_id');
|
||||
$screen_name = $this->arg('screen_name');
|
||||
|
||||
if (empty($this->api_arg) &&
|
||||
empty($id) &&
|
||||
empty($user_id) &&
|
||||
empty($screen_name)) {
|
||||
if (empty($this->api_arg)
|
||||
&& empty($id)
|
||||
&& empty($user_id)
|
||||
&& empty($screen_name)
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -201,6 +228,33 @@ class ApiAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
function basic_auth_process_header()
|
||||
{
|
||||
if (isset($_SERVER['AUTHORIZATION']) || isset($_SERVER['HTTP_AUTHORIZATION'])) {
|
||||
$authorization_header = isset($_SERVER['HTTP_AUTHORIZATION'])? $_SERVER['HTTP_AUTHORIZATION'] : $_SERVER['AUTHORIZATION'];
|
||||
}
|
||||
|
||||
if (isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
$this->auth_user = $_SERVER['PHP_AUTH_USER'];
|
||||
$this->auth_pw = $_SERVER['PHP_AUTH_PW'];
|
||||
} elseif (isset($authorization_header) && strstr(substr($authorization_header, 0, 5), 'Basic')) {
|
||||
// decode the HTTP_AUTHORIZATION header on php-cgi server self
|
||||
// on fcgid server the header name is AUTHORIZATION
|
||||
|
||||
$auth_hash = base64_decode(substr($authorization_header, 6));
|
||||
list($this->auth_user, $this->auth_pw) = explode(':', $auth_hash);
|
||||
|
||||
// set all to null on a empty basic auth request
|
||||
if ($this->auth_user == "") {
|
||||
$this->auth_user = null;
|
||||
$this->auth_pw = null;
|
||||
}
|
||||
} else {
|
||||
$this->auth_user = null;
|
||||
$this->auth_pw = null;
|
||||
}
|
||||
}
|
||||
|
||||
function show_basic_auth_error()
|
||||
{
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
@ -214,7 +268,7 @@ class ApiAction extends Action
|
||||
$this->element('request', null, $_SERVER['REQUEST_URI']);
|
||||
$this->elementEnd('hash');
|
||||
$this->endXML();
|
||||
} else if ($this->content_type == 'json') {
|
||||
} else if ($this->content_type == 'json') {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
$error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']);
|
||||
print(json_encode($error_array));
|
||||
|
@ -399,5 +399,7 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
$this->script('js/jcrop/jquery.Jcrop.min.js');
|
||||
$this->script('js/jcrop/jquery.Jcrop.go.js');
|
||||
}
|
||||
|
||||
$this->autofocus('avatarfile');
|
||||
}
|
||||
}
|
||||
|
@ -160,6 +160,12 @@ class EditgroupAction extends GroupDesignAction
|
||||
}
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('nickname');
|
||||
}
|
||||
|
||||
function trySave()
|
||||
{
|
||||
$cur = common_current_user();
|
||||
|
@ -71,6 +71,12 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
return _('Manage how you get email from %%site.name%%.');
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('email');
|
||||
}
|
||||
|
||||
/**
|
||||
* Content area of the page
|
||||
*
|
||||
|
@ -146,8 +146,10 @@ class FoafAction extends Action
|
||||
while ($sub->fetch()) {
|
||||
if ($sub->token) {
|
||||
$other = Remote_profile::staticGet('id', $sub->subscriber);
|
||||
$profile = Profile::staticGet('id', $sub->subscriber);
|
||||
} else {
|
||||
$other = User::staticGet('id', $sub->subscriber);
|
||||
$profile = Profile::staticGet('id', $sub->subscriber);
|
||||
}
|
||||
if (!$other) {
|
||||
common_debug('Got a bad subscription: '.print_r($sub,true));
|
||||
@ -158,12 +160,15 @@ class FoafAction extends Action
|
||||
} else {
|
||||
$person[$other->uri] = array(LISTENER,
|
||||
$other->id,
|
||||
$other->nickname,
|
||||
$profile->nickname,
|
||||
(empty($sub->token)) ? 'User' : 'Remote_profile');
|
||||
}
|
||||
$other->free();
|
||||
$other = null;
|
||||
unset($other);
|
||||
$profile->free();
|
||||
$profile = null;
|
||||
unset($profile);
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,8 +259,10 @@ class FoafAction extends Action
|
||||
while ($sub->fetch()) {
|
||||
if (!empty($sub->token)) {
|
||||
$other = Remote_profile::staticGet('id', $sub->subscribed);
|
||||
$profile = Profile::staticGet('id', $sub->subscribed);
|
||||
} else {
|
||||
$other = User::staticGet('id', $sub->subscribed);
|
||||
$profile = Profile::staticGet('id', $sub->subscribed);
|
||||
}
|
||||
if (empty($other)) {
|
||||
common_debug('Got a bad subscription: '.print_r($sub,true));
|
||||
@ -264,11 +271,14 @@ class FoafAction extends Action
|
||||
$this->element('sioc:follows', array('rdf:resource' => $other->uri.'#acct'));
|
||||
$person[$other->uri] = array(LISTENEE,
|
||||
$other->id,
|
||||
$other->nickname,
|
||||
$profile->nickname,
|
||||
(empty($sub->token)) ? 'User' : 'Remote_profile');
|
||||
$other->free();
|
||||
$other = null;
|
||||
unset($other);
|
||||
$profile->free();
|
||||
$profile = null;
|
||||
unset($profile);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,6 +445,8 @@ class GrouplogoAction extends GroupDesignAction
|
||||
$this->script('js/jcrop/jquery.Jcrop.min.js');
|
||||
$this->script('js/jcrop/jquery.Jcrop.go.js');
|
||||
}
|
||||
|
||||
$this->autofocus('avatarfile');
|
||||
}
|
||||
|
||||
function showLocalNav()
|
||||
|
@ -90,6 +90,12 @@ class GroupsearchAction extends SearchAction
|
||||
$user_group->free();
|
||||
}
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('q');
|
||||
}
|
||||
}
|
||||
|
||||
class GroupSearchResults extends GroupList
|
||||
|
@ -98,6 +98,12 @@ class InviteAction extends CurrentUserDesignAction
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('addresses');
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
if ($this->mode == 'sent') {
|
||||
|
@ -22,6 +22,7 @@
|
||||
* @category Login
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Sarven Capadisli <csarven@status.net>
|
||||
* @copyright 2008-2009 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/
|
||||
@ -37,6 +38,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
* @category Personal
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Sarven Capadisli <csarven@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/
|
||||
*/
|
||||
@ -158,6 +160,12 @@ class LoginAction extends Action
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('nickname');
|
||||
}
|
||||
|
||||
/**
|
||||
* Title of the page
|
||||
*
|
||||
|
@ -135,6 +135,12 @@ class NoticesearchAction extends SearchAction
|
||||
$this->pagination($page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$page, 'noticesearch', array('q' => $q));
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('q');
|
||||
}
|
||||
}
|
||||
|
||||
class SearchNoticeList extends NoticeList {
|
||||
@ -190,7 +196,7 @@ class SearchNoticeListItem extends NoticeListItem {
|
||||
$result = preg_replace($pattern, '<strong>\\1</strong>', $text);
|
||||
|
||||
/* Remove highlighting from inside links, loop incase multiple highlights in links */
|
||||
$pattern = '/(href="[^"]*)<strong>('.$options.')<\/strong>([^"]*")/iU';
|
||||
$pattern = '/(\w+="[^"]*)<strong>('.$options.')<\/strong>([^"]*")/iU';
|
||||
do {
|
||||
$result = preg_replace($pattern, '\\1\\2\\3', $result, -1, $count);
|
||||
} while ($count);
|
||||
|
@ -71,6 +71,12 @@ class OthersettingsAction extends AccountSettingsAction
|
||||
return _('Manage various other options.');
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('urlshorteningservice');
|
||||
}
|
||||
|
||||
/**
|
||||
* Content area of the page
|
||||
*
|
||||
@ -91,19 +97,20 @@ class OthersettingsAction extends AccountSettingsAction
|
||||
$this->elementStart('fieldset');
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
// I18N
|
||||
|
||||
$services = array(
|
||||
'' => 'None',
|
||||
'ur1.ca' => 'ur1.ca (free service)',
|
||||
'2tu.us' => '2tu.us (free service)',
|
||||
'ptiturl.com' => 'ptiturl.com',
|
||||
'bit.ly' => 'bit.ly',
|
||||
'tinyurl.com' => 'tinyurl.com',
|
||||
'is.gd' => 'is.gd',
|
||||
'snipr.com' => 'snipr.com',
|
||||
'metamark.net' => 'metamark.net'
|
||||
);
|
||||
$services=array();
|
||||
global $_shorteners;
|
||||
if($_shorteners){
|
||||
foreach($_shorteners as $name=>$value)
|
||||
{
|
||||
$services[$name]=$name;
|
||||
if($value['info']['freeService']){
|
||||
// I18N
|
||||
$services[$name].=' (free service)';
|
||||
}
|
||||
}
|
||||
}
|
||||
asort($services);
|
||||
$services['']='None';
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
|
@ -69,6 +69,12 @@ class PasswordsettingsAction extends AccountSettingsAction
|
||||
return _('Change your password.');
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('oldpassword');
|
||||
}
|
||||
|
||||
/**
|
||||
* Content area of the page
|
||||
*
|
||||
|
@ -85,6 +85,12 @@ class PeoplesearchAction extends SearchAction
|
||||
$profile->free();
|
||||
}
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('q');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,6 +23,7 @@
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @author Sarven Capadisli <csarven@status.net>
|
||||
* @copyright 2008-2009 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/
|
||||
@ -41,6 +42,7 @@ require_once INSTALLDIR.'/lib/accountsettingsaction.php';
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @author Sarven Capadisli <csarven@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/
|
||||
*/
|
||||
@ -70,6 +72,12 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
'so people know more about you.');
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('nickname');
|
||||
}
|
||||
|
||||
/**
|
||||
* Content area of the page
|
||||
*
|
||||
|
@ -225,10 +225,10 @@ class PublicAction extends Action
|
||||
function showAnonymousMessage()
|
||||
{
|
||||
if (! (common_config('site','closed') || common_config('site','inviteonly'))) {
|
||||
$m = _('This is %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||
'based on the Free Software [StatusNet](http://status.net/) tool. ' .
|
||||
'[Join now](%%%%action.register%%%%) to share notices about yourself with friends, family, and colleagues! ' .
|
||||
'([Read more](%%%%doc.help%%%%))');
|
||||
'[Join now](%%action.register%%) to share notices about yourself with friends, family, and colleagues! ' .
|
||||
'([Read more](%%doc.help%%))');
|
||||
} else {
|
||||
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||
'based on the Free Software [StatusNet](http://status.net/) tool.');
|
||||
|
@ -136,6 +136,12 @@ class RegisterAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('nickname');
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to register a user
|
||||
*
|
||||
|
@ -69,6 +69,12 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
return _('You can receive SMS messages through email from %%site.name%%.');
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('sms');
|
||||
}
|
||||
|
||||
/**
|
||||
* Content area of the page
|
||||
*
|
||||
|
@ -107,6 +107,12 @@ class SubscriptionsAction extends GalleryAction
|
||||
array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('tag');
|
||||
}
|
||||
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
if (common_logged_in()) {
|
||||
|
@ -99,6 +99,12 @@ class TwitapifriendshipsAction extends TwitterapiAction
|
||||
$other = $this->get_profile($id);
|
||||
$user = $apidata['user']; // Alwyas the auth user
|
||||
|
||||
if ($user->id == $other->id) {
|
||||
$this->clientError(_("You cannot unfollow yourself!"),
|
||||
403, $apidata['content-type']);
|
||||
return;
|
||||
}
|
||||
|
||||
$sub = new Subscription();
|
||||
$sub->subscriber = $user->id;
|
||||
$sub->subscribed = $other->id;
|
||||
|
@ -21,7 +21,7 @@
|
||||
*
|
||||
* @category Twitter
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
@ -41,7 +41,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
|
||||
*
|
||||
* @category Twitter
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
@ -233,4 +233,97 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
|
||||
}
|
||||
}
|
||||
|
||||
function membership($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
common_debug("in groups api action");
|
||||
|
||||
$this->auth_user = $apidata['user'];
|
||||
$group = $this->get_group($apidata['api_arg'], $apidata);
|
||||
|
||||
if (empty($group)) {
|
||||
$this->clientError('Not Found', 404, $apidata['content-type']);
|
||||
return;
|
||||
}
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$title = sprintf(_("Members of %s group"), $group->nickname);
|
||||
$taguribase = common_config('integration', 'taguri');
|
||||
$id = "tag:$taguribase:GroupMembership:".$group->id;
|
||||
$link = common_local_url('showgroup',
|
||||
array('nickname' => $group->nickname));
|
||||
$subtitle = sprintf(_('Members of %1$s on %2$s'),
|
||||
$group->nickname, $sitename);
|
||||
|
||||
$page = (int)$this->arg('page', 1);
|
||||
$count = (int)$this->arg('count', 20);
|
||||
$max_id = (int)$this->arg('max_id', 0);
|
||||
$since_id = (int)$this->arg('since_id', 0);
|
||||
$since = $this->arg('since');
|
||||
|
||||
$member = $group->getMembers(($page-1)*$count,
|
||||
$count, $since_id, $max_id, $since);
|
||||
|
||||
switch($apidata['content-type']) {
|
||||
case 'xml':
|
||||
$this->show_twitter_xml_users($member);
|
||||
break;
|
||||
//TODO implement the RSS and ATOM content types
|
||||
/*case 'rss':
|
||||
$this->show_rss_users($member, $title, $link, $subtitle);
|
||||
break;*/
|
||||
/*case 'atom':
|
||||
if (isset($apidata['api_arg'])) {
|
||||
$selfuri = common_root_url() .
|
||||
'api/statusnet/groups/membership/' .
|
||||
$apidata['api_arg'] . '.atom';
|
||||
} else {
|
||||
$selfuri = common_root_url() .
|
||||
'api/statusnet/groups/membership.atom';
|
||||
}
|
||||
$this->show_atom_users($member, $title, $id, $link,
|
||||
$subtitle, null, $selfuri);
|
||||
break;*/
|
||||
case 'json':
|
||||
$this->show_json_users($member);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(_('API method not found!'), $code = 404);
|
||||
}
|
||||
}
|
||||
|
||||
function is_member($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
common_debug("in groups api action");
|
||||
|
||||
$this->auth_user = $apidata['user'];
|
||||
$group = User_group::staticGet($args['group_id']);
|
||||
if(! $group){
|
||||
$this->clientError(_('Group not found'), $code = 500);
|
||||
}
|
||||
$user = User::staticGet('id', $args['user_id']);
|
||||
if(! $user){
|
||||
$this->clientError(_('User not found'), $code = 500);
|
||||
}
|
||||
|
||||
$is_member=$user->isMember($group);
|
||||
|
||||
switch($apidata['content-type']) {
|
||||
case 'xml':
|
||||
$this->init_document('xml');
|
||||
$this->element('is_member', null, $is_member);
|
||||
$this->end_document('xml');
|
||||
break;
|
||||
case 'json':
|
||||
$this->init_document('json');
|
||||
$this->show_json_objects(array('is_member'=>$is_member));
|
||||
$this->end_document('json');
|
||||
break;
|
||||
default:
|
||||
$this->clientError(_('API method not found!'), $code = 404);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
*
|
||||
* @category Twitter
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
@ -41,7 +41,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
|
||||
*
|
||||
* @category Twitter
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
|
@ -165,7 +165,7 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
($flink->noticesync & FOREIGN_NOTICE_RECV) :
|
||||
false);
|
||||
$this->elementEnd('li');
|
||||
|
||||
} else {
|
||||
// preserve setting even if bidrection bridge toggled off
|
||||
|
||||
if ($flink && ($flink->noticesync & FOREIGN_NOTICE_RECV)) {
|
||||
|
@ -78,14 +78,14 @@ class File extends Memcached_DataObject
|
||||
$file_id = $x->insert();
|
||||
|
||||
if (isset($redir_data['type'])
|
||||
&& ('text/html' === substr($redir_data['type'], 0, 9))
|
||||
&& (('text/html' === substr($redir_data['type'], 0, 9) || 'application/xhtml+xml' === substr($redir_data['type'], 0, 21)))
|
||||
&& ($oembed_data = File_oembed::_getOembed($given_url))) {
|
||||
File_oembed::saveNew($oembed_data, $file_id);
|
||||
}
|
||||
return $x;
|
||||
}
|
||||
|
||||
function processNew($given_url, $notice_id) {
|
||||
function processNew($given_url, $notice_id=null) {
|
||||
if (empty($given_url)) return -1; // error, no url to process
|
||||
$given_url = File_redirection::_canonUrl($given_url);
|
||||
if (empty($given_url)) return -1; // error, no url to process
|
||||
@ -96,7 +96,7 @@ class File extends Memcached_DataObject
|
||||
$redir_data = File_redirection::where($given_url);
|
||||
$redir_url = $redir_data['url'];
|
||||
// TODO: max field length
|
||||
if ($redir_url === $given_url || strlen($redir_url) > 255) {
|
||||
if ($redir_url === $given_url || strlen($redir_url) > 255) {
|
||||
$x = File::saveNew($redir_data, $given_url);
|
||||
$file_id = $x->id;
|
||||
} else {
|
||||
@ -119,7 +119,9 @@ class File extends Memcached_DataObject
|
||||
}
|
||||
}
|
||||
|
||||
File_to_post::processNew($file_id, $notice_id);
|
||||
if (!empty($notice_id)) {
|
||||
File_to_post::processNew($file_id, $notice_id);
|
||||
}
|
||||
return $x;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ class Notice extends Memcached_DataObject
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
/* Notice types */
|
||||
/* Notice types */
|
||||
const LOCAL_PUBLIC = 1;
|
||||
const REMOTE_OMB = 0;
|
||||
const LOCAL_NONPUBLIC = -1;
|
||||
@ -260,17 +260,6 @@ class Notice extends Memcached_DataObject
|
||||
|
||||
$notice->saveUrls();
|
||||
|
||||
// FIXME: why do we have to re-render the content?
|
||||
// Remove this if it's not necessary.
|
||||
|
||||
$orig2 = clone($notice);
|
||||
|
||||
$notice->rendered = common_render_content($final, $notice);
|
||||
if (!$notice->update($orig2)) {
|
||||
common_log_db_error($notice, 'UPDATE', __FILE__);
|
||||
return _('Problem saving notice.');
|
||||
}
|
||||
|
||||
$notice->query('COMMIT');
|
||||
|
||||
Event::handle('EndNoticeSave', array($notice));
|
||||
@ -755,6 +744,10 @@ class Notice extends Memcached_DataObject
|
||||
return new ArrayWrapper($notices);
|
||||
} else {
|
||||
$notice = new Notice();
|
||||
if (empty($ids)) {
|
||||
//if no IDs requested, just return the notice object
|
||||
return $notice;
|
||||
}
|
||||
$notice->whereAdd('id in (' . implode(', ', $ids) . ')');
|
||||
$notice->orderBy('id DESC');
|
||||
|
||||
|
@ -54,7 +54,7 @@ class Status_network extends DB_DataObject
|
||||
global $config;
|
||||
|
||||
$config['db']['database_'.$dbname] = "mysqli://$dbuser:$dbpass@$dbhost/$dbname";
|
||||
$config['db']['ini_'.$dbname] = INSTALLDIR.'/classes/statusnet.ini';
|
||||
$config['db']['ini_'.$dbname] = INSTALLDIR.'/classes/status_network.ini';
|
||||
$config['db']['table_status_network'] = $dbname;
|
||||
|
||||
self::$cache = new Memcache();
|
||||
|
@ -103,10 +103,7 @@ class User extends Memcached_DataObject
|
||||
}
|
||||
$toupdate = implode(', ', $parts);
|
||||
|
||||
$table = $this->tableName();
|
||||
if(common_config('db','quote_identifiers')) {
|
||||
$table = '"' . $table . '"';
|
||||
}
|
||||
$table = common_database_tablename($this->tableName());
|
||||
$qry = 'UPDATE ' . $table . ' SET ' . $toupdate .
|
||||
' WHERE id = ' . $this->id;
|
||||
$orig->decache();
|
||||
@ -630,11 +627,7 @@ class User extends Memcached_DataObject
|
||||
'ORDER BY subscription.created DESC ';
|
||||
|
||||
if ($offset) {
|
||||
if (common_config('db','type') == 'pgsql') {
|
||||
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
} else {
|
||||
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
|
||||
}
|
||||
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
}
|
||||
|
||||
$profile = new Profile();
|
||||
@ -657,11 +650,7 @@ class User extends Memcached_DataObject
|
||||
'AND subscription.subscribed != subscription.subscriber ' .
|
||||
'ORDER BY subscription.created DESC ';
|
||||
|
||||
if (common_config('db','type') == 'pgsql') {
|
||||
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
} else {
|
||||
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
|
||||
}
|
||||
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
|
||||
$profile = new Profile();
|
||||
|
||||
|
@ -12,3 +12,23 @@ alter table user_group
|
||||
|
||||
alter table file_oembed
|
||||
add column mimetype varchar(50) comment 'mime type of resource';
|
||||
|
||||
create table config (
|
||||
|
||||
section varchar(32) comment 'configuration section',
|
||||
setting varchar(32) comment 'configuration setting',
|
||||
value varchar(255) comment 'configuration value',
|
||||
|
||||
constraint primary key (section, setting)
|
||||
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table user_role (
|
||||
|
||||
user_id integer not null comment 'user having the role' references user (id),
|
||||
role varchar(32) not null comment 'string representing the role',
|
||||
created datetime not null comment 'date the role was granted',
|
||||
|
||||
constraint primary key (user_id, role)
|
||||
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
@ -1,2 +1,40 @@
|
||||
// SQL commands to update an 0.8.x version of Laconica
|
||||
// to 0.9.x.
|
||||
-- SQL commands to update an 0.8.x version of Laconica
|
||||
-- to 0.9.x.
|
||||
|
||||
--these are just comments
|
||||
/*
|
||||
alter table notice
|
||||
modify column content text comment 'update content';
|
||||
|
||||
alter table message
|
||||
modify column content text comment 'message content';
|
||||
|
||||
alter table profile
|
||||
modify column bio text comment 'descriptive biography';
|
||||
|
||||
alter table user_group
|
||||
modify column description text comment 'group description';
|
||||
*/
|
||||
|
||||
alter table file_oembed
|
||||
add column mimetype varchar(50) /*comment 'mime type of resource'*/;
|
||||
|
||||
create table config (
|
||||
|
||||
section varchar(32) /* comment 'configuration section'*/,
|
||||
setting varchar(32) /* comment 'configuration setting'*/,
|
||||
value varchar(255) /* comment 'configuration value'*/,
|
||||
|
||||
primary key (section, setting)
|
||||
|
||||
);
|
||||
|
||||
create table user_role (
|
||||
|
||||
user_id integer not null /* comment 'user having the role'*/ references "user" (id),
|
||||
role varchar(32) not null /* comment 'string representing the role'*/,
|
||||
created timestamp /* not null comment 'date the role was granted'*/,
|
||||
|
||||
primary key (user_id, role)
|
||||
|
||||
);
|
||||
|
@ -549,3 +549,23 @@ create index noticecontent_idx on notice using gist(to_tsvector('english',conten
|
||||
create trigger textsearchupdate before insert or update on profile for each row
|
||||
execute procedure tsvector_update_trigger(textsearch, 'pg_catalog.english', nickname, fullname, location, bio, homepage);
|
||||
|
||||
|
||||
create table config (
|
||||
|
||||
section varchar(32) /* comment 'configuration section'*/,
|
||||
setting varchar(32) /* comment 'configuration setting'*/,
|
||||
value varchar(255) /* comment 'configuration value'*/,
|
||||
|
||||
primary key (section, setting)
|
||||
|
||||
);
|
||||
|
||||
create table user_role (
|
||||
|
||||
user_id integer not null /* comment 'user having the role'*/ references "user" (id),
|
||||
role varchar(32) not null /* comment 'string representing the role'*/,
|
||||
created timestamp /* not null comment 'date the role was granted'*/,
|
||||
|
||||
primary key (user_id, role)
|
||||
|
||||
);
|
||||
|
@ -13,7 +13,7 @@ Bugs
|
||||
----
|
||||
|
||||
If you think you've found a bug in the [StatusNet](http://status.net/) software,
|
||||
or if there's a new feature you'd like to see, add it into the [StatusNet bug database](http://status.net/PITS/HomePage). Don't forget to check the list of
|
||||
or if there's a new feature you'd like to see, add it into the [StatusNet bug database](http://status.net/bugs/). Don't forget to check the list of
|
||||
existing bugs to make sure it hasn't already been reported!
|
||||
|
||||
Email
|
||||
|
@ -199,7 +199,8 @@ class OAuthRequest {/*{{{*/
|
||||
} else {
|
||||
// collect request parameters from query string (GET) and post-data (POST) if appropriate (note: POST vars have priority)
|
||||
$req_parameters = $_GET;
|
||||
if ($http_method == "POST" && @strstr($request_headers["Content-Type"], "application/x-www-form-urlencoded") ) {
|
||||
if ($http_method == "POST" &&
|
||||
( @strstr($request_headers["Content-Type"], "application/x-www-form-urlencoded") || @strstr($_ENV["CONTENT_TYPE"], "application/x-www-form-urlencoded") )) {
|
||||
$req_parameters = array_merge($req_parameters, $_POST);
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ class Services_oEmbed
|
||||
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
if (substr($code, 0, 1) != '2') {
|
||||
throw new Services_oEmbed_Exception('Non-200 code returned');
|
||||
throw new Services_oEmbed_Exception('Non-200 code returned. Got code ' . $code);
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
@ -302,8 +302,8 @@ class Services_oEmbed
|
||||
|
||||
// Find all <link /> tags that have a valid oembed type set. We then
|
||||
// extract the href attribute for each type.
|
||||
$regexp = '#<link([^>]*)type="' .
|
||||
'(application/json|text/xml)\+oembed"([^>]*)>#i';
|
||||
$regexp = '#<link([^>]*)type[\s\n]*=[\s\n]*"' .
|
||||
'(application/json|text/xml)\+oembed"([^>]*)>#im';
|
||||
|
||||
$m = $ret = array();
|
||||
if (!preg_match_all($regexp, $body, $m)) {
|
||||
@ -314,7 +314,7 @@ class Services_oEmbed
|
||||
|
||||
foreach ($m[0] as $i => $link) {
|
||||
$h = array();
|
||||
if (preg_match('/href="([^"]+)"/i', $link, $h)) {
|
||||
if (preg_match('/[\s\n]+href[\s\n]*=[\s\n]*"([^"]+)"/im', $link, $h)) {
|
||||
$ret[$m[2][$i]] = $h[1];
|
||||
}
|
||||
}
|
||||
@ -347,7 +347,7 @@ class Services_oEmbed
|
||||
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
if (substr($code, 0, 1) != '2') {
|
||||
throw new Services_oEmbed_Exception('Non-200 code returned');
|
||||
throw new Services_oEmbed_Exception('Non-200 code returned. Got code ' . $code);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
@ -454,7 +454,7 @@ class Stomp
|
||||
*/
|
||||
public function disconnect ()
|
||||
{
|
||||
$header = array();
|
||||
$headers = array();
|
||||
|
||||
if ($this->clientId != null) {
|
||||
$headers["client-id"] = $this->clientId;
|
||||
|
76
index.php
@ -15,6 +15,24 @@
|
||||
*
|
||||
* 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 StatusNet
|
||||
* @package StatusNet
|
||||
* @license GNU Affero General Public License http://www.gnu.org/licenses/
|
||||
* @author Brenda Wallace <shiny@cpan.org>
|
||||
* @author Christopher Vollick <psycotica0@gmail.com>
|
||||
* @author CiaranG <ciaran@ciarang.com>
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Evan Prodromou <evan@controlezvous.ca>
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @author Evan Prodromou <evan@prodromou.name>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Gina Haeussge <osd@foosel.net>
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
||||
* @author Tom Adams <tom@holizz.com>
|
||||
*/
|
||||
|
||||
define('INSTALLDIR', dirname(__FILE__));
|
||||
@ -29,7 +47,8 @@ $action = null;
|
||||
function getPath($req)
|
||||
{
|
||||
if ((common_config('site', 'fancy') || !array_key_exists('PATH_INFO', $_SERVER))
|
||||
&& array_key_exists('p', $req)) {
|
||||
&& array_key_exists('p', $req)
|
||||
) {
|
||||
return $req['p'];
|
||||
} else if (array_key_exists('PATH_INFO', $_SERVER)) {
|
||||
return $_SERVER['PATH_INFO'];
|
||||
@ -45,28 +64,35 @@ function handleError($error)
|
||||
}
|
||||
|
||||
$logmsg = "PEAR error: " . $error->getMessage();
|
||||
if(common_config('site', 'logdebug')) {
|
||||
if (common_config('site', 'logdebug')) {
|
||||
$logmsg .= " : ". $error->getDebugInfo();
|
||||
}
|
||||
common_log(LOG_ERR, $logmsg);
|
||||
if(common_config('site', 'logdebug')) {
|
||||
if (common_config('site', 'logdebug')) {
|
||||
$bt = $error->getBacktrace();
|
||||
foreach ($bt as $line) {
|
||||
common_log(LOG_ERR, $line);
|
||||
}
|
||||
}
|
||||
if ($error instanceof DB_DataObject_Error ||
|
||||
$error instanceof DB_Error) {
|
||||
$msg = sprintf(_('The database for %s isn\'t responding correctly, '.
|
||||
'so the site won\'t work properly. '.
|
||||
'The site admins probably know about the problem, '.
|
||||
'but you can contact them at %s to make sure. '.
|
||||
'Otherwise, wait a few minutes and try again.'),
|
||||
common_config('site', 'name'),
|
||||
common_config('site', 'email'));
|
||||
if ($error instanceof DB_DataObject_Error
|
||||
|| $error instanceof DB_Error
|
||||
) {
|
||||
$msg = sprintf(
|
||||
_(
|
||||
'The database for %s isn\'t responding correctly, '.
|
||||
'so the site won\'t work properly. '.
|
||||
'The site admins probably know about the problem, '.
|
||||
'but you can contact them at %s to make sure. '.
|
||||
'Otherwise, wait a few minutes and try again.'
|
||||
),
|
||||
common_config('site', 'name'),
|
||||
common_config('site', 'email')
|
||||
);
|
||||
} else {
|
||||
$msg = _('An important error occured, probably related to email setup. '.
|
||||
'Check logfiles for more info..');
|
||||
$msg = _(
|
||||
'An important error occured, probably related to email setup. '.
|
||||
'Check logfiles for more info..'
|
||||
);
|
||||
}
|
||||
|
||||
$dac = new DBErrorAction($msg, 500);
|
||||
@ -127,10 +153,11 @@ function main()
|
||||
$_lighty_url = @parse_url($_lighty_url);
|
||||
|
||||
if ($_lighty_url['path'] != '/index.php' && $_lighty_url['path'] != '/') {
|
||||
$_lighty_path = preg_replace('/^'.preg_quote(common_config('site','path')).'\//', '', substr($_lighty_url['path'], 1));
|
||||
$_lighty_path = preg_replace('/^'.preg_quote(common_config('site', 'path')).'\//', '', substr($_lighty_url['path'], 1));
|
||||
$_SERVER['QUERY_STRING'] = 'p='.$_lighty_path;
|
||||
if ($_lighty_url['query'])
|
||||
if ($_lighty_url['query']) {
|
||||
$_SERVER['QUERY_STRING'] .= '&'.$_lighty_url['query'];
|
||||
}
|
||||
parse_str($_lighty_url['query'], $_lighty_query);
|
||||
foreach ($_lighty_query as $key => $val) {
|
||||
$_GET[$key] = $_REQUEST[$key] = $val;
|
||||
@ -141,7 +168,7 @@ function main()
|
||||
$_SERVER['REDIRECT_URL'] = preg_replace("/\?.+$/", "", $_SERVER['REQUEST_URI']);
|
||||
|
||||
// quick check for fancy URL auto-detection support in installer.
|
||||
if (isset($_SERVER['REDIRECT_URL']) && (preg_replace("/^\/$/","",(dirname($_SERVER['REQUEST_URI']))) . '/check-fancy') === $_SERVER['REDIRECT_URL']) {
|
||||
if (isset($_SERVER['REDIRECT_URL']) && (preg_replace("/^\/$/", "", (dirname($_SERVER['REQUEST_URI']))) . '/check-fancy') === $_SERVER['REDIRECT_URL']) {
|
||||
die("Fancy URL support detection succeeded. We suggest you enable this to get fancy (pretty) URLs.");
|
||||
}
|
||||
global $user, $action;
|
||||
@ -149,8 +176,12 @@ function main()
|
||||
Snapshot::check();
|
||||
|
||||
if (!_have_config()) {
|
||||
$msg = sprintf(_("No configuration file found. Try running ".
|
||||
"the installation program first."));
|
||||
$msg = sprintf(
|
||||
_(
|
||||
"No configuration file found. Try running ".
|
||||
"the installation program first."
|
||||
)
|
||||
);
|
||||
$sac = new ServerErrorAction($msg);
|
||||
$sac->showPage();
|
||||
return;
|
||||
@ -196,9 +227,10 @@ function main()
|
||||
// If the site is private, and they're not on one of the "public"
|
||||
// parts of the site, redirect to login
|
||||
|
||||
if (!$user && common_config('site', 'private') &&
|
||||
!isLoginAction($action) &&
|
||||
!preg_match('/rss$/', $action)) {
|
||||
if (!$user && common_config('site', 'private')
|
||||
&& !isLoginAction($action)
|
||||
&& !preg_match('/rss$/', $action)
|
||||
) {
|
||||
common_redirect(common_local_url('login'));
|
||||
return;
|
||||
}
|
||||
|
411
install.php
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
/**
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2009, StatusNet, Inc.
|
||||
*
|
||||
@ -15,8 +15,25 @@
|
||||
*
|
||||
* 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 Installation
|
||||
* @package Installation
|
||||
*
|
||||
* @author Adrian Lang <mail@adrianlang.de>
|
||||
* @author Brenda Wallace <shiny@cpan.org>
|
||||
* @author Brett Taylor <brett@webfroot.co.nz>
|
||||
* @author Brion Vibber <brion@pobox.com>
|
||||
* @author CiaranG <ciaran@ciarang.com>
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Eric Helgeson <helfire@Erics-MBP.local>
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
||||
* @author Tom Adams <tom@holizz.com>
|
||||
* @license GNU Affero General Public License http://www.gnu.org/licenses/
|
||||
*/
|
||||
|
||||
|
||||
define('INSTALLDIR', dirname(__FILE__));
|
||||
|
||||
$external_libraries=array(
|
||||
@ -181,17 +198,34 @@ $external_libraries=array(
|
||||
'check_class'=>'Validate'
|
||||
)
|
||||
);
|
||||
$dbModules = array(
|
||||
'mysql' => array(
|
||||
'name' => 'MySQL',
|
||||
'check_module' => 'mysql', // mysqli?
|
||||
'installer' => 'mysql_db_installer',
|
||||
),
|
||||
'pgsql' => array(
|
||||
'name' => 'PostgreSQL',
|
||||
'check_module' => 'pgsql',
|
||||
'installer' => 'pgsql_db_installer',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* the actual installation.
|
||||
* If call libraries are present, then install
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function main()
|
||||
{
|
||||
if (!checkPrereqs())
|
||||
{
|
||||
if (!checkPrereqs()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( $_GET['checklibs'] ){
|
||||
if ($_GET['checklibs']) {
|
||||
showLibs();
|
||||
}else{
|
||||
} else {
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
handlePost();
|
||||
} else {
|
||||
@ -200,71 +234,97 @@ function main()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if an external libary is present
|
||||
*
|
||||
* @param string $external_library Name of library
|
||||
*
|
||||
* @return boolean indicates if library present
|
||||
*/
|
||||
function haveExternalLibrary($external_library)
|
||||
{
|
||||
if(isset($external_library['include']) && ! include_once($external_library['include'])){
|
||||
if (isset($external_library['include']) && ! include_once $external_library['include'] ) {
|
||||
return false;
|
||||
}
|
||||
if(isset($external_library['check_function']) && ! function_exists($external_library['check_function'])){
|
||||
if (isset($external_library['check_function']) && ! function_exists($external_library['check_function'])) {
|
||||
return false;
|
||||
}
|
||||
if(isset($external_library['check_class']) && ! class_exists($external_library['check_class'])){
|
||||
if (isset($external_library['check_class']) && ! class_exists($external_library['check_class'])) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all is ready for installation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function checkPrereqs()
|
||||
{
|
||||
$pass = true;
|
||||
$pass = true;
|
||||
|
||||
if (file_exists(INSTALLDIR.'/config.php')) {
|
||||
?><p class="error">Config file "config.php" already exists.</p>
|
||||
<?php
|
||||
printf('<p class="error">Config file "config.php" already exists.</p>');
|
||||
$pass = false;
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.2.3', '<')) {
|
||||
?><p class="error">Require PHP version 5.2.3 or greater.</p><?php
|
||||
$pass = false;
|
||||
printf('<p class="error">Require PHP version 5.2.3 or greater.</p>');
|
||||
$pass = false;
|
||||
}
|
||||
|
||||
$reqs = array('gd', 'curl',
|
||||
'xmlwriter', 'mbstring');
|
||||
'xmlwriter', 'mbstring','tidy');
|
||||
|
||||
foreach ($reqs as $req) {
|
||||
if (!checkExtension($req)) {
|
||||
?><p class="error">Cannot load required extension: <code><?php echo $req; ?></code></p><?php
|
||||
$pass = false;
|
||||
printf('<p class="error">Cannot load required extension: <code>%s</code></p>', $req);
|
||||
$pass = false;
|
||||
}
|
||||
}
|
||||
// Make sure we have at least one database module available
|
||||
global $dbModules;
|
||||
$missingExtensions = array();
|
||||
foreach ($dbModules as $type => $info) {
|
||||
if (!checkExtension($info['check_module'])) {
|
||||
$missingExtensions[] = $info['check_module'];
|
||||
}
|
||||
}
|
||||
if (!checkExtension('pgsql') && !checkExtension('mysql')) {
|
||||
?><p class="error">Cannot find mysql or pgsql extension. You need one or the other: <code><?php echo $req; ?></code></p><?php
|
||||
$pass = false;
|
||||
|
||||
if (count($missingExtensions) == count($dbModules)) {
|
||||
$req = implode(', ', $missingExtensions);
|
||||
printf('<p class="error">Cannot find mysql or pgsql extension. You need one or the other: <code>%s</code></p>', $req);
|
||||
$pass = false;
|
||||
}
|
||||
|
||||
if (!is_writable(INSTALLDIR)) {
|
||||
printf('<p class="error">Cannot write config file to: <code>%s</code></p>', INSTALLDIR);
|
||||
printf('<p>On your server, try this command: <code>chmod a+w %s</code>', INSTALLDIR);
|
||||
$pass = false;
|
||||
}
|
||||
|
||||
if (!is_writable(INSTALLDIR)) {
|
||||
?><p class="error">Cannot write config file to: <code><?php echo INSTALLDIR; ?></code></p>
|
||||
<p>On your server, try this command: <code>chmod a+w <?php echo INSTALLDIR; ?></code>
|
||||
<?php
|
||||
$pass = false;
|
||||
}
|
||||
// Check the subdirs used for file uploads
|
||||
$fileSubdirs = array('avatar', 'background', 'file');
|
||||
foreach ($fileSubdirs as $fileSubdir) {
|
||||
$fileFullPath = INSTALLDIR."/$fileSubdir/";
|
||||
if (!is_writable($fileFullPath)) {
|
||||
printf('<p class="error">Cannot write to %s directory: <code>%s</code></p>', $fileSubdir, $fileFullPath);
|
||||
printf('<p>On your server, try this command: <code>chmod a+w %s</code></p>', $fileFullPath);
|
||||
$pass = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the subdirs used for file uploads
|
||||
$fileSubdirs = array('avatar', 'background', 'file');
|
||||
foreach ($fileSubdirs as $fileSubdir) {
|
||||
$fileFullPath = INSTALLDIR."/$fileSubdir/";
|
||||
if (!is_writable($fileFullPath)) {
|
||||
?><p class="error">Cannot write <?php echo $fileSubdir; ?> directory: <code><?php echo $fileFullPath; ?></code></p>
|
||||
<p>On your server, try this command: <code>chmod a+w <?php echo $fileFullPath; ?></code></p>
|
||||
<?php
|
||||
$pass = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $pass;
|
||||
return $pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a php extension is both installed and loaded
|
||||
*
|
||||
* @param string $name of extension to check
|
||||
*
|
||||
* @return boolean whether extension is installed and loaded
|
||||
*/
|
||||
function checkExtension($name)
|
||||
{
|
||||
if (!extension_loaded($name)) {
|
||||
@ -275,15 +335,20 @@ function checkExtension($name)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show list of libraries
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showLibs()
|
||||
{
|
||||
global $external_libraries;
|
||||
$present_libraries=array();
|
||||
$absent_libraries=array();
|
||||
foreach($external_libraries as $external_library){
|
||||
if(haveExternalLibrary($external_library)){
|
||||
foreach ($external_libraries as $external_library) {
|
||||
if (haveExternalLibrary($external_library)) {
|
||||
$present_libraries[]=$external_library;
|
||||
}else{
|
||||
} else {
|
||||
$absent_libraries[]=$external_library;
|
||||
}
|
||||
}
|
||||
@ -298,22 +363,21 @@ function showLibs()
|
||||
<h2>Absent Libraries</h2>
|
||||
<ul id="absent_libraries">
|
||||
E_O_T;
|
||||
foreach($absent_libraries as $library)
|
||||
{
|
||||
foreach ($absent_libraries as $library) {
|
||||
echo '<li>';
|
||||
if($library['url']){
|
||||
if ($library['url']) {
|
||||
echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>';
|
||||
}else{
|
||||
} else {
|
||||
echo htmlentities($library['name']);
|
||||
}
|
||||
echo '<ul>';
|
||||
if($library['deb']){
|
||||
if ($library['deb']) {
|
||||
echo '<li class="deb package">deb: <a href="apt:' . urlencode($library['deb']) . '">' . htmlentities($library['deb']) . '</a></li>';
|
||||
}
|
||||
if($library['rpm']){
|
||||
if ($library['rpm']) {
|
||||
echo '<li class="rpm package">rpm: ' . htmlentities($library['rpm']) . '</li>';
|
||||
}
|
||||
if($library['pear']){
|
||||
if ($library['pear']) {
|
||||
echo '<li class="pear package">pear: ' . htmlentities($library['pear']) . '</li>';
|
||||
}
|
||||
echo '</ul>';
|
||||
@ -323,12 +387,11 @@ E_O_T;
|
||||
<h2>Installed Libraries</h2>
|
||||
<ul id="present_libraries">
|
||||
E_O_T;
|
||||
foreach($present_libraries as $library)
|
||||
{
|
||||
foreach ($present_libraries as $library) {
|
||||
echo '<li>';
|
||||
if($library['url']){
|
||||
if ($library['url']) {
|
||||
echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>';
|
||||
}else{
|
||||
} else {
|
||||
echo htmlentities($library['name']);
|
||||
}
|
||||
echo '</li>';
|
||||
@ -340,6 +403,15 @@ E_O_T;
|
||||
|
||||
function showForm()
|
||||
{
|
||||
global $dbModules;
|
||||
$dbRadios = '';
|
||||
$checked = 'checked="checked" '; // Check the first one which exists
|
||||
foreach ($dbModules as $type => $info) {
|
||||
if (checkExtension($info['check_module'])) {
|
||||
$dbRadios .= "<input type=\"radio\" name=\"dbtype\" id=\"dbtype-$type\" value=\"$type\" $checked/> $info[name]<br />\n";
|
||||
$checked = '';
|
||||
}
|
||||
}
|
||||
echo<<<E_O_T
|
||||
</ul>
|
||||
</dd>
|
||||
@ -376,8 +448,7 @@ function showForm()
|
||||
<li>
|
||||
|
||||
<label for="dbtype">Type</label>
|
||||
<input type="radio" name="dbtype" id="fancy-mysql" value="mysql" checked='checked' /> MySQL<br />
|
||||
<input type="radio" name="dbtype" id="dbtype-pgsql" value="pgsql" /> PostgreSQL<br />
|
||||
$dbRadios
|
||||
<p class="form_guide">Database type</p>
|
||||
</li>
|
||||
|
||||
@ -406,17 +477,12 @@ E_O_T;
|
||||
|
||||
function updateStatus($status, $error=false)
|
||||
{
|
||||
?>
|
||||
<li <?php echo ($error) ? 'class="error"': ''; ?>><?php echo $status;?></li>
|
||||
|
||||
<?php
|
||||
echo '<li ' . ($error) ? 'class="error"': '';
|
||||
echo ">$status</li>";
|
||||
}
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
?>
|
||||
|
||||
<?php
|
||||
$host = $_POST['host'];
|
||||
$dbtype = $_POST['dbtype'];
|
||||
$database = $_POST['database'];
|
||||
@ -427,55 +493,41 @@ function handlePost()
|
||||
$server = $_SERVER['HTTP_HOST'];
|
||||
$path = substr(dirname($_SERVER['PHP_SELF']), 1);
|
||||
|
||||
?>
|
||||
echo <<<STR
|
||||
<dl class="system_notice">
|
||||
<dt>Page notice</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<?php
|
||||
$fail = false;
|
||||
STR;
|
||||
$fail = false;
|
||||
|
||||
if (empty($host)) {
|
||||
updateStatus("No hostname specified.", true);
|
||||
$fail = true;
|
||||
$fail = true;
|
||||
}
|
||||
|
||||
if (empty($database)) {
|
||||
updateStatus("No database specified.", true);
|
||||
$fail = true;
|
||||
$fail = true;
|
||||
}
|
||||
|
||||
if (empty($username)) {
|
||||
updateStatus("No username specified.", true);
|
||||
$fail = true;
|
||||
$fail = true;
|
||||
}
|
||||
|
||||
// if (empty($password)) {
|
||||
// updateStatus("No password specified.", true);
|
||||
// $fail = true;
|
||||
// }
|
||||
|
||||
if (empty($sitename)) {
|
||||
updateStatus("No sitename specified.", true);
|
||||
$fail = true;
|
||||
$fail = true;
|
||||
}
|
||||
|
||||
if($fail){
|
||||
showForm();
|
||||
if ($fail) {
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: use PEAR::DB or PDO instead of our own switch
|
||||
|
||||
switch($dbtype) {
|
||||
case 'mysql':
|
||||
$db = mysql_db_installer($host, $database, $username, $password);
|
||||
break;
|
||||
case 'pgsql':
|
||||
$db = pgsql_db_installer($host, $database, $username, $password);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
global $dbModules;
|
||||
$db = call_user_func($dbModules[$dbtype]['installer'], $host, $database, $username, $password);
|
||||
|
||||
if (!$db) {
|
||||
// database connection failed, do not move on to create config file.
|
||||
@ -498,112 +550,110 @@ function handlePost()
|
||||
|
||||
updateStatus("StatusNet has been installed at $link");
|
||||
updateStatus("You can visit your <a href='$link'>new StatusNet site</a>.");
|
||||
?>
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
function pgsql_db_installer($host, $database, $username, $password) {
|
||||
$connstring = "dbname=$database host=$host user=$username";
|
||||
function Pgsql_Db_installer($host, $database, $username, $password)
|
||||
{
|
||||
$connstring = "dbname=$database host=$host user=$username";
|
||||
|
||||
//No password would mean trust authentication used.
|
||||
if (!empty($password)) {
|
||||
$connstring .= " password=$password";
|
||||
}
|
||||
updateStatus("Starting installation...");
|
||||
updateStatus("Checking database...");
|
||||
$conn = pg_connect($connstring);
|
||||
//No password would mean trust authentication used.
|
||||
if (!empty($password)) {
|
||||
$connstring .= " password=$password";
|
||||
}
|
||||
updateStatus("Starting installation...");
|
||||
updateStatus("Checking database...");
|
||||
$conn = pg_connect($connstring);
|
||||
|
||||
if ($conn ===false) {
|
||||
updateStatus("Failed to connect to database: $connstring");
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
if ($conn ===false) {
|
||||
updateStatus("Failed to connect to database: $connstring");
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
|
||||
//ensure database encoding is UTF8
|
||||
$record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
|
||||
if ($record->server_encoding != 'UTF8') {
|
||||
updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
//ensure database encoding is UTF8
|
||||
$record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
|
||||
if ($record->server_encoding != 'UTF8') {
|
||||
updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
|
||||
updateStatus("Running database script...");
|
||||
//wrap in transaction;
|
||||
pg_query($conn, 'BEGIN');
|
||||
$res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
|
||||
updateStatus("Running database script...");
|
||||
//wrap in transaction;
|
||||
pg_query($conn, 'BEGIN');
|
||||
$res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
|
||||
|
||||
if ($res === false) {
|
||||
updateStatus("Can't run database script.", true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
foreach (array('sms_carrier' => 'SMS carrier',
|
||||
if ($res === false) {
|
||||
updateStatus("Can't run database script.", true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
foreach (array('sms_carrier' => 'SMS carrier',
|
||||
'notice_source' => 'notice source',
|
||||
'foreign_services' => 'foreign service')
|
||||
as $scr => $name) {
|
||||
updateStatus(sprintf("Adding %s data to database...", $name));
|
||||
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
|
||||
if ($res === false) {
|
||||
updateStatus(sprintf("Can't run %d script.", $name), true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pg_query($conn, 'COMMIT');
|
||||
updateStatus(sprintf("Adding %s data to database...", $name));
|
||||
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
|
||||
if ($res === false) {
|
||||
updateStatus(sprintf("Can't run %d script.", $name), true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pg_query($conn, 'COMMIT');
|
||||
|
||||
if (empty($password)) {
|
||||
$sqlUrl = "pgsql://$username@$host/$database";
|
||||
}
|
||||
else {
|
||||
$sqlUrl = "pgsql://$username:$password@$host/$database";
|
||||
}
|
||||
if (empty($password)) {
|
||||
$sqlUrl = "pgsql://$username@$host/$database";
|
||||
} else {
|
||||
$sqlUrl = "pgsql://$username:$password@$host/$database";
|
||||
}
|
||||
|
||||
$db = array('type' => 'pgsql', 'database' => $sqlUrl);
|
||||
$db = array('type' => 'pgsql', 'database' => $sqlUrl);
|
||||
|
||||
return $db;
|
||||
return $db;
|
||||
}
|
||||
|
||||
function mysql_db_installer($host, $database, $username, $password) {
|
||||
updateStatus("Starting installation...");
|
||||
updateStatus("Checking database...");
|
||||
function Mysql_Db_installer($host, $database, $username, $password)
|
||||
{
|
||||
updateStatus("Starting installation...");
|
||||
updateStatus("Checking database...");
|
||||
|
||||
$conn = mysql_connect($host, $username, $password);
|
||||
if (!$conn) {
|
||||
updateStatus("Can't connect to server '$host' as '$username'.", true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
updateStatus("Changing to database...");
|
||||
$res = mysql_select_db($database, $conn);
|
||||
if (!$res) {
|
||||
updateStatus("Can't change to database.", true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
updateStatus("Running database script...");
|
||||
$res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
|
||||
if ($res === false) {
|
||||
updateStatus("Can't run database script.", true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
foreach (array('sms_carrier' => 'SMS carrier',
|
||||
$conn = mysql_connect($host, $username, $password);
|
||||
if (!$conn) {
|
||||
updateStatus("Can't connect to server '$host' as '$username'.", true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
updateStatus("Changing to database...");
|
||||
$res = mysql_select_db($database, $conn);
|
||||
if (!$res) {
|
||||
updateStatus("Can't change to database.", true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
updateStatus("Running database script...");
|
||||
$res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
|
||||
if ($res === false) {
|
||||
updateStatus("Can't run database script.", true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
foreach (array('sms_carrier' => 'SMS carrier',
|
||||
'notice_source' => 'notice source',
|
||||
'foreign_services' => 'foreign service')
|
||||
as $scr => $name) {
|
||||
updateStatus(sprintf("Adding %s data to database...", $name));
|
||||
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
|
||||
if ($res === false) {
|
||||
updateStatus(sprintf("Can't run %d script.", $name), true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
updateStatus(sprintf("Adding %s data to database...", $name));
|
||||
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
|
||||
if ($res === false) {
|
||||
updateStatus(sprintf("Can't run %d script.", $name), true);
|
||||
showForm();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$sqlUrl = "mysqli://$username:$password@$host/$database";
|
||||
$db = array('type' => 'mysql', 'database' => $sqlUrl);
|
||||
return $db;
|
||||
$sqlUrl = "mysqli://$username:$password@$host/$database";
|
||||
$db = array('type' => 'mysql', 'database' => $sqlUrl);
|
||||
return $db;
|
||||
}
|
||||
|
||||
function writeConf($sitename, $server, $path, $fancy, $db)
|
||||
@ -624,7 +674,7 @@ function writeConf($sitename, $server, $path, $fancy, $db)
|
||||
|
||||
// database
|
||||
"\$config['db']['database'] = '{$db['database']}';\n\n".
|
||||
($type == 'pgsql' ? "\$config['db']['quote_identifiers'] = true;\n\n":'').
|
||||
($db['type'] == 'pgsql' ? "\$config['db']['quote_identifiers'] = true;\n\n":'').
|
||||
"\$config['db']['type'] = '{$db['type']}';\n\n".
|
||||
|
||||
"?>";
|
||||
@ -634,7 +684,16 @@ function writeConf($sitename, $server, $path, $fancy, $db)
|
||||
return $res;
|
||||
}
|
||||
|
||||
function runDbScript($filename, $conn, $type = 'mysql')
|
||||
/**
|
||||
* Install schema into the database
|
||||
*
|
||||
* @param string $filename location of database schema file
|
||||
* @param dbconn $conn connection to database
|
||||
* @param string $type type of database, currently mysql or pgsql
|
||||
*
|
||||
* @return boolean - indicating success or failure
|
||||
*/
|
||||
function runDbScript($filename, $conn, $type = 'mysqli')
|
||||
{
|
||||
$sql = trim(file_get_contents($filename));
|
||||
$stmts = explode(';', $sql);
|
||||
@ -645,7 +704,7 @@ function runDbScript($filename, $conn, $type = 'mysql')
|
||||
}
|
||||
// FIXME: use PEAR::DB or PDO instead of our own switch
|
||||
switch ($type) {
|
||||
case 'mysql':
|
||||
case 'mysqli':
|
||||
$res = mysql_query($stmt, $conn);
|
||||
if ($res === false) {
|
||||
$error = mysql_error();
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
|
||||
|
||||
class ShortUrlApi
|
||||
abstract class ShortUrlApi
|
||||
{
|
||||
protected $service_url;
|
||||
protected $long_limit = 27;
|
||||
@ -35,11 +35,9 @@ class ShortUrlApi
|
||||
return $url;
|
||||
}
|
||||
|
||||
protected function shorten_imp($url) {
|
||||
return "To Override";
|
||||
}
|
||||
protected abstract function shorten_imp($url);
|
||||
|
||||
private function is_long($url) {
|
||||
protected function is_long($url) {
|
||||
return strlen($url) >= common_config('site', 'shorturllength');
|
||||
}
|
||||
|
||||
@ -71,61 +69,3 @@ class ShortUrlApi
|
||||
}
|
||||
}
|
||||
|
||||
class LilUrl extends ShortUrlApi
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct('http://ur1.ca/');
|
||||
}
|
||||
|
||||
protected function shorten_imp($url) {
|
||||
$data['longurl'] = $url;
|
||||
$response = $this->http_post($data);
|
||||
if (!$response) return $url;
|
||||
$y = @simplexml_load_string($response);
|
||||
if (!isset($y->body)) return $url;
|
||||
$x = $y->body->p[0]->a->attributes();
|
||||
if (isset($x['href'])) return $x['href'];
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PtitUrl extends ShortUrlApi
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct('http://ptiturl.com/?creer=oui&action=Reduire&url=');
|
||||
}
|
||||
|
||||
protected function shorten_imp($url) {
|
||||
$response = $this->http_get($url);
|
||||
if (!$response) return $url;
|
||||
$response = $this->tidy($response);
|
||||
$y = @simplexml_load_string($response);
|
||||
if (!isset($y->body)) return $url;
|
||||
$xml = $y->body->center->table->tr->td->pre->a->attributes();
|
||||
if (isset($xml['href'])) return $xml['href'];
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
class TightUrl extends ShortUrlApi
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct('http://2tu.us/?save=y&url=');
|
||||
}
|
||||
|
||||
protected function shorten_imp($url) {
|
||||
$response = $this->http_get($url);
|
||||
if (!$response) return $url;
|
||||
$response = $this->tidy($response);
|
||||
$y = @simplexml_load_string($response);
|
||||
if (!isset($y->body)) return $url;
|
||||
$xml = $y->body->p[0]->code[0]->a->attributes();
|
||||
if (isset($xml['href'])) return $xml['href'];
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
|
105
lib/command.php
@ -114,7 +114,6 @@ class StatsCommand extends Command
|
||||
|
||||
class FavCommand extends Command
|
||||
{
|
||||
|
||||
var $other = null;
|
||||
|
||||
function __construct($user, $other)
|
||||
@ -158,6 +157,108 @@ class FavCommand extends Command
|
||||
|
||||
$channel->output($this->user, _('Notice marked as fave.'));
|
||||
}
|
||||
|
||||
}
|
||||
class JoinCommand extends Command
|
||||
{
|
||||
var $other = null;
|
||||
|
||||
function __construct($user, $other)
|
||||
{
|
||||
parent::__construct($user);
|
||||
$this->other = $other;
|
||||
}
|
||||
|
||||
function execute($channel)
|
||||
{
|
||||
|
||||
$nickname = common_canonical_nickname($this->other);
|
||||
$group = User_group::staticGet('nickname', $nickname);
|
||||
$cur = $this->user;
|
||||
|
||||
if (!$group) {
|
||||
$channel->error($cur, _('No such group.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($cur->isMember($group)) {
|
||||
$channel->error($cur, _('You are already a member of that group'));
|
||||
return;
|
||||
}
|
||||
if (Group_block::isBlocked($group, $cur->getProfile())) {
|
||||
$channel->error($cur, _('You have been blocked from that group by the admin.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$member = new Group_member();
|
||||
|
||||
$member->group_id = $group->id;
|
||||
$member->profile_id = $cur->id;
|
||||
$member->created = common_sql_now();
|
||||
|
||||
$result = $member->insert();
|
||||
if (!$result) {
|
||||
common_log_db_error($member, 'INSERT', __FILE__);
|
||||
$channel->error($cur, sprintf(_('Could not join user %s to group %s'),
|
||||
$cur->nickname, $group->nickname));
|
||||
return;
|
||||
}
|
||||
|
||||
$channel->output($cur, sprintf(_('%s joined group %s'),
|
||||
$cur->nickname,
|
||||
$group->nickname));
|
||||
}
|
||||
|
||||
}
|
||||
class DropCommand extends Command
|
||||
{
|
||||
var $other = null;
|
||||
|
||||
function __construct($user, $other)
|
||||
{
|
||||
parent::__construct($user);
|
||||
$this->other = $other;
|
||||
}
|
||||
|
||||
function execute($channel)
|
||||
{
|
||||
|
||||
$nickname = common_canonical_nickname($this->other);
|
||||
$group = User_group::staticGet('nickname', $nickname);
|
||||
$cur = $this->user;
|
||||
|
||||
if (!$group) {
|
||||
$channel->error($cur, _('No such group.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$cur->isMember($group)) {
|
||||
$channel->error($cur, _('You are not a member of that group.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$member = new Group_member();
|
||||
|
||||
$member->group_id = $group->id;
|
||||
$member->profile_id = $cur->id;
|
||||
|
||||
if (!$member->find(true)) {
|
||||
$channel->error($cur,_('Could not find membership record.'));
|
||||
return;
|
||||
}
|
||||
$result = $member->delete();
|
||||
if (!$result) {
|
||||
common_log_db_error($member, 'INSERT', __FILE__);
|
||||
$channel->error($cur, sprintf(_('Could not remove user %s to group %s'),
|
||||
$cur->nickname, $group->nickname));
|
||||
return;
|
||||
}
|
||||
|
||||
$channel->output($cur, sprintf(_('%s left group %s'),
|
||||
$cur->nickname,
|
||||
$group->nickname));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WhoisCommand extends Command
|
||||
@ -396,6 +497,8 @@ class HelpCommand extends Command
|
||||
"get <nickname> - get last notice from user\n".
|
||||
"whois <nickname> - get profile info on user\n".
|
||||
"fav <nickname> - add user's last notice as a 'fave'\n".
|
||||
"join <group> - join group\n".
|
||||
"drop <group> - leave group\n".
|
||||
"stats - get your stats\n".
|
||||
"stop - same as 'off'\n".
|
||||
"quit - same as 'off'\n".
|
||||
|
@ -70,6 +70,26 @@ class CommandInterpreter
|
||||
} else {
|
||||
return new OffCommand($user);
|
||||
}
|
||||
case 'join':
|
||||
if (!$arg) {
|
||||
return null;
|
||||
}
|
||||
list($other, $extra) = explode(' ', $arg, 2);
|
||||
if ($extra) {
|
||||
return null;
|
||||
} else {
|
||||
return new JoinCommand($user, $other);
|
||||
}
|
||||
case 'drop':
|
||||
if (!$arg) {
|
||||
return null;
|
||||
}
|
||||
list($other, $extra) = explode(' ', $arg, 2);
|
||||
if ($extra) {
|
||||
return null;
|
||||
} else {
|
||||
return new DropCommand($user, $other);
|
||||
}
|
||||
case 'follow':
|
||||
case 'sub':
|
||||
if (!$arg) {
|
||||
|
@ -327,6 +327,8 @@ class DesignSettingsAction extends AccountSettingsAction
|
||||
$this->script('js/farbtastic/farbtastic.js');
|
||||
$this->script('js/farbtastic/farbtastic.go.js');
|
||||
$this->script('js/userdesign.go.js');
|
||||
|
||||
$this->autofocus('design_background-image_file');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,13 +132,16 @@ class GalleryAction extends OwnerDesignAction
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li', array('id'=>'filter_tags_item'));
|
||||
$this->elementStart('form', array('name' => 'bytag',
|
||||
'id' => 'bytag',
|
||||
'id' => 'form_filter_bytag',
|
||||
'action' => common_path('?action=' . $this->trimmed('action')),
|
||||
'method' => 'post'));
|
||||
$this->elementStart('fieldset');
|
||||
$this->element('legend', null, _('Select tag to filter'));
|
||||
$this->dropdown('tag', _('Tag'), $content,
|
||||
_('Choose a tag to narrow list'), false, $tag);
|
||||
$this->hidden('nickname', $this->user->nickname);
|
||||
$this->submit('submit', _('Go'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
|
@ -412,4 +412,29 @@ class HTMLOutputter extends XMLOutputter
|
||||
$this->element('p', 'form_guide', $instructions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal script to autofocus the given element on page onload.
|
||||
*
|
||||
* @param string $id element ID, must refer to an existing element
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
function autofocus($id)
|
||||
{
|
||||
$this->elementStart('script', array('type' => 'text/javascript'));
|
||||
$this->raw('
|
||||
<!--
|
||||
$(document).ready(function() {
|
||||
var el = $("#' . $id . '");
|
||||
if (el.length) {
|
||||
el.focus();
|
||||
}
|
||||
});
|
||||
-->
|
||||
');
|
||||
$this->elementEnd('script');
|
||||
}
|
||||
}
|
||||
|
@ -213,26 +213,20 @@ class MailboxAction extends CurrentUserDesignAction
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'entry-content');
|
||||
$this->elementStart('dl', 'timestamp');
|
||||
$this->element('dt', null, _('Published'));
|
||||
$this->elementStart('dd', null);
|
||||
$dt = common_date_iso8601($message->created);
|
||||
$this->elementStart('a', array('rel' => 'bookmark',
|
||||
'class' => 'timestamp',
|
||||
'href' => $messageurl));
|
||||
$dt = common_date_iso8601($message->created);
|
||||
$this->element('abbr', array('class' => 'published',
|
||||
'title' => $dt),
|
||||
common_date_string($message->created));
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
|
||||
if ($message->source) {
|
||||
$this->elementStart('dl', 'device');
|
||||
$this->elementStart('dt');
|
||||
$this->text(_('From'));
|
||||
$this->elementEnd('dt');
|
||||
$this->showSource($message->source);
|
||||
$this->elementEnd('dl');
|
||||
$this->elementStart('span', 'source');
|
||||
$this->text(_('from'));
|
||||
$this->element('span', 'device', $this->showSource($message->source));
|
||||
$this->elementEnd('span');
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
|
||||
@ -277,18 +271,18 @@ class MailboxAction extends CurrentUserDesignAction
|
||||
case 'mail':
|
||||
case 'omb':
|
||||
case 'api':
|
||||
$this->element('dd', null, $source_name);
|
||||
$this->element('span', 'device', $source_name);
|
||||
break;
|
||||
default:
|
||||
$ns = Notice_source::staticGet($source);
|
||||
if ($ns) {
|
||||
$this->elementStart('dd', null);
|
||||
$this->elementStart('span', 'device');
|
||||
$this->element('a', array('href' => $ns->url,
|
||||
'rel' => 'external'),
|
||||
$ns->name);
|
||||
$this->elementEnd('dd');
|
||||
'rel' => 'external'),
|
||||
$ns->name);
|
||||
$this->elementEnd('span');
|
||||
} else {
|
||||
$this->element('dd', null, $source_name);
|
||||
$this->out->element('span', 'device', $source_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2008 StatusNet, Inc.
|
||||
* @copyright 2009 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/
|
||||
*/
|
||||
|
@ -76,4 +76,18 @@ class Plugin
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* the name of the shortener
|
||||
* shortenerInfo associative array with additional information. One possible element is 'freeService' which can be true or false
|
||||
* shortener array, first element is the name of the class, second element is an array to be passed as constructor parameters to the class
|
||||
*/
|
||||
function registerUrlShortener($name, $shortenerInfo, $shortener)
|
||||
{
|
||||
global $_shorteners;
|
||||
if(!is_array($_shorteners)){
|
||||
$_shorteners=array();
|
||||
}
|
||||
$_shorteners[$name]=array('info'=>$shortenerInfo, 'callInfo'=>$shortener);
|
||||
}
|
||||
}
|
||||
|
180
lib/twitter.php
@ -154,80 +154,134 @@ function broadcast_twitter($notice)
|
||||
TWITTER_SERVICE);
|
||||
|
||||
if (is_twitter_bound($notice, $flink)) {
|
||||
|
||||
$user = $flink->getUser();
|
||||
|
||||
// XXX: Hack to get around PHP cURL's use of @ being a a meta character
|
||||
$statustxt = preg_replace('/^@/', ' @', $notice->content);
|
||||
|
||||
$token = TwitterOAuthClient::unpackToken($flink->credentials);
|
||||
|
||||
$client = new TwitterOAuthClient($token->key, $token->secret);
|
||||
|
||||
$status = null;
|
||||
|
||||
try {
|
||||
$status = $client->statusesUpdate($statustxt);
|
||||
} catch (OAuthClientCurlException $e) {
|
||||
|
||||
if ($e->getMessage() == 'The requested URL returned error: 401') {
|
||||
|
||||
$errmsg = sprintf('User %1$s (user id: %2$s) has an invalid ' .
|
||||
'Twitter OAuth access token.',
|
||||
$user->nickname, $user->id);
|
||||
common_log(LOG_WARNING, $errmsg);
|
||||
|
||||
// Bad auth token! We need to delete the foreign_link
|
||||
// to Twitter and inform the user.
|
||||
|
||||
remove_twitter_link($flink);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
// Some other error happened, so we should probably
|
||||
// try to send again later.
|
||||
|
||||
$errmsg = sprintf('cURL error trying to send notice to Twitter ' .
|
||||
'for user %1$s (user id: %2$s) - ' .
|
||||
'code: %3$s message: $4$s.',
|
||||
$user->nickname, $user->id,
|
||||
$e->getCode(), $e->getMessage());
|
||||
common_log(LOG_WARNING, $errmsg);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (TwitterOAuthClient::isPackedToken($flink->credentials)) {
|
||||
return broadcast_oauth($notice, $flink);
|
||||
} else {
|
||||
return broadcast_basicauth($notice, $flink);
|
||||
}
|
||||
|
||||
if (empty($status)) {
|
||||
|
||||
// This could represent a failure posting,
|
||||
// or the Twitter API might just be behaving flakey.
|
||||
|
||||
$errmsg = sprint('No data returned by Twitter API when ' .
|
||||
'trying to send update for %1$s (user id %2$s).',
|
||||
$user->nickname, $user->id);
|
||||
common_log(LOG_WARNING, $errmsg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Notice crossed the great divide
|
||||
|
||||
$msg = sprintf('Twitter bridge posted notice %s to Twitter.',
|
||||
$notice->id);
|
||||
common_log(LOG_INFO, $msg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function broadcast_oauth($notice, $flink) {
|
||||
$user = $flink->getUser();
|
||||
$statustxt = format_status($notice);
|
||||
// Convert !groups to #hashes
|
||||
$statustxt = preg_replace('/(^|\s)!([A-Za-z0-9]{1,64})/', "\\1#\\2", $statustxt);
|
||||
$token = TwitterOAuthClient::unpackToken($flink->credentials);
|
||||
$client = new TwitterOAuthClient($token->key, $token->secret);
|
||||
$status = null;
|
||||
|
||||
try {
|
||||
$status = $client->statusesUpdate($statustxt);
|
||||
} catch (OAuthClientCurlException $e) {
|
||||
return process_error($e, $flink);
|
||||
}
|
||||
|
||||
if (empty($status)) {
|
||||
|
||||
// This could represent a failure posting,
|
||||
// or the Twitter API might just be behaving flakey.
|
||||
|
||||
$errmsg = sprintf('Twitter bridge - No data returned by Twitter API when ' .
|
||||
'trying to send update for %1$s (user id %2$s).',
|
||||
$user->nickname, $user->id);
|
||||
common_log(LOG_WARNING, $errmsg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Notice crossed the great divide
|
||||
|
||||
$msg = sprintf('Twitter bridge - posted notice %s to Twitter using OAuth.',
|
||||
$notice->id);
|
||||
common_log(LOG_INFO, $msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function broadcast_basicauth($notice, $flink)
|
||||
{
|
||||
$user = $flink->getUser();
|
||||
|
||||
$statustxt = format_status($notice);
|
||||
|
||||
$client = new TwitterBasicAuthClient($flink);
|
||||
$status = null;
|
||||
|
||||
try {
|
||||
$status = $client->statusesUpdate($statustxt);
|
||||
} catch (BasicAuthCurlException $e) {
|
||||
return process_error($e, $flink);
|
||||
}
|
||||
|
||||
if (empty($status)) {
|
||||
|
||||
$errmsg = sprintf('Twitter bridge - No data returned by Twitter API when ' .
|
||||
'trying to send update for %1$s (user id %2$s).',
|
||||
$user->nickname, $user->id);
|
||||
common_log(LOG_WARNING, $errmsg);
|
||||
|
||||
$errmsg = sprintf('No data returned by Twitter API when ' .
|
||||
'trying to send update for %1$s (user id %2$s).',
|
||||
$user->nickname, $user->id);
|
||||
common_log(LOG_WARNING, $errmsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
$msg = sprintf('Twitter bridge - posted notice %s to Twitter using basic auth.',
|
||||
$notice->id);
|
||||
common_log(LOG_INFO, $msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function process_error($e, $flink)
|
||||
{
|
||||
$user = $flink->getUser();
|
||||
$errmsg = $e->getMessage();
|
||||
$delivered = false;
|
||||
|
||||
switch($errmsg) {
|
||||
case 'The requested URL returned error: 401':
|
||||
$logmsg = sprintf('Twiter bridge - User %1$s (user id: %2$s) has an invalid ' .
|
||||
'Twitter screen_name/password combo or an invalid acesss token.',
|
||||
$user->nickname, $user->id);
|
||||
$delivered = true;
|
||||
remove_twitter_link($flink);
|
||||
break;
|
||||
case 'The requested URL returned error: 403':
|
||||
$logmsg = sprintf('Twitter bridge - User %1$s (user id: %2$s) has exceeded ' .
|
||||
'his/her Twitter request limit.',
|
||||
$user->nickname, $user->id);
|
||||
break;
|
||||
default:
|
||||
$logmsg = sprintf('Twitter bridge - cURL error trying to send notice to Twitter ' .
|
||||
'for user %1$s (user id: %2$s) - ' .
|
||||
'code: %3$s message: %4$s.',
|
||||
$user->nickname, $user->id,
|
||||
$e->getCode(), $e->getMessage());
|
||||
break;
|
||||
}
|
||||
|
||||
common_log(LOG_WARNING, $logmsg);
|
||||
|
||||
return $delivered;
|
||||
}
|
||||
|
||||
function format_status($notice)
|
||||
{
|
||||
// XXX: Hack to get around PHP cURL's use of @ being a a meta character
|
||||
return preg_replace('/^@/', ' @', $notice->content);
|
||||
}
|
||||
|
||||
function remove_twitter_link($flink)
|
||||
{
|
||||
$user = $flink->getUser();
|
||||
|
||||
common_log(LOG_INFO, 'Removing Twitter bridge Foreign link for ' .
|
||||
"user $user->nickname (user id: $user->id).");
|
||||
"user $user->nickname (user id: $user->id).");
|
||||
|
||||
$result = $flink->delete();
|
||||
|
||||
|
@ -595,7 +595,6 @@ class TwitterapiAction extends Action
|
||||
|
||||
$this->init_document('rss');
|
||||
|
||||
$this->elementStart('channel');
|
||||
$this->element('title', null, $title);
|
||||
$this->element('link', null, $link);
|
||||
if (!is_null($suplink)) {
|
||||
@ -621,7 +620,6 @@ class TwitterapiAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$this->elementEnd('channel');
|
||||
$this->end_twitter_rss();
|
||||
}
|
||||
|
||||
@ -668,7 +666,6 @@ class TwitterapiAction extends Action
|
||||
|
||||
$this->init_document('rss');
|
||||
|
||||
$this->elementStart('channel');
|
||||
$this->element('title', null, $title);
|
||||
$this->element('link', null, $link);
|
||||
$this->element('description', null, $subtitle);
|
||||
@ -687,7 +684,6 @@ class TwitterapiAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$this->elementEnd('channel');
|
||||
$this->end_twitter_rss();
|
||||
}
|
||||
|
||||
@ -792,6 +788,52 @@ class TwitterapiAction extends Action
|
||||
$this->end_document('xml');
|
||||
}
|
||||
|
||||
function show_twitter_xml_users($user)
|
||||
{
|
||||
|
||||
$this->init_document('xml');
|
||||
$this->elementStart('users', array('type' => 'array'));
|
||||
|
||||
if (is_array($user)) {
|
||||
foreach ($group as $g) {
|
||||
$twitter_user = $this->twitter_user_array($g);
|
||||
$this->show_twitter_xml_user($twitter_user,'user');
|
||||
}
|
||||
} else {
|
||||
while ($user->fetch()) {
|
||||
$twitter_user = $this->twitter_user_array($user);
|
||||
$this->show_twitter_xml_user($twitter_user);
|
||||
}
|
||||
}
|
||||
|
||||
$this->elementEnd('users');
|
||||
$this->end_document('xml');
|
||||
}
|
||||
|
||||
function show_json_users($user)
|
||||
{
|
||||
|
||||
$this->init_document('json');
|
||||
|
||||
$users = array();
|
||||
|
||||
if (is_array($user)) {
|
||||
foreach ($user as $u) {
|
||||
$twitter_user = $this->twitter_user_array($u);
|
||||
array_push($users, $twitter_user);
|
||||
}
|
||||
} else {
|
||||
while ($user->fetch()) {
|
||||
$twitter_user = $this->twitter_user_array($user);
|
||||
array_push($users, $twitter_user);
|
||||
}
|
||||
}
|
||||
|
||||
$this->show_json_objects($users);
|
||||
|
||||
$this->end_document('json');
|
||||
}
|
||||
|
||||
function show_single_json_group($group)
|
||||
{
|
||||
$this->init_document('json');
|
||||
@ -944,11 +986,14 @@ class TwitterapiAction extends Action
|
||||
function init_twitter_rss()
|
||||
{
|
||||
$this->startXML();
|
||||
$this->elementStart('rss', array('version' => '2.0'));
|
||||
$this->elementStart('rss', array('version' => '2.0', 'xmlns:atom'=>'http://www.w3.org/2005/Atom'));
|
||||
$this->elementStart('channel');
|
||||
Event::handle('StartApiRss', array($this));
|
||||
}
|
||||
|
||||
function end_twitter_rss()
|
||||
{
|
||||
$this->elementEnd('channel');
|
||||
$this->elementEnd('rss');
|
||||
$this->endXML();
|
||||
}
|
||||
@ -960,6 +1005,7 @@ class TwitterapiAction extends Action
|
||||
$this->elementStart('feed', array('xmlns' => 'http://www.w3.org/2005/Atom',
|
||||
'xml:lang' => 'en-US',
|
||||
'xmlns:thr' => 'http://purl.org/syndication/thread/1.0'));
|
||||
Event::handle('StartApiAtom', array($this));
|
||||
}
|
||||
|
||||
function end_twitter_atom()
|
||||
|
236
lib/twitterbasicauthclient.php
Normal file
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Class for doing OAuth calls against Twitter
|
||||
*
|
||||
* 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 Integration
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 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') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception wrapper for cURL errors
|
||||
*
|
||||
* @category Integration
|
||||
* @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 BasicAuthCurlException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for talking to the Twitter API with HTTP Basic Auth.
|
||||
*
|
||||
* @category Integration
|
||||
* @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 TwitterBasicAuthClient
|
||||
{
|
||||
var $screen_name = null;
|
||||
var $password = null;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
* @param Foreign_link $flink a Foreign_link storing the
|
||||
* Twitter user's password, etc.
|
||||
*/
|
||||
function __construct($flink)
|
||||
{
|
||||
$fuser = $flink->getForeignUser();
|
||||
$this->screen_name = $fuser->nickname;
|
||||
$this->password = $flink->credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Twitter's /statuses/update API method
|
||||
*
|
||||
* @param string $status text of the status
|
||||
* @param int $in_reply_to_status_id optional id of the status it's
|
||||
* a reply to
|
||||
*
|
||||
* @return mixed the status
|
||||
*/
|
||||
function statusesUpdate($status, $in_reply_to_status_id = null)
|
||||
{
|
||||
$url = 'https://twitter.com/statuses/update.json';
|
||||
$params = array('status' => $status,
|
||||
'source' => common_config('integration', 'source'),
|
||||
'in_reply_to_status_id' => $in_reply_to_status_id);
|
||||
$response = $this->httpRequest($url, $params);
|
||||
$status = json_decode($response);
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Twitter's /statuses/friends_timeline API method
|
||||
*
|
||||
* @param int $since_id show statuses after this id
|
||||
* @param int $max_id show statuses before this id
|
||||
* @param int $cnt number of statuses to show
|
||||
* @param int $page page number
|
||||
*
|
||||
* @return mixed an array of statuses
|
||||
*/
|
||||
function statusesFriendsTimeline($since_id = null, $max_id = null,
|
||||
$cnt = null, $page = null)
|
||||
{
|
||||
$url = 'https://twitter.com/statuses/friends_timeline.json';
|
||||
$params = array('since_id' => $since_id,
|
||||
'max_id' => $max_id,
|
||||
'count' => $cnt,
|
||||
'page' => $page);
|
||||
$qry = http_build_query($params);
|
||||
|
||||
if (!empty($qry)) {
|
||||
$url .= "?$qry";
|
||||
}
|
||||
|
||||
$response = $this->httpRequest($url);
|
||||
$statuses = json_decode($response);
|
||||
return $statuses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Twitter's /statuses/friends API method
|
||||
*
|
||||
* @param int $id id of the user whom you wish to see friends of
|
||||
* @param int $user_id numerical user id
|
||||
* @param int $screen_name screen name
|
||||
* @param int $page page number
|
||||
*
|
||||
* @return mixed an array of twitter users and their latest status
|
||||
*/
|
||||
function statusesFriends($id = null, $user_id = null, $screen_name = null,
|
||||
$page = null)
|
||||
{
|
||||
$url = "https://twitter.com/statuses/friends.json";
|
||||
|
||||
$params = array('id' => $id,
|
||||
'user_id' => $user_id,
|
||||
'screen_name' => $screen_name,
|
||||
'page' => $page);
|
||||
$qry = http_build_query($params);
|
||||
|
||||
if (!empty($qry)) {
|
||||
$url .= "?$qry";
|
||||
}
|
||||
|
||||
$response = $this->httpRequest($url);
|
||||
$friends = json_decode($response);
|
||||
return $friends;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Twitter's /statuses/friends/ids API method
|
||||
*
|
||||
* @param int $id id of the user whom you wish to see friends of
|
||||
* @param int $user_id numerical user id
|
||||
* @param int $screen_name screen name
|
||||
* @param int $page page number
|
||||
*
|
||||
* @return mixed a list of ids, 100 per page
|
||||
*/
|
||||
function friendsIds($id = null, $user_id = null, $screen_name = null,
|
||||
$page = null)
|
||||
{
|
||||
$url = "https://twitter.com/friends/ids.json";
|
||||
|
||||
$params = array('id' => $id,
|
||||
'user_id' => $user_id,
|
||||
'screen_name' => $screen_name,
|
||||
'page' => $page);
|
||||
$qry = http_build_query($params);
|
||||
|
||||
if (!empty($qry)) {
|
||||
$url .= "?$qry";
|
||||
}
|
||||
|
||||
$response = $this->httpRequest($url);
|
||||
$ids = json_decode($response);
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a HTTP request using cURL.
|
||||
*
|
||||
* @param string $url Where to make the request
|
||||
* @param array $params post parameters
|
||||
*
|
||||
* @return mixed the request
|
||||
*/
|
||||
function httpRequest($url, $params = null, $auth = true)
|
||||
{
|
||||
$options = array(
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_FAILONERROR => true,
|
||||
CURLOPT_HEADER => false,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_USERAGENT => 'StatusNet',
|
||||
CURLOPT_CONNECTTIMEOUT => 120,
|
||||
CURLOPT_TIMEOUT => 120,
|
||||
CURLOPT_HTTPAUTH => CURLAUTH_ANY,
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
|
||||
// Twitter is strict about accepting invalid "Expect" headers
|
||||
|
||||
CURLOPT_HTTPHEADER => array('Expect:')
|
||||
);
|
||||
|
||||
if (isset($params)) {
|
||||
$options[CURLOPT_POST] = true;
|
||||
$options[CURLOPT_POSTFIELDS] = $params;
|
||||
}
|
||||
|
||||
if ($auth) {
|
||||
$options[CURLOPT_USERPWD] = $this->screen_name .
|
||||
':' . $this->password;
|
||||
}
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, $options);
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if ($response === false) {
|
||||
$msg = curl_error($ch);
|
||||
$code = curl_errno($ch);
|
||||
throw new BasicAuthCurlException($msg, $code);
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
* @category Integration
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2008 StatusNet, Inc.
|
||||
* @copyright 2009 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/
|
||||
*/
|
||||
@ -81,6 +81,15 @@ class TwitterOAuthClient extends OAuthClient
|
||||
return new OAuthToken($vals[0], $vals[1]);
|
||||
}
|
||||
|
||||
static function isPackedToken($str)
|
||||
{
|
||||
if (strpos($str, chr(0)) === false) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a link to Twitter's endpoint for authorizing a request token
|
||||
*
|
||||
@ -109,7 +118,7 @@ class TwitterOAuthClient extends OAuthClient
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Twitter's /stutuses/update API method
|
||||
* Calls Twitter's /statuses/update API method
|
||||
*
|
||||
* @param string $status text of the status
|
||||
* @param int $in_reply_to_status_id optional id of the status it's
|
||||
@ -128,7 +137,7 @@ class TwitterOAuthClient extends OAuthClient
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Twitter's /stutuses/friends_timeline API method
|
||||
* Calls Twitter's /statuses/friends_timeline API method
|
||||
*
|
||||
* @param int $since_id show statuses after this id
|
||||
* @param int $max_id show statuses before this id
|
||||
@ -158,7 +167,7 @@ class TwitterOAuthClient extends OAuthClient
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Twitter's /stutuses/friends API method
|
||||
* Calls Twitter's /statuses/friends API method
|
||||
*
|
||||
* @param int $id id of the user whom you wish to see friends of
|
||||
* @param int $user_id numerical user id
|
||||
@ -188,7 +197,7 @@ class TwitterOAuthClient extends OAuthClient
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Twitter's /stutuses/friends/ids API method
|
||||
* Calls Twitter's /statuses/friends/ids API method
|
||||
*
|
||||
* @param int $id id of the user whom you wish to see friends of
|
||||
* @param int $user_id numerical user id
|
||||
|
158
lib/util.php
@ -59,7 +59,7 @@ function common_init_language()
|
||||
textdomain("statusnet");
|
||||
setlocale(LC_CTYPE, 'C');
|
||||
if(!$locale_set) {
|
||||
common_log(LOG_INFO,'Language requested:'.$language.' - locale could not be set:',__FILE__);
|
||||
common_log(LOG_INFO, 'Language requested:' . $language . ' - locale could not be set. Perhaps that system locale is not installed.', __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,7 +413,7 @@ function common_replace_urls_callback($text, $callback, $notice_id = null) {
|
||||
// Start off with a regex
|
||||
$regex = '#'.
|
||||
'(?:^|[\s\(\)\[\]\{\}\\\'\\\";]+)(?![\@\!\#])'.
|
||||
'(?P<url>'.
|
||||
'('.
|
||||
'(?:'.
|
||||
'(?:'. //Known protocols
|
||||
'(?:'.
|
||||
@ -421,7 +421,7 @@ function common_replace_urls_callback($text, $callback, $notice_id = null) {
|
||||
'|'.
|
||||
'(?:(?:mailto|aim|tel|xmpp):)'.
|
||||
')'.
|
||||
'(?:[\pN\pL\-\_\+]+(?::[\pN\pL\-\_\+]+)?\@)?'. //user:pass@
|
||||
'(?:[\pN\pL\-\_\+\%\~]+(?::[\pN\pL\-\_\+\%\~]+)?\@)?'. //user:pass@
|
||||
'(?:'.
|
||||
'(?:'.
|
||||
'\[[\pN\pL\-\_\:\.]+(?<![\.\:])\]'. //[dns]
|
||||
@ -432,9 +432,9 @@ function common_replace_urls_callback($text, $callback, $notice_id = null) {
|
||||
')'.
|
||||
'|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'. //IPv4
|
||||
'|(?:'. //IPv6
|
||||
'\[?(?:(?:(?:[0-9A-Fa-f]{1,4}:){7}(?:(?:[0-9A-Fa-f]{1,4})|:))|(?:(?:[0-9A-Fa-f]{1,4}:){6}(?::|(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})|(?::[0-9A-Fa-f]{1,4})))|(?:(?:[0-9A-Fa-f]{1,4}:){5}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:){4}(?::[0-9A-Fa-f]{1,4}){0,1}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:){3}(?::[0-9A-Fa-f]{1,4}){0,2}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:){2}(?::[0-9A-Fa-f]{1,4}){0,3}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:)(?::[0-9A-Fa-f]{1,4}){0,4}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?::(?::[0-9A-Fa-f]{1,4}){0,5}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))\]?'.
|
||||
'\[?(?:(?:(?:[0-9A-Fa-f]{1,4}:){7}(?:(?:[0-9A-Fa-f]{1,4})|:))|(?:(?:[0-9A-Fa-f]{1,4}:){6}(?::|(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})|(?::[0-9A-Fa-f]{1,4})))|(?:(?:[0-9A-Fa-f]{1,4}:){5}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:){4}(?::[0-9A-Fa-f]{1,4}){0,1}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:){3}(?::[0-9A-Fa-f]{1,4}){0,2}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:){2}(?::[0-9A-Fa-f]{1,4}){0,3}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:[0-9A-Fa-f]{1,4}:)(?::[0-9A-Fa-f]{1,4}){0,4}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?::(?::[0-9A-Fa-f]{1,4}){0,5}(?:(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|(?:(?::[0-9A-Fa-f]{1,4}){1,2})))|(?:(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))\]?(?<!:)'.
|
||||
')|(?:'. //DNS
|
||||
'(?:[\pN\pL\-\_\+]+(?:\:[\pN\pL\-\_\+]+)?\@)?'. //user:pass@
|
||||
'(?:[\pN\pL\-\_\+\%\~]+(?:\:[\pN\pL\-\_\+\%\~]+)?\@)?'. //user:pass@
|
||||
'[\pN\pL\-\_]+(?:\.[\pN\pL\-\_]+)*\.'.
|
||||
//tld list from http://data.iana.org/TLD/tlds-alpha-by-domain.txt, also added local, loc, and onion
|
||||
'(?:AC|AD|AE|AERO|AF|AG|AI|AL|AM|AN|AO|AQ|AR|ARPA|AS|ASIA|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BIZ|BJ|BM|BN|BO|BR|BS|BT|BV|BW|BY|BZ|CA|CAT|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|COM|COOP|CR|CU|CV|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EDU|EE|EG|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GOV|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|INFO|INT|IO|IQ|IR|IS|IT|JE|JM|JO|JOBS|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MG|MH|MIL|MK|ML|MM|MN|MO|MOBI|MP|MQ|MR|MS|MT|MU|MUSEUM|MV|MW|MX|MY|MZ|NA|NAME|NC|NE|NET|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|ORG|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PRO|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|ST|SU|SV|SY|SZ|TC|TD|TEL|TF|TG|TH|TJ|TK|TL|TM|TN|TO|TP|TR|TRAVEL|TT|TV|TW|TZ|UA|UG|UK|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|XN--0ZWM56D|测试|XN--11B5BS3A9AJ6G|परीक्षा|XN--80AKHBYKNJ4F|испытание|XN--9T4B11YI5A|테스트|XN--DEBA0AD|טעסט|XN--G6W251D|測試|XN--HGBK6AJ7F53BBA|آزمایشی|XN--HLCJ6AYA9ESC7A|பரிட்சை|XN--JXALPDLP|δοκιμή|XN--KGBECHTV|إختبار|XN--ZCKZAH|テスト|YE|YT|YU|ZA|ZM|ZW|local|loc|onion)'.
|
||||
@ -442,22 +442,22 @@ function common_replace_urls_callback($text, $callback, $notice_id = null) {
|
||||
')'.
|
||||
'(?:'.
|
||||
'(?:\:\d+)?'. //:port
|
||||
'(?:/[\pN\pL$\[\]\,\!\(\)\.\-\_\+\/\=\&\;]*)?'. // /path
|
||||
'(?:\?[\pN\pL\$\[\]\,\!\(\)\.\-\_\+\/\=\&\;\/]*)?'. // ?query string
|
||||
'(?:\#[\pN\pL$\[\]\,\!\(\)\.\-\_\+\/\=\&\;\/\?\#]*)?'. // #fragment
|
||||
'(?:/[\pN\pL$\[\]\,\!\(\)\.\:\-\_\+\/\=\&\;\%\~\*\$\+\'\"]*)?'. // /path
|
||||
'(?:\?[\pN\pL\$\[\]\,\!\(\)\.\:\-\_\+\/\=\&\;\%\~\*\$\+\'\"\/]*)?'. // ?query string
|
||||
'(?:\#[\pN\pL$\[\]\,\!\(\)\.\:\-\_\+\/\=\&\;\%\~\*\$\+\'\"\/\?\#]*)?'. // #fragment
|
||||
')(?<![\?\.\,\#\,])'.
|
||||
')'.
|
||||
'#ixu';
|
||||
preg_match_all($regex,$text,$matches);
|
||||
//preg_match_all($regex,$text,$matches);
|
||||
//print_r($matches);
|
||||
return preg_replace_callback($regex, curry(callback_helper,$callback,$notice_id) ,$text);
|
||||
return preg_replace_callback($regex, curry('callback_helper',$callback,$notice_id) ,$text);
|
||||
}
|
||||
|
||||
function callback_helper($matches, $callback, $notice_id) {
|
||||
$url=$matches['url'];
|
||||
$url=$matches[1];
|
||||
$left = strpos($matches[0],$url);
|
||||
$right = $left+strlen($url);
|
||||
|
||||
|
||||
$groupSymbolSets=array(
|
||||
array(
|
||||
'left'=>'(',
|
||||
@ -491,13 +491,11 @@ function callback_helper($matches, $callback, $notice_id) {
|
||||
$url=substr($url,0,-1);
|
||||
}
|
||||
}while($original_url!=$url);
|
||||
|
||||
|
||||
|
||||
|
||||
if(empty($notice_id)){
|
||||
$result = call_user_func_array($callback,$url);
|
||||
}else{
|
||||
$result = call_user_func_array($callback, array($url,$notice_id) );
|
||||
$result = call_user_func_array($callback, array(array($url,$notice_id)) );
|
||||
}
|
||||
return substr($matches[0],0,$left) . $result . substr($matches[0],$right);
|
||||
}
|
||||
@ -508,16 +506,13 @@ function curry($fn) {
|
||||
array_shift($args);
|
||||
$id = uniqid('_partial');
|
||||
$GLOBALS[$id] = array($fn, $args);
|
||||
return create_function(
|
||||
'',
|
||||
'
|
||||
$args = func_get_args();
|
||||
return call_user_func_array(
|
||||
$GLOBALS["'.$id.'"][0],
|
||||
array_merge(
|
||||
$args,
|
||||
$GLOBALS["'.$id.'"][1]));
|
||||
');
|
||||
return create_function('',
|
||||
'$args = func_get_args(); '.
|
||||
'return call_user_func_array('.
|
||||
'$GLOBALS["'.$id.'"][0],'.
|
||||
'array_merge('.
|
||||
'$args,'.
|
||||
'$GLOBALS["'.$id.'"][1]));');
|
||||
}
|
||||
|
||||
function common_linkify($url) {
|
||||
@ -525,7 +520,7 @@ function common_linkify($url) {
|
||||
// functions
|
||||
$url = htmlspecialchars_decode($url);
|
||||
|
||||
if(strpos($url, '@')!==false && strpos($url, ':')===false){
|
||||
if(strpos($url, '@') !== false && strpos($url, ':') === false) {
|
||||
//url is an email address without the mailto: protocol
|
||||
return XMLStringer::estring('a', array('href' => "mailto:$url", 'rel' => 'external'), $url);
|
||||
}
|
||||
@ -547,42 +542,30 @@ function common_linkify($url) {
|
||||
$attachment_id = null;
|
||||
$has_thumb = false;
|
||||
|
||||
// Check to see whether there's a filename associated with this URL.
|
||||
// If there is, it's an upload and qualifies as an attachment
|
||||
// Check to see whether this is a known "attachment" URL.
|
||||
|
||||
$localfile = File::staticGet('url', $longurl);
|
||||
$f = File::staticGet('url', $longurl);
|
||||
|
||||
if (!empty($localfile)) {
|
||||
if (isset($localfile->filename)) {
|
||||
$is_attachment = true;
|
||||
$attachment_id = $localfile->id;
|
||||
}
|
||||
if (empty($f)) {
|
||||
// XXX: this writes to the database. :<
|
||||
$f = File::processNew($longurl);
|
||||
}
|
||||
|
||||
// if this URL is an attachment, then we set class='attachment' and id='attahcment-ID'
|
||||
// where ID is the id of the attachment for the given URL.
|
||||
//
|
||||
// we need a better test telling what can be shown as an attachment
|
||||
// we're currently picking up oembeds only.
|
||||
// I think the best option is another file_view table in the db
|
||||
// and associated dbobject.
|
||||
if (!empty($f)) {
|
||||
if (isset($f->filename)) {
|
||||
$is_attachment = true;
|
||||
$attachment_id = $f->id;
|
||||
} else { // if it has OEmbed info, it's an attachment, too
|
||||
$foe = File_oembed::staticGet('file_id', $f->id);
|
||||
if (!empty($foe)) {
|
||||
$is_attachment = true;
|
||||
$attachment_id = $f->id;
|
||||
|
||||
$query = "select file_oembed.file_id as file_id from file join file_oembed on file.id = file_oembed.file_id where file.url='$longurl'";
|
||||
$file = new File;
|
||||
$file->query($query);
|
||||
$file->fetch();
|
||||
|
||||
if (!empty($file->file_id)) {
|
||||
$is_attachment = true;
|
||||
$attachment_id = $file->file_id;
|
||||
|
||||
$query = "select file_thumbnail.file_id as file_id from file join file_thumbnail on file.id = file_thumbnail.file_id where file.url='$longurl'";
|
||||
$file2 = new File;
|
||||
$file2->query($query);
|
||||
$file2->fetch();
|
||||
|
||||
if (!empty($file2)) {
|
||||
$has_thumb = true;
|
||||
$thumb = File_thumbnail::staticGet('file_id', $f->id);
|
||||
if (!empty($thumb)) {
|
||||
$has_thumb = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1390,58 +1373,19 @@ function common_shorten_url($long_url)
|
||||
} else {
|
||||
$svc = $user->urlshorteningservice;
|
||||
}
|
||||
|
||||
$curlh = curl_init();
|
||||
curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait
|
||||
curl_setopt($curlh, CURLOPT_USERAGENT, 'StatusNet');
|
||||
curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
switch($svc) {
|
||||
case 'ur1.ca':
|
||||
require_once INSTALLDIR.'/lib/Shorturl_api.php';
|
||||
$short_url_service = new LilUrl;
|
||||
$short_url = $short_url_service->shorten($long_url);
|
||||
break;
|
||||
|
||||
case '2tu.us':
|
||||
$short_url_service = new TightUrl;
|
||||
require_once INSTALLDIR.'/lib/Shorturl_api.php';
|
||||
$short_url = $short_url_service->shorten($long_url);
|
||||
break;
|
||||
|
||||
case 'ptiturl.com':
|
||||
require_once INSTALLDIR.'/lib/Shorturl_api.php';
|
||||
$short_url_service = new PtitUrl;
|
||||
$short_url = $short_url_service->shorten($long_url);
|
||||
break;
|
||||
|
||||
case 'bit.ly':
|
||||
curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($long_url));
|
||||
$short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl;
|
||||
break;
|
||||
|
||||
case 'is.gd':
|
||||
curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($long_url));
|
||||
$short_url = curl_exec($curlh);
|
||||
break;
|
||||
case 'snipr.com':
|
||||
curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($long_url));
|
||||
$short_url = curl_exec($curlh);
|
||||
break;
|
||||
case 'metamark.net':
|
||||
curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($long_url));
|
||||
$short_url = curl_exec($curlh);
|
||||
break;
|
||||
case 'tinyurl.com':
|
||||
curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($long_url));
|
||||
$short_url = curl_exec($curlh);
|
||||
break;
|
||||
default:
|
||||
$short_url = false;
|
||||
global $_shorteners;
|
||||
if(! $_shorteners[$svc]){
|
||||
//the user selected service doesn't exist, so default to ur1.ca
|
||||
$svc = 'ur1.ca';
|
||||
}
|
||||
|
||||
curl_close($curlh);
|
||||
$reflectionObj = new ReflectionClass($_shorteners[$svc]['callInfo'][0]);
|
||||
$short_url_service = $reflectionObj->newInstanceArgs($_shorteners[$svc]['callInfo'][1]);
|
||||
$short_url = $short_url_service->shorten($long_url);
|
||||
|
||||
if(substr($short_url,0,7)=='http://'){
|
||||
$short_url = substr($short_url,7);
|
||||
}
|
||||
return $short_url;
|
||||
}
|
||||
|
||||
|
64
plugins/LilUrl/LilUrlPlugin.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Plugin to push RSS/Atom updates to a PubSubHubBub hub
|
||||
*
|
||||
* 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 Plugin
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @copyright 2009 Craig Andrews http://candrews.integralblue.com
|
||||
* @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);
|
||||
}
|
||||
|
||||
require_once(INSTALLDIR.'/lib/Shorturl_api.php');
|
||||
|
||||
class LilUrlPlugin extends Plugin
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function onInitializePlugin(){
|
||||
$this->registerUrlShortener(
|
||||
'ur1.ca',
|
||||
array('freeService'=>true),
|
||||
array('LilUrl',array('http://ur1.ca/'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LilUrl extends ShortUrlApi
|
||||
{
|
||||
protected function shorten_imp($url) {
|
||||
$data['longurl'] = $url;
|
||||
$response = $this->http_post($data);
|
||||
if (!$response) return $url;
|
||||
$y = @simplexml_load_string($response);
|
||||
if (!isset($y->body)) return $url;
|
||||
$x = $y->body->p[0]->a->attributes();
|
||||
if (isset($x['href'])) return $x['href'];
|
||||
return $url;
|
||||
}
|
||||
}
|
@ -75,6 +75,8 @@ class LinkbackPlugin extends Plugin
|
||||
|
||||
function linkbackUrl($url)
|
||||
{
|
||||
common_log(LOG_DEBUG,"Attempting linkback for " . $url);
|
||||
|
||||
$orig = $url;
|
||||
$url = htmlspecialchars_decode($orig);
|
||||
$scheme = parse_url($url, PHP_URL_SCHEME);
|
||||
@ -134,15 +136,20 @@ class LinkbackPlugin extends Plugin
|
||||
"User-Agent: " . $this->userAgent(),
|
||||
'content' => $request)));
|
||||
$file = file_get_contents($endpoint, false, $context);
|
||||
$response = xmlrpc_decode($file);
|
||||
if (xmlrpc_is_fault($response)) {
|
||||
if (!$file) {
|
||||
common_log(LOG_WARNING,
|
||||
"Pingback request failed for '$url' ($endpoint)");
|
||||
} else {
|
||||
$response = xmlrpc_decode($file);
|
||||
if (xmlrpc_is_fault($response)) {
|
||||
common_log(LOG_WARNING,
|
||||
"Pingback error for '$url' ($endpoint): ".
|
||||
"$response[faultString] ($response[faultCode])");
|
||||
} else {
|
||||
common_log(LOG_INFO,
|
||||
} else {
|
||||
common_log(LOG_INFO,
|
||||
"Pingback success for '$url' ($endpoint): ".
|
||||
"'$response'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,12 @@ class OpenidloginAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('openid_url');
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('OpenID Login');
|
||||
|
@ -72,6 +72,12 @@ class OpenidsettingsAction extends AccountSettingsAction
|
||||
' Manage your associated OpenIDs from here.');
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('openid_url');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for OpenID management
|
||||
*
|
||||
|
62
plugins/PtitUrl/PtitUrlPlugin.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Plugin to push RSS/Atom updates to a PubSubHubBub hub
|
||||
*
|
||||
* 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 Plugin
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @copyright 2009 Craig Andrews http://candrews.integralblue.com
|
||||
* @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);
|
||||
}
|
||||
|
||||
class PtitUrlPlugin extends Plugin
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function onInitializePlugin(){
|
||||
$this->registerUrlShortener(
|
||||
'ptiturl.com',
|
||||
array(),
|
||||
array('PtitUrl',array('http://ptiturl.com/?creer=oui&action=Reduire&url='))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PtitUrl extends ShortUrlApi
|
||||
{
|
||||
protected function shorten_imp($url) {
|
||||
$response = $this->http_get($url);
|
||||
if (!$response) return $url;
|
||||
$response = $this->tidy($response);
|
||||
$y = @simplexml_load_string($response);
|
||||
if (!isset($y->body)) return $url;
|
||||
$xml = $y->body->center->table->tr->td->pre->a->attributes();
|
||||
if (isset($xml['href'])) return $xml['href'];
|
||||
return $url;
|
||||
}
|
||||
}
|
122
plugins/PubSubHubBub/PubSubHubBubPlugin.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Plugin to push RSS/Atom updates to a PubSubHubBub hub
|
||||
*
|
||||
* 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 Plugin
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @copyright 2009 Craig Andrews http://candrews.integralblue.com
|
||||
* @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);
|
||||
}
|
||||
|
||||
define('DEFAULT_HUB','http://2pubsubhubbub.appspot.com');
|
||||
|
||||
require_once(INSTALLDIR.'/plugins/PubSubHubBub/publisher.php');
|
||||
|
||||
class PubSubHubBubPlugin extends Plugin
|
||||
{
|
||||
private $hub;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function onInitializePlugin(){
|
||||
$this->hub = common_config('PubSubHubBub', 'hub');
|
||||
if(empty($this->hub)){
|
||||
$this->hub = DEFAULT_HUB;
|
||||
}
|
||||
}
|
||||
|
||||
function onStartApiAtom($action){
|
||||
$action->element('link',array('rel'=>'hub','href'=>$this->hub),null);
|
||||
}
|
||||
|
||||
function onStartApiRss($action){
|
||||
$action->element('atom:link',array('rel'=>'hub','href'=>$this->hub),null);
|
||||
}
|
||||
|
||||
function onEndNoticeSave($notice){
|
||||
$publisher = new Publisher($this->hub);
|
||||
|
||||
$feeds = array();
|
||||
|
||||
//public timeline feeds
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'statuses','method' => 'public_timeline.rss'));
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'statuses','method' => 'public_timeline.atom'));
|
||||
|
||||
//author's own feeds
|
||||
$user = User::staticGet('id',$notice->profile_id);
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'statuses','method' => 'user_timeline','argument' => $user->nickname.'.rss'));
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'statuses','method' => 'user_timeline','argument' => $user->nickname.'.atom'));
|
||||
|
||||
//tag feeds
|
||||
$tag = new Notice_tag();
|
||||
$tag->notice_id = $notice->id;
|
||||
if ($tag->find()) {
|
||||
while ($tag->fetch()) {
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'tags','method' => 'timeline', 'argument'=>$tag->tag.'.atom'));
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'tags','method' => 'timeline', 'argument'=>$tag->tag.'.rss'));
|
||||
}
|
||||
}
|
||||
|
||||
//group feeds
|
||||
$group_inbox = new Group_inbox();
|
||||
$group_inbox->notice_id = $notice->id;
|
||||
if ($group_inbox->find()) {
|
||||
while ($group_inbox->fetch()) {
|
||||
$group = User_group::staticGet('id',$group_inbox->group_id);
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'groups','method' => 'timeline','argument' => $group->nickname.'.rss'));
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'groups','method' => 'timeline','argument' => $group->nickname.'.atom'));
|
||||
}
|
||||
}
|
||||
|
||||
//feed of each user that subscribes to the notice's author
|
||||
$notice_inbox = new Notice_inbox();
|
||||
$notice_inbox->notice_id = $notice->id;
|
||||
if ($notice_inbox->find()) {
|
||||
while ($notice_inbox->fetch()) {
|
||||
$user = User::staticGet('id',$notice_inbox->user_id);
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'statuses','method' => 'user_timeline','argument' => $user->nickname.'.rss'));
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'statuses','method' => 'user_timeline','argument' => $user->nickname.'.atom'));
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: when the reply page gets RSS and ATOM feeds, implement this
|
||||
//feed of user replied to
|
||||
if($notice->reply_to){
|
||||
$user = User::staticGet('id',$notice->reply_to);
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'statuses','method' => 'user_timeline','argument' => $user->nickname.'.rss'));
|
||||
$feeds[]=common_local_url('api',array('apiaction' => 'statuses','method' => 'user_timeline','argument' => $user->nickname.'.atom'));
|
||||
}*/
|
||||
|
||||
foreach(array_unique($feeds) as $feed){
|
||||
if(! $publisher->publish_update($feed)){
|
||||
common_log_line(LOG_WARNING,$feed.' was not published to hub at '.$this->hub.':'.$publisher->last_response());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
86
plugins/PubSubHubBub/publisher.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
// a PHP client library for pubsubhubbub
|
||||
// as defined at http://code.google.com/p/pubsubhubbub/
|
||||
// written by Josh Fraser | joshfraser.com | josh@eventvue.com
|
||||
// Released under Apache License 2.0
|
||||
|
||||
class Publisher {
|
||||
|
||||
protected $hub_url;
|
||||
protected $last_response;
|
||||
|
||||
// create a new Publisher
|
||||
public function __construct($hub_url) {
|
||||
|
||||
if (!isset($hub_url))
|
||||
throw new Exception('Please specify a hub url');
|
||||
|
||||
if (!preg_match("|^https?://|i",$hub_url))
|
||||
throw new Exception('The specified hub url does not appear to be valid: '.$hub_url);
|
||||
|
||||
$this->hub_url = $hub_url;
|
||||
}
|
||||
|
||||
// accepts either a single url or an array of urls
|
||||
public function publish_update($topic_urls, $http_function = false) {
|
||||
if (!isset($topic_urls))
|
||||
throw new Exception('Please specify a topic url');
|
||||
|
||||
// check that we're working with an array
|
||||
if (!is_array($topic_urls)) {
|
||||
$topic_urls = array($topic_urls);
|
||||
}
|
||||
|
||||
// set the mode to publish
|
||||
$post_string = "hub.mode=publish";
|
||||
// loop through each topic url
|
||||
foreach ($topic_urls as $topic_url) {
|
||||
|
||||
// lightweight check that we're actually working w/ a valid url
|
||||
if (!preg_match("|^https?://|i",$topic_url))
|
||||
throw new Exception('The specified topic url does not appear to be valid: '.$topic_url);
|
||||
|
||||
// append the topic url parameters
|
||||
$post_string .= "&hub.url=".urlencode($topic_url);
|
||||
}
|
||||
|
||||
// make the http post request and return true/false
|
||||
// easy to over-write to use your own http function
|
||||
if ($http_function)
|
||||
return $http_function($this->hub_url,$post_string);
|
||||
else
|
||||
return $this->http_post($this->hub_url,$post_string);
|
||||
}
|
||||
|
||||
// returns any error message from the latest request
|
||||
public function last_response() {
|
||||
return $this->last_response;
|
||||
}
|
||||
|
||||
// default http function that uses curl to post to the hub endpoint
|
||||
private function http_post($url, $post_string) {
|
||||
|
||||
// add any additional curl options here
|
||||
$options = array(CURLOPT_URL => $url,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $post_string,
|
||||
CURLOPT_USERAGENT => "PubSubHubbub-Publisher-PHP/1.0");
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, $options);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$this->last_response = $response;
|
||||
$info = curl_getinfo($ch);
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
// all good
|
||||
if ($info['http_code'] == 204)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
79
plugins/SimpleUrl/SimpleUrlPlugin.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Plugin to push RSS/Atom updates to a PubSubHubBub hub
|
||||
*
|
||||
* 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 Plugin
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @copyright 2009 Craig Andrews http://candrews.integralblue.com
|
||||
* @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);
|
||||
}
|
||||
|
||||
class SimpleUrlPlugin extends Plugin
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function onInitializePlugin(){
|
||||
$this->registerUrlShortener(
|
||||
'is.gd',
|
||||
array(),
|
||||
array('SimpleUrl',array('http://is.gd/api.php?longurl='))
|
||||
);
|
||||
$this->registerUrlShortener(
|
||||
'snipr.com',
|
||||
array(),
|
||||
array('SimpleUrl',array('http://snipr.com/site/snip?r=simple&link='))
|
||||
);
|
||||
$this->registerUrlShortener(
|
||||
'metamark.net',
|
||||
array(),
|
||||
array('SimpleUrl',array('http://metamark.net/api/rest/simple?long_url='))
|
||||
);
|
||||
$this->registerUrlShortener(
|
||||
'tinyurl.com',
|
||||
array(),
|
||||
array('SimpleUrl',array('http://tinyurl.com/api-create.php?url='))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SimpleUrl extends ShortUrlApi
|
||||
{
|
||||
protected function shorten_imp($url) {
|
||||
$curlh = curl_init();
|
||||
curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait
|
||||
curl_setopt($curlh, CURLOPT_USERAGENT, 'StatusNet');
|
||||
curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
curl_setopt($curlh, CURLOPT_URL, $this->service_url.urlencode($url));
|
||||
$short_url = curl_exec($curlh);
|
||||
|
||||
curl_close($curlh);
|
||||
return $short_url;
|
||||
}
|
||||
}
|
62
plugins/TightUrl/TightUrlPlugin.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Plugin to push RSS/Atom updates to a PubSubHubBub hub
|
||||
*
|
||||
* 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 Plugin
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @copyright 2009 Craig Andrews http://candrews.integralblue.com
|
||||
* @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);
|
||||
}
|
||||
|
||||
class TightUrlPlugin extends Plugin
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function onInitializePlugin(){
|
||||
$this->registerUrlShortener(
|
||||
'2tu.us',
|
||||
array('freeService'=>true),
|
||||
array('TightUrl',array('http://2tu.us/?save=y&url='))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TightUrl extends ShortUrlApi
|
||||
{
|
||||
protected function shorten_imp($url) {
|
||||
$response = $this->http_get($url);
|
||||
if (!$response) return $url;
|
||||
$response = $this->tidy($response);
|
||||
$y = @simplexml_load_string($response);
|
||||
if (!isset($y->body)) return $url;
|
||||
$xml = $y->body->p[0]->code[0]->a->attributes();
|
||||
if (isset($xml['href'])) return $xml['href'];
|
||||
return $url;
|
||||
}
|
||||
}
|
@ -142,13 +142,20 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon
|
||||
{
|
||||
$friends = array();
|
||||
|
||||
$token = TwitterOAuthClient::unpackToken($flink->credentials);
|
||||
$client = null;
|
||||
|
||||
$client = new TwitterOAuthClient($token->key, $token->secret);
|
||||
if (TwitterOAuthClient::isPackedToken($flink->credentials)) {
|
||||
$token = TwitterOAuthClient::unpackToken($flink->credentials);
|
||||
$client = new TwitterOAuthClient($token->key, $token->secret);
|
||||
common_debug($this->name() . '- Grabbing friends IDs with OAuth.');
|
||||
} else {
|
||||
$client = new TwitterBasicAuthClient($flink);
|
||||
common_debug($this->name() . '- Grabbing friends IDs with basic auth.');
|
||||
}
|
||||
|
||||
try {
|
||||
$friends_ids = $client->friendsIds();
|
||||
} catch (OAuthCurlException $e) {
|
||||
} catch (Exception $e) {
|
||||
common_log(LOG_WARNING, $this->name() .
|
||||
' - cURL error getting friend ids ' .
|
||||
$e->getCode() . ' - ' . $e->getMessage());
|
||||
@ -177,7 +184,7 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon
|
||||
|
||||
try {
|
||||
$more_friends = $client->statusesFriends(null, null, null, $i);
|
||||
} catch (OAuthCurlException $e) {
|
||||
} catch (Exception $e) {
|
||||
common_log(LOG_WARNING, $this->name() .
|
||||
' - cURL error getting Twitter statuses/friends ' .
|
||||
"page $i - " . $e->getCode() . ' - ' .
|
||||
|
@ -148,9 +148,9 @@ class TwitterStatusFetcher extends ParallelizingDaemon
|
||||
|
||||
function getTimeline($flink)
|
||||
{
|
||||
if (empty($flink)) {
|
||||
if (empty($flink)) {
|
||||
common_log(LOG_WARNING, $this->name() .
|
||||
" - Can't retrieve Foreign_link for foreign ID $fid");
|
||||
" - Can't retrieve Foreign_link for foreign ID $fid");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -161,17 +161,24 @@ class TwitterStatusFetcher extends ParallelizingDaemon
|
||||
// to start importing? How many statuses? Right now I'm going
|
||||
// with the default last 20.
|
||||
|
||||
$token = TwitterOAuthClient::unpackToken($flink->credentials);
|
||||
$client = null;
|
||||
|
||||
$client = new TwitterOAuthClient($token->key, $token->secret);
|
||||
if (TwitterOAuthClient::isPackedToken($flink->credentials)) {
|
||||
$token = TwitterOAuthClient::unpackToken($flink->credentials);
|
||||
$client = new TwitterOAuthClient($token->key, $token->secret);
|
||||
common_debug($this->name() . ' - Grabbing friends timeline with OAuth.');
|
||||
} else {
|
||||
$client = new TwitterBasicAuthClient($flink);
|
||||
common_debug($this->name() . ' - Grabbing friends timeline with basic auth.');
|
||||
}
|
||||
|
||||
$timeline = null;
|
||||
|
||||
try {
|
||||
$timeline = $client->statusesFriendsTimeline();
|
||||
} catch (OAuthClientCurlException $e) {
|
||||
} catch (Exception $e) {
|
||||
common_log(LOG_WARNING, $this->name() .
|
||||
' - OAuth client unable to get friends timeline for user ' .
|
||||
' - Twitter client unable to get friends timeline for user ' .
|
||||
$flink->user_id . ' - code: ' .
|
||||
$e->getCode() . 'msg: ' . $e->getMessage());
|
||||
}
|
||||
|
@ -25,14 +25,36 @@ class URLDetectionTest extends PHPUnit_Framework_TestCase
|
||||
static public function provider()
|
||||
{
|
||||
return array(
|
||||
array('not a link :: no way',
|
||||
'not a link :: no way'),
|
||||
array('http://127.0.0.1',
|
||||
'<a href="http://127.0.0.1/" rel="external">http://127.0.0.1</a>'),
|
||||
array('127.0.0.1',
|
||||
'<a href="http://127.0.0.1/" rel="external">127.0.0.1</a>'),
|
||||
array('127.0.0.1:99',
|
||||
'<a href="http://127.0.0.1:99/" rel="external">127.0.0.1:99</a>'),
|
||||
array('127.0.0.1/test.php',
|
||||
'<a href="http://127.0.0.1/test.php" rel="external">127.0.0.1/test.php</a>'),
|
||||
array('127.0.0.1/Name:test.php',
|
||||
'<a href="http://127.0.0.1/Name:test.php" rel="external">127.0.0.1/Name:test.php</a>'),
|
||||
array('127.0.0.1/~test',
|
||||
'<a href="http://127.0.0.1/~test" rel="external">127.0.0.1/~test</a>'),
|
||||
array('127.0.0.1/+test',
|
||||
'<a href="http://127.0.0.1/+test" rel="external">127.0.0.1/+test</a>'),
|
||||
array('127.0.0.1/$test',
|
||||
'<a href="http://127.0.0.1/$test" rel="external">127.0.0.1/$test</a>'),
|
||||
array('127.0.0.1/\'test',
|
||||
'<a href="http://127.0.0.1/\'test" rel="external">127.0.0.1/\'test</a>'),
|
||||
array('127.0.0.1/"test',
|
||||
'<a href="http://127.0.0.1/"test" rel="external">127.0.0.1/"test</a>'),
|
||||
array('127.0.0.1/-test',
|
||||
'<a href="http://127.0.0.1/-test" rel="external">127.0.0.1/-test</a>'),
|
||||
array('127.0.0.1/_test',
|
||||
'<a href="http://127.0.0.1/_test" rel="external">127.0.0.1/_test</a>'),
|
||||
array('127.0.0.1/!test',
|
||||
'<a href="http://127.0.0.1/!test" rel="external">127.0.0.1/!test</a>'),
|
||||
array('127.0.0.1/*test',
|
||||
'<a href="http://127.0.0.1/*test" rel="external">127.0.0.1/*test</a>'),
|
||||
array('127.0.0.1/test%20stuff',
|
||||
'<a href="http://127.0.0.1/test%20stuff" rel="external">127.0.0.1/test%20stuff</a>'),
|
||||
array('http://[::1]:99/test.php',
|
||||
'<a href="http://[::1]:99/test.php" rel="external">http://[::1]:99/test.php</a>'),
|
||||
array('http://::1/test.php',
|
||||
|
@ -156,7 +156,8 @@ font-weight:bold;
|
||||
#form_notice_delete legend,
|
||||
#form_password_recover legend,
|
||||
#form_password_change legend,
|
||||
.form_entity_block legend {
|
||||
.form_entity_block legend,
|
||||
#form_filter_bytag legend {
|
||||
display:none;
|
||||
}
|
||||
|
||||
@ -510,6 +511,7 @@ margin-top:7px;
|
||||
margin-bottom:7px;
|
||||
margin-left:18px;
|
||||
float:left;
|
||||
max-width:322px;
|
||||
}
|
||||
#form_notice .error,
|
||||
#form_notice .success {
|
||||
@ -1049,36 +1051,37 @@ display:none;
|
||||
#filter_tags ul {
|
||||
list-style-type:none;
|
||||
}
|
||||
#filter_tags ul li {
|
||||
#filter_tags li {
|
||||
float:left;
|
||||
margin-left:7px;
|
||||
padding-left:7px;
|
||||
border-left-width:1px;
|
||||
border-left-style:solid;
|
||||
}
|
||||
#filter_tags ul li.child_1 {
|
||||
#filter_tags #filter_tags_all {
|
||||
margin-left:0;
|
||||
border-left:0;
|
||||
padding-left:0;
|
||||
}
|
||||
#filter_tags ul li#filter_tags_all a {
|
||||
#filter_tags_all a {
|
||||
font-weight:bold;
|
||||
margin-top:7px;
|
||||
float:left;
|
||||
}
|
||||
|
||||
#filter_tags ul li#filter_tags_item label {
|
||||
#filter_tags_item label {
|
||||
margin-right:7px;
|
||||
}
|
||||
#filter_tags ul li#filter_tags_item label,
|
||||
#filter_tags ul li#filter_tags_item select {
|
||||
display:inline;
|
||||
}
|
||||
#filter_tags ul li#filter_tags_item p {
|
||||
#filter_tags_item label,
|
||||
#filter_tags_item select {
|
||||
float:left;
|
||||
}
|
||||
#filter_tags_item p {
|
||||
float:left;
|
||||
clear:both;
|
||||
margin-left:38px;
|
||||
}
|
||||
#filter_tags ul li#filter_tags_item input {
|
||||
#filter_tags_item .submit {
|
||||
position:relative;
|
||||
top:3px;
|
||||
left:3px;
|
||||
|
@ -849,6 +849,10 @@ float:left;
|
||||
font-size:1.025em;
|
||||
}
|
||||
|
||||
.notice div.entry-content .timestamp {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.notice div.entry-content dl,
|
||||
.notice div.entry-content dt,
|
||||
.notice div.entry-content dd {
|
||||
@ -866,15 +870,12 @@ display:inline-block;
|
||||
text-transform:lowercase;
|
||||
}
|
||||
|
||||
|
||||
.notice-options {
|
||||
padding-left:2%;
|
||||
float:left;
|
||||
width:50%;
|
||||
position:relative;
|
||||
font-size:0.95em;
|
||||
width:12.5%;
|
||||
width:90px;
|
||||
float:right;
|
||||
margin-right:11px;
|
||||
}
|
||||
|
||||
.notice-options a {
|
||||
@ -897,38 +898,28 @@ left:29px;
|
||||
.notice-options .notice_delete {
|
||||
right:0;
|
||||
}
|
||||
.notice-options .notice_reply dt {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.notice-options input,
|
||||
.notice-options a {
|
||||
text-indent:-9999px;
|
||||
outline:none;
|
||||
}
|
||||
|
||||
.notice-options .notice_reply a,
|
||||
.notice-options input.submit {
|
||||
display:block;
|
||||
border:0;
|
||||
}
|
||||
.notice-options .notice_reply a,
|
||||
.notice-options .notice_delete a {
|
||||
.notice-options .notice_reply,
|
||||
.notice-options .notice_delete {
|
||||
text-decoration:none;
|
||||
padding-left:16px;
|
||||
}
|
||||
|
||||
.notice-options form input.submit {
|
||||
width:16px;
|
||||
padding:2px 0;
|
||||
}
|
||||
|
||||
.notice-options .notice_delete dt,
|
||||
.notice-options .form_favor legend,
|
||||
.notice-options .form_disfavor legend {
|
||||
display:none;
|
||||
}
|
||||
.notice-options .notice_delete fieldset,
|
||||
.notice-options .form_favor fieldset,
|
||||
.notice-options .form_disfavor fieldset {
|
||||
border:0;
|
||||
|
@ -30,10 +30,10 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
||||
}
|
||||
input, textarea, select,
|
||||
.entity_remote_subscribe {
|
||||
border-color:#aaa;
|
||||
border-color:#AAAAAA;
|
||||
}
|
||||
#filter_tags ul li {
|
||||
border-color:#ddd;
|
||||
border-color:#DDDDDD;
|
||||
}
|
||||
|
||||
.form_settings input.form_action-primary {
|
||||
@ -50,11 +50,14 @@ background-color:#9BB43E;
|
||||
input:focus, textarea:focus, select:focus,
|
||||
#form_notice.warning #notice_data-text {
|
||||
border-color:#9BB43E;
|
||||
box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
|
||||
-moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
|
||||
-webkit-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
|
||||
}
|
||||
input.submit,
|
||||
.entity_remote_subscribe,
|
||||
#site_nav_local_views a {
|
||||
color:#fff;
|
||||
color:#FFFFFF;
|
||||
}
|
||||
|
||||
a,
|
||||
@ -62,10 +65,13 @@ a,
|
||||
div.notice-options input,
|
||||
.form_user_block input.submit,
|
||||
.form_user_unblock input.submit,
|
||||
.form_group_block input.submit,
|
||||
.form_group_unblock input.submit,
|
||||
.entity_send-a-message a,
|
||||
.form_user_nudge input.submit,
|
||||
.entity_nudge p,
|
||||
.form_settings input.form_action-primary {
|
||||
.form_settings input.form_action-primary,
|
||||
.form_make_admin input.submit {
|
||||
color:#002E6E;
|
||||
}
|
||||
|
||||
@ -82,13 +88,6 @@ border-top-color:#CEE1E9;
|
||||
border-top-color:#87B4C8;
|
||||
}
|
||||
|
||||
#content .notice p.entry-content a:visited {
|
||||
background-color:#fcfcfc;
|
||||
}
|
||||
#content .notice p.entry-content .vcard a {
|
||||
background-color:#fcfffc;
|
||||
}
|
||||
|
||||
.aside .section {
|
||||
background-color:#F1F5F8;
|
||||
background-position:100% 0;
|
||||
@ -97,10 +96,10 @@ background-repeat:no-repeat;
|
||||
}
|
||||
|
||||
#notice_text-count {
|
||||
color:#333;
|
||||
color:#333333;
|
||||
}
|
||||
#form_notice.warning #notice_text-count {
|
||||
color:#000;
|
||||
color:#000000;
|
||||
}
|
||||
#form_notice label[for=notice_data-attach] {
|
||||
background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%;
|
||||
@ -109,28 +108,43 @@ background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no
|
||||
opacity:0;
|
||||
}
|
||||
|
||||
#form_notice.processing #notice_action-submit {
|
||||
background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
|
||||
#wrap form.processing input.submit {
|
||||
background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
|
||||
cursor:wait;
|
||||
text-indent:-9999px;
|
||||
outline:none;
|
||||
}
|
||||
|
||||
#content {
|
||||
box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3);
|
||||
-moz-box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3);
|
||||
-webkit-box-shadow:5px 7px 7px rgba(194, 194, 194, 0.3);
|
||||
}
|
||||
#content,
|
||||
#site_nav_local_views a,
|
||||
.aside .section {
|
||||
border-color:#fff;
|
||||
border-color:#FFFFFF;
|
||||
}
|
||||
#content,
|
||||
#site_nav_local_views .current a {
|
||||
background-color:#fff;
|
||||
background-color:#FFFFFF;
|
||||
}
|
||||
|
||||
#site_nav_local_views li {
|
||||
box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5);
|
||||
-moz-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5);
|
||||
-webkit-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.5);
|
||||
}
|
||||
#site_nav_local_views a {
|
||||
background-color:rgba(135, 180, 200, 0.3);
|
||||
background-color:rgba(194, 194, 194, 0.5);
|
||||
}
|
||||
#site_nav_local_views a:hover {
|
||||
background-color:rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
#site_nav_local_views .current a {
|
||||
text-shadow: rgba(194,194,194,0.5) 1px 1px 1px;
|
||||
}
|
||||
|
||||
|
||||
.error {
|
||||
background-color:#F7E8E8;
|
||||
@ -140,10 +154,7 @@ background-color:#EFF3DC;
|
||||
}
|
||||
|
||||
#anon_notice {
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
#showstream #anon_notice {
|
||||
color:#FFFFFF;
|
||||
}
|
||||
|
||||
#export_data li a {
|
||||
@ -165,7 +176,10 @@ background-image:url(../../base/images/icons/icon_foaf.gif);
|
||||
.form_user_nudge input.submit,
|
||||
.form_user_block input.submit,
|
||||
.form_user_unblock input.submit,
|
||||
.entity_nudge p {
|
||||
.form_group_block input.submit,
|
||||
.form_group_unblock input.submit,
|
||||
.entity_nudge p,
|
||||
.form_make_admin input.submit {
|
||||
background-position: 0 40%;
|
||||
background-repeat: no-repeat;
|
||||
background-color:transparent;
|
||||
@ -175,7 +189,7 @@ background-color:transparent;
|
||||
.form_user_subscribe input.submit,
|
||||
.form_user_unsubscribe input.submit {
|
||||
background-color:#9BB43E;
|
||||
color:#fff;
|
||||
color:#FFFFFF;
|
||||
}
|
||||
.form_user_unsubscribe input.submit,
|
||||
.form_group_leave input.submit,
|
||||
@ -194,20 +208,23 @@ background-image:url(../../base/images/icons/twotone/green/quote.gif);
|
||||
background-image:url(../../base/images/icons/twotone/green/mail.gif);
|
||||
}
|
||||
.form_user_block input.submit,
|
||||
.form_user_unblock input.submit {
|
||||
.form_user_unblock input.submit,
|
||||
.form_group_block input.submit,
|
||||
.form_group_unblock input.submit {
|
||||
background-image:url(../../base/images/icons/twotone/green/shield.gif);
|
||||
}
|
||||
.form_make_admin input.submit {
|
||||
background-image:url(../../base/images/icons/twotone/green/admin.gif);
|
||||
}
|
||||
|
||||
/* NOTICES */
|
||||
.notices li.over {
|
||||
background-color:#fcfcfc;
|
||||
.notice .attachment {
|
||||
background:transparent url(../../base/images/icons/twotone/green/clip-02.gif) no-repeat 0 45%;
|
||||
}
|
||||
|
||||
.notice-options .notice_reply a,
|
||||
.notice-options form input.submit {
|
||||
background-color:transparent;
|
||||
#attachments .attachment {
|
||||
background:none;
|
||||
}
|
||||
.notice-options .notice_reply a {
|
||||
.notice-options .notice_reply {
|
||||
background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%;
|
||||
}
|
||||
.notice-options form.form_favor input.submit {
|
||||
@ -216,7 +233,7 @@ background:transparent url(../../base/images/icons/twotone/green/favourite.gif)
|
||||
.notice-options form.form_disfavor input.submit {
|
||||
background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%;
|
||||
}
|
||||
.notice-options .notice_delete a {
|
||||
.notice-options .notice_delete {
|
||||
background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%;
|
||||
}
|
||||
|
||||
@ -224,19 +241,32 @@ background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-r
|
||||
.notices div.notice-options {
|
||||
opacity:0.4;
|
||||
}
|
||||
.notices li.hover div.entry-content,
|
||||
.notices li.hover div.notice-options {
|
||||
.notices li:hover div.entry-content,
|
||||
.notices li:hover div.notice-options {
|
||||
opacity:1;
|
||||
}
|
||||
div.entry-content {
|
||||
color:#333;
|
||||
}
|
||||
div.notice-options a,
|
||||
div.notice-options input {
|
||||
font-family:sans-serif;
|
||||
}
|
||||
.notices li.hover {
|
||||
background-color:#fcfcfc;
|
||||
#content .notices li:hover {
|
||||
background-color:rgba(240, 240, 240, 0.2);
|
||||
}
|
||||
#conversation .notices li:hover {
|
||||
background-color:transparent;
|
||||
}
|
||||
|
||||
.notices .notices {
|
||||
background-color:rgba(200, 200, 200, 0.050);
|
||||
}
|
||||
.notices .notices .notices {
|
||||
background-color:rgba(200, 200, 200, 0.100);
|
||||
}
|
||||
.notices .notices .notices .notices {
|
||||
background-color:rgba(200, 200, 200, 0.150);
|
||||
}
|
||||
.notices .notices .notices .notices .notices {
|
||||
background-color:rgba(200, 200, 200, 0.300);
|
||||
}
|
||||
/*END: NOTICES */
|
||||
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 6.2 KiB |
@ -94,10 +94,11 @@ background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no
|
||||
opacity:0;
|
||||
}
|
||||
|
||||
#form_notice.processing #notice_action-submit {
|
||||
#wrap form.processing input.submit {
|
||||
background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
|
||||
cursor:wait;
|
||||
text-indent:-9999px;
|
||||
outline:none;
|
||||
}
|
||||
|
||||
#content {
|
||||
@ -223,10 +224,6 @@ background:transparent url(../../base/images/icons/twotone/green/favourite.gif)
|
||||
.notice-options form.form_disfavor input.submit {
|
||||
background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%;
|
||||
}
|
||||
.notice-options form.form_favor.processing input.submit,
|
||||
.notice-options form.form_disfavor.processing input.submit {
|
||||
background:transparent url(../../base/images/icons/icon_processing.gif) no-repeat 0 45%;
|
||||
}
|
||||
.notice-options .notice_delete {
|
||||
background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 6.2 KiB |
@ -94,10 +94,11 @@ background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no
|
||||
opacity:0;
|
||||
}
|
||||
|
||||
#form_notice.processing #notice_action-submit {
|
||||
#wrap form.processing input.submit {
|
||||
background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
|
||||
cursor:wait;
|
||||
text-indent:-9999px;
|
||||
outline:none;
|
||||
}
|
||||
|
||||
#content {
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 6.2 KiB |