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
/*
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2008, 2009, StatusNet, Inc.
*
@ -15,9 +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 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/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);
}
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 +89,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 +135,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 +154,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,27 @@
*
* 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@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
{
@ -27,6 +45,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 +55,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 +64,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 +97,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 +115,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 +131,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);
}
}
@ -181,10 +202,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;
@ -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()
{
header('HTTP/1.1 401 Unauthorized');
@ -216,7 +265,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

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

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

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

@ -38,7 +38,7 @@ require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
*
* @category Action
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @author Evan Prodromou <evan@status.net>
* @author Robin Millette <millette@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @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/>.
*/
if (!defined('LACONICA')) { exit(1); }
if (!defined('STATUSNET')) {
exit(1);
}
/**
* 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/>.
*/
if (!defined('LACONICA')) { exit(1); }
if (!defined('STATUSNET')) {
exit(1);
}
/**
* 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()),
('IdentiFox','IdentiFox','http://www.bitbucket.org/uncryptic/identifox/', now()),
('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()),
('Jiminy','Jiminy','http://code.google.com/p/jiminy/', 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()),

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

@ -15,6 +15,21 @@
*
* 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@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__));
@ -29,7 +44,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 +61,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 +150,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 +165,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 +173,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 +224,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

@ -15,6 +15,22 @@
*
* 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@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__));
@ -181,17 +197,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 (!empty($_GET['checklibs'])) {
showLibs();
}else{
} else {
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
handlePost();
} 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)
{
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',
@ -234,37 +278,52 @@ function checkPrereqs()
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;
}
}
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;
// 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 (!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;
}
if (count($missingExtensions) == count($dbModules)) {
$req = implode(', ', $missingExtensions);
printf('<p class="error">Cannot find mysql or pgsql extension. You need one or the other.');
$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;
}
}
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;
}
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)
{
if (!extension_loaded($name)) {
@ -275,15 +334,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 +362,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 (isset($library['url'])) {
echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>';
}else{
} else {
echo htmlentities($library['name']);
}
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>';
}
if($library['rpm']){
if (isset($library['rpm'])) {
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 '</ul>';
@ -323,12 +386,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 +402,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 +447,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 +476,16 @@ E_O_T;
function updateStatus($status, $error=false)
{
?>
<li <?php echo ($error) ? 'class="error"': ''; ?>><?php echo $status;?></li>
echo '<li';
<?php
if ($error) {
echo ' class="error"';
}
echo ">$status</li>";
}
function handlePost()
{
?>
<?php
$host = $_POST['host'];
$dbtype = $_POST['dbtype'];
$database = $_POST['database'];
@ -427,55 +496,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 +553,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)
@ -634,7 +687,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 +707,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

@ -284,6 +284,8 @@ $config =
array('contentlimit' => null),
'message' =>
array('contentlimit' => null),
'http' =>
array('client' => 'curl'), // XXX: should this be the default?
);
$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.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');
}
}

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");
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__);
}
}
@ -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
'|(?:'. //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\-\_]+)*\.'.
@ -442,13 +442,13 @@ 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);
}
@ -1383,6 +1383,9 @@ function common_shorten_url($long_url)
$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

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

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

@ -25,6 +25,8 @@ 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',
@ -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>'),
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',

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

View File

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