Merge branch '0.9.x' into pluginize-twitter-bridge

* 0.9.x: (57 commits)
  Updated csarven emails to csarven@status.net and removed dupes
  statusize new HTTP classes
  dedupe evans
  change all evans to evan@status.net
  add post to curlclient
  fix user-agent for curlclient
  add get to curl client
  add cURL client with HEAD method
  add user agent and correct version check to httpclient
  statusize OpenID plugin
  add http client config value
  update httpclient class
  move httputil to httpclient
  Start a common library for HTTP client stuff
  check correct define (not backwards compatible)
  Fixed broken list items in installer output
  Got rid of a bunch of ugly warnings
  Add Jiminy to notice sources
  Make it impossible to delete self-subscriptions via the API
  Fix bad merge d7ae0ed4fd
  ...
This commit is contained in:
Zach Copley 2009-09-16 12:40:22 -07:00
commit 0190785b73
49 changed files with 1001 additions and 338 deletions

View File

@ -1,5 +1,5 @@
<?php <?php
/* /**
* StatusNet - the distributed open-source microblogging tool * StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2008, 2009, StatusNet, Inc. * Copyright (C) 2008, 2009, StatusNet, Inc.
* *
@ -15,9 +15,25 @@
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Actions
* @package Actions
* @author Evan Prodromou <evan@status.net>
* @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@status.net>
* @author Craig Andrews <candrews@integralblue.com>
* @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@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/personalgroupnav.php';
require_once INSTALLDIR.'/lib/noticelist.php'; require_once INSTALLDIR.'/lib/noticelist.php';
@ -43,8 +59,8 @@ class AllAction extends ProfileAction
$this->notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); $this->notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
} }
if($this->page > 1 && $this->notice->N == 0){ if ($this->page > 1 && $this->notice->N == 0) {
$this->serverError(_('No such page'),$code=404); $this->serverError(_('No such page'), $code = 404);
} }
return true; return true;
@ -73,20 +89,33 @@ class AllAction extends ProfileAction
function getFeeds() function getFeeds()
{ {
return array(new Feed(Feed::RSS1, return array(
common_local_url('allrss', array('nickname' => new Feed(Feed::RSS1,
$this->user->nickname)), common_local_url(
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)), 'allrss', array(
new Feed(Feed::RSS2, 'nickname' =>
common_local_url('api', array('apiaction' => 'statuses', $this->user->nickname)
'method' => 'friends_timeline', ),
'argument' => $this->user->nickname.'.rss')), sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)), new Feed(Feed::RSS2,
new Feed(Feed::ATOM, common_local_url(
common_local_url('api', array('apiaction' => 'statuses', 'api', array(
'method' => 'friends_timeline', 'apiaction' => 'statuses',
'argument' => $this->user->nickname.'.atom')), 'method' => 'friends_timeline',
sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname))); '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() function showLocalNav()
@ -106,8 +135,7 @@ class AllAction extends ProfileAction
} else { } 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); $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); $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 +154,19 @@ class AllAction extends ProfileAction
$this->showEmptyListMessage(); $this->showEmptyListMessage();
} }
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->pagination(
$this->page, 'all', array('nickname' => $this->user->nickname)); $this->page > 1, $cnt > NOTICES_PER_PAGE,
$this->page, 'all', array('nickname' => $this->user->nickname)
);
} }
function showPageTitle() function showPageTitle()
{ {
$user =& common_current_user(); $user =& common_current_user();
if ($user && ($user->id == $this->user->id)) { if ($user && ($user->id == $this->user->id)) {
$this->element('h1', NULL, _("You and friends")); $this->element('h1', null, _("You and friends"));
} else { } 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 <?php
/* /**
* StatusNet - the distributed open-source microblogging tool * StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2008, 2009, StatusNet, Inc. * Copyright (C) 2008, 2009, StatusNet, Inc.
* *
@ -15,9 +15,27 @@
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Actions
* @package Actions
* @author Evan Prodromou <evan@status.net>
* @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 Gina Haeussge <osd@foosel.net>
* @author Mike Cochrane <mikec@mikenz.geek.nz>
* @author Sarven Capadisli <csarven@status.net>
* @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 class ApiAction extends Action
{ {
@ -27,6 +45,8 @@ class ApiAction extends Action
var $api_arg; var $api_arg;
var $api_method; var $api_method;
var $api_action; var $api_action;
var $auth_user;
var $auth_pw;
function handle($args) function handle($args)
{ {
@ -35,6 +55,7 @@ class ApiAction extends Action
$this->api_action = $this->arg('apiaction'); $this->api_action = $this->arg('apiaction');
$method = $this->arg('method'); $method = $this->arg('method');
$argument = $this->arg('argument'); $argument = $this->arg('argument');
$this->basic_auth_process_header();
if (isset($argument)) { if (isset($argument)) {
$cmdext = explode('.', $argument); $cmdext = explode('.', $argument);
@ -43,30 +64,30 @@ class ApiAction extends Action
$this->content_type = strtolower($cmdext[1]); $this->content_type = strtolower($cmdext[1]);
} else { } 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); $cmdext = explode('.', $method);
$this->api_method = $cmdext[0]; $this->api_method = $cmdext[0];
$this->content_type = strtolower($cmdext[1]); $this->content_type = strtolower($cmdext[1]);
} }
if ($this->requires_auth()) { 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"'); header('WWW-Authenticate: Basic realm="StatusNet API"');
# If the user hits cancel -- bam! //If the user hits cancel -- bam!
$this->show_basic_auth_error(); $this->show_basic_auth_error();
} else { } else {
$nickname = $_SERVER['PHP_AUTH_USER']; $nickname = $this->auth_user;
$password = $_SERVER['PHP_AUTH_PW']; $password = $this->auth_pw;
$user = common_check_user($nickname, $password); $user = common_check_user($nickname, $password);
if ($user) { if ($user) {
$this->user = $user; $this->user = $user;
$this->process_command(); $this->process_command();
} else { } else {
# basic authentication failed //basic authentication failed
list($proxy, $ip) = common_client_ip(); list($proxy, $ip) = common_client_ip();
common_log(LOG_WARNING, "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip."); common_log(LOG_WARNING, "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip.");
@ -76,12 +97,12 @@ class ApiAction extends Action
} else { } else {
// Caller might give us a username even if not required // Caller might give us a username even if not required
if (isset($_SERVER['PHP_AUTH_USER'])) { if (isset($this->auth_user)) {
$user = User::staticGet('nickname', $_SERVER['PHP_AUTH_USER']); $user = User::staticGet('nickname', $this->auth_user);
if ($user) { if ($user) {
$this->user = $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(); $this->process_command();
@ -94,7 +115,7 @@ class ApiAction extends Action
$actionfile = INSTALLDIR."/actions/$action.php"; $actionfile = INSTALLDIR."/actions/$action.php";
if (file_exists($actionfile)) { if (file_exists($actionfile)) {
require_once($actionfile); include_once $actionfile;
$action_class = ucfirst($action)."Action"; $action_class = ucfirst($action)."Action";
$action_obj = new $action_class(); $action_obj = new $action_class();
@ -110,10 +131,10 @@ class ApiAction extends Action
call_user_func(array($action_obj, $this->api_method), $_REQUEST, $apidata); call_user_func(array($action_obj, $this->api_method), $_REQUEST, $apidata);
} else { } else {
$this->clientError("API method not found!", $code=404); $this->clientError("API method not found!", $code = 404);
} }
} else { } else {
$this->clientError("API method not found!", $code=404); $this->clientError("API method not found!", $code = 404);
} }
} }
@ -181,10 +202,11 @@ class ApiAction extends Action
$user_id = $this->arg('user_id'); $user_id = $this->arg('user_id');
$screen_name = $this->arg('screen_name'); $screen_name = $this->arg('screen_name');
if (empty($this->api_arg) && if (empty($this->api_arg)
empty($id) && && empty($id)
empty($user_id) && && empty($user_id)
empty($screen_name)) { && empty($screen_name)
) {
return true; return true;
} else { } else {
return false; return false;
@ -203,6 +225,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() function show_basic_auth_error()
{ {
header('HTTP/1.1 401 Unauthorized'); header('HTTP/1.1 401 Unauthorized');
@ -216,7 +265,7 @@ class ApiAction extends Action
$this->element('request', null, $_SERVER['REQUEST_URI']); $this->element('request', null, $_SERVER['REQUEST_URI']);
$this->elementEnd('hash'); $this->elementEnd('hash');
$this->endXML(); $this->endXML();
} else if ($this->content_type == 'json') { } else if ($this->content_type == 'json') {
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
$error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']);
print(json_encode($error_array)); 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.min.js');
$this->script('js/jcrop/jquery.Jcrop.go.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() function trySave()
{ {
$cur = common_current_user(); $cur = common_current_user();

View File

@ -71,6 +71,12 @@ class EmailsettingsAction extends AccountSettingsAction
return _('Manage how you get email from %%site.name%%.'); return _('Manage how you get email from %%site.name%%.');
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('email');
}
/** /**
* Content area of the page * Content area of the page
* *

View File

@ -41,7 +41,7 @@ require_once INSTALLDIR.'/lib/omb.php';
* *
* @category Action * @category Action
* @package Laconica * @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca> * @author Evan Prodromou <evan@status.net>
* @author Robin Millette <millette@controlyourself.ca> * @author Robin Millette <millette@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://laconi.ca/ * @link http://laconi.ca/

View File

@ -445,6 +445,8 @@ class GrouplogoAction extends GroupDesignAction
$this->script('js/jcrop/jquery.Jcrop.min.js'); $this->script('js/jcrop/jquery.Jcrop.min.js');
$this->script('js/jcrop/jquery.Jcrop.go.js'); $this->script('js/jcrop/jquery.Jcrop.go.js');
} }
$this->autofocus('avatarfile');
} }
function showLocalNav() function showLocalNav()

View File

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

View File

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

View File

@ -22,6 +22,7 @@
* @category Login * @category Login
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @author Sarven Capadisli <csarven@status.net>
* @copyright 2008-2009 StatusNet, Inc. * @copyright 2008-2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
@ -37,6 +38,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @category Personal * @category Personal
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @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 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
@ -158,6 +160,12 @@ class LoginAction extends Action
$this->showPage(); $this->showPage();
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('nickname');
}
/** /**
* Title of the page * Title of the page
* *

View File

@ -135,6 +135,12 @@ class NoticesearchAction extends SearchAction
$this->pagination($page > 1, $cnt > NOTICES_PER_PAGE, $this->pagination($page > 1, $cnt > NOTICES_PER_PAGE,
$page, 'noticesearch', array('q' => $q)); $page, 'noticesearch', array('q' => $q));
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('q');
}
} }
class SearchNoticeList extends NoticeList { class SearchNoticeList extends NoticeList {
@ -190,7 +196,7 @@ class SearchNoticeListItem extends NoticeListItem {
$result = preg_replace($pattern, '<strong>\\1</strong>', $text); $result = preg_replace($pattern, '<strong>\\1</strong>', $text);
/* Remove highlighting from inside links, loop incase multiple highlights in links */ /* Remove highlighting from inside links, loop incase multiple highlights in links */
$pattern = '/(href="[^"]*)<strong>('.$options.')<\/strong>([^"]*")/iU'; $pattern = '/(\w+="[^"]*)<strong>('.$options.')<\/strong>([^"]*")/iU';
do { do {
$result = preg_replace($pattern, '\\1\\2\\3', $result, -1, $count); $result = preg_replace($pattern, '\\1\\2\\3', $result, -1, $count);
} while ($count); } while ($count);

View File

@ -71,6 +71,12 @@ class OthersettingsAction extends AccountSettingsAction
return _('Manage various other options.'); return _('Manage various other options.');
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('urlshorteningservice');
}
/** /**
* Content area of the page * Content area of the page
* *

View File

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

View File

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

View File

@ -23,6 +23,7 @@
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @author Sarven Capadisli <csarven@status.net>
* @copyright 2008-2009 StatusNet, Inc. * @copyright 2008-2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
@ -41,6 +42,7 @@ require_once INSTALLDIR.'/lib/accountsettingsaction.php';
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @author Zach Copley <zach@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 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
@ -70,6 +72,12 @@ class ProfilesettingsAction extends AccountSettingsAction
'so people know more about you.'); 'so people know more about you.');
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('nickname');
}
/** /**
* Content area of the page * Content area of the page
* *

View File

@ -136,6 +136,12 @@ class RegisterAction extends Action
} }
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('nickname');
}
/** /**
* Try to register a user * 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%%.'); return _('You can receive SMS messages through email from %%site.name%%.');
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('sms');
}
/** /**
* Content area of the page * Content area of the page
* *

View File

@ -107,6 +107,12 @@ class SubscriptionsAction extends GalleryAction
array('nickname' => $this->user->nickname)); array('nickname' => $this->user->nickname));
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('tag');
}
function showEmptyListMessage() function showEmptyListMessage()
{ {
if (common_logged_in()) { if (common_logged_in()) {

View File

@ -99,6 +99,12 @@ class TwitapifriendshipsAction extends TwitterapiAction
$other = $this->get_profile($id); $other = $this->get_profile($id);
$user = $apidata['user']; // Alwyas the auth user $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 = new Subscription();
$sub->subscriber = $user->id; $sub->subscriber = $user->id;
$sub->subscribed = $other->id; $sub->subscribed = $other->id;

View File

@ -38,7 +38,7 @@ require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
* *
* @category Action * @category Action
* @package Laconica * @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca> * @author Evan Prodromou <evan@status.net>
* @author Robin Millette <millette@controlyourself.ca> * @author Robin Millette <millette@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://laconi.ca/ * @link http://laconi.ca/

4
classes/Config.php Executable file → Normal file
View File

@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
if (!defined('LACONICA')) { exit(1); } if (!defined('STATUSNET')) {
exit(1);
}
/** /**
* Table Definition for config * Table Definition for config

4
classes/Deleted_notice.php Executable file → Normal file
View File

@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
if (!defined('LACONICA')) { exit(1); } if (!defined('STATUSNET')) {
exit(1);
}
/** /**
* Table Definition for notice * Table Definition for notice

0
classes/statusnet.ini Executable file → Normal file
View File

View File

@ -21,6 +21,7 @@ VALUES
('identichat','identichat','http://identichat.prosody.im/', now()), ('identichat','identichat','http://identichat.prosody.im/', now()),
('IdentiFox','IdentiFox','http://www.bitbucket.org/uncryptic/identifox/', now()), ('IdentiFox','IdentiFox','http://www.bitbucket.org/uncryptic/identifox/', now()),
('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()), ('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()),
('Jiminy','Jiminy','http://code.google.com/p/jiminy/', now()),
('LaTwit','LaTwit','http://latwit.mac65.com/', now()), ('LaTwit','LaTwit','http://latwit.mac65.com/', now()),
('LiveTweeter', 'LiveTweeter', 'http://addons.songbirdnest.com/addon/1204', now()), ('LiveTweeter', 'LiveTweeter', 'http://addons.songbirdnest.com/addon/1204', now()),
('livetweeter', 'livetweeter', 'http://addons.songbirdnest.com/addon/1204', now()), ('livetweeter', 'livetweeter', 'http://addons.songbirdnest.com/addon/1204', now()),

View File

@ -199,7 +199,8 @@ class OAuthRequest {/*{{{*/
} else { } else {
// collect request parameters from query string (GET) and post-data (POST) if appropriate (note: POST vars have priority) // collect request parameters from query string (GET) and post-data (POST) if appropriate (note: POST vars have priority)
$req_parameters = $_GET; $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); $req_parameters = array_merge($req_parameters, $_POST);
} }

View File

@ -15,6 +15,21 @@
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * 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@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@status.net>
* @author Tom Adams <tom@holizz.com>
*/ */
define('INSTALLDIR', dirname(__FILE__)); define('INSTALLDIR', dirname(__FILE__));
@ -29,7 +44,8 @@ $action = null;
function getPath($req) function getPath($req)
{ {
if ((common_config('site', 'fancy') || !array_key_exists('PATH_INFO', $_SERVER)) if ((common_config('site', 'fancy') || !array_key_exists('PATH_INFO', $_SERVER))
&& array_key_exists('p', $req)) { && array_key_exists('p', $req)
) {
return $req['p']; return $req['p'];
} else if (array_key_exists('PATH_INFO', $_SERVER)) { } else if (array_key_exists('PATH_INFO', $_SERVER)) {
return $_SERVER['PATH_INFO']; return $_SERVER['PATH_INFO'];
@ -45,28 +61,35 @@ function handleError($error)
} }
$logmsg = "PEAR error: " . $error->getMessage(); $logmsg = "PEAR error: " . $error->getMessage();
if(common_config('site', 'logdebug')) { if (common_config('site', 'logdebug')) {
$logmsg .= " : ". $error->getDebugInfo(); $logmsg .= " : ". $error->getDebugInfo();
} }
common_log(LOG_ERR, $logmsg); common_log(LOG_ERR, $logmsg);
if(common_config('site', 'logdebug')) { if (common_config('site', 'logdebug')) {
$bt = $error->getBacktrace(); $bt = $error->getBacktrace();
foreach ($bt as $line) { foreach ($bt as $line) {
common_log(LOG_ERR, $line); common_log(LOG_ERR, $line);
} }
} }
if ($error instanceof DB_DataObject_Error || if ($error instanceof DB_DataObject_Error
$error instanceof DB_Error) { || $error instanceof DB_Error
$msg = sprintf(_('The database for %s isn\'t responding correctly, '. ) {
'so the site won\'t work properly. '. $msg = sprintf(
'The site admins probably know about the problem, '. _(
'but you can contact them at %s to make sure. '. 'The database for %s isn\'t responding correctly, '.
'Otherwise, wait a few minutes and try again.'), 'so the site won\'t work properly. '.
common_config('site', 'name'), 'The site admins probably know about the problem, '.
common_config('site', 'email')); '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 { } else {
$msg = _('An important error occured, probably related to email setup. '. $msg = _(
'Check logfiles for more info..'); 'An important error occured, probably related to email setup. '.
'Check logfiles for more info..'
);
} }
$dac = new DBErrorAction($msg, 500); $dac = new DBErrorAction($msg, 500);
@ -127,10 +150,11 @@ function main()
$_lighty_url = @parse_url($_lighty_url); $_lighty_url = @parse_url($_lighty_url);
if ($_lighty_url['path'] != '/index.php' && $_lighty_url['path'] != '/') { 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; $_SERVER['QUERY_STRING'] = 'p='.$_lighty_path;
if ($_lighty_url['query']) if ($_lighty_url['query']) {
$_SERVER['QUERY_STRING'] .= '&'.$_lighty_url['query']; $_SERVER['QUERY_STRING'] .= '&'.$_lighty_url['query'];
}
parse_str($_lighty_url['query'], $_lighty_query); parse_str($_lighty_url['query'], $_lighty_query);
foreach ($_lighty_query as $key => $val) { foreach ($_lighty_query as $key => $val) {
$_GET[$key] = $_REQUEST[$key] = $val; $_GET[$key] = $_REQUEST[$key] = $val;
@ -141,7 +165,7 @@ function main()
$_SERVER['REDIRECT_URL'] = preg_replace("/\?.+$/", "", $_SERVER['REQUEST_URI']); $_SERVER['REDIRECT_URL'] = preg_replace("/\?.+$/", "", $_SERVER['REQUEST_URI']);
// quick check for fancy URL auto-detection support in installer. // 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."); die("Fancy URL support detection succeeded. We suggest you enable this to get fancy (pretty) URLs.");
} }
global $user, $action; global $user, $action;
@ -149,8 +173,12 @@ function main()
Snapshot::check(); Snapshot::check();
if (!_have_config()) { if (!_have_config()) {
$msg = sprintf(_("No configuration file found. Try running ". $msg = sprintf(
"the installation program first.")); _(
"No configuration file found. Try running ".
"the installation program first."
)
);
$sac = new ServerErrorAction($msg); $sac = new ServerErrorAction($msg);
$sac->showPage(); $sac->showPage();
return; return;
@ -196,9 +224,10 @@ function main()
// If the site is private, and they're not on one of the "public" // If the site is private, and they're not on one of the "public"
// parts of the site, redirect to login // parts of the site, redirect to login
if (!$user && common_config('site', 'private') && if (!$user && common_config('site', 'private')
!isLoginAction($action) && && !isLoginAction($action)
!preg_match('/rss$/', $action)) { && !preg_match('/rss$/', $action)
) {
common_redirect(common_local_url('login')); common_redirect(common_local_url('login'));
return; return;
} }

View File

@ -15,6 +15,22 @@
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * 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@status.net>
* @author Robin Millette <millette@controlyourself.ca>
* @author Sarven Capadisli <csarven@status.net>
* @author Tom Adams <tom@holizz.com>
* @license GNU Affero General Public License http://www.gnu.org/licenses/
*/ */
define('INSTALLDIR', dirname(__FILE__)); define('INSTALLDIR', dirname(__FILE__));
@ -181,17 +197,34 @@ $external_libraries=array(
'check_class'=>'Validate' '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() function main()
{ {
if (!checkPrereqs()) if (!checkPrereqs()) {
{
return; return;
} }
if( $_GET['checklibs'] ){ if (!empty($_GET['checklibs'])) {
showLibs(); showLibs();
}else{ } else {
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
handlePost(); handlePost();
} else { } else {
@ -200,33 +233,44 @@ 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) 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; 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; 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 false;
} }
return true; return true;
} }
/**
* Check if all is ready for installation
*
* @return void
*/
function checkPrereqs() function checkPrereqs()
{ {
$pass = true; $pass = true;
if (file_exists(INSTALLDIR.'/config.php')) { if (file_exists(INSTALLDIR.'/config.php')) {
?><p class="error">Config file &quot;config.php&quot; already exists.</p> printf('<p class="error">Config file &quot;config.php&quot; already exists.</p>');
<?php
$pass = false; $pass = false;
} }
if (version_compare(PHP_VERSION, '5.2.3', '<')) { if (version_compare(PHP_VERSION, '5.2.3', '<')) {
?><p class="error">Require PHP version 5.2.3 or greater.</p><?php printf('<p class="error">Require PHP version 5.2.3 or greater.</p>');
$pass = false; $pass = false;
} }
$reqs = array('gd', 'curl', $reqs = array('gd', 'curl',
@ -234,37 +278,52 @@ function checkPrereqs()
foreach ($reqs as $req) { foreach ($reqs as $req) {
if (!checkExtension($req)) { if (!checkExtension($req)) {
?><p class="error">Cannot load required extension: <code><?php echo $req; ?></code></p><?php printf('<p class="error">Cannot load required extension: <code>%s</code></p>', $req);
$pass = false; $pass = false;
} }
} }
if (!checkExtension('pgsql') && !checkExtension('mysql')) { // Make sure we have at least one database module available
?><p class="error">Cannot find mysql or pgsql extension. You need one or the other: <code><?php echo $req; ?></code></p><?php global $dbModules;
$pass = false; $missingExtensions = array();
foreach ($dbModules as $type => $info) {
if (!checkExtension($info['check_module'])) {
$missingExtensions[] = $info['check_module'];
}
} }
if (!is_writable(INSTALLDIR)) { if (count($missingExtensions) == count($dbModules)) {
?><p class="error">Cannot write config file to: <code><?php echo INSTALLDIR; ?></code></p> $req = implode(', ', $missingExtensions);
<p>On your server, try this command: <code>chmod a+w <?php echo INSTALLDIR; ?></code> printf('<p class="error">Cannot find mysql or pgsql extension. You need one or the other.');
<?php $pass = false;
$pass = false; }
}
// Check the subdirs used for file uploads if (!is_writable(INSTALLDIR)) {
$fileSubdirs = array('avatar', 'background', 'file'); printf('<p class="error">Cannot write config file to: <code>%s</code></p>', INSTALLDIR);
foreach ($fileSubdirs as $fileSubdir) { printf('<p>On your server, try this command: <code>chmod a+w %s</code>', INSTALLDIR);
$fileFullPath = INSTALLDIR."/$fileSubdir/"; $pass = false;
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; // 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;
}
}
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) function checkExtension($name)
{ {
if (!extension_loaded($name)) { if (!extension_loaded($name)) {
@ -275,15 +334,20 @@ function checkExtension($name)
return true; return true;
} }
/**
* Show list of libraries
*
* @return void
*/
function showLibs() function showLibs()
{ {
global $external_libraries; global $external_libraries;
$present_libraries=array(); $present_libraries=array();
$absent_libraries=array(); $absent_libraries=array();
foreach($external_libraries as $external_library){ foreach ($external_libraries as $external_library) {
if(haveExternalLibrary($external_library)){ if (haveExternalLibrary($external_library)) {
$present_libraries[]=$external_library; $present_libraries[]=$external_library;
}else{ } else {
$absent_libraries[]=$external_library; $absent_libraries[]=$external_library;
} }
} }
@ -298,22 +362,21 @@ function showLibs()
<h2>Absent Libraries</h2> <h2>Absent Libraries</h2>
<ul id="absent_libraries"> <ul id="absent_libraries">
E_O_T; E_O_T;
foreach($absent_libraries as $library) foreach ($absent_libraries as $library) {
{
echo '<li>'; echo '<li>';
if($library['url']){ if (isset($library['url'])) {
echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>'; echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>';
}else{ } else {
echo htmlentities($library['name']); echo htmlentities($library['name']);
} }
echo '<ul>'; echo '<ul>';
if($library['deb']){ if (isset($library['deb'])) {
echo '<li class="deb package">deb: <a href="apt:' . urlencode($library['deb']) . '">' . htmlentities($library['deb']) . '</a></li>'; echo '<li class="deb package">deb: <a href="apt:' . urlencode($library['deb']) . '">' . htmlentities($library['deb']) . '</a></li>';
} }
if($library['rpm']){ if (isset($library['rpm'])) {
echo '<li class="rpm package">rpm: ' . htmlentities($library['rpm']) . '</li>'; echo '<li class="rpm package">rpm: ' . htmlentities($library['rpm']) . '</li>';
} }
if($library['pear']){ if (isset($library['pear'])) {
echo '<li class="pear package">pear: ' . htmlentities($library['pear']) . '</li>'; echo '<li class="pear package">pear: ' . htmlentities($library['pear']) . '</li>';
} }
echo '</ul>'; echo '</ul>';
@ -323,12 +386,11 @@ E_O_T;
<h2>Installed Libraries</h2> <h2>Installed Libraries</h2>
<ul id="present_libraries"> <ul id="present_libraries">
E_O_T; E_O_T;
foreach($present_libraries as $library) foreach ($present_libraries as $library) {
{
echo '<li>'; echo '<li>';
if($library['url']){ if ($library['url']) {
echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>'; echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>';
}else{ } else {
echo htmlentities($library['name']); echo htmlentities($library['name']);
} }
echo '</li>'; echo '</li>';
@ -340,6 +402,15 @@ E_O_T;
function showForm() 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 echo<<<E_O_T
</ul> </ul>
</dd> </dd>
@ -376,8 +447,7 @@ function showForm()
<li> <li>
<label for="dbtype">Type</label> <label for="dbtype">Type</label>
<input type="radio" name="dbtype" id="fancy-mysql" value="mysql" checked='checked' /> MySQL<br /> $dbRadios
<input type="radio" name="dbtype" id="dbtype-pgsql" value="pgsql" /> PostgreSQL<br />
<p class="form_guide">Database type</p> <p class="form_guide">Database type</p>
</li> </li>
@ -406,17 +476,16 @@ E_O_T;
function updateStatus($status, $error=false) function updateStatus($status, $error=false)
{ {
?> echo '<li';
<li <?php echo ($error) ? 'class="error"': ''; ?>><?php echo $status;?></li>
<?php if ($error) {
echo ' class="error"';
}
echo ">$status</li>";
} }
function handlePost() function handlePost()
{ {
?>
<?php
$host = $_POST['host']; $host = $_POST['host'];
$dbtype = $_POST['dbtype']; $dbtype = $_POST['dbtype'];
$database = $_POST['database']; $database = $_POST['database'];
@ -427,55 +496,41 @@ function handlePost()
$server = $_SERVER['HTTP_HOST']; $server = $_SERVER['HTTP_HOST'];
$path = substr(dirname($_SERVER['PHP_SELF']), 1); $path = substr(dirname($_SERVER['PHP_SELF']), 1);
?> echo <<<STR
<dl class="system_notice"> <dl class="system_notice">
<dt>Page notice</dt> <dt>Page notice</dt>
<dd> <dd>
<ul> <ul>
<?php STR;
$fail = false; $fail = false;
if (empty($host)) { if (empty($host)) {
updateStatus("No hostname specified.", true); updateStatus("No hostname specified.", true);
$fail = true; $fail = true;
} }
if (empty($database)) { if (empty($database)) {
updateStatus("No database specified.", true); updateStatus("No database specified.", true);
$fail = true; $fail = true;
} }
if (empty($username)) { if (empty($username)) {
updateStatus("No username specified.", true); updateStatus("No username specified.", true);
$fail = true; $fail = true;
} }
// if (empty($password)) {
// updateStatus("No password specified.", true);
// $fail = true;
// }
if (empty($sitename)) { if (empty($sitename)) {
updateStatus("No sitename specified.", true); updateStatus("No sitename specified.", true);
$fail = true; $fail = true;
} }
if($fail){ if ($fail) {
showForm(); showForm();
return; return;
} }
// FIXME: use PEAR::DB or PDO instead of our own switch global $dbModules;
$db = call_user_func($dbModules[$dbtype]['installer'], $host, $database, $username, $password);
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:
}
if (!$db) { if (!$db) {
// database connection failed, do not move on to create config file. // database connection failed, do not move on to create config file.
@ -498,112 +553,110 @@ function handlePost()
updateStatus("StatusNet has been installed at $link"); updateStatus("StatusNet has been installed at $link");
updateStatus("You can visit your <a href='$link'>new StatusNet site</a>."); updateStatus("You can visit your <a href='$link'>new StatusNet site</a>.");
?>
<?php
} }
function pgsql_db_installer($host, $database, $username, $password) { function Pgsql_Db_installer($host, $database, $username, $password)
$connstring = "dbname=$database host=$host user=$username"; {
$connstring = "dbname=$database host=$host user=$username";
//No password would mean trust authentication used. //No password would mean trust authentication used.
if (!empty($password)) { if (!empty($password)) {
$connstring .= " password=$password"; $connstring .= " password=$password";
} }
updateStatus("Starting installation..."); updateStatus("Starting installation...");
updateStatus("Checking database..."); updateStatus("Checking database...");
$conn = pg_connect($connstring); $conn = pg_connect($connstring);
if ($conn ===false) { if ($conn ===false) {
updateStatus("Failed to connect to database: $connstring"); updateStatus("Failed to connect to database: $connstring");
showForm(); showForm();
return false; return false;
} }
//ensure database encoding is UTF8 //ensure database encoding is UTF8
$record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding')); $record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
if ($record->server_encoding != 'UTF8') { if ($record->server_encoding != 'UTF8') {
updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding)); updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
showForm(); showForm();
return false; return false;
} }
updateStatus("Running database script..."); updateStatus("Running database script...");
//wrap in transaction; //wrap in transaction;
pg_query($conn, 'BEGIN'); pg_query($conn, 'BEGIN');
$res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql'); $res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
if ($res === false) { if ($res === false) {
updateStatus("Can't run database script.", true); updateStatus("Can't run database script.", true);
showForm(); showForm();
return false; return false;
} }
foreach (array('sms_carrier' => 'SMS carrier', foreach (array('sms_carrier' => 'SMS carrier',
'notice_source' => 'notice source', 'notice_source' => 'notice source',
'foreign_services' => 'foreign service') 'foreign_services' => 'foreign service')
as $scr => $name) { as $scr => $name) {
updateStatus(sprintf("Adding %s data to database...", $name)); updateStatus(sprintf("Adding %s data to database...", $name));
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql'); $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
if ($res === false) { if ($res === false) {
updateStatus(sprintf("Can't run %d script.", $name), true); updateStatus(sprintf("Can't run %d script.", $name), true);
showForm(); showForm();
return false; return false;
} }
} }
pg_query($conn, 'COMMIT'); pg_query($conn, 'COMMIT');
if (empty($password)) { if (empty($password)) {
$sqlUrl = "pgsql://$username@$host/$database"; $sqlUrl = "pgsql://$username@$host/$database";
} } else {
else { $sqlUrl = "pgsql://$username:$password@$host/$database";
$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) { function Mysql_Db_installer($host, $database, $username, $password)
updateStatus("Starting installation..."); {
updateStatus("Checking database..."); updateStatus("Starting installation...");
updateStatus("Checking database...");
$conn = mysql_connect($host, $username, $password); $conn = mysql_connect($host, $username, $password);
if (!$conn) { if (!$conn) {
updateStatus("Can't connect to server '$host' as '$username'.", true); updateStatus("Can't connect to server '$host' as '$username'.", true);
showForm(); showForm();
return false; return false;
} }
updateStatus("Changing to database..."); updateStatus("Changing to database...");
$res = mysql_select_db($database, $conn); $res = mysql_select_db($database, $conn);
if (!$res) { if (!$res) {
updateStatus("Can't change to database.", true); updateStatus("Can't change to database.", true);
showForm(); showForm();
return false; return false;
} }
updateStatus("Running database script..."); updateStatus("Running database script...");
$res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn); $res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
if ($res === false) { if ($res === false) {
updateStatus("Can't run database script.", true); updateStatus("Can't run database script.", true);
showForm(); showForm();
return false; return false;
} }
foreach (array('sms_carrier' => 'SMS carrier', foreach (array('sms_carrier' => 'SMS carrier',
'notice_source' => 'notice source', 'notice_source' => 'notice source',
'foreign_services' => 'foreign service') 'foreign_services' => 'foreign service')
as $scr => $name) { as $scr => $name) {
updateStatus(sprintf("Adding %s data to database...", $name)); updateStatus(sprintf("Adding %s data to database...", $name));
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn); $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
if ($res === false) { if ($res === false) {
updateStatus(sprintf("Can't run %d script.", $name), true); updateStatus(sprintf("Can't run %d script.", $name), true);
showForm(); showForm();
return false; return false;
} }
} }
$sqlUrl = "mysqli://$username:$password@$host/$database"; $sqlUrl = "mysqli://$username:$password@$host/$database";
$db = array('type' => 'mysql', 'database' => $sqlUrl); $db = array('type' => 'mysql', 'database' => $sqlUrl);
return $db; return $db;
} }
function writeConf($sitename, $server, $path, $fancy, $db) function writeConf($sitename, $server, $path, $fancy, $db)
@ -634,7 +687,16 @@ function writeConf($sitename, $server, $path, $fancy, $db)
return $res; 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)); $sql = trim(file_get_contents($filename));
$stmts = explode(';', $sql); $stmts = explode(';', $sql);
@ -645,7 +707,7 @@ function runDbScript($filename, $conn, $type = 'mysql')
} }
// FIXME: use PEAR::DB or PDO instead of our own switch // FIXME: use PEAR::DB or PDO instead of our own switch
switch ($type) { switch ($type) {
case 'mysql': case 'mysqli':
$res = mysql_query($stmt, $conn); $res = mysql_query($stmt, $conn);
if ($res === false) { if ($res === false) {
$error = mysql_error(); $error = mysql_error();

View File

@ -284,6 +284,8 @@ $config =
array('contentlimit' => null), array('contentlimit' => null),
'message' => 'message' =>
array('contentlimit' => null), array('contentlimit' => null),
'http' =>
array('client' => 'curl'), // XXX: should this be the default?
); );
$config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options');

179
lib/curlclient.php Normal file
View File

@ -0,0 +1,179 @@
n<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Utility class for wrapping Curl
*
* 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 HTTP
* @package StatusNet
* @author Evan Prodromou <evan@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')) {
exit(1);
}
define(CURLCLIENT_VERSION, "0.1");
/**
* Wrapper for Curl
*
* Makes Curl HTTP client calls within our HTTPClient framework
*
* @category HTTP
* @package StatusNet
* @author Evan Prodromou <evan@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 CurlClient extends HTTPClient
{
function __construct()
{
}
function head($url, $headers=null)
{
$ch = curl_init($url);
$this->setup($ch);
curl_setopt_array($ch,
array(CURLOPT_NOBODY => true));
if (!is_null($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$result = curl_exec($ch);
curl_close($ch);
return $this->parseResults($result);
}
function get($url, $headers=null)
{
$ch = curl_init($url);
$this->setup($ch);
if (!is_null($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$result = curl_exec($ch);
curl_close($ch);
return $this->parseResults($result);
}
function post($url, $headers=null, $body=null)
{
$ch = curl_init($url);
$this->setup($ch);
curl_setopt($ch, CURLOPT_POST, true);
if (!is_null($body)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
if (!is_null($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$result = curl_exec($ch);
curl_close($ch);
return $this->parseResults($result);
}
function setup($ch)
{
curl_setopt_array($ch,
array(CURLOPT_USERAGENT => $this->userAgent(),
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true));
}
function userAgent()
{
$version = curl_version();
return parent::userAgent() . " CurlClient/".CURLCLIENT_VERSION . " cURL/" . $version['version'];
}
function parseResults($results)
{
$resp = new HTTPResponse();
$lines = explode("\r\n", $results);
if (preg_match("#^HTTP/1.[01] (\d\d\d) .+$#", $lines[0], $match)) {
$resp->code = $match[1];
} else {
throw Exception("Bad format: initial line is not HTTP status line");
}
$lastk = null;
for ($i = 1; $i < count($lines); $i++) {
$l =& $lines[$i];
if (mb_strlen($l) == 0) {
$resp->body = implode("\r\n", array_slice($lines, $i + 1));
break;
}
if (preg_match("#^(\S+):\s+(.*)$#", $l, $match)) {
$k = $match[1];
$v = $match[2];
if (array_key_exists($k, $resp->headers)) {
if (is_array($resp->headers[$k])) {
$resp->headers[$k][] = $v;
} else {
$resp->headers[$k] = array($resp->headers[$k], $v);
}
} else {
$resp->headers[$k] = $v;
}
$lastk = $k;
} else if (preg_match("#^\s+(.*)$#", $l, $match)) {
// continuation line
if (is_null($lastk)) {
throw Exception("Bad format: initial whitespace in headers");
}
$h =& $resp->headers[$lastk];
if (is_array($h)) {
$n = count($h);
$h[$n-1] .= $match[1];
} else {
$h .= $match[1];
}
}
}
return $resp;
}
}

View File

@ -327,6 +327,8 @@ class DesignSettingsAction extends AccountSettingsAction
$this->script('js/farbtastic/farbtastic.js'); $this->script('js/farbtastic/farbtastic.js');
$this->script('js/farbtastic/farbtastic.go.js'); $this->script('js/farbtastic/farbtastic.go.js');
$this->script('js/userdesign.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->elementEnd('li');
$this->elementStart('li', array('id'=>'filter_tags_item')); $this->elementStart('li', array('id'=>'filter_tags_item'));
$this->elementStart('form', array('name' => 'bytag', $this->elementStart('form', array('name' => 'bytag',
'id' => 'bytag', 'id' => 'form_filter_bytag',
'action' => common_path('?action=' . $this->trimmed('action')), 'action' => common_path('?action=' . $this->trimmed('action')),
'method' => 'post')); 'method' => 'post'));
$this->elementStart('fieldset');
$this->element('legend', null, _('Select tag to filter'));
$this->dropdown('tag', _('Tag'), $content, $this->dropdown('tag', _('Tag'), $content,
_('Choose a tag to narrow list'), false, $tag); _('Choose a tag to narrow list'), false, $tag);
$this->hidden('nickname', $this->user->nickname); $this->hidden('nickname', $this->user->nickname);
$this->submit('submit', _('Go')); $this->submit('submit', _('Go'));
$this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');

View File

@ -412,4 +412,29 @@ class HTMLOutputter extends XMLOutputter
$this->element('p', 'form_guide', $instructions); $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');
}
} }

122
lib/httpclient.php Normal file
View File

@ -0,0 +1,122 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Utility for doing HTTP-related things
*
* 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 Action
* @package StatusNet
* @author Evan Prodromou <evan@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')) {
exit(1);
}
/**
* Useful structure for HTTP responses
*
* We make HTTP calls in several places, and we have several different
* ways of doing them. This class hides the specifics of what underlying
* library (curl or PHP-HTTP or whatever) that's used.
*
* @category HTTP
* @package StatusNet
* @author Evan Prodromou <evan@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 HTTPResponse
{
public $code = null;
public $headers = null;
public $body = null;
}
/**
* Utility class for doing HTTP client stuff
*
* We make HTTP calls in several places, and we have several different
* ways of doing them. This class hides the specifics of what underlying
* library (curl or PHP-HTTP or whatever) that's used.
*
* @category HTTP
* @package StatusNet
* @author Evan Prodromou <evan@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 HTTPClient
{
static $_client = null;
static function start()
{
if (!is_null(self::$_client)) {
return self::$_client;
}
$type = common_config('http', 'client');
switch ($type) {
case 'curl':
self::$_client = new CurlClient();
break;
default:
throw new Exception("Unknown HTTP client type '$type'");
break;
}
return self::$_client;
}
function head($url, $headers)
{
throw new Exception("HEAD method unimplemented");
}
function get($url, $headers)
{
throw new Exception("GET method unimplemented");
}
function post($url, $headers, $body)
{
throw new Exception("POST method unimplemented");
}
function put($url, $headers, $body)
{
throw new Exception("PUT method unimplemented");
}
function delete($url, $headers)
{
throw new Exception("DELETE method unimplemented");
}
function userAgent()
{
return "StatusNet/".STATUSNET_VERSION." (".STATUSNET_CODENAME.")";
}
}

View File

@ -59,7 +59,7 @@ function common_init_language()
textdomain("statusnet"); textdomain("statusnet");
setlocale(LC_CTYPE, 'C'); setlocale(LC_CTYPE, 'C');
if(!$locale_set) { 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__);
} }
} }
@ -432,7 +432,7 @@ 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 '|(?:(?: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 '|(?:'. //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 ')|(?:'. //DNS
'(?:[\pN\pL\-\_\+\%\~]+(?:\:[\pN\pL\-\_\+\%\~]+)?\@)?'. //user:pass@ '(?:[\pN\pL\-\_\+\%\~]+(?:\:[\pN\pL\-\_\+\%\~]+)?\@)?'. //user:pass@
'[\pN\pL\-\_]+(?:\.[\pN\pL\-\_]+)*\.'. '[\pN\pL\-\_]+(?:\.[\pN\pL\-\_]+)*\.'.
@ -442,13 +442,13 @@ function common_replace_urls_callback($text, $callback, $notice_id = null) {
')'. ')'.
'(?:'. '(?:'.
'(?:\:\d+)?'. //:port '(?:\:\d+)?'. //:port
'(?:/[\pN\pL$\[\]\,\!\(\)\.\:\-\_\+\/\=\&\;\%\~]*)?'. // /path '(?:/[\pN\pL$\[\]\,\!\(\)\.\:\-\_\+\/\=\&\;\%\~\*\$\+\'\"]*)?'. // /path
'(?:\?[\pN\pL\$\[\]\,\!\(\)\.\:\-\_\+\/\=\&\;\%\~\/]*)?'. // ?query string '(?:\?[\pN\pL\$\[\]\,\!\(\)\.\:\-\_\+\/\=\&\;\%\~\*\$\+\'\"\/]*)?'. // ?query string
'(?:\#[\pN\pL$\[\]\,\!\(\)\.\:\-\_\+\/\=\&\;\%\~\/\?\#]*)?'. // #fragment '(?:\#[\pN\pL$\[\]\,\!\(\)\.\:\-\_\+\/\=\&\;\%\~\*\$\+\'\"\/\?\#]*)?'. // #fragment
')(?<![\?\.\,\#\,])'. ')(?<![\?\.\,\#\,])'.
')'. ')'.
'#ixu'; '#ixu';
preg_match_all($regex,$text,$matches); //preg_match_all($regex,$text,$matches);
//print_r($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);
} }
@ -1383,6 +1383,9 @@ function common_shorten_url($long_url)
$short_url_service = $reflectionObj->newInstanceArgs($_shorteners[$svc]['callInfo'][1]); $short_url_service = $reflectionObj->newInstanceArgs($_shorteners[$svc]['callInfo'][1]);
$short_url = $short_url_service->shorten($long_url); $short_url = $short_url_service->shorten($long_url);
if(substr($short_url,0,7)=='http://'){
$short_url = substr($short_url,7);
}
return $short_url; return $short_url;
} }

View File

@ -75,6 +75,8 @@ class LinkbackPlugin extends Plugin
function linkbackUrl($url) function linkbackUrl($url)
{ {
common_log(LOG_DEBUG,"Attempting linkback for " . $url);
$orig = $url; $orig = $url;
$url = htmlspecialchars_decode($orig); $url = htmlspecialchars_decode($orig);
$scheme = parse_url($url, PHP_URL_SCHEME); $scheme = parse_url($url, PHP_URL_SCHEME);
@ -134,15 +136,20 @@ class LinkbackPlugin extends Plugin
"User-Agent: " . $this->userAgent(), "User-Agent: " . $this->userAgent(),
'content' => $request))); 'content' => $request)));
$file = file_get_contents($endpoint, false, $context); $file = file_get_contents($endpoint, false, $context);
$response = xmlrpc_decode($file); if (!$file) {
if (xmlrpc_is_fault($response)) {
common_log(LOG_WARNING, 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): ". "Pingback error for '$url' ($endpoint): ".
"$response[faultString] ($response[faultCode])"); "$response[faultString] ($response[faultCode])");
} else { } else {
common_log(LOG_INFO, common_log(LOG_INFO,
"Pingback success for '$url' ($endpoint): ". "Pingback success for '$url' ($endpoint): ".
"'$response'"); "'$response'");
}
} }
} }

View File

@ -1,6 +1,6 @@
<?php <?php
/** /**
* Laconica, the distributed open-source microblogging tool * StatusNet, the distributed open-source microblogging tool
* *
* PHP version 5 * PHP version 5
* *
@ -18,14 +18,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
* @category Plugin * @category Plugin
* @package Laconica * @package StatusNet
* @author Evan Prodromou <evan@controlyourself.ca> * @author Evan Prodromou <evan@status.net>
* @copyright 2009 Control Yourself, Inc. * @copyright 2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/ * @link http://status.net/
*/ */
if (!defined('LACONICA')) { if (!defined('STATUSNET')) {
exit(1); exit(1);
} }
@ -36,10 +36,10 @@ if (!defined('LACONICA')) {
* and identity system. * and identity system.
* *
* @category Plugin * @category Plugin
* @package Laconica * @package StatusNet
* @author Evan Prodromou <evan@controlyourself.ca> * @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/ * @link http://status.net/
* @link http://openid.net/ * @link http://openid.net/
*/ */

View File

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

View File

@ -72,6 +72,12 @@ class OpenidsettingsAction extends AccountSettingsAction
' Manage your associated OpenIDs from here.'); ' Manage your associated OpenIDs from here.');
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('openid_url');
}
/** /**
* Show the form for OpenID management * Show the form for OpenID management
* *

View File

@ -25,6 +25,8 @@ class URLDetectionTest extends PHPUnit_Framework_TestCase
static public function provider() static public function provider()
{ {
return array( return array(
array('not a link :: no way',
'not a link :: no way'),
array('http://127.0.0.1', array('http://127.0.0.1',
'<a href="http://127.0.0.1/" rel="external">http://127.0.0.1</a>'), '<a href="http://127.0.0.1/" rel="external">http://127.0.0.1</a>'),
array('127.0.0.1', array('127.0.0.1',
@ -35,6 +37,22 @@ class URLDetectionTest extends PHPUnit_Framework_TestCase
'<a href="http://127.0.0.1/Name:test.php" rel="external">127.0.0.1/Name:test.php</a>'), '<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', array('127.0.0.1/~test',
'<a href="http://127.0.0.1/~test" rel="external">127.0.0.1/~test</a>'), '<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', 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>'), '<a href="http://127.0.0.1/test%20stuff" rel="external">127.0.0.1/test%20stuff</a>'),
array('http://[::1]:99/test.php', array('http://[::1]:99/test.php',

View File

@ -156,7 +156,8 @@ font-weight:bold;
#form_notice_delete legend, #form_notice_delete legend,
#form_password_recover legend, #form_password_recover legend,
#form_password_change legend, #form_password_change legend,
.form_entity_block legend { .form_entity_block legend,
#form_filter_bytag legend {
display:none; display:none;
} }
@ -510,6 +511,7 @@ margin-top:7px;
margin-bottom:7px; margin-bottom:7px;
margin-left:18px; margin-left:18px;
float:left; float:left;
max-width:322px;
} }
#form_notice .error, #form_notice .error,
#form_notice .success { #form_notice .success {
@ -1049,36 +1051,37 @@ display:none;
#filter_tags ul { #filter_tags ul {
list-style-type:none; list-style-type:none;
} }
#filter_tags ul li { #filter_tags li {
float:left; float:left;
margin-left:7px; margin-left:7px;
padding-left:7px; padding-left:7px;
border-left-width:1px; border-left-width:1px;
border-left-style:solid; border-left-style:solid;
} }
#filter_tags ul li.child_1 { #filter_tags #filter_tags_all {
margin-left:0; margin-left:0;
border-left:0; border-left:0;
padding-left:0; padding-left:0;
} }
#filter_tags ul li#filter_tags_all a { #filter_tags_all a {
font-weight:bold; font-weight:bold;
margin-top:7px; margin-top:7px;
float:left; float:left;
} }
#filter_tags ul li#filter_tags_item label { #filter_tags_item label {
margin-right:7px; margin-right:7px;
} }
#filter_tags ul li#filter_tags_item label, #filter_tags_item label,
#filter_tags ul li#filter_tags_item select { #filter_tags_item select {
display:inline;
}
#filter_tags ul li#filter_tags_item p {
float:left; float:left;
}
#filter_tags_item p {
float:left;
clear:both;
margin-left:38px; margin-left:38px;
} }
#filter_tags ul li#filter_tags_item input { #filter_tags_item .submit {
position:relative; position:relative;
top:3px; top:3px;
left:3px; left:3px;

View File

@ -849,6 +849,10 @@ float:left;
font-size:1.025em; font-size:1.025em;
} }
.notice div.entry-content .timestamp {
display:inline-block;
}
.notice div.entry-content dl, .notice div.entry-content dl,
.notice div.entry-content dt, .notice div.entry-content dt,
.notice div.entry-content dd { .notice div.entry-content dd {
@ -866,15 +870,12 @@ display:inline-block;
text-transform:lowercase; text-transform:lowercase;
} }
.notice-options { .notice-options {
padding-left:2%;
float:left;
width:50%;
position:relative; position:relative;
font-size:0.95em; font-size:0.95em;
width:12.5%; width:90px;
float:right; float:right;
margin-right:11px;
} }
.notice-options a { .notice-options a {
@ -897,38 +898,28 @@ left:29px;
.notice-options .notice_delete { .notice-options .notice_delete {
right:0; right:0;
} }
.notice-options .notice_reply dt {
display:none;
}
.notice-options input, .notice-options input,
.notice-options a { .notice-options a {
text-indent:-9999px; text-indent:-9999px;
outline:none; outline:none;
} }
.notice-options .notice_reply a,
.notice-options input.submit { .notice-options input.submit {
display:block; display:block;
border:0; border:0;
} }
.notice-options .notice_reply a, .notice-options .notice_reply,
.notice-options .notice_delete a { .notice-options .notice_delete {
text-decoration:none; text-decoration:none;
padding-left:16px; padding-left:16px;
} }
.notice-options form input.submit { .notice-options form input.submit {
width:16px; width:16px;
padding:2px 0; padding:2px 0;
} }
.notice-options .notice_delete dt,
.notice-options .form_favor legend, .notice-options .form_favor legend,
.notice-options .form_disfavor legend { .notice-options .form_disfavor legend {
display:none; display:none;
} }
.notice-options .notice_delete fieldset,
.notice-options .form_favor fieldset, .notice-options .form_favor fieldset,
.notice-options .form_disfavor fieldset { .notice-options .form_disfavor fieldset {
border:0; border:0;

View File

@ -30,10 +30,10 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
} }
input, textarea, select, input, textarea, select,
.entity_remote_subscribe { .entity_remote_subscribe {
border-color:#aaa; border-color:#AAAAAA;
} }
#filter_tags ul li { #filter_tags ul li {
border-color:#ddd; border-color:#DDDDDD;
} }
.form_settings input.form_action-primary { .form_settings input.form_action-primary {
@ -50,11 +50,14 @@ background-color:#9BB43E;
input:focus, textarea:focus, select:focus, input:focus, textarea:focus, select:focus,
#form_notice.warning #notice_data-text { #form_notice.warning #notice_data-text {
border-color:#9BB43E; 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, input.submit,
.entity_remote_subscribe, .entity_remote_subscribe,
#site_nav_local_views a { #site_nav_local_views a {
color:#fff; color:#FFFFFF;
} }
a, a,
@ -62,10 +65,13 @@ a,
div.notice-options input, div.notice-options input,
.form_user_block input.submit, .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,
.entity_send-a-message a, .entity_send-a-message a,
.form_user_nudge input.submit, .form_user_nudge input.submit,
.entity_nudge p, .entity_nudge p,
.form_settings input.form_action-primary { .form_settings input.form_action-primary,
.form_make_admin input.submit {
color:#002E6E; color:#002E6E;
} }
@ -82,13 +88,6 @@ border-top-color:#CEE1E9;
border-top-color:#87B4C8; 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 { .aside .section {
background-color:#F1F5F8; background-color:#F1F5F8;
background-position:100% 0; background-position:100% 0;
@ -97,10 +96,10 @@ background-repeat:no-repeat;
} }
#notice_text-count { #notice_text-count {
color:#333; color:#333333;
} }
#form_notice.warning #notice_text-count { #form_notice.warning #notice_text-count {
color:#000; color:#000000;
} }
#form_notice label[for=notice_data-attach] { #form_notice label[for=notice_data-attach] {
background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; 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; opacity:0;
} }
#form_notice.processing #notice_action-submit { #wrap form.processing input.submit {
background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
cursor:wait; cursor:wait;
text-indent:-9999px; 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, #content,
#site_nav_local_views a, #site_nav_local_views a,
.aside .section { .aside .section {
border-color:#fff; border-color:#FFFFFF;
} }
#content, #content,
#site_nav_local_views .current a { #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 { #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 { #site_nav_local_views a:hover {
background-color:rgba(255, 255, 255, 0.7); 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 { .error {
background-color:#F7E8E8; background-color:#F7E8E8;
@ -140,10 +154,7 @@ background-color:#EFF3DC;
} }
#anon_notice { #anon_notice {
color:#fff; color:#FFFFFF;
}
#showstream #anon_notice {
} }
#export_data li a { #export_data li a {
@ -165,7 +176,10 @@ background-image:url(../../base/images/icons/icon_foaf.gif);
.form_user_nudge input.submit, .form_user_nudge input.submit,
.form_user_block input.submit, .form_user_block input.submit,
.form_user_unblock 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-position: 0 40%;
background-repeat: no-repeat; background-repeat: no-repeat;
background-color:transparent; background-color:transparent;
@ -175,7 +189,7 @@ background-color:transparent;
.form_user_subscribe input.submit, .form_user_subscribe input.submit,
.form_user_unsubscribe input.submit { .form_user_unsubscribe input.submit {
background-color:#9BB43E; background-color:#9BB43E;
color:#fff; color:#FFFFFF;
} }
.form_user_unsubscribe input.submit, .form_user_unsubscribe input.submit,
.form_group_leave 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); background-image:url(../../base/images/icons/twotone/green/mail.gif);
} }
.form_user_block input.submit, .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); 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 */
.notices li.over { .notice .attachment {
background-color:#fcfcfc; background:transparent url(../../base/images/icons/twotone/green/clip-02.gif) no-repeat 0 45%;
} }
#attachments .attachment {
.notice-options .notice_reply a, background:none;
.notice-options form input.submit {
background-color:transparent;
} }
.notice-options .notice_reply a { .notice-options .notice_reply {
background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%;
} }
.notice-options form.form_favor input.submit { .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 { .notice-options form.form_disfavor input.submit {
background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; 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%; 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 { .notices div.notice-options {
opacity:0.4; opacity:0.4;
} }
.notices li.hover div.entry-content, .notices li:hover div.entry-content,
.notices li.hover div.notice-options { .notices li:hover div.notice-options {
opacity:1; opacity:1;
} }
div.entry-content {
color:#333;
}
div.notice-options a, div.notice-options a,
div.notice-options input { div.notice-options input {
font-family:sans-serif; font-family:sans-serif;
} }
.notices li.hover { #content .notices li:hover {
background-color:#fcfcfc; 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 */ /*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; 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%; background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
cursor:wait; cursor:wait;
text-indent:-9999px; text-indent:-9999px;
outline:none;
} }
#content { #content {
@ -223,10 +224,6 @@ background:transparent url(../../base/images/icons/twotone/green/favourite.gif)
.notice-options form.form_disfavor input.submit { .notice-options form.form_disfavor input.submit {
background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; 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 { .notice-options .notice_delete {
background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; 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; 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%; background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
cursor:wait; cursor:wait;
text-indent:-9999px; text-indent:-9999px;
outline:none;
} }
#content { #content {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -1,7 +1,7 @@
/** Howto: create a statusnet theme /** Howto: create a statusnet theme
* *
* @package StatusNet * @package StatusNet
* @author Sarven Capadisli <csarven@controlyourself.ca> * @author Sarven Capadisli <csarven@status.net>
* @copyright 2009 Control Yourself, Inc. * @copyright 2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/ * @link http://laconi.ca/