git.gnu.io has moved to IP address 209.51.188.249 -- please double check where you are logging in.

Commit a5de2152 authored by Evan Prodromou's avatar Evan Prodromou

Merge branch 'master' of gitorious.org:statusnet/mainline

parents 6d8e01ad 634752f0
......@@ -57,7 +57,7 @@ require_once INSTALLDIR . '/lib/apiauth.php';
class ApiStatusesDestroyAction extends ApiAuthAction
{
var $status = null;
var $status = null;
/**
* Take arguments for running
......@@ -120,18 +120,11 @@ class ApiStatusesDestroyAction extends ApiAuthAction
$replies->get('notice_id', $this->notice_id);
$replies->delete();
$this->notice->delete();
if ($this->format == 'xml') {
$this->showSingleXmlStatus($this->notice);
} elseif ($this->format == 'json') {
$this->show_single_json_status($this->notice);
}
$this->showNotice();
} else {
$this->clientError(_('You may not delete another user\'s status.'),
403, $this->format);
}
$this->showNotice();
}
/**
......
......@@ -150,7 +150,7 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction
header('Content-Type: application/atom+xml; charset=utf-8');
$atom = new AtomNoticeFeed();
$atom = new AtomNoticeFeed($this->auth_user);
$atom->setId($id);
$atom->setTitle($title);
......
......@@ -152,7 +152,7 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction
header('Content-Type: application/atom+xml; charset=utf-8');
$atom = new AtomNoticeFeed();
$atom = new AtomNoticeFeed($this->auth_user);
$atom->setId($id);
$atom->setTitle($title);
......
......@@ -105,7 +105,7 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
function showTimeline()
{
// We'll pull common formatting out of this for other formats
$atom = new AtomGroupNoticeFeed($this->group);
$atom = new AtomGroupNoticeFeed($this->group, $this->auth_user);
$self = $this->getSelfUri();
......
......@@ -151,7 +151,7 @@ class ApiTimelineHomeAction extends ApiBareAuthAction
header('Content-Type: application/atom+xml; charset=utf-8');
$atom = new AtomNoticeFeed();
$atom = new AtomNoticeFeed($this->auth_user);
$atom->setId($id);
$atom->setTitle($title);
......
......@@ -151,7 +151,7 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction
header('Content-Type: application/atom+xml; charset=utf-8');
$atom = new AtomNoticeFeed();
$atom = new AtomNoticeFeed($this->auth_user);
$atom->setId($id);
$atom->setTitle($title);
......
......@@ -130,7 +130,7 @@ class ApiTimelinePublicAction extends ApiPrivateAuthAction
header('Content-Type: application/atom+xml; charset=utf-8');
$atom = new AtomNoticeFeed();
$atom = new AtomNoticeFeed($this->auth_user);
$atom->setId($id);
$atom->setTitle($title);
......
......@@ -117,7 +117,7 @@ class ApiTimelineRetweetsOfMeAction extends ApiAuthAction
header('Content-Type: application/atom+xml; charset=utf-8');
$atom = new AtomNoticeFeed();
$atom = new AtomNoticeFeed($this->auth_user);
$atom->setId($id);
$atom->setTitle($title);
......
......@@ -138,7 +138,7 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
header('Content-Type: application/atom+xml; charset=utf-8');
$atom = new AtomNoticeFeed();
$atom = new AtomNoticeFeed($this->auth_user);
$atom->setId($id);
$atom->setTitle($title);
......
......@@ -115,7 +115,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction
// We'll use the shared params from the Atom stub
// for other feed types.
$atom = new AtomUserNoticeFeed($this->user);
$atom = new AtomUserNoticeFeed($this->user, $this->auth_user);
$link = common_local_url(
'showstream',
......
......@@ -95,7 +95,9 @@ class FoafAction extends Action
// Would be nice to tell if they were a Person or not (e.g. a #person usertag?)
$this->elementStart('Agent', array('rdf:about' =>
$this->user->uri));
$this->element('mbox_sha1sum', null, sha1('mailto:' . $this->user->email));
if ($this->user->email) {
$this->element('mbox_sha1sum', null, sha1('mailto:' . $this->user->email));
}
if ($this->profile->fullname) {
$this->element('name', null, $this->profile->fullname);
}
......
......@@ -116,7 +116,11 @@ class File extends Memcached_DataObject
return false;
}
function processNew($given_url, $notice_id=null) {
/**
* @fixme refactor this mess, it's gotten pretty scary.
* @param bool $followRedirects
*/
function processNew($given_url, $notice_id=null, $followRedirects=true) {
if (empty($given_url)) return -1; // error, no url to process
$given_url = File_redirection::_canonUrl($given_url);
if (empty($given_url)) return -1; // error, no url to process
......@@ -124,6 +128,10 @@ class File extends Memcached_DataObject
if (empty($file)) {
$file_redir = File_redirection::staticGet('url', $given_url);
if (empty($file_redir)) {
// @fixme for new URLs this also looks up non-redirect data
// such as target content type, size, etc, which we need
// for File::saveNew(); so we call it even if not following
// new redirects.
$redir_data = File_redirection::where($given_url);
if (is_array($redir_data)) {
$redir_url = $redir_data['url'];
......@@ -134,11 +142,19 @@ class File extends Memcached_DataObject
throw new ServerException("Can't process url '$given_url'");
}
// TODO: max field length
if ($redir_url === $given_url || strlen($redir_url) > 255) {
if ($redir_url === $given_url || strlen($redir_url) > 255 || !$followRedirects) {
$x = File::saveNew($redir_data, $given_url);
$file_id = $x->id;
} else {
$x = File::processNew($redir_url, $notice_id);
// This seems kind of messed up... for now skipping this part
// if we're already under a redirect, so we don't go into
// horrible infinite loops if we've been given an unstable
// redirect (where the final destination of the first request
// doesn't match what we get when we ask for it again).
//
// Seen in the wild with clojure.org, which redirects through
// wikispaces for auth and appends session data in the URL params.
$x = File::processNew($redir_url, $notice_id, /*followRedirects*/false);
$file_id = $x->id;
File_redirection::saveNew($redir_data, $file_id, $given_url);
}
......
......@@ -97,15 +97,20 @@ class Notice extends Memcached_DataObject
// For auditing purposes, save a record that the notice
// was deleted.
$deleted = new Deleted_notice();
// @fixme we have some cases where things get re-run and so the
// insert fails.
$deleted = Deleted_notice::staticGet('id', $this->id);
if (!$deleted) {
$deleted = new Deleted_notice();
$deleted->id = $this->id;
$deleted->profile_id = $this->profile_id;
$deleted->uri = $this->uri;
$deleted->created = $this->created;
$deleted->deleted = common_sql_now();
$deleted->id = $this->id;
$deleted->profile_id = $this->profile_id;
$deleted->uri = $this->uri;
$deleted->created = $this->created;
$deleted->deleted = common_sql_now();
$deleted->insert();
$deleted->insert();
}
// Clear related records
......@@ -1235,7 +1240,7 @@ class Notice extends Memcached_DataObject
$noticeInfoAttr = array(
'local_id' => $this->id, // local notice ID (useful to clients for ordering)
'source' => $this->source // the client name (source attribution)
'source' => $this->source, // the client name (source attribution)
);
$ns = $this->getSource();
......@@ -1246,7 +1251,11 @@ class Notice extends Memcached_DataObject
}
if (!empty($cur)) {
$noticeInfoAttr['favorited'] = ($cur->hasFave($this)) ? 'true' : 'false';
$noticeInfoAttr['favorite'] = ($cur->hasFave($this)) ? "true" : "false";
}
if (!empty($this->repeat_of)) {
$noticeInfoAttr['repeat_of'] = $this->repeat_of;
}
$xs->element('statusnet:notice_info', $noticeInfoAttr, null);
......
......@@ -9,6 +9,7 @@ VALUES
('bti','bti','http://gregkh.github.com/bti/', now()),
('choqok', 'Choqok', 'http://choqok.gnufolks.org/', now()),
('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()),
('DarterosStatus', 'Darteros Status', 'http://www.darteros.com/doc/Darteros_Status', now()),
('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()),
('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()),
('drupal','Drupal','http://drupal.org/', now()),
......
......@@ -50,12 +50,13 @@ class AtomGroupNoticeFeed extends AtomNoticeFeed
* Constructor
*
* @param Group $group the group for the feed
* @param User $cur the current authenticated user, if any
* @param boolean $indent flag to turn indenting on or off
*
* @return void
*/
function __construct($group, $indent = true) {
parent::__construct($indent);
function __construct($group, $cur = null, $indent = true) {
parent::__construct($cur, $indent);
$this->group = $group;
$title = sprintf(_("%s timeline"), $group->nickname);
......
......@@ -44,9 +44,22 @@ if (!defined('STATUSNET'))
*/
class AtomNoticeFeed extends Atom10Feed
{
function __construct($indent = true) {
var $cur;
/**
* Constructor - adds a bunch of XML namespaces we need in our
* notice-specific Atom feeds, and allows setting the current
* authenticated user (useful for API methods).
*
* @param User $cur the current authenticated user (optional)
* @param boolean $indent Whether to indent XML output
*
*/
function __construct($cur = null, $indent = true) {
parent::__construct($indent);
$this->cur = $cur;
// Feeds containing notice info use these namespaces
$this->addNamespace(
......@@ -115,7 +128,7 @@ class AtomNoticeFeed extends Atom10Feed
$source = $this->showSource();
$author = $this->showAuthor();
$cur = common_current_user();
$cur = empty($this->cur) ? common_current_user() : $this->cur;
$this->addEntryRaw($notice->asAtomEntry(false, $source, $author, $cur));
}
......
......@@ -50,13 +50,14 @@ class AtomUserNoticeFeed extends AtomNoticeFeed
* Constructor
*
* @param User $user the user for the feed
* @param User $cur the current authenticated user, if any
* @param boolean $indent flag to turn indenting on or off
*
* @return void
*/
function __construct($user, $indent = true) {
parent::__construct($indent);
function __construct($user, $cur = null, $indent = true) {
parent::__construct($cur, $indent);
$this->user = $user;
if (!empty($user)) {
$profile = $user->getProfile();
......
......@@ -61,7 +61,7 @@ if (!function_exists('dpgettext')) {
* Not currently exposed in PHP's gettext module; implemented to be compat
* with gettext.h's macros.
*
* @param string $domain domain identifier, or null for default domain
* @param string $domain domain identifier
* @param string $context context identifier, should be some key like "menu|file"
* @param string $msgid English source text
* @return string original or translated message
......@@ -106,7 +106,7 @@ if (!function_exists('dnpgettext')) {
* Not currently exposed in PHP's gettext module; implemented to be compat
* with gettext.h's macros.
*
* @param string $domain domain identifier, or null for default domain
* @param string $domain domain identifier
* @param string $context context identifier, should be some key like "menu|file"
* @param string $msg singular English source text
* @param string $plural plural English source text
......@@ -180,7 +180,11 @@ function _m($msg/*, ...*/)
}
/**
* Looks for which plugin we've been called from to set the gettext domain.
* Looks for which plugin we've been called from to set the gettext domain;
* if not in a plugin subdirectory, we'll use the default 'statusnet'.
*
* Note: we can't return null for default domain since most of the PHP gettext
* wrapper functions turn null into "" before passing to the backend library.
*
* @param array $backtrace debug_backtrace() output
* @return string
......@@ -205,12 +209,20 @@ function _mdomain($backtrace)
if (DIRECTORY_SEPARATOR !== '/') {
$path = strtr($path, DIRECTORY_SEPARATOR, '/');
}
$cut = strpos($path, '/plugins/') + 9;
$cut2 = strpos($path, '/', $cut);
if ($cut && $cut2) {
$cached[$path] = substr($path, $cut, $cut2 - $cut);
$plug = strpos($path, '/plugins/');
if ($plug === false) {
// We're not in a plugin; return default domain.
return 'statusnet';
} else {
return null;
$cut = $plug + 9;
$cut2 = strpos($path, '/', $cut);
if ($cut2) {
$cached[$path] = substr($path, $cut, $cut2 - $cut);
} else {
// We might be running directly from the plugins dir?
// If so, there's no place to store locale info.
return 'statusnet';
}
}
}
return $cached[$path];
......
......@@ -122,7 +122,19 @@ class StompQueueManager extends QueueManager
public function enqueue($object, $queue)
{
$this->_connect();
return $this->_doEnqueue($object, $queue, $this->defaultIdx);
if (common_config('queue', 'stomp_enqueue_on')) {
// We're trying to force all writes to a single server.
// WARNING: this might do odd things if that server connection dies.
$idx = array_search(common_config('queue', 'stomp_enqueue_on'),
$this->servers);
if ($idx === false) {
common_log(LOG_ERR, 'queue stomp_enqueue_on setting does not match our server list.');
$idx = $this->defaultIdx;
}
} else {
$idx = $this->defaultIdx;
}
return $this->_doEnqueue($object, $queue, $idx);
}
/**
......
......@@ -38,11 +38,11 @@ editor or write them down.
In Facebook's application editor, specify the following URLs for your app:
- Canvas Callback URL : http://example.net/mublog/facebook/app/
- Post-Remove Callback URL: http://example.net/mublog/facebook/app/remove
- Post-Add Redirect URL : http://apps.facebook.com/yourapp/
- Canvas Page URL : http://apps.facebook.com/yourapp/
- Connect URL : http://example.net/mublog/
- Canvas Callback URL : http://example.net/mublog/facebook/app/
- Post-Remove Callback URL : http://example.net/mublog/facebook/app/remove
- Post-Authorize Redirect URL : http://apps.facebook.com/yourapp/
- Canvas Page URL : http://apps.facebook.com/yourapp/
- Connect URL : http://example.net/mublog/
*** ATTENTION ***
These URLs have changed slightly since StatusNet version 0.8.1,
......
......@@ -45,7 +45,9 @@ class Facebook {
public $user;
public $profile_user;
public $canvas_user;
public $ext_perms = array();
protected $base_domain;
/*
* Create a Facebook client like this:
*
......@@ -104,17 +106,17 @@ class Facebook {
*
* For nitty-gritty details of when each of these is used, check out
* http://wiki.developers.facebook.com/index.php/Verifying_The_Signature
*
* @param bool resolve_auth_token convert an auth token into a session
*/
public function validate_fb_params($resolve_auth_token=true) {
public function validate_fb_params() {
$this->fb_params = $this->get_valid_fb_params($_POST, 48 * 3600, 'fb_sig');
// note that with preload FQL, it's possible to receive POST params in
// addition to GET, so use a different prefix to differentiate them
if (!$this->fb_params) {
$fb_params = $this->get_valid_fb_params($_GET, 48 * 3600, 'fb_sig');
$fb_post_params = $this->get_valid_fb_params($_POST, 48 * 3600, 'fb_post_sig');
$fb_post_params = $this->get_valid_fb_params($_POST,
48 * 3600, // 48 hours
'fb_post_sig');
$this->fb_params = array_merge($fb_params, $fb_post_params);
}
......@@ -128,6 +130,9 @@ class Facebook {
$this->fb_params['canvas_user'] : null;
$this->base_domain = isset($this->fb_params['base_domain']) ?
$this->fb_params['base_domain'] : null;
$this->ext_perms = isset($this->fb_params['ext_perms']) ?
explode(',', $this->fb_params['ext_perms'])
: array();
if (isset($this->fb_params['session_key'])) {
$session_key = $this->fb_params['session_key'];
......@@ -141,13 +146,11 @@ class Facebook {
$this->set_user($user,
$session_key,
$expires);
}
// if no Facebook parameters were found in the GET or POST variables,
// then fall back to cookies, which may have cached user information
// Cookies are also used to receive session data via the Javascript API
else if ($cookies =
$this->get_valid_fb_params($_COOKIE, null, $this->api_key)) {
} else if ($cookies =
$this->get_valid_fb_params($_COOKIE, null, $this->api_key)) {
// if no Facebook parameters were found in the GET or POST variables,
// then fall back to cookies, which may have cached user information
// Cookies are also used to receive session data via the Javascript API
$base_domain_cookie = 'base_domain_' . $this->api_key;
if (isset($_COOKIE[$base_domain_cookie])) {
$this->base_domain = $_COOKIE[$base_domain_cookie];
......@@ -160,25 +163,6 @@ class Facebook {
$cookies['session_key'],
$expires);
}
// finally, if we received no parameters, but the 'auth_token' GET var
// is present, then we are in the middle of auth handshake,
// so go ahead and create the session
else if ($resolve_auth_token && isset($_GET['auth_token']) &&
$session = $this->do_get_session($_GET['auth_token'])) {
if ($this->generate_session_secret &&
!empty($session['secret'])) {
$session_secret = $session['secret'];
}
if (isset($session['base_domain'])) {
$this->base_domain = $session['base_domain'];
}
$this->set_user($session['uid'],
$session['session_key'],
$session['expires'],
isset($session_secret) ? $session_secret : null);
}
return !empty($this->fb_params);
}
......@@ -309,11 +293,28 @@ class Facebook {
// require_add and require_install have been removed.
// see http://developer.facebook.com/news.php?blog=1&story=116 for more details
public function require_login() {
if ($user = $this->get_loggedin_user()) {
public function require_login($required_permissions = '') {
$user = $this->get_loggedin_user();
$has_permissions = true;
if ($required_permissions) {
$this->require_frame();
$permissions = array_map('trim', explode(',', $required_permissions));
foreach ($permissions as $permission) {
if (!in_array($permission, $this->ext_perms)) {
$has_permissions = false;
break;
}
}
}
if ($user && $has_permissions) {
return $user;
}
$this->redirect($this->get_login_url(self::current_url(), $this->in_frame()));
$this->redirect(
$this->get_login_url(self::current_url(), $this->in_frame(),
$required_permissions));
}
public function require_frame() {
......@@ -342,10 +343,11 @@ class Facebook {
return $page . '?' . http_build_query($params);
}
public function get_login_url($next, $canvas) {
public function get_login_url($next, $canvas, $req_perms = '') {
$page = self::get_facebook_url().'/login.php';
$params = array('api_key' => $this->api_key,
'v' => '1.0');
$params = array('api_key' => $this->api_key,
'v' => '1.0',
'req_perms' => $req_perms);
if ($next) {
$params['next'] = $next;
......
......@@ -569,7 +569,7 @@ function toggleDisplay(id, type) {
return $this->call_method('facebook.events.invite',
array('eid' => $eid,
'uids' => $uids,
'personal_message', $personal_message));
'personal_message' => $personal_message));
}
/**
......@@ -1350,53 +1350,6 @@ function toggleDisplay(id, type) {
);
}
/**
* Dashboard API
*/
/**
* Set the news for the specified user.
*
* @param int $uid The user for whom you are setting news for
* @param string $news Text of news to display
*
* @return bool Success
*/
public function dashboard_setNews($uid, $news) {
return $this->call_method('facebook.dashboard.setNews',
array('uid' => $uid,
'news' => $news)
);
}
/**
* Get the current news of the specified user.
*
* @param int $uid The user to get the news of
*
* @return string The text of the current news for the user
*/
public function dashboard_getNews($uid) {
return json_decode(
$this->call_method('facebook.dashboard.getNews',
array('uid' => $uid)
), true);
}
/**
* Set the news for the specified user.
*
* @param int $uid The user you are clearing the news of
*
* @return bool Success
*/
public function dashboard_clearNews($uid) {
return $this->call_method('facebook.dashboard.clearNews',
array('uid' => $uid)
);
}
/**
* Creates a note with the specified title and content.
......@@ -2005,7 +1958,7 @@ function toggleDisplay(id, type) {
* @return array A list of strings describing any compile errors for the
* submitted FBML
*/
function profile_setFBML($markup,
public function profile_setFBML($markup,
$uid=null,
$profile='',
$profile_action='',
......@@ -3267,9 +3220,8 @@ function toggleDisplay(id, type) {
} else {
$get['v'] = '1.0';
}
if (isset($this->use_ssl_resources) &&
$this->use_ssl_resources) {
$post['return_ssl_resources'] = true;
if (isset($this->use_ssl_resources)) {
$post['return_ssl_resources'] = (bool) $this->use_ssl_resources;
}
return array($get, $post);
}
......
......@@ -54,22 +54,11 @@ class FacebooksettingsAction extends FacebookAction
$noticesync = $this->boolean('noticesync');
$replysync = $this->boolean('replysync');
$prefix = $this->trimmed('prefix');
$original = clone($this->flink);
$this->flink->set_flags($noticesync, false, $replysync, false);
$result = $this->flink->update($original);
if ($prefix == '' || $prefix == '0') {
// Facebook bug: saving empty strings to prefs now fails
// http://bugs.developers.facebook.com/show_bug.cgi?id=7110
$trimmed = $prefix . ' ';
} else {
$trimmed = substr($prefix, 0, 128);
}
$this->facebook->api_client->data_setUserPreference(FACEBOOK_NOTICE_PREFIX,
$trimmed);
if ($result === false) {
$this->showForm(_m('There was a problem saving your sync preferences!'));
} else {
......@@ -110,16 +99,6 @@ class FacebooksettingsAction extends FacebookAction
$this->elementStart('li');
$prefix = trim($this->facebook->api_client->data_getUserPreference(FACEBOOK_NOTICE_PREFIX));
$this->input('prefix', _m('Prefix'),
($prefix) ? $prefix : null,
_m('A string to prefix notices with.'));
$this->elementEnd('li');
$this->elementStart('li');
$this->submit('save', _m('Save'));
$this->elementEnd('li');
......
This diff is collapsed.
......@@ -125,8 +125,8 @@ class MapstractionPlugin extends Plugin
$action->script('http://tile.cloudmade.com/wml/0.2/web-maps-lite.js');
break;
case 'google':
$action->script(sprintf('http://maps.google.com/maps?file=api&v=2&sensor=false&key=%s',
$this->apikey));
$action->script(sprintf('http://maps.google.com/maps?file=api&v=2&sensor=false&key=%s',
urlencode($this->apikey)));
break;
case 'microsoft':
$action->script('http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6');
......@@ -137,7 +137,7 @@ class MapstractionPlugin extends Plugin
break;
case 'yahoo':
$action->script(sprintf('http://api.maps.yahoo.com/ajaxymap?v=3.8&appid=%s',
$this->apikey));
urlencode($this->apikey)));
break;
case 'geocommons': // don't support this yet
default:
......
......@@ -104,7 +104,7 @@ function showMapstraction(element, notices) {
pt = new mxn.LatLonPoint(lat, lon);
mkr = new mxn.Marker(pt);
mkr.setIcon(n['user']['profile_image_url']);
mkr.setIcon(n['user']['profile_image_url'], [24, 24]);
mkr.setInfoBubble('<a href="'+ n['user']['profile_url'] + '">' + n['user']['screen_name'] + '</a>' + ' ' + n['html'] +
'<br/><a href="'+ n['url'] + '">'+ n['created_at'] + '</a>');
......
......@@ -20,7 +20,7 @@
* @category Plugin
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2009 StatusNet, Inc.
* @copyright 2009-2010 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/
*/
......@@ -45,7 +45,19 @@ if (!defined('STATUSNET')) {
class OpenIDPlugin extends Plugin
{
public $openidOnly = false;
// Plugin parameter: set true to disallow non-OpenID logins
// If set, overrides the setting in database or $config['site']['openidonly']
public $openidOnly = null;
function initialize()
{
parent::initialize();
if ($this->openidOnly !== null) {
global $config;
$config['site']['openidonly'] = (bool)$this->openidOnly;
}
}
/**
* Add OpenID-related paths to the router table
......@@ -67,6 +79,7 @@ class OpenIDPlugin extends Plugin
$m->connect('index.php?action=finishaddopenid',