Merge branch '0.9.x' of git@gitorious.org:statusnet/mainline into 0.9.x

This commit is contained in:
Evan Prodromou 2009-09-15 17:16:35 -04:00
commit 13147143fc
73 changed files with 2049 additions and 661 deletions

View File

@ -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
View File

@ -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:

View File

@ -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));
}
}

View File

@ -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));

View File

@ -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');
}
}

View File

@ -160,6 +160,12 @@ class EditgroupAction extends GroupDesignAction
}
}
function showScripts()
{
parent::showScripts();
$this->autofocus('nickname');
}
function trySave()
{
$cur = common_current_user();

View File

@ -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
*

View File

@ -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);
}
}

View File

@ -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()

View File

@ -90,6 +90,12 @@ class GroupsearchAction extends SearchAction
$user_group->free();
}
}
function showScripts()
{
parent::showScripts();
$this->autofocus('q');
}
}
class GroupSearchResults extends GroupList

View File

@ -98,6 +98,12 @@ class InviteAction extends CurrentUserDesignAction
$this->showPage();
}
function showScripts()
{
parent::showScripts();
$this->autofocus('addresses');
}
function title()
{
if ($this->mode == 'sent') {

View File

@ -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
*

View File

@ -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);

View File

@ -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');

View File

@ -69,6 +69,12 @@ class PasswordsettingsAction extends AccountSettingsAction
return _('Change your password.');
}
function showScripts()
{
parent::showScripts();
$this->autofocus('oldpassword');
}
/**
* Content area of the page
*

View File

@ -85,6 +85,12 @@ class PeoplesearchAction extends SearchAction
$profile->free();
}
}
function showScripts()
{
parent::showScripts();
$this->autofocus('q');
}
}
/**

View File

@ -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
*

View File

@ -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.');

View File

@ -136,6 +136,12 @@ class RegisterAction extends Action
}
}
function showScripts()
{
parent::showScripts();
$this->autofocus('nickname');
}
/**
* Try to register a user
*

View File

@ -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
*

View File

@ -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()) {

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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)) {

View File

@ -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;
}

View File

@ -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');

View File

@ -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();

View File

@ -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();

View File

@ -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;

View File

@ -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)
);

View File

@ -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)
);

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -454,7 +454,7 @@ class Stomp
*/
public function disconnect ()
{
$header = array();
$headers = array();
if ($this->clientId != null) {
$headers["client-id"] = $this->clientId;

View File

@ -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;
}

View File

@ -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 &quot;config.php&quot; already exists.</p>
<?php
printf('<p class="error">Config file &quot;config.php&quot; 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();

View File

@ -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;
}
}

View File

@ -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".

View File

@ -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) {

View File

@ -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');
}
/**

View 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');

View File

@ -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');
}
}

View File

@ -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;
}

View File

@ -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/
*/

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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()

View 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;
}
}

View File

@ -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

View File

@ -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;
}

View 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;
}
}

View File

@ -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'");
}
}
}

View File

@ -84,6 +84,12 @@ class OpenidloginAction extends Action
}
}
function showScripts()
{
parent::showScripts();
$this->autofocus('openid_url');
}
function title()
{
return _('OpenID Login');

View File

@ -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
*

View 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;
}
}

View 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());
}
}
}
}

View 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;
}
}
?>

View 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;
}
}

View 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;
}
}

View File

@ -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() . ' - ' .

View File

@ -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());
}

View File

@ -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/&quot;test" rel="external">127.0.0.1/&quot;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',

View File

@ -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;

View File

@ -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;

View File

@ -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 */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -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%;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -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 {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB