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

This commit is contained in:
Brion Vibber 2009-09-20 21:13:00 -07:00
commit f7f8ac87a7
19 changed files with 739 additions and 389 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
{
@ -37,7 +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();
$this->basic_auth_process_header();
if (isset($argument)) {
$cmdext = explode('.', $argument);
@ -46,7 +64,7 @@ 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]);
@ -55,10 +73,10 @@ class ApiAction extends Action
if ($this->requires_auth()) {
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 = $this->auth_user;
@ -69,7 +87,7 @@ class ApiAction extends Action
$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.");
@ -84,7 +102,7 @@ class ApiAction extends Action
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();
@ -97,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();
@ -113,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);
}
}
@ -184,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;
@ -208,35 +227,29 @@ 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['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
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);
$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;
}
// 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()
@ -252,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

@ -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/
@ -143,67 +143,4 @@ class FinishremotesubscribeAction extends Action
$user->nickname)),
303);
}
function add_avatar($profile, $url)
{
$temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
copy($url, $temp_filename);
$imagefile = new ImageFile($profile->id, $temp_filename);
$filename = Avatar::filename($profile->id,
image_type_to_extension($imagefile->type),
null,
common_timestamp());
rename($temp_filename, Avatar::path($filename));
return $profile->setOriginal($filename);
}
function access_token($omb)
{
common_debug('starting request for access token', __FILE__);
$con = omb_oauth_consumer();
$tok = new OAuthToken($omb['token'], $omb['secret']);
common_debug('using request token "'.$tok.'"', __FILE__);
$url = $omb['access_token_url'];
common_debug('using access token url "'.$url.'"', __FILE__);
# XXX: Is this the right thing to do? Strip off GET params and make them
# POST params? Seems wrong to me.
$parsed = parse_url($url);
$params = array();
parse_str($parsed['query'], $params);
$req = OAuthRequest::from_consumer_and_token($con, $tok, "POST", $url, $params);
$req->set_parameter('omb_version', OMB_VERSION_01);
# XXX: test to see if endpoint accepts this signature method
$req->sign_request(omb_hmac_sha1(), $con, $tok);
# We re-use this tool's fetcher, since it's pretty good
common_debug('posting to access token url "'.$req->get_normalized_http_url().'"', __FILE__);
common_debug('posting request data "'.$req->to_postdata().'"', __FILE__);
$fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
$result = $fetcher->post($req->get_normalized_http_url(),
$req->to_postdata(),
array('User-Agent: StatusNet/' . STATUSNET_VERSION));
common_debug('got result: "'.print_r($result,true).'"', __FILE__);
if ($result->status != 200) {
return null;
}
parse_str($result->body, $return);
return array($return['oauth_token'], $return['oauth_token_secret']);
}
}

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

@ -136,6 +136,11 @@ class TwitapistatusesAction extends TwitterapiAction
}
function home_timeline($args, $apidata)
{
call_user_func(array($this, 'friends_timeline'), $args, $apidata);
}
function user_timeline($args, $apidata)
{
parent::handle($args);

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/
@ -55,46 +55,13 @@ class UpdateprofileAction extends Action
*/
function prepare($argarray)
{
$version = $req->get_parameter('omb_version');
if ($version != OMB_VERSION_01) {
$this->clientError(_('Unsupported OMB version'), 400);
return false;
}
# First, check to see if listenee exists
$listenee = $req->get_parameter('omb_listenee');
$remote = Remote_profile::staticGet('uri', $listenee);
if (!$remote) {
$this->clientError(_('Profile unknown'), 404);
return false;
}
# Second, check to see if they should be able to post updates!
# We see if there are any subscriptions to that remote user with
# the given token.
$sub = new Subscription();
$sub->subscribed = $remote->id;
$sub->token = $token->key;
if (!$sub->find(true)) {
$this->clientError(_('You did not send us that profile'), 403);
return false;
}
$profile = Profile::staticGet('id', $remote->id);
if (!$profile) {
# This one is our fault
$this->serverError(_('Remote profile with no matching profile'), 500);
return false;
}
$nickname = $req->get_parameter('omb_listenee_nickname');
if ($nickname && !Validate::string($nickname, array('min_length' => 1,
'max_length' => 64,
'format' => NICKNAME_FMT))) {
$this->clientError(_('Nickname must have only lowercase letters and numbers and no spaces.'));
return false;
}
$license = $req->get_parameter('omb_listenee_license');
if ($license && !common_valid_http_url($license)) {
$this->clientError(sprintf(_("Invalid license URL '%s'"), $license));
parent::prepare($argarray);
$license = $_POST['omb_listenee_license'];
$site_license = common_config('license', 'url');
if (!common_compatible_license($license, $site_license)) {
$this->clientError(sprintf(_('Listenee stream license %s is not '.
'compatible with site license %s.'),
$license, $site_license));
return false;
}
return true;
@ -113,4 +80,4 @@ class UpdateprofileAction extends Action
return;
}
}
}
}

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

@ -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 StatusNet
* @package StatusNet
* @author Brenda Wallace <shiny@cpan.org>
* @author Christopher Vollick <psycotica0@gmail.com>
* @author CiaranG <ciaran@ciarang.com>
* @author Craig Andrews <candrews@integralblue.com>
* @author Evan Prodromou <evan@controlezvous.ca>
* @author Gina Haeussge <osd@foosel.net>
* @author Jeffery To <jeffery.to@gmail.com>
* @author Mike Cochrane <mikec@mikenz.geek.nz>
* @author Robin Millette <millette@controlyourself.ca>
* @author Sarven Capadisli <csarven@controlyourself.ca>
* @author Tom Adams <tom@holizz.com>
*
* @license GNU Affero General Public License http://www.gnu.org/licenses/
*/
define('INSTALLDIR', dirname(__FILE__));
@ -29,7 +45,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 +62,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 +151,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 +166,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 +174,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 +225,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,24 @@
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category 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/
* @version 0.9
* @link http://status.net
*/
define('INSTALLDIR', dirname(__FILE__));
@ -181,17 +199,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 +235,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 +280,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 +336,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 +364,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 +388,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 +404,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 +449,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 +478,11 @@ E_O_T;
function updateStatus($status, $error=false)
{
?>
<li <?php echo ($error) ? 'class="error"': ''; ?>><?php echo $status;?></li>
<?php
echo '<li' . ($error ? ' class="error"': '' ) . ">$status</li>";
}
function handlePost()
{
?>
<?php
$host = $_POST['host'];
$dbtype = $_POST['dbtype'];
$database = $_POST['database'];
@ -427,55 +493,41 @@ function handlePost()
$server = $_SERVER['HTTP_HOST'];
$path = substr(dirname($_SERVER['PHP_SELF']), 1);
?>
echo <<<STR
<dl class="system_notice">
<dt>Page notice</dt>
<dd>
<ul>
<?php
$fail = false;
STR;
$fail = false;
if (empty($host)) {
updateStatus("No hostname specified.", true);
$fail = true;
$fail = true;
}
if (empty($database)) {
updateStatus("No database specified.", true);
$fail = true;
$fail = true;
}
if (empty($username)) {
updateStatus("No username specified.", true);
$fail = true;
$fail = true;
}
// if (empty($password)) {
// updateStatus("No password specified.", true);
// $fail = true;
// }
if (empty($sitename)) {
updateStatus("No sitename specified.", true);
$fail = true;
$fail = true;
}
if($fail){
showForm();
if ($fail) {
showForm();
return;
}
// FIXME: use PEAR::DB or PDO instead of our own switch
switch($dbtype) {
case 'mysql':
$db = mysql_db_installer($host, $database, $username, $password);
break;
case 'pgsql':
$db = pgsql_db_installer($host, $database, $username, $password);
break;
default:
}
global $dbModules;
$db = call_user_func($dbModules[$dbtype]['installer'], $host, $database, $username, $password);
if (!$db) {
// database connection failed, do not move on to create config file.
@ -498,112 +550,110 @@ function handlePost()
updateStatus("StatusNet has been installed at $link");
updateStatus("You can visit your <a href='$link'>new StatusNet site</a>.");
?>
<?php
}
function pgsql_db_installer($host, $database, $username, $password) {
$connstring = "dbname=$database host=$host user=$username";
function Pgsql_Db_installer($host, $database, $username, $password)
{
$connstring = "dbname=$database host=$host user=$username";
//No password would mean trust authentication used.
if (!empty($password)) {
$connstring .= " password=$password";
}
updateStatus("Starting installation...");
updateStatus("Checking database...");
$conn = pg_connect($connstring);
//No password would mean trust authentication used.
if (!empty($password)) {
$connstring .= " password=$password";
}
updateStatus("Starting installation...");
updateStatus("Checking database...");
$conn = pg_connect($connstring);
if ($conn ===false) {
updateStatus("Failed to connect to database: $connstring");
showForm();
return false;
}
if ($conn ===false) {
updateStatus("Failed to connect to database: $connstring");
showForm();
return false;
}
//ensure database encoding is UTF8
$record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
if ($record->server_encoding != 'UTF8') {
updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
showForm();
return false;
}
//ensure database encoding is UTF8
$record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
if ($record->server_encoding != 'UTF8') {
updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
showForm();
return false;
}
updateStatus("Running database script...");
//wrap in transaction;
pg_query($conn, 'BEGIN');
$res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
updateStatus("Running database script...");
//wrap in transaction;
pg_query($conn, 'BEGIN');
$res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
if ($res === false) {
updateStatus("Can't run database script.", true);
showForm();
return false;
}
foreach (array('sms_carrier' => 'SMS carrier',
if ($res === false) {
updateStatus("Can't run database script.", true);
showForm();
return false;
}
foreach (array('sms_carrier' => 'SMS carrier',
'notice_source' => 'notice source',
'foreign_services' => 'foreign service')
as $scr => $name) {
updateStatus(sprintf("Adding %s data to database...", $name));
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
if ($res === false) {
updateStatus(sprintf("Can't run %d script.", $name), true);
showForm();
return false;
}
}
pg_query($conn, 'COMMIT');
updateStatus(sprintf("Adding %s data to database...", $name));
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
if ($res === false) {
updateStatus(sprintf("Can't run %d script.", $name), true);
showForm();
return false;
}
}
pg_query($conn, 'COMMIT');
if (empty($password)) {
$sqlUrl = "pgsql://$username@$host/$database";
}
else {
$sqlUrl = "pgsql://$username:$password@$host/$database";
}
if (empty($password)) {
$sqlUrl = "pgsql://$username@$host/$database";
} else {
$sqlUrl = "pgsql://$username:$password@$host/$database";
}
$db = array('type' => 'pgsql', 'database' => $sqlUrl);
$db = array('type' => 'pgsql', 'database' => $sqlUrl);
return $db;
return $db;
}
function mysql_db_installer($host, $database, $username, $password) {
updateStatus("Starting installation...");
updateStatus("Checking database...");
function Mysql_Db_installer($host, $database, $username, $password)
{
updateStatus("Starting installation...");
updateStatus("Checking database...");
$conn = mysql_connect($host, $username, $password);
if (!$conn) {
updateStatus("Can't connect to server '$host' as '$username'.", true);
showForm();
return false;
}
updateStatus("Changing to database...");
$res = mysql_select_db($database, $conn);
if (!$res) {
updateStatus("Can't change to database.", true);
showForm();
return false;
}
updateStatus("Running database script...");
$res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
if ($res === false) {
updateStatus("Can't run database script.", true);
showForm();
return false;
}
foreach (array('sms_carrier' => 'SMS carrier',
$conn = mysql_connect($host, $username, $password);
if (!$conn) {
updateStatus("Can't connect to server '$host' as '$username'.", true);
showForm();
return false;
}
updateStatus("Changing to database...");
$res = mysql_select_db($database, $conn);
if (!$res) {
updateStatus("Can't change to database.", true);
showForm();
return false;
}
updateStatus("Running database script...");
$res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
if ($res === false) {
updateStatus("Can't run database script.", true);
showForm();
return false;
}
foreach (array('sms_carrier' => 'SMS carrier',
'notice_source' => 'notice source',
'foreign_services' => 'foreign service')
as $scr => $name) {
updateStatus(sprintf("Adding %s data to database...", $name));
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
if ($res === false) {
updateStatus(sprintf("Can't run %d script.", $name), true);
showForm();
return false;
}
}
updateStatus(sprintf("Adding %s data to database...", $name));
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
if ($res === false) {
updateStatus(sprintf("Can't run %d script.", $name), true);
showForm();
return false;
}
}
$sqlUrl = "mysqli://$username:$password@$host/$database";
$db = array('type' => 'mysql', 'database' => $sqlUrl);
return $db;
$sqlUrl = "mysqli://$username:$password@$host/$database";
$db = array('type' => 'mysql', 'database' => $sqlUrl);
return $db;
}
function writeConf($sitename, $server, $path, $fancy, $db)
@ -634,7 +684,16 @@ function writeConf($sitename, $server, $path, $fancy, $db)
return $res;
}
function runDbScript($filename, $conn, $type = 'mysql')
/**
* Install schema into the database
*
* @param string $filename location of database schema file
* @param dbconn $conn connection to database
* @param string $type type of database, currently mysql or pgsql
*
* @return boolean - indicating success or failure
*/
function runDbScript($filename, $conn, $type = 'mysqli')
{
$sql = trim(file_get_contents($filename));
$stmts = explode(';', $sql);
@ -645,7 +704,7 @@ function runDbScript($filename, $conn, $type = 'mysql')
}
// FIXME: use PEAR::DB or PDO instead of our own switch
switch ($type) {
case 'mysql':
case 'mysqli':
$res = mysql_query($stmt, $conn);
if ($res === false) {
$error = mysql_error();

View File

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

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

@ -80,14 +80,9 @@ function omb_broadcast_notice($notice)
$posted = array();
while ($rp->fetch()) {
if (!array_key_exists($rp->postnoticeurl, $posted)) {
common_log(LOG_DEBUG, 'Posting to ' . $rp->postnoticeurl);
if (omb_post_notice_keys($notice, $rp->postnoticeurl, $rp->token, $rp->secret)) {
common_log(LOG_DEBUG, 'Finished to ' . $rp->postnoticeurl);
$posted[$rp->postnoticeurl] = true;
} else {
common_log(LOG_DEBUG, 'Failed posting to ' . $rp->postnoticeurl);
}
if (isset($posted[$rp->postnoticeurl])) {
/* We already posted to this url. */
continue;
}
common_debug('Posting to ' . $rp->postnoticeurl, __FILE__);

View File

@ -265,12 +265,12 @@ class Router
$m->connect('api/statuses/:method',
array('action' => 'api',
'apiaction' => 'statuses'),
array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|mentions|show|friends|followers|featured)(\.(atom|rss|xml|json))?'));
array('method' => '(public_timeline|home_timeline|friends_timeline|user_timeline|update|replies|mentions|show|friends|followers|featured)(\.(atom|rss|xml|json))?'));
$m->connect('api/statuses/:method/:argument',
array('action' => 'api',
'apiaction' => 'statuses'),
array('method' => '(|user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)'));
array('method' => '(user_timeline|home_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)'));
// users
@ -429,7 +429,7 @@ class Router
$m->connect('api/statuses/:method/:argument',
array('action' => 'api',
'apiaction' => 'statuses'),
array('method' => '(|user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)'));
array('method' => '(user_timeline|home_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)'));
$m->connect('api/statusnet/groups/:method/:argument',
array('action' => 'api',

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

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