Merge branch 'testing' into 0.9.x

This commit is contained in:
Brion Vibber 2010-05-21 13:15:08 -07:00
commit 6eae5d6a7e
16 changed files with 172 additions and 27 deletions

View File

@ -87,13 +87,15 @@ class BlockAction extends ProfileFormAction
{ {
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($this->arg('no')) { if ($this->arg('no')) {
$this->returnToArgs(); $this->returnToPrevious();
} elseif ($this->arg('yes')) { } elseif ($this->arg('yes')) {
$this->handlePost(); $this->handlePost();
$this->returnToArgs(); $this->returnToPrevious();
} else { } else {
$this->showPage(); $this->showPage();
} }
} else {
$this->showPage();
} }
} }
@ -118,6 +120,12 @@ class BlockAction extends ProfileFormAction
*/ */
function areYouSureForm() function areYouSureForm()
{ {
// @fixme if we ajaxify the confirmation form, skip the preview on ajax hits
$profile = new ArrayWrapper(array($this->profile));
$preview = new ProfileList($profile, $this);
$preview->show();
$id = $this->profile->id; $id = $this->profile->id;
$this->elementStart('form', array('id' => 'block-' . $id, $this->elementStart('form', array('id' => 'block-' . $id,
'method' => 'post', 'method' => 'post',
@ -187,4 +195,38 @@ class BlockAction extends ProfileFormAction
$this->autofocus('form_action-yes'); $this->autofocus('form_action-yes');
} }
/**
* Override for form session token checks; on our first hit we're just
* requesting confirmation, which doesn't need a token. We need to be
* able to take regular GET requests from email!
*
* @throws ClientException if token is bad on POST request or if we have
* confirmation parameters which could trigger something.
*/
function checkSessionToken()
{
if ($_SERVER['REQUEST_METHOD'] == 'POST' ||
$this->arg('yes') ||
$this->arg('no')) {
return parent::checkSessionToken();
}
}
/**
* If we reached this form without returnto arguments, return to the
* current user's subscription list.
*
* @return string URL
*/
function defaultReturnTo()
{
$user = common_current_user();
if ($user) {
return common_local_url('subscribers',
array('nickname' => $user->nickname));
} else {
return common_local_url('public');
}
}
} }

View File

@ -92,10 +92,10 @@ class DeleteuserAction extends ProfileFormAction
{ {
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($this->arg('no')) { if ($this->arg('no')) {
$this->returnToArgs(); $this->returnToPrevious();
} elseif ($this->arg('yes')) { } elseif ($this->arg('yes')) {
$this->handlePost(); $this->handlePost();
$this->returnToArgs(); $this->returnToPrevious();
} else { } else {
$this->showPage(); $this->showPage();
} }

View File

@ -117,7 +117,7 @@ class GroupblockAction extends RedirectingAction
parent::handle($args); parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($this->arg('no')) { if ($this->arg('no')) {
$this->returnToArgs(); $this->returnToPrevious();
} elseif ($this->arg('yes')) { } elseif ($this->arg('yes')) {
$this->blockProfile(); $this->blockProfile();
} elseif ($this->arg('blockto')) { } elseif ($this->arg('blockto')) {
@ -207,7 +207,7 @@ class GroupblockAction extends RedirectingAction
return false; return false;
} }
$this->returnToArgs(); $this->returnToPrevious();
} }
/** /**

View File

@ -304,4 +304,7 @@ $default =
array('subscribers' => true, array('subscribers' => true,
'members' => true, 'members' => true,
'peopletag' => true), 'peopletag' => true),
'http' => // HTTP client settings when contacting other sites
array('ssl_cafile' => false // To enable SSL cert validation, point to a CA bundle (eg '/usr/lib/ssl/certs/ca-certificates.crt')
),
); );

View File

@ -132,7 +132,19 @@ class HTTPClient extends HTTP_Request2
// ought to be investigated to see if we can handle // ought to be investigated to see if we can handle
// it gracefully in that case as well. // it gracefully in that case as well.
$this->config['protocol_version'] = '1.0'; $this->config['protocol_version'] = '1.0';
// Default state of OpenSSL seems to have no trusted
// SSL certificate authorities, which breaks hostname
// verification and means we have a hard time communicating
// with other sites' HTTPS interfaces.
//
// Turn off verification unless we've configured a CA bundle.
if (common_config('http', 'ssl_cafile')) {
$this->config['ssl_cafile'] = common_config('http', 'ssl_cafile');
} else {
$this->config['ssl_verify_peer'] = false;
}
parent::__construct($url, $method, $config); parent::__construct($url, $method, $config);
$this->setHeader('User-Agent', $this->userAgent()); $this->setHeader('User-Agent', $this->userAgent());
} }

View File

@ -245,6 +245,11 @@ function mail_subscribe_notify_profile($listenee, $other)
$other->getBestName(), $other->getBestName(),
common_config('site', 'name')); common_config('site', 'name'));
$blocklink = sprintf(_("If you believe this account is being used abusively, " .
"you can block them from your subscribers list and " .
"report as spam to site administrators at %s"),
common_local_url('block', array('profileid' => $other->id)));
// TRANS: Main body of new-subscriber notification e-mail // TRANS: Main body of new-subscriber notification e-mail
$body = sprintf(_('%1$s is now listening to your notices on %2$s.'."\n\n". $body = sprintf(_('%1$s is now listening to your notices on %2$s.'."\n\n".
"\t".'%3$s'."\n\n". "\t".'%3$s'."\n\n".
@ -264,9 +269,10 @@ function mail_subscribe_notify_profile($listenee, $other)
($other->homepage) ? ($other->homepage) ?
// TRANS: Profile info line in new-subscriber notification e-mail // TRANS: Profile info line in new-subscriber notification e-mail
sprintf(_("Homepage: %s"), $other->homepage) . "\n" : '', sprintf(_("Homepage: %s"), $other->homepage) . "\n" : '',
($other->bio) ? (($other->bio) ?
// TRANS: Profile info line in new-subscriber notification e-mail // TRANS: Profile info line in new-subscriber notification e-mail
sprintf(_("Bio: %s"), $other->bio) . "\n\n" : '', sprintf(_("Bio: %s"), $other->bio) . "\n" : '') .
"\n\n" . $blocklink . "\n",
common_config('site', 'name'), common_config('site', 'name'),
common_local_url('emailsettings')); common_local_url('emailsettings'));

View File

@ -60,7 +60,16 @@ class ProfileFormAction extends RedirectingAction
$this->checkSessionToken(); $this->checkSessionToken();
if (!common_logged_in()) { if (!common_logged_in()) {
$this->clientError(_('Not logged in.')); if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->clientError(_('Not logged in.'));
} else {
// Redirect to login.
common_set_returnto($this->selfUrl());
$user = common_current_user();
if (Event::handle('RedirectToLogin', array($this, $user))) {
common_redirect(common_local_url('login'), 303);
}
}
return false; return false;
} }
@ -97,7 +106,7 @@ class ProfileFormAction extends RedirectingAction
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->handlePost(); $this->handlePost();
$this->returnToArgs(); $this->returnToPrevious();
} }
} }

View File

@ -53,12 +53,13 @@ class RedirectingAction extends Action
* *
* To be called only after successful processing. * To be called only after successful processing.
* *
* @fixme rename this -- it obscures Action::returnToArgs() which * Note: this was named returnToArgs() up through 0.9.2, which
* returns a list of arguments, and is a bit confusing. * caused problems because there's an Action::returnToArgs()
* already which does something different.
* *
* @return void * @return void
*/ */
function returnToArgs() function returnToPrevious()
{ {
// Now, gotta figure where we go back to // Now, gotta figure where we go back to
$action = false; $action = false;
@ -77,7 +78,7 @@ class RedirectingAction extends Action
if ($action) { if ($action) {
common_redirect(common_local_url($action, $args, $params), 303); common_redirect(common_local_url($action, $args, $params), 303);
} else { } else {
$url = $this->defaultReturnToUrl(); $url = $this->defaultReturnTo();
} }
common_redirect($url, 303); common_redirect($url, 303);
} }

View File

@ -136,6 +136,11 @@ class Router
$m->connect('main/'.$a, array('action' => $a)); $m->connect('main/'.$a, array('action' => $a));
} }
// Also need a block variant accepting ID on URL for mail links
$m->connect('main/block/:profileid',
array('action' => 'block'),
array('profileid' => '[0-9]+'));
$m->connect('main/sup/:seconds', array('action' => 'sup'), $m->connect('main/sup/:seconds', array('action' => 'sup'),
array('seconds' => '[0-9]+')); array('seconds' => '[0-9]+'));

View File

@ -1939,6 +1939,15 @@ function common_url_to_nickname($url)
$path = preg_replace('@/$@', '', $parts['path']); $path = preg_replace('@/$@', '', $parts['path']);
$path = preg_replace('@^/@', '', $path); $path = preg_replace('@^/@', '', $path);
$path = basename($path); $path = basename($path);
// Hack for MediaWiki user pages, in the form:
// http://example.com/wiki/User:Myname
// ('User' may be localized.)
if (strpos($path, ':')) {
$parts = array_filter(explode(':', $path));
$path = $parts[count($parts) - 1];
}
if ($path) { if ($path) {
return common_nicknamize($path); return common_nicknamize($path);
} }

View File

@ -104,9 +104,13 @@ function facebookBroadcastNotice($notice)
$status = "$prefix $notice->content"; $status = "$prefix $notice->content";
common_debug("FacebookPlugin - checking for publish_stream permission for user $user->id");
$can_publish = $facebook->api_client->users_hasAppPermission('publish_stream', $can_publish = $facebook->api_client->users_hasAppPermission('publish_stream',
$fbuid); $fbuid);
common_debug("FacebookPlugin - checking for status_update permission for user $user->id");
$can_update = $facebook->api_client->users_hasAppPermission('status_update', $can_update = $facebook->api_client->users_hasAppPermission('status_update',
$fbuid); $fbuid);
if (!empty($attachments) && $can_publish == 1) { if (!empty($attachments) && $can_publish == 1) {
@ -114,15 +118,15 @@ function facebookBroadcastNotice($notice)
$facebook->api_client->stream_publish($status, $fbattachment, $facebook->api_client->stream_publish($status, $fbattachment,
null, null, $fbuid); null, null, $fbuid);
common_log(LOG_INFO, common_log(LOG_INFO,
"Posted notice $notice->id w/attachment " . "FacebookPlugin - Posted notice $notice->id w/attachment " .
"to Facebook user's stream (fbuid = $fbuid)."); "to Facebook user's stream (fbuid = $fbuid).");
} elseif ($can_update == 1 || $can_publish == 1) { } elseif ($can_update == 1 || $can_publish == 1) {
$facebook->api_client->users_setStatus($status, $fbuid, false, true); $facebook->api_client->users_setStatus($status, $fbuid, false, true);
common_log(LOG_INFO, common_log(LOG_INFO,
"Posted notice $notice->id to Facebook " . "FacebookPlugin - Posted notice $notice->id to Facebook " .
"as a status update (fbuid = $fbuid)."); "as a status update (fbuid = $fbuid).");
} else { } else {
$msg = "Not sending notice $notice->id to Facebook " . $msg = "FacebookPlugin - Not sending notice $notice->id to Facebook " .
"because user $user->nickname hasn't given the " . "because user $user->nickname hasn't given the " .
'Facebook app \'status_update\' or \'publish_stream\' permission.'; 'Facebook app \'status_update\' or \'publish_stream\' permission.';
common_log(LOG_WARNING, $msg); common_log(LOG_WARNING, $msg);
@ -138,7 +142,7 @@ function facebookBroadcastNotice($notice)
$code = $e->getCode(); $code = $e->getCode();
$msg = "Facebook returned error code $code: " . $msg = "FacebookPlugin - Facebook returned error code $code: " .
$e->getMessage() . ' - ' . $e->getMessage() . ' - ' .
"Unable to update Facebook status (notice $notice->id) " . "Unable to update Facebook status (notice $notice->id) " .
"for $user->nickname (user id: $user->id)!"; "for $user->nickname (user id: $user->id)!";

View File

@ -84,7 +84,7 @@ class DiscoveryHints {
$hints['fullname'] = implode(' ', $hcard['n']); $hints['fullname'] = implode(' ', $hcard['n']);
} }
if (array_key_exists('photo', $hcard)) { if (array_key_exists('photo', $hcard) && count($hcard['photo'])) {
$hints['avatar'] = $hcard['photo'][0]; $hints['avatar'] = $hcard['photo'][0];
} }

View File

@ -12,6 +12,20 @@ registered prior to that timestamp.
addPlugin('RequireValidatedEmail', addPlugin('RequireValidatedEmail',
array('grandfatherCutoff' => 'Dec 7, 2009'); array('grandfatherCutoff' => 'Dec 7, 2009');
You can also exclude the validation checks from OpenID accounts
connected to a trusted provider, by providing a list of regular
expressions to match their provider URLs.
For example, to trust WikiHow and Wikipedia users:
addPlugin('RequireValidatedEmailPlugin', array(
'trustedOpenIDs' => array(
'!^http://\w+\.wikihow\.com/!',
'!^http://\w+\.wikipedia\.org/!',
),
));
Todo: Todo:
* add a more visible indicator that validation is still outstanding * add a more visible indicator that validation is still outstanding

View File

@ -37,6 +37,20 @@ class RequireValidatedEmailPlugin extends Plugin
// without the validation requirement. // without the validation requirement.
public $grandfatherCutoff=null; public $grandfatherCutoff=null;
// If OpenID plugin is installed, users with a verified OpenID
// association whose provider URL matches one of these regexes
// will be considered to be sufficiently valid for our needs.
//
// For example, to trust WikiHow and Wikipedia OpenID users:
//
// addPlugin('RequireValidatedEmailPlugin', array(
// 'trustedOpenIDs' => array(
// '!^http://\w+\.wikihow\.com/!',
// '!^http://\w+\.wikipedia\.org/!',
// ),
// ));
public $trustedOpenIDs=array();
function __construct() function __construct()
{ {
parent::__construct(); parent::__construct();
@ -90,13 +104,17 @@ class RequireValidatedEmailPlugin extends Plugin
*/ */
protected function validated($user) protected function validated($user)
{ {
if ($this->grandfathered($user)) {
return true;
}
// The email field is only stored after validation... // The email field is only stored after validation...
// Until then you'll find them in confirm_address. // Until then you'll find them in confirm_address.
return !empty($user->email); $knownGood = !empty($user->email) ||
$this->grandfathered($user) ||
$this->hasTrustedOpenID($user);
// Give other plugins a chance to override, if they can validate
// that somebody's ok despite a non-validated email.
Event::handle('RequireValidatedEmailPlugin_Override', array($user, &$knownGood));
return $knownGood;
} }
/** /**
@ -118,6 +136,28 @@ class RequireValidatedEmailPlugin extends Plugin
return false; return false;
} }
/**
* Override for RequireValidatedEmail plugin. If we have a user who's
* not validated an e-mail, but did come from a trusted provider,
* we'll consider them ok.
*/
function hasTrustedOpenID($user)
{
if ($this->trustedOpenIDs && class_exists('User_openid')) {
foreach ($this->trustedOpenIDs as $regex) {
$oid = new User_openid();
$oid->user_id = $user->id;
$oid->find();
while ($oid->fetch()) {
if (preg_match($regex, $oid->canonical)) {
return true;
}
}
}
}
return false;
}
function onPluginVersion(&$versions) function onPluginVersion(&$versions)
{ {
$versions[] = array('name' => 'Require Validated Email', $versions[] = array('name' => 'Require Validated Email',

View File

@ -81,7 +81,7 @@ class ClearflagAction extends ProfileFormAction
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->handlePost(); $this->handlePost();
if (!$this->boolean('ajax')) { if (!$this->boolean('ajax')) {
$this->returnToArgs(); $this->returnToPrevious();
} }
} }
} }

View File

@ -87,7 +87,7 @@ class FlagprofileAction extends ProfileFormAction
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->handlePost(); $this->handlePost();
if (!$this->boolean('ajax')) { if (!$this->boolean('ajax')) {
$this->returnToArgs(); $this->returnToPrevious();
} }
} }
} }