Plugins
=======
-Beginning with the 0.7.x branch, StatusNet has supported a simple but
+GNU social supports a simple but
powerful plugin architecture. Important events in the code are named,
like 'StartNoticeSave', and other software can register interest
in those events. When the events happen, the other software is called
This will look for and load files named 'ExamplePlugin.php' or
'Example/ExamplePlugin.php' either in the plugins/ directory (for
-plugins that ship with StatusNet) or in the local/ directory (for
+plugins that ship with GNU social) or in the local/ directory (for
plugins you write yourself or that you get from somewhere else) or
local/plugins/.
class AllAction extends ShowstreamAction
{
- var $notice;
-
- protected function getStream()
+ public function getStream()
{
if ($this->scoped instanceof Profile && $this->scoped->isLocal() && $this->scoped->getUser()->streamModeOnly()) {
$stream = new InboxNoticeStream($this->target, $this->scoped);
function title()
{
- if (!empty($this->scoped) && $this->scoped->id == $this->target->id) {
+ if (!empty($this->scoped) && $this->scoped->sameAs($this->target)) {
// TRANS: Title of a user's own start page.
return _('Home timeline');
} else {
common_local_url(
'ApiTimelineFriends', array(
'format' => 'as',
- 'id' => $this->target->nickname
+ 'id' => $this->target->getNickname()
)
),
// TRANS: %s is user nickname.
- sprintf(_('Feed for friends of %s (Activity Streams JSON)'), $this->target->nickname)),
+ sprintf(_('Feed for friends of %s (Activity Streams JSON)'), $this->target->getNickname())),
new Feed(Feed::RSS1,
common_local_url(
'allrss', array(
'nickname' =>
- $this->target->nickname)
+ $this->target->getNickname())
),
// TRANS: %s is user nickname.
- sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->target->nickname)),
+ sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->target->getNickname())),
new Feed(Feed::RSS2,
common_local_url(
'ApiTimelineFriends', array(
'format' => 'rss',
- 'id' => $this->target->nickname
+ 'id' => $this->target->getNickname()
)
),
// TRANS: %s is user nickname.
- sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->target->nickname)),
+ sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->target->getNickname())),
new Feed(Feed::ATOM,
common_local_url(
'ApiTimelineFriends', array(
'format' => 'atom',
- 'id' => $this->target->nickname
+ 'id' => $this->target->getNickname()
)
),
// TRANS: %s is user nickname.
- sprintf(_('Feed for friends of %s (Atom)'), $this->target->nickname))
+ sprintf(_('Feed for friends of %s (Atom)'), $this->target->getNickname()))
);
}
function showEmptyListMessage()
{
// TRANS: Empty list message. %s is a user nickname.
- $message = sprintf(_('This is the timeline for %s and friends but no one has posted anything yet.'), $this->target->nickname) . ' ';
+ $message = sprintf(_('This is the timeline for %s and friends but no one has posted anything yet.'), $this->target->getNickname()) . ' ';
if (common_logged_in()) {
if ($this->target->id === $this->scoped->id) {
} else {
// TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@".
// TRANS: This message contains Markdown links. Keep "](" together.
- $message .= sprintf(_('You can try to [nudge %1$s](../%2$s) from their profile or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->target->nickname, $this->target->nickname, '@' . $this->target->nickname);
+ $message .= sprintf(_('You can try to [nudge %1$s](../%2$s) from their profile or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->target->getNickname(), $this->target->getNickname(), '@' . $this->target->getNickname());
}
} else {
// TRANS: Encouragement displayed on empty timeline user pages for anonymous users.
// TRANS: %s is a user nickname. This message contains Markdown links. Keep "](" together.
- $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->target->nickname);
+ $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->target->getNickname());
}
$this->elementStart('div', 'guide');
function showContent()
{
if (Event::handle('StartShowAllContent', array($this))) {
-
- $profile = null;
-
- $current_user = common_current_user();
-
- if (!empty($current_user)) {
- $profile = $current_user->getProfile();
- }
-
- if (!empty($current_user) && $current_user->streamModeOnly()) {
+ if ($this->scoped instanceof Profile && $this->scoped->isLocal() && $this->scoped->getUser()->streamModeOnly()) {
$nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));
} else {
- $nl = new ThreadedNoticeList($this->notice, $this, $profile);
+ $nl = new ThreadedNoticeList($this->notice, $this, $this->scoped);
}
$cnt = $nl->show();
$this->pagination(
$this->page > 1, $cnt > NOTICES_PER_PAGE,
- $this->page, 'all', array('nickname' => $this->target->nickname)
+ $this->page, 'all', array('nickname' => $this->target->getNickname())
);
Event::handle('EndShowAllContent', array($this));
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/rssaction.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* RSS feed for user and friends timeline.
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*/
-class AllrssAction extends Rss10Action
+class AllrssAction extends TargetedRss10Action
{
- var $user = null;
-
- /**
- * Initialization.
- *
- * @param array $args Web and URL arguments
- *
- * @return boolean false if user doesn't exist
- *
- */
- function prepare($args)
- {
- parent::prepare($args);
- $nickname = $this->trimmed('nickname');
- $this->user = User::getKV('nickname', $nickname);
-
- if (!$this->user) {
- // TRANS: Client error when user not found for an rss related action.
- $this->clientError(_('No such user.'));
- } else {
- $this->notices = $this->getNotices($this->limit);
- return true;
- }
- }
-
- /**
- * Get notices
- *
- * @param integer $limit max number of notices to return
- *
- * @return array notices
- */
- function getNotices($limit=0)
+ protected function getNotices()
{
- $stream = new InboxNoticeStream($this->user->getProfile());
- $notice = $stream->getNotices(0, $limit, null, null);
-
- $notices = array();
-
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
-
- return $notices;
+ $stream = new InboxNoticeStream($this->target);
+ return $stream->getNotices(0, $this->limit)->fetchAll();
}
/**
*/
function getChannel()
{
- $user = $this->user;
$c = array('url' => common_local_url('allrss',
array('nickname' =>
- $user->nickname)),
+ $this->target->getNickname())),
// TRANS: Message is used as link title. %s is a user nickname.
- 'title' => sprintf(_('%s and friends'), $user->nickname),
+ 'title' => sprintf(_('%s and friends'), $this->target->getNickname()),
'link' => common_local_url('all',
array('nickname' =>
- $user->nickname)),
+ $this->target->getNickname())),
// TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
'description' => sprintf(_('Updates from %1$s and friends on %2$s!'),
- $user->nickname, common_config('site', 'name')));
+ $this->target->getNickname(), common_config('site', 'name')));
return $c;
}
-
- /**
- * Get image.
- *
- * @return string user avatar URL or null
- */
- function getImage()
- {
- $user = $this->user;
- $profile = $user->getProfile();
- if (!$profile) {
- return null;
- }
- return $profile->avatarUrl(AVATAR_PROFILE_SIZE);
- }
}
{
var $notices = null;
- /**
- * Take arguments for running
- *
- * @param array $args $_REQUEST args
- *
- * @return boolean success flag
- */
- function prepare($args)
+ protected function prepare(array $args=array())
{
parent::prepare($args);
- common_debug("apitimelinetag prepare()");
-
$this->tag = $this->arg('tag');
$this->notices = $this->getNotices();
*
* @return void
*/
- function handle($args)
+ protected function handle()
{
- parent::handle($args);
+ parent::handle();
$this->showTimeline();
}
*/
function getNotices()
{
- $notices = array();
-
- $notice = Notice_tag::getStream(
- $this->tag,
- ($this->page - 1) * $this->count,
- $this->count + 1,
- $this->since_id,
- $this->max_id
- );
-
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
+ $notice = Notice_tag::getStream($this->tag)->getNotices(($this->page - 1) * $this->count,
+ $this->count + 1,
+ $this->since_id,
+ $this->max_id);
- return $notices;
+ return $notice->fetchAll();
}
/**
* @link http://status.net/
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
// @todo FIXME: documentation needed.
-class DeletenoticeAction extends Action
+class DeletenoticeAction extends FormAction
{
- var $error = null;
- var $user = null;
- var $notice = null;
- var $profile = null;
- var $user_profile = null;
+ protected $notice = null;
- function prepare($args)
+ protected function doPreparation()
{
- parent::prepare($args);
-
- $this->user = common_current_user();
-
- if (!$this->user) {
- // TRANS: Error message displayed when trying to perform an action that requires a logged in user.
- common_user_error(_('Not logged in.'));
- exit;
- }
-
- $notice_id = $this->trimmed('notice');
- $this->notice = Notice::getKV($notice_id);
-
- if (!$this->notice) {
- // TRANS: Error message displayed trying to delete a non-existing notice.
- common_user_error(_('No such notice.'));
- exit;
- }
-
- $this->profile = $this->notice->getProfile();
- $this->user_profile = $this->user->getProfile();
+ $this->notice = Notice::getByID($this->trimmed('notice'));
- return true;
- }
-
- function handle($args)
- {
- parent::handle($args);
-
- if ($this->notice->profile_id != $this->user_profile->id &&
- !$this->user->hasRight(Right::DELETEOTHERSNOTICE)) {
+ if (!$this->scoped->sameAs($this->notice->getProfile()) &&
+ !$this->scoped->hasRight(Right::DELETEOTHERSNOTICE)) {
// TRANS: Error message displayed trying to delete a notice that was not made by the current user.
- common_user_error(_('Cannot delete this notice.'));
- exit;
+ $this->clientError(_('Cannot delete this notice.'));
}
- // XXX: Ajax!
- if ($_SERVER['REQUEST_METHOD'] == 'POST') {
- $this->deleteNotice();
- } else if ($_SERVER['REQUEST_METHOD'] == 'GET') {
- $this->showForm();
- }
- }
-
- /**
- * Show the page notice
- *
- * Shows instructions for the page
- *
- * @return void
- */
- function showPageNotice()
- {
- $instr = $this->getInstructions();
- $output = common_markup_to_html($instr);
-
- $this->elementStart('div', 'instructions');
- $this->raw($output);
- $this->elementEnd('div');
+ $this->formOpts['notice'] = $this->notice;
}
function getInstructions()
return _('Delete notice');
}
- /**
- * Wrapper for showing a page
- *
- * Stores an error and shows the page
- *
- * @param string $error Error, if any
- *
- * @return void
- */
- function showForm($error = null)
- {
- $this->error = $error;
- $this->showPage();
- }
-
- /**
- * Insert delete notice form into the content
- *
- * @return void
- */
- function showContent()
- {
- $this->elementStart('form', array('id' => 'form_notice_delete',
- 'class' => 'form_settings',
- 'method' => 'post',
- 'action' => common_local_url('deletenotice')));
- $this->elementStart('fieldset');
- // TRANS: Fieldset legend for the delete notice form.
- $this->element('legend', null, _('Delete notice'));
- $this->hidden('token', common_session_token());
- $this->hidden('notice', $this->trimmed('notice'));
- // TRANS: Message for the delete notice form.
- $this->element('p', null, _('Are you sure you want to delete this notice?'));
- $this->submit('form_action-no',
- // TRANS: Button label on the delete notice form.
- _m('BUTTON','No'),
- 'submit form_action-primary',
- 'no',
- // TRANS: Submit button title for 'No' when deleting a notice.
- _('Do not delete this notice.'));
- $this->submit('form_action-yes',
- // TRANS: Button label on the delete notice form.
- _m('BUTTON','Yes'),
- 'submit form_action-secondary',
- 'yes',
- // TRANS: Submit button title for 'Yes' when deleting a notice.
- _('Delete this notice.'));
- $this->elementEnd('fieldset');
- $this->elementEnd('form');
- }
-
- function deleteNotice()
+ protected function doPost()
{
- // CSRF protection
- $token = $this->trimmed('token');
-
- if (!$token || $token != common_session_token()) {
- // TRANS: Client error displayed when the session token does not match or is not given.
- $this->showForm(_('There was a problem with your session token. ' .
- 'Try again, please.'));
- return;
- }
-
if ($this->arg('yes')) {
- if (Event::handle('StartDeleteOwnNotice', array($this->user, $this->notice))) {
+ if (Event::handle('StartDeleteOwnNotice', array($this->scoped->getUser(), $this->notice))) {
$this->notice->delete();
- Event::handle('EndDeleteOwnNotice', array($this->user, $this->notice));
+ Event::handle('EndDeleteOwnNotice', array($this->scoped->getUser(), $this->notice));
}
- }
-
- $url = common_get_returnto();
-
- if ($url) {
- common_set_returnto(null);
} else {
- $url = common_local_url('public');
+ common_redirect(common_get_returnto(), 303);
}
- common_redirect($url, 303);
+ common_redirect(common_local_url('top'), 303);
}
}
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
+if (!defined('GNUSOCIAL')) { exit(1); }
define('LISTENER', 1);
define('LISTENEE', -1);
define('BOTH', 0);
// @todo XXX: Documentation missing.
-class FoafAction extends Action
+class FoafAction extends ManagedAction
{
function isReadOnly($args)
{
return true;
}
- function prepare($args)
+ protected function doPreparation()
{
- parent::prepare($args);
-
$nickname_arg = $this->arg('nickname');
if (empty($nickname_arg)) {
return true;
}
- function handle($args)
+ public function showPage()
{
- parent::handle($args);
-
header('Content-Type: application/rdf+xml');
$this->startXML();
* @link http://status.net/
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/rssaction.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
define('MEMBERS_PER_SECTION', 27);
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
-class groupRssAction extends Rss10Action
+class GroupRssAction extends TargetedRss10Action
{
/** group we're viewing. */
- var $group = null;
+ protected $group = null;
/**
* Is this page read-only?
return true;
}
- /**
- * Prepare the action
- *
- * Reads and validates arguments and instantiates the attributes.
- *
- * @param array $args $_REQUEST args
- *
- * @return boolean success flag
- */
- function prepare($args)
+ protected function doStreamPreparation()
{
- parent::prepare($args);
$nickname_arg = $this->arg('nickname');
$nickname = common_canonical_nickname($nickname_arg);
$local = Local_group::getKV('nickname', $nickname);
- if (!$local) {
+ if (!$local instanceof Local_group) {
// TRANS: Client error displayed when requesting a group RSS feed for group that does not exist.
$this->clientError(_('No such group.'), 404);
}
- $this->group = User_group::getKV('id', $local->group_id);
-
- if (!$this->group) {
- // TRANS: Client error displayed when requesting a group RSS feed for an object that is not a group.
- $this->clientError(_('No such group.'), 404);
- }
-
- $this->notices = $this->getNotices($this->limit);
- return true;
+ $this->group = $local->getGroup();
+ $this->target = $this->group->getProfile();
}
- function getNotices($limit=0)
+ protected function getNotices()
{
- $group = $this->group;
-
- if (is_null($group)) {
- return null;
- }
-
- $notices = array();
- $notice = $group->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
-
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
-
- return $notices;
+ $stream = $this->group->getNotices(0, $this->limit);
+ return $stream->fetchAll();
}
function getChannel()
{
- $group = $this->group;
$c = array('url' => common_local_url('grouprss',
array('nickname' =>
- $group->nickname)),
+ $this->target->getNickname())),
// TRANS: Message is used as link title. %s is a user nickname.
- 'title' => sprintf(_('%s timeline'), $group->nickname),
- 'link' => common_local_url('showgroup', array('nickname' => $group->nickname)),
+ 'title' => sprintf(_('%s timeline'), $this->target->getNickname()),
+ 'link' => common_local_url('showgroup', array('nickname' => $this->target->getNickname())),
// TRANS: Message is used as link description. %1$s is a group name, %2$s is a site name.
'description' => sprintf(_('Updates from members of %1$s on %2$s!'),
- $group->nickname, common_config('site', 'name')));
+ $this->target->getNickname(), common_config('site', 'name')));
return $c;
}
}
Event::handle('EndLogout', array($this));
- common_redirect(common_local_url('startpage'));
+ common_redirect(common_local_url('top'));
}
// Accessed through the action on events
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/rssaction.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* RSS feed for notice search action class.
*/
class NoticesearchrssAction extends Rss10Action
{
- function init()
- {
- return true;
- }
-
- function prepare($args)
- {
- parent::prepare($args);
- $this->notices = $this->getNotices();
- return true;
- }
-
- function getNotices($limit=0)
+ protected function getNotices()
{
$q = $this->trimmed('q');
$notices = array();
$search_engine = $notice->getSearchEngine('notice');
$search_engine->set_sort_mode('chron');
- if (!$limit) $limit = 20;
- $search_engine->limit(0, $limit, true);
+ $search_engine->limit(0, $this->limit, true);
if (false === $search_engine->query($q)) {
$cnt = 0;
} else {
{
// TRANS: Instructions at top of plugin admin page.
return _('Additional plugins can be enabled and configured manually. ' .
- 'See the <a href="http://status.net/wiki/Plugins">online plugin ' .
+ 'See the <a href="https://git.gnu.io/gnu/gnu-social/blob/master/plugins/README.md">online plugin ' .
'documentation</a> for more details.');
}
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/rssaction.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* RSS feed for public timeline.
*/
class PublicrssAction extends Rss10Action
{
- /**
- * Read arguments and initialize members
- *
- * @param array $args Arguments from $_REQUEST
- * @return boolean success
- */
- function prepare($args)
- {
- parent::prepare($args);
- $this->notices = $this->getNotices($this->limit);
- return true;
- }
-
- /**
- * Initialization.
- *
- * @return boolean true
- */
- function init()
- {
- return true;
- }
-
/**
* Get notices
*
*
* @return array notices
*/
- function getNotices($limit=0)
+ protected function getNotices()
{
- $notices = array();
- $notice = Notice::publicStream(0, ($limit == 0) ? 48 : $limit);
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
-
- return $notices;
+ $stream = Notice::publicStream(0, $this->limit);
+ return $stream->fetchAll();
}
/**
* @link http://status.net/
*/
-if (!defined('STATUSNET')) {
- // This check helps protect against security problems;
- // your code file can't be executed directly from the web.
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Redirect to a given URL
* @link http://status.net/
*/
-class RedirecturlAction extends Action
+class RedirecturlAction extends ManagedAction
{
- protected $id = null;
protected $file = null;
- /**
- * For initializing members of the class.
- *
- * @param array $argarray misc. arguments
- *
- * @return boolean true
- */
- function prepare($argarray)
+ protected function doPreparation()
{
- parent::prepare($argarray);
-
- $this->id = $this->trimmed('id');
-
- if (empty($this->id)) {
- // TRANS: Client exception thrown when no ID parameter was provided.
- throw new ClientException(_('No id parameter.'));
- }
-
- $this->file = File::getKV('id', $this->id);
-
- if (empty($this->file)) {
- // TRANS: Client exception thrown when an invalid ID parameter was provided for a file.
- // TRANS: %d is the provided ID for which the file is not present (number).
- throw new ClientException(sprintf(_('No such file "%d".'),
- $this->id),
- 404);
- }
+ $this->file = File::getByID($this->int('id'));
return true;
}
- /**
- * Handler method
- *
- * @param array $argarray is ignored since it's now passed in in prepare()
- *
- * @return void
- */
- function handle($argarray=null)
+ public function showPage()
{
common_redirect($this->file->url, 307);
}
- /**
- * Return true if read only.
- *
- * MAY override
- *
- * @param array $args other arguments
- *
- * @return boolean is read only action?
- */
function isReadOnly($args)
{
return true;
}
- /**
- * Return last modified, if applicable.
- *
- * MAY override
- *
- * @return string last modified http header
- */
function lastModified()
{
// For comparison with If-Last-Modified
*/
function etag()
{
- return 'W/"' . implode(':', array($this->arg('action'),
+ return 'W/"' . implode(':', array($this->getActionName(),
common_user_cache_hash(),
common_language(),
- $this->file->id)) . '"';
+ $this->file->getID())) . '"';
}
}
*/
class RepliesAction extends ShowstreamAction
{
- var $page = null;
- var $notice;
-
- protected function getStream()
+ public function getStream()
{
return new ReplyNoticeStream($this->target->getID(), $this->scoped);
}
// TRANS: Link for feed with replies for a user.
// TRANS: %s is a user nickname.
sprintf(_('Replies feed for %s (Activity Streams JSON)'),
- $this->user->nickname)),
+ $this->target->getNickname())),
new Feed(Feed::RSS1,
common_local_url('repliesrss',
array('nickname' => $this->target->getNickname())),
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
-
-require_once(INSTALLDIR.'/lib/rssaction.php');
+if (!defined('GNUSOCIAL')) { exit(1); }
// Formatting of RSS handled by Rss10Action
-class RepliesrssAction extends Rss10Action
+class RepliesrssAction extends TargetedRss10Action
{
- var $user = null;
-
- function prepare($args)
+ protected function getNotices()
{
- parent::prepare($args);
- $nickname = $this->trimmed('nickname');
- $this->user = User::getKV('nickname', $nickname);
-
- if (!$this->user) {
- // TRANS: Client error displayed when providing a non-existing nickname in a RSS 1.0 action.
- $this->clientError(_('No such user.'));
- } else {
- $this->notices = $this->getNotices($this->limit);
- return true;
- }
- }
-
- function getNotices($limit=0)
- {
- $user = $this->user;
-
- $notice = $user->getReplies(0, ($limit == 0) ? 48 : $limit);
-
- $notices = array();
-
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
-
- return $notices;
+ $stream = $this->target->getReplies(0, $this->limit);
+ return $stream->fetchAll();
}
function getChannel()
{
- $user = $this->user;
$c = array('url' => common_local_url('repliesrss',
array('nickname' =>
- $user->nickname)),
+ $this->target->getNickname())),
// TRANS: RSS reply feed title. %s is a user nickname.
- 'title' => sprintf(_("Replies to %s"), $user->nickname),
+ 'title' => sprintf(_("Replies to %s"), $this->target->getNickname()),
'link' => common_local_url('replies',
- array('nickname' =>
- $user->nickname)),
+ array('nickname' => $this->target->getNickname())),
// TRANS: RSS reply feed description.
// TRANS: %1$s is a user nickname, %2$s is the StatusNet site name.
'description' => sprintf(_('Replies to %1$s on %2$s.'),
- $user->nickname, common_config('site', 'name')));
+ $this->target->getNickname(), common_config('site', 'name')));
return $c;
}
- function getImage()
- {
- $profile = $this->user->getProfile();
- return $profile->avatarUrl(AVATAR_PROFILE_SIZE);
- }
-
function isReadOnly($args)
{
return true;
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Prints out a static robots.txt
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*/
-class RobotstxtAction extends Action
+class RobotstxtAction extends ManagedAction
{
- /**
- * Handles requests
- *
- * Since this is a relatively static document, we
- * don't do a prepare()
- *
- * @param array $args GET, POST, and URL params; unused.
- *
- * @return void
- */
- function handle($args)
+ public function showPage()
{
if (Event::handle('StartRobotsTxt', array($this))) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
-class ShowstreamAction extends ProfileAction
+class ShowstreamAction extends NoticestreamAction
{
- var $notice;
+ protected $target = null;
protected function doPreparation()
{
// showstream requires a nickname
- $nickname_arg = $this->arg('nickname');
+ $nickname_arg = $this->trimmed('nickname');
$nickname = common_canonical_nickname($nickname_arg);
// Permanent redirect on non-canonical nickname
-
if ($nickname_arg != $nickname) {
$args = array('nickname' => $nickname);
if ($this->arg('page') && $this->arg('page') != 1) {
}
common_redirect(common_local_url($this->getActionName(), $args), 301);
}
- $this->user = User::getKV('nickname', $nickname);
- if (!$this->user) {
+ try {
+ $user = User::getByNickname($nickname);
+ } catch (NoSuchUserException $e) {
$group = Local_group::getKV('nickname', $nickname);
if ($group instanceof Local_group) {
common_redirect($group->getProfile()->getUrl());
}
- // TRANS: Client error displayed when calling a profile action without specifying a user.
- $this->clientError(_('No such user.'), 404);
- }
-
- $this->target = $this->user->getProfile();
- }
- protected function profileActionPreparation()
- {
- $stream = $this->getStream();
- $this->notice = $stream->getNotices(($this->page-1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
-
- if ($this->page > 1 && $this->notice->N == 0) {
- // TRANS: Client error when page not found (404).
- $this->clientError(_('No such page.'), 404);
+ // No user nor group found, throw the NoSuchUserException again
+ throw $e;
}
+
+ $this->target = $user->getProfile();
}
- protected function getStream()
+ public function getStream()
{
if (empty($this->tag)) {
$stream = new ProfileNoticeStream($this->target, $this->scoped);
{
parent::showSections();
if (!common_config('performance', 'high')) {
- $cloud = new PersonalTagCloudSection($this, $this->user);
+ $cloud = new PersonalTagCloudSection($this->target, $this);
$cloud->show();
}
}
{
$options = parent::noticeFormOptions();
- if (!$this->scoped instanceof Profile || $this->scoped->id != $this->target->id) {
+ if (!$this->scoped instanceof Profile || !$this->scoped->sameAs($this->target)) {
$options['to_profile'] = $this->target;
}
+++ /dev/null
-<?php
-/**
- * Startpage action. Decides what to show on the first page.
- */
-
-if (!defined('GNUSOCIAL')) { exit(1); }
-
-class StartpageAction extends ManagedAction
-{
- function isReadOnly($args)
- {
- return true;
- }
-
- function showPage()
- {
- if (common_config('singleuser', 'enabled')) {
- $user = User::singleUser();
- common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)), 303);
- } elseif (common_config('public', 'localonly')) {
- common_redirect(common_local_url('public'), 303);
- } else {
- common_redirect(common_local_url('networkpublic'), 303);
- }
- }
-}
* @link http://status.net/
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* A list of the user's subscriptions
function showPageNotice()
{
- if ($this->scoped instanceof Profile && $this->scoped->id === $this->target->id) {
+ if ($this->scoped instanceof Profile && $this->scoped->sameAs($this->getTarget())) {
$this->element('p', null,
// TRANS: Page notice for page with an overview of all subscriptions
// TRANS: of the logged in user's own profile.
common_set_returnto($this->selfUrl());
- $this->notice = Notice_tag::getStream($this->tag, (($this->page-1)*NOTICES_PER_PAGE), NOTICES_PER_PAGE + 1);
+ $this->notice = Notice_tag::getStream($this->tag)->getNotices(($this->page-1)*NOTICES_PER_PAGE,
+ NOTICES_PER_PAGE + 1);
if($this->page > 1 && $this->notice->N == 0){
// TRANS: Client error when page not found (404).
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
-
-require_once(INSTALLDIR.'/lib/rssaction.php');
+if (!defined('GNUSOCIAL')) { exit(1); }
// Formatting of RSS handled by Rss10Action
+
class TagrssAction extends Rss10Action
{
- var $tag;
+ protected $tag;
- function prepare($args) {
- parent::prepare($args);
+ protected function doStreamPreparation()
+ {
$tag = common_canonical_tag($this->trimmed('tag'));
$this->tag = Notice_tag::getKV('tag', $tag);
- if (!$this->tag) {
+ if (!$this->tag instanceof Notice_tag) {
// TRANS: Client error when requesting a tag feed for a non-existing tag.
$this->clientError(_('No such tag.'));
- } else {
- $this->notices = $this->getNotices($this->limit);
- return true;
}
}
- function getNotices($limit=0)
+ protected function getNotices()
{
- $tag = $this->tag;
-
- if (is_null($tag)) {
- return null;
- }
-
- $notice = Notice_tag::getStream($tag->tag, 0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
-
- return $notices;
+ $stream = Notice_tag::getStream($this->tag->tag)->getNotices(0, $this->limit);
+ return $stream->fetchAll();
}
function getChannel()
* 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 Top
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET')) {
- // This check helps protect against security problems;
- // your code file can't be executed directly from the web.
- exit(1);
-}
-
-/**
- * An action to redirect to the top of the site
- *
* @category Action
- * @package StatusNet
+ * @package GNUsocial
* @author Evan Prodromou <evan@status.net>
+ * @author Mikael Nordfeldth <mmn@hethane.se>
* @copyright 2010 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link http://status.net/
+ * @copyright 2015 Free Software Foundation, Inc.
+ * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL 3.0
+ * @link https://gnu.io/social
*/
-class TopAction extends Action
-{
- /**
- * For initializing members of the class.
- *
- * @param array $argarray misc. arguments
- *
- * @return boolean true
- */
+if (!defined('GNUSOCIAL')) { exit(1); }
- function prepare($argarray)
- {
- parent::prepare($argarray);
- return true;
- }
-
- /**
- * Handler method
- *
- * @param array $argarray is ignored since it's now passed in in prepare()
- *
- * @return void
- */
-
- function handle($argarray=null)
+class TopAction extends ManagedAction
+{
+ public function showPage()
{
if (common_config('singleuser', 'enabled')) {
- $url = common_local_url('showstream', array('nickname' => User::singleUserNickname()));
+ $user = User::singleUser();
+ common_redirect(common_local_url('showstream', array('nickname' => $user->getNickname())), 303);
+ } elseif (common_config('public', 'localonly')) {
+ common_redirect(common_local_url('public'), 303);
} else {
- $url = common_local_url('public');
+ common_redirect(common_local_url('networkpublic'), 303);
}
-
- // XXX: Permanent? I think so.
-
- common_redirect($url, 301);
-
- return;
}
}
if ($this->page == 1) {
// TRANS: Page title for first page of groups for a user.
// TRANS: %s is a nickname.
- return sprintf(_('%s groups'), $this->user->nickname);
+ return sprintf(_('%s groups'), $this->getTarget()->getNickname());
} else {
// TRANS: Page title for all but the first page of groups for a user.
// TRANS: %1$s is a nickname, %2$d is a page number.
return sprintf(_('%1$s groups, page %2$d'),
- $this->user->nickname,
+ $this->getTarget()->getNickname(),
$this->page);
}
}
$offset = ($this->page-1) * GROUPS_PER_PAGE;
$limit = GROUPS_PER_PAGE + 1;
- $groups = $this->user->getGroups($offset, $limit);
+ $groups = $this->getTarget()->getGroups($offset, $limit);
if ($groups instanceof User_group) {
- $gl = new GroupList($groups, $this->user, $this);
+ $gl = new GroupList($groups, $this->getTarget(), $this);
$cnt = $gl->show();
$this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE,
$this->page, 'usergroups',
- array('nickname' => $this->user->nickname));
+ array('nickname' => $this->getTarget()->getNickname()));
} else {
$this->showEmptyListMessage();
}
{
// TRANS: Text on group page for a user that is not a member of any group.
// TRANS: %s is a user nickname.
- $message = sprintf(_('%s is not a member of any group.'), $this->user->nickname) . ' ';
+ $message = sprintf(_('%s is not a member of any group.'), $this->getTarget()->getNickname()) . ' ';
if (common_logged_in()) {
$current_user = common_current_user();
- if ($this->user->id === $current_user->id) {
+ if ($this->scoped->sameAs($this->getTarget())) {
// TRANS: Text on group page for a user that is not a member of any group. This message contains
// TRANS: a Markdown link in the form [link text](link) and a variable that should not be changed.
$message .= _('Try [searching for groups](%%action.groupsearch%%) and joining them.');
function showProfileBlock()
{
- $block = new AccountProfileBlock($this, $this->profile);
+ $block = new AccountProfileBlock($this, $this->getTarget());
$block->show();
}
}
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
-
-require_once(INSTALLDIR.'/lib/rssaction.php');
+if (!defined('GNUSOCIAL')) { exit(1); }
// Formatting of RSS handled by Rss10Action
-class UserrssAction extends Rss10Action
+class UserrssAction extends TargetedRss10Action
{
- var $tag = null;
+ protected $tag = null;
- function prepare($args)
+ protected function doStreamPreparation()
{
- parent::prepare($args);
- $nickname = $this->trimmed('nickname');
- $this->user = User::getKV('nickname', $nickname);
$this->tag = $this->trimmed('tag');
-
- if (!$this->user) {
- // TRANS: Client error displayed when user not found for an action.
- $this->clientError(_('No such user.'));
- }
-
- if (!empty($this->tag)) {
- $this->notices = $this->getTaggedNotices();
- } else {
- $this->notices = $this->getNotices();
- }
-
- return true;
- }
-
- function getTaggedNotices()
- {
- $notice = $this->user->getTaggedNotices(
- $this->tag,
- 0,
- ($this->limit == 0) ? NOTICES_PER_PAGE : $this->limit,
- 0,
- 0
- );
-
- $notices = array();
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
-
- return $notices;
}
-
- function getNotices()
+ protected function getNotices()
{
- $notice = $this->user->getNotices(
- 0,
- ($this->limit == 0) ? NOTICES_PER_PAGE : $this->limit
- );
-
- $notices = array();
- while ($notice->fetch()) {
- $notices[] = clone($notice);
+ if (!empty($this->tag)) {
+ $stream = $this->target->getTaggedNotices($this->tag, 0, $this->limit);
+ return $stream->fetchAll();
}
+ // otherwise we fetch a normal user stream
- return $notices;
+ $stream = $this->target->getNotices(0, $this->limit);
+ return $stream->fetchAll();
}
function getChannel()
{
- $user = $this->user;
- $profile = $user->getProfile();
$c = array('url' => common_local_url('userrss',
array('nickname' =>
- $user->nickname)),
+ $this->target->getNickname())),
// TRANS: Message is used as link title. %s is a user nickname.
- 'title' => sprintf(_('%s timeline'), $user->nickname),
- 'link' => $profile->profileurl,
+ 'title' => sprintf(_('%s timeline'), $this->target->getNickname()),
+ 'link' => $this->target->getUrl(),
// TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
'description' => sprintf(_('Updates from %1$s on %2$s!'),
- $user->nickname, common_config('site', 'name')));
+ $this->target->getNickname(), common_config('site', 'name')));
return $c;
}
- function getImage()
- {
- $profile = $this->user->getProfile();
- return $profile->avatarUrl(AVATAR_PROFILE_SIZE);
- }
-
// override parent to add X-SUP-ID URL
- function initRss($limit=0)
+ function initRss()
{
- $url = common_local_url('sup', null, null, $this->user->id);
+ $url = common_local_url('sup', null, null, $this->target->getID());
header('X-SUP-ID: '.$url);
- parent::initRss($limit);
+ parent::initRss();
}
function isReadOnly($args)
* size (optional): byte size from Content-Length header
* time (optional): timestamp from Last-Modified header
*/
- public function where($in_url, $discover=true) {
+ static function where($in_url, $discover=true) {
// let's see if we know this...
try {
$a = File::getByUrl($in_url);
try {
$b = File_redirection::getByUrl($in_url);
// this is a redirect to $b->file_id
- $a = File::getKV('id', $b->file_id);
+ $a = File::getByID($b->file_id);
return $a->url;
} catch (NoResultException $e) {
// Oh well, let's keep going
if ($discover) {
$ret = File_redirection::lookupWhere($in_url);
return $ret;
- } else {
- // No manual dereferencing; leave the unknown URL as is.
- return $in_url;
}
+
+ // No manual dereferencing; leave the unknown URL as is.
+ return $in_url;
}
/**
* @param User $user whose shortening options to use; defaults to the current web session user
* @return string
*/
- function makeShort($long_url, $user=null)
+ static function makeShort($long_url, $user=null)
{
$canon = File_redirection::_canonUrl($long_url);
// Did we get one? Is it shorter?
- if (!empty($short_url)) {
- return $short_url;
- } else {
- return $long_url;
- }
+ return !empty($short_url) ? $short_url : $long_url;
}
/**
* @return string
*/
- function forceShort($long_url, $user)
+ static function forceShort($long_url, $user)
{
$canon = File_redirection::_canonUrl($long_url);
$short_url = File_redirection::_userMakeShort($canon, $user, true);
// Did we get one? Is it shorter?
- if (!empty($short_url)) {
- return $short_url;
- } else {
- return $long_url;
- }
+ return !empty($short_url) ? $short_url : $long_url;
}
static function _userMakeShort($long_url, User $user=null, $force = false) {
$group->find(true);
if (!$group instanceof User_group) {
common_log(LOG_ERR, 'User_group does not exist for Local_group: '.$this->group_id);
- throw new NoResultException($group);
+ throw new NoSuchGroupException(array('id' => $this->group_id));
}
return $group;
}
$this->_attachments[$this->id] = $attachments;
}
- function publicStream($offset=0, $limit=20, $since_id=0, $max_id=0)
+ static function publicStream($offset=0, $limit=20, $since_id=null, $max_id=null)
{
$stream = new PublicNoticeStream();
return $stream->getNotices($offset, $limit, $since_id, $max_id);
}
-
- function conversationStream($id, $offset=0, $limit=20, $since_id=0, $max_id=0)
+ static function conversationStream($id, $offset=0, $limit=20, $since_id=null, $max_id=null)
{
$stream = new ConversationNoticeStream($id);
-
return $stream->getNotices($offset, $limit, $since_id, $max_id);
}
*/
function hasConversation()
{
- if (!empty($this->conversation)) {
- $conversation = Notice::conversationStream(
- $this->conversation,
- 1,
- 1
- );
-
- if ($conversation->N > 0) {
- return true;
- }
+ if (empty($this->conversation)) {
+ // this notice is not part of a conversation apparently
+ // FIXME: all notices should have a conversation value, right?
+ return false;
}
- return false;
+
+ $stream = new ConversationNoticeStream($this->conversation);
+ $notice = $stream->getNotices(/*offset*/ 1, /*limit*/ 1);
+
+ // if our "offset 1, limit 1" query got a result, return true else false
+ return $notice->N > 0;
}
/**
$root = new Notice;
$root->conversation = $this->conversation;
$root->orderBy('notice.created ASC');
- $root->find();
- $root->fetch();
+ $root->find(true); // true means "fetch first result"
$root->free();
return $root;
}
return $notice->fetchAll('id');
}
- function locationOptions($lat, $lon, $location_id, $location_ns, $profile = null)
+ static function locationOptions($lat, $lon, $location_id, $location_ns, $profile = null)
{
$options = array();
static function getStream($tag, $offset=0, $limit=20, $sinceId=0, $maxId=0)
{
$stream = new TagNoticeStream($tag);
-
- return $stream->getNotices($offset, $limit, $sinceId, $maxId);
+ return $stream;
}
function blowCache($blowLast=false)
return null;
}
+ function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
+ {
+ return Reply::stream($this->getID(), $offset, $limit, $since_id, $before_id);
+ }
+
function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
{
$stream = new TaggedProfileNoticeStream($this, $tag);
return $this;
}
+ public function sameAs(Profile $other)
+ {
+ return $this->getID() === $other->getID();
+ }
+
/**
* This will perform shortenLinks with the connected User object.
*
return $result;
}
- function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
+ static function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
{
$stream = new ReplyNoticeStream($user_id);
-
return $stream->getNotices($offset, $limit, $since_id, $max_id);
}
}
return $rq;
}
- public function exists(Profile $subscriber, Profile $other)
+ static function exists(Profile $subscriber, Profile $other)
{
- $sub = Subscription_queue::pkeyGet(array('subscriber' => $subscriber->id,
- 'subscribed' => $other->id));
+ $sub = Subscription_queue::pkeyGet(array('subscriber' => $subscriber->getID(),
+ 'subscribed' => $other->getID()));
return ($sub instanceof Subscription_queue);
}
return $this->_profile[$this->id];
}
+ public function sameAs(Profile $other)
+ {
+ return $this->getProfile()->sameAs($other);
+ }
+
public function getUri()
{
return $this->uri;
return $this->getProfile()->getNickname();
}
+ static function getByNickname($nickname)
+ {
+ $user = User::getKV('nickname', $nickname);
+ if (!$user instanceof User) {
+ throw new NoSuchUserException(array('nickname' => $nickname));
+ }
+
+ return $user;
+ }
+
function isSubscribed(Profile $other)
{
return $this->getProfile()->isSubscribed($other);
function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
{
- return Reply::stream($this->id, $offset, $limit, $since_id, $before_id);
+ return $this->getProfile()->getReplies($offset, $limit, $since_id, $before_id);
}
function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) {
* identity check.
*
* LIBRARY DESIGN
- *
+ *
* This consumer library is designed with that flow in mind. The goal
* is to make it as easy as possible to perform the above steps
* securely.
$loader->fromSession($endpoint_data);
$message = Auth_OpenID_Message::fromPostArgs($query);
- $response = $this->consumer->complete($message, $endpoint,
+ $response = $this->consumer->complete($message, $endpoint,
$current_url);
$this->session->del($this->_token_key);
$this->store = $store;
$this->negotiator = Auth_OpenID_getDefaultNegotiator();
$this->_use_assocs = (is_null($this->store) ? false : true);
+ if (get_class($this->store) == "Auth_OpenID_DumbStore") {
+ $this->_use_assocs = false;
+ }
$this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
'_completeInvalid');
return call_user_func_array(array($this, $method),
- array($message, &$endpoint, $return_to));
+ array($message, $endpoint, $return_to));
}
/**
list($unused, $services) = call_user_func_array($this->discoverMethod,
array(
$claimed_id,
- &$this->fetcher,
+ $this->fetcher,
));
if (!$services) {
/**
* @access private
*/
- function _verifyDiscoveryServices($claimed_id,
+ function _verifyDiscoveryServices($claimed_id,
$services, $to_match_endpoints)
{
// Search the services resulting from discovery to find one
foreach ($services as $endpoint) {
foreach ($to_match_endpoints as $to_match_endpoint) {
- $result = $this->_verifyDiscoverySingle($endpoint,
+ $result = $this->_verifyDiscoverySingle($endpoint,
$to_match_endpoint);
if (!Auth_OpenID::isFailure($result)) {
}
}
$ca_message = $message->copy();
- $ca_message->setArg(Auth_OpenID_OPENID_NS, 'mode',
+ $ca_message->setArg(Auth_OpenID_OPENID_NS, 'mode',
'check_authentication');
return $ca_message;
}
$expires_in = Auth_OpenID::intval($expires_in_str);
if ($expires_in === false) {
-
+
$err = sprintf("Could not parse expires_in from association ".
"response %s", print_r($assoc_response, true));
return new Auth_OpenID_FailureResponse(null, $err);
function htmlMarkup($realm, $return_to=null, $immediate=false,
$form_tag_attrs=null)
{
- $form = $this->formMarkup($realm, $return_to, $immediate,
+ $form = $this->formMarkup($realm, $return_to, $immediate,
$form_tag_attrs);
if (Auth_OpenID::isFailure($form)) {
}
if ($handle = opendir($dir)) {
- while ($item = readdir($handle)) {
+ while (false !== ($item = readdir($handle))) {
if (!in_array($item, array('.', '..'))) {
if (is_dir($dir . $item)) {
// no handle given, receiving the latest issued
$serverKey = $this->associationServerKey($server_url);
- $lastKey = $this->redis->lpop($serverKey);
- if (!$lastKey) { return null; }
+ $lastKey = $this->redis->lindex($serverKey, -1);
+ if (!$lastKey) {
+ // no previous association with this server
+ return null;
+ }
// get association, return null if failed
return $this->getAssociationFromServer($lastKey);
// SETNX will set the value only of the key doesn't exist yet.
$nonceKey = $this->nonceKey($server_url, $salt);
- $added = $this->predis->setnx($nonceKey);
+ $added = $this->redis->setnx($nonceKey, "1");
if ($added) {
// Will set expiration
- $this->predis->expire($nonceKey, $Auth_OpenID_SKEW);
+ $this->redis->expire($nonceKey, $Auth_OpenID_SKEW);
return true;
} else {
return false;
if ($parts['host'] == 'localhost') {
return true;
}
-
+
$host_parts = explode('.', $parts['host']);
if ($parts['wildcard']) {
// Remove the empty string from the beginning of the array
}
call_user_func_array($discover_function,
- array($relying_party_url, &$fetcher));
+ array($relying_party_url, $fetcher));
$return_to_urls = array();
$matching_endpoints = Auth_OpenID_extractReturnURL($endpoints);
list($yadis_url, $services) = call_user_func_array($discover_cb,
array(
$this->url,
- &$fetcher,
+ $fetcher,
));
$manager = $this->createManager($services, $yadis_url);
$this->reset();
$c = curl_init();
+ if (defined('Auth_OpenID_DISABLE_SSL_VERIFYPEER')
+ && Auth_OpenID_DISABLE_SSL_VERIFYPEER === true) {
+ trigger_error(
+ 'You have disabled SSL verifcation, this is a TERRIBLE ' .
+ 'idea in almost all cases. Set Auth_OpenID_DISABLE_SSL_' .
+ 'VERIFYPEER to false if you want to be safe again',
+ E_USER_WARNING);
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
+ }
if ($c === false) {
Auth_OpenID::log(
$this->_entity_replacements));
}
- /**
- * Replace HTML entities (amp, lt, gt, and quot) as well as
- * numeric entities (e.g. #x9f;) with their actual values and
- * return the new string.
- *
- * @access private
- * @param string $str The string in which to look for entities
- * @return string $new_str The new string entities decoded
- */
- function replaceEntities($str)
- {
- foreach ($this->_entity_replacements as $old => $new) {
- $str = preg_replace(sprintf("/&%s;/", $old), $new, $str);
- }
-
- // Replace numeric entities because html_entity_decode doesn't
- // do it for us.
- $str = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $str);
- $str = preg_replace('~&#([0-9]+);~e', 'chr(\\1)', $str);
-
- return $str;
- }
-
/**
* Strip single and double quotes off of a string, if they are
* present.
$link_attrs = array();
foreach ($attr_matches[0] as $index => $full_match) {
$name = $attr_matches[1][$index];
- $value = $this->replaceEntities(
+ $value = html_entity_decode(
$this->removeQuotes($attr_matches[2][$index]));
$link_attrs[strtolower($name)] = $value;
return false;
}
+ if (isset($this->doc->doctype)) {
+ return false;
+ }
+
$this->xpath = new DOMXPath($this->doc);
if ($this->xpath) {
function Auth_Yadis_getXMLParser()
{
global $__Auth_Yadis_defaultParser;
-
+
if (isset($__Auth_Yadis_defaultParser)) {
return $__Auth_Yadis_defaultParser;
}
-
+
foreach(Auth_Yadis_getSupportedExtensions() as $extension => $classname)
{
if (extension_loaded($extension))
return $p;
}
}
-
+
return false;
}
foreach ($filters as $filter) {
- if (call_user_func_array($filter, array(&$service))) {
+ if (call_user_func_array($filter, array($service))) {
$matches++;
if ($filter_mode == SERVICES_YADIS_MATCH_ANY) {
}
$yadis_result = call_user_func_array($discover_func,
- array($input_url, &$fetcher));
+ array($input_url, $fetcher));
if ($yadis_result === null) {
return array($input_url, array());
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version CVS: $Id: mimeDecode.php,v 1.48 2006/12/03 13:43:33 cipri Exp $
+ * @version CVS: $Id: mimeDecode.php 305875 2010-12-01 07:17:10Z alan_k $
* @link http://pear.php.net/package/Mail_mime
*/
*/
var $_decode_headers;
+ /**
+ * Flag to determine whether to include attached messages
+ * as body in the returned object. Depends on $_include_bodies
+ *
+ * @var boolean
+ * @access private
+ */
+ var $_rfc822_bodies;
+
/**
* Constructor.
*
$this->_body = $body;
$this->_decode_bodies = false;
$this->_include_bodies = true;
+ $this->_rfc822_bodies = false;
}
/**
function decode($params = null)
{
// determine if this method has been called statically
- $isStatic = !(isset($this) && get_class($this) == __CLASS__);
+ $isStatic = empty($this) || !is_a($this, __CLASS__);
// Have we been called statically?
// If so, create an object and pass details to that.
$params['decode_bodies'] : false;
$this->_decode_headers = isset($params['decode_headers']) ?
$params['decode_headers'] : false;
+ $this->_rfc822_bodies = isset($params['rfc_822bodies']) ?
+ $params['rfc_822bodies'] : false;
$structure = $this->_decode($this->_header, $this->_body);
if ($structure === false) {
$headers = $this->_parseHeaders($headers);
foreach ($headers as $value) {
+ $value['value'] = $this->_decode_headers ? $this->_decodeHeader($value['value']) : $value['value'];
if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) {
$return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]);
$return->headers[strtolower($value['name'])][] = $value['value'];
}
}
- reset($headers);
- while (list($key, $value) = each($headers)) {
+
+ foreach ($headers as $key => $value) {
$headers[$key]['name'] = strtolower($headers[$key]['name']);
switch ($headers[$key]['name']) {
}
if (isset($content_type['other'])) {
- while (list($p_name, $p_value) = each($content_type['other'])) {
+ foreach($content_type['other'] as $p_name => $p_value) {
$return->ctype_parameters[$p_name] = $p_value;
}
}
$content_disposition = $this->_parseHeaderValue($headers[$key]['value']);
$return->disposition = $content_disposition['value'];
if (isset($content_disposition['other'])) {
- while (list($p_name, $p_value) = each($content_disposition['other'])) {
+ foreach($content_disposition['other'] as $p_name => $p_value) {
$return->d_parameters[$p_name] = $p_value;
}
}
case 'multipart/alternative':
case 'multipart/related':
case 'multipart/mixed':
+ case 'application/vnd.wap.multipart.related':
if(!isset($content_type['other']['boundary'])){
$this->_error = 'No boundary found for ' . $content_type['value'] . ' part';
return false;
break;
case 'message/rfc822':
- $obj = &new Mail_mimeDecode($body);
+ if ($this->_rfc822_bodies) {
+ $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
+ $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body);
+ }
+ $obj = new Mail_mimeDecode($body);
$return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies,
'decode_bodies' => $this->_decode_bodies,
'decode_headers' => $this->_decode_headers));
if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
return array($match[1], $match[2]);
}
+ // bug #17325 - empty bodies are allowed. - we just check that at least one line
+ // of headers exist..
+ if (count(explode("\n",$input))) {
+ return array($input, '');
+ }
$this->_error = 'Could not split header and body';
return false;
}
if ($input !== '') {
// Unfold the input
$input = preg_replace("/\r?\n/", "\r\n", $input);
+ //#7065 - wrapping.. with encoded stuff.. - probably not needed,
+ // wrapping space should only get removed if the trailing item on previous line is a
+ // encoded character
+ $input = preg_replace("/=\r\n(\t| )+/", '=', $input);
$input = preg_replace("/\r\n(\t| )+/", ' ', $input);
+
$headers = explode("\r\n", trim($input));
foreach ($headers as $value) {
$return[] = array(
'name' => $hdr_name,
- 'value' => $this->_decode_headers ? $this->_decodeHeader($hdr_value) : $hdr_value
+ 'value' => $hdr_value
);
}
} else {
function _parseHeaderValue($input)
{
- if (($pos = strpos($input, ';')) !== false) {
+ if (($pos = strpos($input, ';')) === false) {
+ $input = $this->_decode_headers ? $this->_decodeHeader($input) : $input;
+ $return['value'] = trim($input);
+ return $return;
+ }
+
+
- $return['value'] = trim(substr($input, 0, $pos));
- $input = trim(substr($input, $pos+1));
+ $value = substr($input, 0, $pos);
+ $value = $this->_decode_headers ? $this->_decodeHeader($value) : $value;
+ $return['value'] = trim($value);
+ $input = trim(substr($input, $pos+1));
- if (strlen($input) > 0) {
+ if (!strlen($input) > 0) {
+ return $return;
+ }
+ // at this point input contains xxxx=".....";zzzz="...."
+ // since we are dealing with quoted strings, we need to handle this properly..
+ $i = 0;
+ $l = strlen($input);
+ $key = '';
+ $val = false; // our string - including quotes..
+ $q = false; // in quote..
+ $lq = ''; // last quote..
+
+ while ($i < $l) {
+
+ $c = $input[$i];
+ //var_dump(array('i'=>$i,'c'=>$c,'q'=>$q, 'lq'=>$lq, 'key'=>$key, 'val' =>$val));
- // This splits on a semi-colon, if there's no preceeding backslash
- // Now works with quoted values; had to glue the \; breaks in PHP
- // the regex is already bordering on incomprehensible
- $splitRegex = '/([^;\'"]*[\'"]([^\'"]*([^\'"]*)*)[\'"][^;\'"]*|([^;]+))(;|$)/';
- preg_match_all($splitRegex, $input, $matches);
- $parameters = array();
- for ($i=0; $i<count($matches[0]); $i++) {
- $param = $matches[0][$i];
- while (substr($param, -2) == '\;') {
- $param .= $matches[0][++$i];
+ $escaped = false;
+ if ($c == '\\') {
+ $i++;
+ if ($i == $l-1) { // end of string.
+ break;
+ }
+ $escaped = true;
+ $c = $input[$i];
+ }
+
+
+ // state - in key..
+ if ($val === false) {
+ if (!$escaped && $c == '=') {
+ $val = '';
+ $key = trim($key);
+ $i++;
+ continue;
+ }
+ if (!$escaped && $c == ';') {
+ if ($key) { // a key without a value..
+ $key= trim($key);
+ $return['other'][$key] = '';
+ $return['other'][strtolower($key)] = '';
+ }
+ $key = '';
+ }
+ $key .= $c;
+ $i++;
+ continue;
+ }
+
+ // state - in value.. (as $val is set..)
+
+ if ($q === false) {
+ // not in quote yet.
+ if ((!strlen($val) || $lq !== false) && $c == ' ' || $c == "\t") {
+ $i++;
+ continue; // skip leading spaces after '=' or after '"'
+ }
+ if (!$escaped && ($c == '"' || $c == "'")) {
+ // start quoted area..
+ $q = $c;
+ // in theory should not happen raw text in value part..
+ // but we will handle it as a merged part of the string..
+ $val = !strlen(trim($val)) ? '' : trim($val);
+ $i++;
+ continue;
+ }
+ // got end....
+ if (!$escaped && $c == ';') {
+
+ $val = trim($val);
+ $added = false;
+ if (preg_match('/\*[0-9]+$/', $key)) {
+ // this is the extended aaa*0=...;aaa*1=.... code
+ // it assumes the pieces arrive in order, and are valid...
+ $key = preg_replace('/\*[0-9]+$/', '', $key);
+ if (isset($return['other'][$key])) {
+ $return['other'][$key] .= $val;
+ if (strtolower($key) != $key) {
+ $return['other'][strtolower($key)] .= $val;
+ }
+ $added = true;
+ }
+ // continue and use standard setters..
+ }
+ if (!$added) {
+ $return['other'][$key] = $val;
+ $return['other'][strtolower($key)] = $val;
}
- $parameters[] = $param;
+ $val = false;
+ $key = '';
+ $lq = false;
+ $i++;
+ continue;
}
- for ($i = 0; $i < count($parameters); $i++) {
- $param_name = trim(substr($parameters[$i], 0, $pos = strpos($parameters[$i], '=')), "'\";\t\\ ");
- $param_value = trim(str_replace('\;', ';', substr($parameters[$i], $pos + 1)), "'\";\t\\ ");
- if ($param_value[0] == '"') {
- $param_value = substr($param_value, 1, -1);
+ $val .= $c;
+ $i++;
+ continue;
+ }
+
+ // state - in quote..
+ if (!$escaped && $c == $q) { // potential exit state..
+
+ // end of quoted string..
+ $lq = $q;
+ $q = false;
+ $i++;
+ continue;
+ }
+
+ // normal char inside of quoted string..
+ $val.= $c;
+ $i++;
+ }
+
+ // do we have anything left..
+ if (strlen(trim($key)) || $val !== false) {
+
+ $val = trim($val);
+ $added = false;
+ if ($val !== false && preg_match('/\*[0-9]+$/', $key)) {
+ // no dupes due to our crazy regexp.
+ $key = preg_replace('/\*[0-9]+$/', '', $key);
+ if (isset($return['other'][$key])) {
+ $return['other'][$key] .= $val;
+ if (strtolower($key) != $key) {
+ $return['other'][strtolower($key)] .= $val;
}
- $return['other'][$param_name] = $param_value;
- $return['other'][strtolower($param_name)] = $param_value;
+ $added = true;
}
+ // continue and use standard setters..
+ }
+ if (!$added) {
+ $return['other'][$key] = $val;
+ $return['other'][strtolower($key)] = $val;
}
- } else {
- $return['value'] = trim($input);
}
-
+ // decode values.
+ foreach($return['other'] as $key =>$val) {
+ $return['other'][$key] = $this->_decode_headers ? $this->_decodeHeader($val) : $val;
+ }
+ //print_r($return);
return $return;
}
if ($boundary == $bs_check) {
$boundary = $bs_possible;
}
+ $tmp = preg_split("/--".preg_quote($boundary, '/')."((?=\s)|--)/", $input);
- $tmp = explode('--' . $boundary, $input);
-
- for ($i = 1; $i < count($tmp) - 1; $i++) {
- $parts[] = $tmp[$i];
+ $len = count($tmp) -1;
+ for ($i = 1; $i < $len; $i++) {
+ if (strlen(trim($tmp[$i]))) {
+ $parts[] = $tmp[$i];
+ }
+ }
+
+ // add the last part on if it does not end with the 'closing indicator'
+ if (!empty($tmp[$len]) && strlen(trim($tmp[$len])) && $tmp[$len][0] != '-') {
+ $parts[] = $tmp[$len];
}
-
return $parts;
}
case "to":
case "cc":
case "bcc":
- $to = ",".$item['value'];
+ $to .= ",".$item['value'];
default:
break;
}
/**
* Validation class
*
- * Copyright (c) 1997-2006 Pierre-Alain Joye,Tomas V.V.Cox, Amir Saied
+ * Copyright (c) 1997-2006 Pierre-Alain Joye,Tomas V.V.Cox, Amir Saied
*
- * This source file is subject to the New BSD license, That is bundled
- * with this package in the file LICENSE, and is available through
- * the world-wide-web at
- * http://www.opensource.org/licenses/bsd-license.php
- * If you did not receive a copy of the new BSDlicense and are unable
- * to obtain it through the world-wide-web, please send a note to
- * pajoye@php.net so we can mail you a copy immediately.
+ * This source file is subject to the New BSD license, That is bundled
+ * with this package in the file LICENSE, and is available through
+ * the world-wide-web at
+ * http://www.opensource.org/licenses/bsd-license.php
+ * If you did not receive a copy of the new BSDlicense and are unable
+ * to obtain it through the world-wide-web, please send a note to
+ * pajoye@php.net so we can mail you a copy immediately.
*
- * Author: Tomas V.V.Cox <cox@idecnet.com>
- * Pierre-Alain Joye <pajoye@php.net>
- * Amir Mohammad Saied <amir@php.net>
+ * Author: Tomas V.V.Cox <cox@idecnet.com>
+ * Pierre-Alain Joye <pajoye@php.net>
+ * Amir Mohammad Saied <amir@php.net>
*
*
* Package to validate various datas. It includes :
* @author Amir Mohammad Saied <amir@php.net>
* @copyright 1997-2006 Pierre-Alain Joye,Tomas V.V.Cox,Amir Mohammad Saied
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Validate.php,v 1.134 2009/01/28 12:27:33 davidc Exp $
+ * @version CVS: $Id$
* @link http://pear.php.net/package/Validate
*/
+// {{{ Constants
/**
* Methods for common data validations
*/
define('VALIDATE_ALPHA_LOWER', 'a-z');
define('VALIDATE_ALPHA_UPPER', 'A-Z');
define('VALIDATE_ALPHA', VALIDATE_ALPHA_LOWER . VALIDATE_ALPHA_UPPER);
-define('VALIDATE_EALPHA_LOWER', VALIDATE_ALPHA_LOWER . 'áéíóúýàèìòùäëïöüÿâêîôûãñõ¨åæç½ðøþß');
-define('VALIDATE_EALPHA_UPPER', VALIDATE_ALPHA_UPPER . 'ÁÉÍÓÚÝÀÈÌÒÙÄËÏÖܾÂÊÎÔÛÃÑÕ¦ÅÆǼÐØÞ');
+define('VALIDATE_EALPHA_LOWER', VALIDATE_ALPHA_LOWER . 'áéíóúýàèìòùäëïöüÿâêîôûãñõ¨åæç½ðøþß');
+define('VALIDATE_EALPHA_UPPER', VALIDATE_ALPHA_UPPER . 'ÁÉÍÓÚÝÀÈÌÒÙÄËÏÖܾÂÊÎÔÛÃÑÕ¦ÅÆǼÐØÞ');
define('VALIDATE_EALPHA', VALIDATE_EALPHA_LOWER . VALIDATE_EALPHA_UPPER);
define('VALIDATE_PUNCTUATION', VALIDATE_SPACE . '\.,;\:&"\'\?\!\(\)');
-define('VALIDATE_NAME', VALIDATE_EALPHA . VALIDATE_SPACE . "'" . "-");
-define('VALIDATE_STREET', VALIDATE_NUM . VALIDATE_NAME . "/\\ºª\.");
+define('VALIDATE_NAME', VALIDATE_EALPHA . VALIDATE_SPACE . "'" . '\-');
+define('VALIDATE_STREET', VALIDATE_NUM . VALIDATE_NAME . "/\\ºª\.");
define('VALIDATE_ITLD_EMAILS', 1);
define('VALIDATE_GTLD_EMAILS', 2);
define('VALIDATE_CCTLD_EMAILS', 4);
define('VALIDATE_ALL_EMAILS', 8);
+// }}}
/**
* Validation class
*/
class Validate
{
+ // {{{ International, Generic and Country code TLDs
/**
* International Top-Level Domain
*
'ye','yt','yu','za',
'zm','zw',
);
+ // }}}
/**
* Validate a tag URI (RFC4151)
if(!empty($options["VALIDATE_GTLD_EMAILS"])) array_push($validate, 'gtld');
if(!empty($options["VALIDATE_CCTLD_EMAILS"])) array_push($validate, 'cctld');
+ if (count($validate) === 0) {
+ array_push($validate, 'itld', 'gtld', 'cctld');
+ }
+
$self = new Validate;
$toValidate = array();
return $e;
}
-
+
/**
* Execute the validation
*
* 'use_rfc822' => 'true',
* 'VALIDATE_GTLD_EMAILS' => 'true',
* 'VALIDATE_CCTLD_EMAILS' => 'true',
- * 'VALIDATE_ITLD_EMAILS' => 'true',
+ * 'VALIDATE_ITLD_EMAILS' => 'true',
* );
*
* @return boolean true if valid email, false if not
*/
$hasIDNA = false;
- if (@include_once('Net/IDNA.php')) {
+ if (Validate::_includePathFileExists('Net/IDNA.php')) {
+ include_once('Net/IDNA.php');
$hasIDNA = true;
}
if ($hasIDNA === true) {
if (strpos($email, '@') !== false) {
- list($name, $domain) = explode('@', $email, 2);
+ $tmpEmail = explode('@', $email);
+ $domain = array_pop($tmpEmail);
- // Check if the domain contains characters > 127 which means
+ // Check if the domain contains characters > 127 which means
// it's an idn domain name.
$chars = count_chars($domain, 1);
if (!empty($chars) && max(array_keys($chars)) > 127) {
$domain = $idna->encode($domain);
}
- $email = "$name@$domain";
+ array_push($tmpEmail, $domain);
+ $email = implode('@', $tmpEmail);
}
}
-
+
/**
* @todo Fix bug here.. even if it passes this, it won't be passing
* The regular expression below
(?:(?:(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:[0-1]?[0-9]?[0-9]))\.){3}
(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:[0-1]?[0-9]?[0-9]))))(?(5)\])|
((?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?\.)*[a-z0-9](?:[-a-z0-9]*[a-z0-9])?) #6 domain as hostname
- \.((?:([^- ])[-a-z]*[-a-z]))) #7 TLD
+ \.((?:([^- ])[-a-z]*[-a-z]))) #7 TLD
$&xi';
//checks if exists the domain (MX or A)
if ($use_rfc822? Validate::__emailRFC822($email, $options) :
preg_match($regex, $email)) {
if ($check_domain && function_exists('checkdnsrr')) {
- list ($account, $domain) = explode('@', $email);
+ $domain = preg_replace('/[^-a-z.0-9]/i', '', array_pop(explode('@', $email)));
if (checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A')) {
return true;
}
*
* @param string &$date Date
* @param string $num Length
- * @param string $opt Unknown
+ * @param string $opt Unknown
*
* @access private
* @return string
$class = implode('_', $validateType);
$classPath = str_replace('_', DIRECTORY_SEPARATOR, $class);
$class = 'Validate_' . $class;
- if (!@include_once "Validate/$classPath.php") {
- trigger_error("$class isn't installed or you may have some permissoin issues", E_USER_ERROR);
+ if (Validate::_includePathFileExists("Validate/$classPath.php")) {
+ include_once "Validate/$classPath.php";
+ } else {
+ trigger_error("$class isn't installed or you may have some permission issues", E_USER_ERROR);
}
$ce = substr(phpversion(), 0, 1) > 4 ?
}
return $valid;
}
+
+ /**
+ * Determine whether specified file exists along the include path.
+ *
+ * @param string $filename file to search for
+ *
+ * @access private
+ *
+ * @return bool true if file exists
+ */
+ function _includePathFileExists($filename)
+ {
+ $paths = explode(":", ini_get("include_path"));
+ $result = false;
+
+ while ((!($result)) && (list($key,$val) = each($paths))) {
+ $result = file_exists($val . "/" . $filename);
+ }
+ return $result;
+ }
}
V: { // Variables
},
+ /**
+ * list of callbacks, categorized into _callbacks['event_name'] = [ callback_function_1, callback_function_2 ]
+ *
+ * @access private
+ */
+ _callbacks: {},
+
/**
* Map of localized message strings exported to script from the PHP
* side via Action::getScriptMessages().
// Make sure we don't have a mixed HTTP/HTTPS submission...
form.attr('action', SN.U.RewriteAjaxAction(form.attr('action')));
- /**
- * Show a response feedback bit under the new-notice dialog.
- *
- * @param {String} cls: CSS class name to use ('error' or 'success')
- * @param {String} text
- * @access private
- */
- var showFeedback = function (cls, text) {
- form.append(
- $('<p class="form_response"></p>')
- .addClass(cls)
- .text(text)
- );
- };
-
/**
* Hide the previous response feedback, if any.
*/
removeFeedback();
if (textStatus == 'timeout') {
// @fixme i18n
- showFeedback('error', 'Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists.');
+ SN.U.showFeedback(form, 'error', 'Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists.');
} else {
var response = SN.U.GetResponseXML(xhr);
if ($('.' + SN.C.S.Error, response).length > 0) {
SN.U.FormNoticeEnhancements(form);
} else {
// @fixme i18n
- showFeedback('error', '(Sorry! We had trouble sending your notice (' + xhr.status + ' ' + xhr.statusText + '). Please report the problem to the site administrator if this happens again.');
+ SN.U.showFeedback(form, 'error', '(Sorry! We had trouble sending your notice (' + xhr.status + ' ' + xhr.statusText + '). Please report the problem to the site administrator if this happens again.');
}
}
}
removeFeedback();
var errorResult = $('#' + SN.C.S.Error, data);
if (errorResult.length > 0) {
- showFeedback('error', errorResult.text());
+ SN.U.showFeedback(form, 'error', errorResult.text());
} else {
- var commandResult = $('#' + SN.C.S.CommandResult, data);
- if (commandResult.length > 0) {
- showFeedback('success', commandResult.text());
- } else {
- // New notice post was successful. If on our timeline, show it!
- var notice = document._importNode($('li', data)[0], true);
- var notices = $('#notices_primary .notices:first');
- var replyItem = form.closest('li.notice-reply');
-
- if (replyItem.length > 0) {
- // If this is an inline reply, remove the form...
- var list = form.closest('.threaded-replies');
-
- var id = $(notice).attr('id');
- if ($('#' + id).length == 0) {
- $(notice).insertBefore(replyItem);
- } // else Realtime came through before us...
-
- replyItem.remove();
-
- } else if (notices.length > 0 && SN.U.belongsOnTimeline(notice)) {
- // Not a reply. If on our timeline, show it at the top!
-
- if ($('#' + notice.id).length === 0) {
- var notice_irt_value = form.find('[name=inreplyto]').val();
- var notice_irt = '#notices_primary #notice-' + notice_irt_value;
- if ($('body')[0].id == 'conversation') {
- if (notice_irt_value.length > 0 && $(notice_irt + ' .notices').length < 1) {
- $(notice_irt).append('<ul class="notices"></ul>');
- }
- $($(notice_irt + ' .notices')[0]).append(notice);
- } else {
- notices.prepend(notice);
- }
- $('#' + notice.id)
- .css({display: 'none'})
- .fadeIn(2500);
- SN.U.NoticeWithAttachment($('#' + notice.id));
- SN.U.switchInputFormTab(null);
- }
- } else {
- // Not on a timeline that this belongs on?
- // Just show a success message.
- // @fixme inline
- showFeedback('success', $('title', data).text());
- }
- }
- form.resetForm();
- form.find('[name=inreplyto]').val('');
- form.find('.attach-status').remove();
- SN.U.FormNoticeEnhancements(form);
+ SN.E.ajaxNoticePosted(form, data, textStatus);
}
},
complete: function (xhr, textStatus) {
label.attr('title', label.text());
check.change(function () {
- if (check.prop('checked') === true || $.cookie(SN.C.S.NoticeDataGeoCookie) === null) {
+ if (check.prop('checked') === true || $.cookie(SN.C.S.NoticeDataGeoCookie) === undefined) {
label
.attr('title', NoticeDataGeo_text.ShareDisable)
.addClass('checked');
- if ($.cookie(SN.C.S.NoticeDataGeoCookie) === null || $.cookie(SN.C.S.NoticeDataGeoCookie) == 'disabled') {
+ if ($.cookie(SN.C.S.NoticeDataGeoCookie) === undefined || $.cookie(SN.C.S.NoticeDataGeoCookie) == 'disabled') {
if (navigator.geolocation) {
SN.U.NoticeGeoStatus(form, 'Requesting location from browser...');
navigator.geolocation.getCurrentPosition(
* @fixme what is this?
*/
Delete: function () {
- $.cookie(SN.C.S.StatusNetInstance, null);
+ $.removeCookie(SN.C.S.StatusNetInstance);
}
},
var extended = $(selector);
extended.removeClass('extended_menu');
return void(0);
+ },
+
+ /**
+ * Show a response feedback bit under a form.
+ *
+ * @param {Element} form: the new-notice form usually
+ * @param {String} cls: CSS class name to use ('error' or 'success')
+ * @param {String} text
+ * @access public
+ */
+ showFeedback: function (form, cls, text) {
+ form.append(
+ $('<p class="form_response"></p>')
+ .addClass(cls)
+ .text(text)
+ );
+ },
+
+ addCallback: function (ename, callback) {
+ // initialize to array if it's undefined
+ if (typeof SN._callbacks[ename] === 'undefined') {
+ SN._callbacks[ename] = [];
+ }
+ SN._callbacks[ename].push(callback);
+ },
+
+ runCallbacks: function (ename, data) {
+ if (typeof SN._callbacks[ename] === 'undefined') {
+ return;
+ }
+ for (cbname in SN._callbacks[ename]) {
+ SN._callbacks[ename][cbname](data);
+ }
}
},
+ E: { /* Events */
+ /* SN.E.ajaxNoticePosted, called when a notice has been posted successfully via an AJAX form
+ @param form the originating form element
+ @param data data from success() callback
+ @param textStatus textStatus from success() callback
+ */
+ ajaxNoticePosted: function (form, data, textStatus) {
+ var commandResult = $('#' + SN.C.S.CommandResult, data);
+ if (commandResult.length > 0) {
+ SN.U.showFeedback(form, 'success', commandResult.text());
+ } else {
+ // New notice post was successful. If on our timeline, show it!
+ var notice = document._importNode($('li', data)[0], true);
+ var notices = $('#notices_primary .notices:first');
+ var replyItem = form.closest('li.notice-reply');
+
+ if (replyItem.length > 0) {
+ // If this is an inline reply, remove the form...
+ var list = form.closest('.threaded-replies');
+
+ var id = $(notice).attr('id');
+ if ($('#' + id).length == 0) {
+ $(notice).insertBefore(replyItem);
+ } // else Realtime came through before us...
+
+ replyItem.remove();
+
+ } else if (notices.length > 0 && SN.U.belongsOnTimeline(notice)) {
+ // Not a reply. If on our timeline, show it at the top!
+
+ if ($('#' + notice.id).length === 0) {
+ var notice_irt_value = form.find('[name=inreplyto]').val();
+ var notice_irt = '#notices_primary #notice-' + notice_irt_value;
+ if ($('body')[0].id == 'conversation') {
+ if (notice_irt_value.length > 0 && $(notice_irt + ' .notices').length < 1) {
+ $(notice_irt).append('<ul class="notices"></ul>');
+ }
+ $($(notice_irt + ' .notices')[0]).append(notice);
+ } else {
+ notices.prepend(notice);
+ }
+ $('#' + notice.id)
+ .css({display: 'none'})
+ .fadeIn(2500);
+ SN.U.NoticeWithAttachment($('#' + notice.id));
+ SN.U.switchInputFormTab(null);
+ }
+ } else {
+ // Not on a timeline that this belongs on?
+ // Just show a success message.
+ // @fixme inline
+ SN.U.showFeedback(form, 'success', $('title', data).text());
+ }
+ }
+ form.resetForm();
+ form.find('[name=inreplyto]').val('');
+ form.find('.attach-status').remove();
+ SN.U.FormNoticeEnhancements(form);
+
+ SN.U.runCallbacks('notice_posted', {"notice": notice});
+ },
+ },
+
+
Init: {
/**
* If user is logged in, run setup code for the new notice form:
*
* @return nothing
*/
- function showPage()
+ public function showPage()
{
if (GNUsocial::isAjax()) {
self::showAjax();
*/
function showFeeds()
{
- $feeds = $this->getFeeds();
-
- if ($feeds) {
- foreach ($feeds as $feed) {
- $this->element('link', array('rel' => $feed->rel(),
- 'href' => $feed->url,
- 'type' => $feed->mimeType(),
- 'title' => $feed->title));
- }
+ foreach ($this->getFeeds() as $feed) {
+ $this->element('link', array('rel' => $feed->rel(),
+ 'href' => $feed->url,
+ 'type' => $feed->mimeType(),
+ 'title' => $feed->title));
}
}
function showExportData()
{
$feeds = $this->getFeeds();
- if ($feeds) {
- $fl = new FeedList($this);
- $fl->show($feeds);
+ if (!empty($feeds)) {
+ $fl = new FeedList($this, $feeds);
+ $fl->show();
}
}
*/
function getFeeds()
{
- return null;
+ return array();
}
/**
static function validateUri($uri)
{
// Check mailto: URIs first
+ $validate = new Validate();
if (preg_match('/^mailto:(.*)$/', $uri, $match)) {
- return Validate::email($match[1], common_config('email', 'check_domain'));
+ return $validate->email($match[1], common_config('email', 'check_domain'));
}
- if (Validate::uri($uri)) {
+ if ($validate->uri($uri)) {
return true;
}
// Possibly an upstream bug; tag: URIs aren't validated properly
// unless you explicitly ask for them. All other schemes are accepted
// for basic URI validation without asking.
- if (Validate::uri($uri, array('allowed_scheme' => array('tag')))) {
+ if ($validate->uri($uri, array('allowed_scheme' => array('tag')))) {
return true;
}
$twitter_user['friends_count'] = $profile->subscriptionCount();
- $twitter_user['created_at'] = $this->dateTwitter($profile->created);
+ $twitter_user['created_at'] = self::dateTwitter($profile->created);
$timezone = 'UTC';
$twitter_status = array();
$twitter_status['text'] = $notice->content;
$twitter_status['truncated'] = false; # Not possible on StatusNet
- $twitter_status['created_at'] = $this->dateTwitter($notice->created);
+ $twitter_status['created_at'] = self::dateTwitter($notice->created);
try {
// We could just do $notice->reply_to but maybe the future holds a
// different story for parenting.
$twitter_group['homepage'] = $group->homepage;
$twitter_group['description'] = $group->description;
$twitter_group['location'] = $group->location;
- $twitter_group['created'] = $this->dateTwitter($group->created);
- $twitter_group['modified'] = $this->dateTwitter($group->modified);
+ $twitter_group['created'] = self::dateTwitter($group->created);
+ $twitter_group['modified'] = self::dateTwitter($group->modified);
return $twitter_group;
}
$this->endDocument('xml');
}
- function dateTwitter($dt)
+ static function dateTwitter($dt)
{
$dateStr = date('d F Y H:i:s', strtotime($dt));
$d = new DateTime($dateStr, new DateTimeZone('UTC'));
foreach ($notices as $notice) {
$this->addEntryFromNotice($notice);
}
- } else {
+ } elseif ($notices instanceof Notice) {
while ($notices->fetch()) {
$this->addEntryFromNotice($notices);
}
+ } else {
+ throw new ServerException('addEntryFromNotices got neither an array nor a Notice object');
}
}
*
* @param Notice $notice a Notice to add
*/
- function addEntryFromNotice($notice)
+ function addEntryFromNotice(Notice $notice)
{
try {
$source = $this->showSource();
// yuck!
static function mediatype($filename) {
- $ext = strtolower(end(explode('.', $filename)));
+ $parts = explode('.', $filename);
+ $ext = strtolower(end($parts));
if ($ext == 'jpeg') {
$ext = 'jpg';
}
'OpportunisticQM' => array(),
'OStatus' => array(),
'Poll' => array(),
- 'QnA' => array(),
'SearchSub' => array(),
'TagSub' => array(),
'WebFinger' => array(),
--- /dev/null
+<?php
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+class DeletenoticeForm extends Form
+{
+ protected $notice = null;
+
+ function __construct(HTMLOutputter $out=null, array $formOpts=array())
+ {
+ if (!array_key_exists('notice', $formOpts) || !$formOpts['notice'] instanceof Notice) {
+ throw new ServerException('No notice provided to DeletenoticeForm');
+ }
+
+ parent::__construct($out);
+
+ $this->notice = $formOpts['notice'];
+ }
+
+ function id()
+ {
+ return 'form_notice_delete-' . $this->notice->getID();
+ }
+
+ function formClass()
+ {
+ return 'form_settings';
+ }
+
+ function action()
+ {
+ return common_local_url('deletenotice', array('notice' => $this->notice->getID()));
+ }
+
+ function formLegend()
+ {
+ $this->out->element('legend', null, _('Delete notice'));
+ }
+
+ function formData()
+ {
+ $this->out->element('p', null, _('Are you sure you want to delete this notice?'));
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+ function formActions()
+ {
+ $this->out->submit('form_action-no',
+ // TRANS: Button label on the delete notice form.
+ _m('BUTTON','No'),
+ 'submit form_action-primary',
+ 'no',
+ // TRANS: Submit button title for 'No' when deleting a notice.
+ _('Do not delete this notice.'));
+ $this->out->submit('form_action-yes',
+ // TRANS: Button label on the delete notice form.
+ _m('BUTTON','Yes'),
+ 'submit form_action-secondary',
+ 'yes',
+ // TRANS: Submit button title for 'Yes' when deleting a notice.
+ _('Delete this notice.'));
+ }
+}
* @link http://status.net/
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Widget for showing a list of feeds
{
var $action = null;
- function __construct($action=null)
+ protected $feeds = null;
+
+ public function __construct(Action $action=null, array $feeds=array())
{
- parent::__construct($action);
- $this->action = $action;
+ parent::__construct($action);
+ $this->action = $action;
+ $this->feeds = $feeds;
}
- function show($feeds)
+ public function show()
{
- if (Event::handle('StartShowFeedLinkList', array($this->action, &$feeds))) {
- if (!empty($feeds)) {
+ if (Event::handle('StartShowFeedLinkList', array($this->action, &$this->feeds))) {
+ if (!empty($this->feeds)) {
$this->out->elementStart('div', array('id' => 'export_data',
'class' => 'section'));
// TRANS: Header for feed links (h2).
$this->out->element('h2', null, _('Feeds'));
$this->out->elementStart('ul', array('class' => 'xoxo'));
- foreach ($feeds as $feed) {
+ foreach ($this->feeds as $feed) {
$this->feedItem($feed);
}
$this->out->elementEnd('ul');
$this->out->elementEnd('div');
}
- Event::handle('EndShowFeedLinkList', array($this->action, &$feeds));
+ Event::handle('EndShowFeedLinkList', array($this->action, &$this->feeds));
}
}
protected function prepare(array $args=array()) {
parent::prepare($args);
- $this->form = $this->form ?: $this->action;
+ $this->form = $this->form ?: ucfirst($this->action);
$this->args['form'] = $this->form;
$this->type = !is_null($this->type) ? $this->type : $this->trimmed('type');
define('GNUSOCIAL_ENGINE_URL', 'https://www.gnu.org/software/social/');
define('GNUSOCIAL_BASE_VERSION', '1.2.0');
-define('GNUSOCIAL_LIFECYCLE', 'alpha1'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release'
+define('GNUSOCIAL_LIFECYCLE', 'alpha2'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release'
define('GNUSOCIAL_VERSION', GNUSOCIAL_BASE_VERSION . '-' . GNUSOCIAL_LIFECYCLE);
_('See all groups you belong to.'));
}
- function item($actionName, $args, $label, $description, $id=null, $cls=null)
+ function item($actionName, array $args, $label, $description, $id=null, $cls=null)
{
if ($actionName != 'placeholder') {
return parent::item($actionName, $args, $label, $description, $id, $cls);
return true;
}
- function onEndShowHeadElements($action)
+ function onEndShowHeadElements(Action $action)
{
- $aname = $action->trimmed('action');
-
- if ($aname == 'shownotice') {
+ if ($action instanceof ShownoticeAction) {
$user_im_prefs = new User_im_prefs();
- $user_im_prefs->user_id = $action->profile->id;
+ $user_im_prefs->user_id = $action->notice->getProfile()->getID();
$user_im_prefs->transport = $this->transport;
if ($user_im_prefs->find() && $user_im_prefs->fetch() && $user_im_prefs->microid && $action->notice->uri) {
'content' => $id->toString()));
}
- } else if ($aname == 'showstream') {
+ } elseif ($action instanceof ShowstreamAction) {
$user_im_prefs = new User_im_prefs();
- $user_im_prefs->user_id = $action->user->id;
+ $user_im_prefs->user_id = $action->getTarget()->getID();
$user_im_prefs->transport = $this->transport;
- if ($user_im_prefs->find() && $user_im_prefs->fetch() && $user_im_prefs->microid && $action->profile->profileurl) {
+ if ($user_im_prefs->find() && $user_im_prefs->fetch() && $user_im_prefs->microid && $action->getTarget()->getUrl()) {
$id = new Microid($this->microiduri($user_im_prefs->screenname),
$action->selfUrl());
$action->element('meta', array('name' => 'microid',
$this->out = $out;
if (empty($buttonText)) {
// TRANS: Default button text for inviting more users to the StatusNet instance.
- $this->buttonText = _m('BUTTON', 'Invite more colleagues');
+ $this->buttonText = _m('BUTTON', 'Invite more people');
} else {
$this->buttonText = $buttonText;
}
function mail_backend()
{
static $backend = null;
+ global $_PEAR;
if (!$backend) {
- $backend = Mail::factory(common_config('mail', 'backend'),
+ $mail = new Mail();
+ $backend = $mail->factory(common_config('mail', 'backend'),
common_config('mail', 'params') ?: array());
- if (PEAR::isError($backend)) {
+ if ($_PEAR->isError($backend)) {
common_server_error($backend->getMessage(), 500);
}
}
--- /dev/null
+<?php
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+abstract class NoticestreamAction extends ProfileAction
+{
+ protected $notice = null; // holds the stream result
+
+ protected function prepare(array $args=array()) {
+ parent::prepare($args);
+
+ // fetch the actual stream stuff
+ $stream = $this->getStream();
+ $this->notice = $stream->getNotices(($this->page-1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+
+ if ($this->page > 1 && $this->notice->N == 0) {
+ // TRANS: Client error when page not found (404).
+ $this->clientError(_('No such page.'), 404);
+ }
+
+ return true;
+ }
+
+ // this fetches the NoticeStream
+ abstract public function getStream();
+}
$this->out->elementStart('li', 'hashptag mode-' . $mode);
// Avoid space by using raw output.
$pt = '<span class="mark_hash">#</span><a rel="tag" href="' .
- $this->url($this->tag->tag) .
- '">' . $this->tag->tag . '</a>';
+ htmlspecialchars($this->url()) .
+ '">' . htmlspecialchars($this->tag->tag) . '</a>';
$this->out->raw($pt);
$this->out->elementEnd('li');
}
* @link http://status.net/
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Personal tag cloud section
*/
class PersonalTagCloudSection extends TagCloudSection
{
- var $user = null;
+ protected $profile = null;
- function __construct($out=null, $user=null)
+ function __construct(Profile $profile, HTMLOutputter $out=null)
{
parent::__construct($out);
- $this->user = $user;
+ $this->profile = $profile;
}
function title()
$tag = Memcached_DataObject::cachedQuery('Notice_tag',
sprintf($qry,
- $this->user->id),
+ $this->profile->getID()),
3600);
return $tag;
}
protected function prepare(array $args=array())
{
- // this will call ->doPreparation() which lower classes can use
+ // this will call ->doPreparation() which child classes use to set $this->target
parent::prepare($args);
if ($this->target->hasRole(Profile_role::SILENCED)
throw new ClientException(_('This profile has been silenced by site moderators'), 403);
}
- // backwards compatibility until all actions are fixed to use $this->target
- $this->profile = $this->target;
-
$this->tag = $this->trimmed('tag');
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
common_set_returnto($this->selfUrl());
- // fetch the actual stream stuff
- $this->profileActionPreparation();
-
return true;
}
public function getTarget()
{
+ if (!$this->target instanceof Profile) {
+ throw new ServerException('No target profile in ProfileAction class');
+ }
return $this->target;
}
class ProfileListItem extends Widget
{
/** Current profile. */
+ protected $target = null;
var $profile = null;
/** Action object using us. */
var $action = null;
- function __construct($profile, $action)
+ // FIXME: Directory plugin sends a User_group here, but should send a Profile and handle User_group specifics itself
+ function __construct($target, HTMLOutputter $action)
{
parent::__construct($action);
- $this->profile = $profile;
+ $this->target = $target;
+ $this->profile = $this->target;
$this->action = $action;
}
+ function getTarget()
+ {
+ return $this->target;
+ }
+
function show()
{
if (Event::handle('StartProfileListItem', array($this))) {
function title()
{
// TRANS: Title for inbox tag cloud section.
- return _m('TITLE', 'Trending topics');
+ return _m('TITLE', 'Trends');
}
function getTags()
if (Event::handle('StartInitializeRouter', array(&$m))) {
+ // top of the menu hierarchy, sometimes "Home"
+ $m->connect('', array('action' => 'top'));
+
+ // public endpoints
+
$m->connect('robots.txt', array('action' => 'robotstxt'));
$m->connect('opensearch/people', array('action' => 'opensearch',
'deleteaccount',
'restoreaccount',
'top',
+ 'public',
);
foreach ($main as $a) {
$m->connect('main/'.$a, array('action' => $a));
}
- $m->connect('main/public', array('action' => 'public'));
$m->connect('main/all', array('action' => 'networkpublic'));
$m->connect('main/tagprofile/:id', array('action' => 'tagprofile'),
array('action' => 'shownotice'),
array('notice' => '[0-9]+'));
- $m->connect('notice/delete/:notice',
+ $m->connect('notice/:notice/delete',
array('action' => 'deletenotice'),
array('notice' => '[0-9]+'));
- $m->connect('notice/delete', array('action' => 'deletenotice'));
-
// conversation
$m->connect('conversation/:id',
array('action' => 'rsd',
'nickname' => $nickname));
- $m->connect('',
- array('action' => 'startpage'));
-
// peopletags
$m->connect('peopletags',
}
}
- $m->connect('', array('action' => 'startpage'));
- $m->connect('main/public', array('action' => 'public'));
- $m->connect('main/all', array('action' => 'networkpublic'));
$m->connect('rss', array('action' => 'publicrss'));
$m->connect('featuredrss', array('action' => 'featuredrss'));
$m->connect('featured/', array('action' => 'featured'));
array('action' => 'subqueue'),
array('nickname' => Nickname::DISPLAY_FMT));
+ // some targeted RSS 1.0 actions (extends TargetedRss10Action)
+ foreach (array('all', 'replies') as $a) {
+ $m->connect(':nickname/'.$a.'/rss',
+ array('action' => $a.'rss'),
+ array('nickname' => Nickname::DISPLAY_FMT));
+ }
+
// people tags
$m->connect(':nickname/peopletags',
array('nickname' => Nickname::DISPLAY_FMT));
}
- foreach (array('all', 'replies') as $a) {
- $m->connect(':nickname/'.$a.'/rss',
- array('action' => $a.'rss'),
- array('nickname' => Nickname::DISPLAY_FMT));
- }
-
$m->connect(':nickname/avatar',
array('action' => 'avatarbynickname'),
array('nickname' => Nickname::DISPLAY_FMT));
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Base class for RSS 1.0 feed actions
+ *
+ * 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 Mail
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Earle Martin <earle@downlode.org>
+ * @copyright 2008-9 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('GNUSOCIAL')) { exit(1); }
+
+define('DEFAULT_RSS_LIMIT', 48);
+
+class Rss10Action extends ManagedAction
+{
+ // This will contain the details of each feed item's author and be used to generate SIOC data.
+
+ var $creators = array();
+ var $limit = DEFAULT_RSS_LIMIT;
+ var $notices = null;
+ var $tags_already_output = array();
+
+ public function isReadOnly($args)
+ {
+ return true;
+ }
+
+ protected function doPreparation()
+ {
+ $this->limit = $this->int('limit');
+
+ if (empty($this->limit)) {
+ $this->limit = DEFAULT_RSS_LIMIT;
+ }
+
+ if (common_config('site', 'private')) {
+ if (!isset($_SERVER['PHP_AUTH_USER'])) {
+
+ // This header makes basic auth go
+ header('WWW-Authenticate: Basic realm="GNU social RSS"');
+
+ // If the user hits cancel -- bam!
+ $this->show_basic_auth_error();
+ // the above calls 'exit'
+ } else {
+ $nickname = $_SERVER['PHP_AUTH_USER'];
+ $password = $_SERVER['PHP_AUTH_PW'];
+
+ if (!common_check_user($nickname, $password)) {
+ // basic authentication failed
+ list($proxy, $ip) = common_client_ip();
+
+ common_log(LOG_WARNING, "Failed RSS auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip.");
+ $this->show_basic_auth_error();
+ // the above calls 'exit'
+ }
+ }
+ }
+
+ $this->doStreamPreparation();
+
+ $this->notices = $this->getNotices($this->limit);
+ }
+
+ protected function doStreamPreparation()
+ {
+ // for example if we need to set $this->target or something
+ }
+
+ function show_basic_auth_error()
+ {
+ header('HTTP/1.1 401 Unauthorized');
+ header('Content-Type: application/xml; charset=utf-8');
+ $this->startXML();
+ $this->elementStart('hash');
+ $this->element('error', null, 'Could not authenticate you.');
+ $this->element('request', null, $_SERVER['REQUEST_URI']);
+ $this->elementEnd('hash');
+ $this->endXML();
+ exit;
+ }
+
+ /**
+ * Get the notices to output in this stream.
+ *
+ * @return array an array of Notice objects sorted in reverse chron
+ */
+
+ protected function getNotices()
+ {
+ return array();
+ }
+
+ /**
+ * Get a description of the channel
+ *
+ * Returns an array with the following
+ * @return array
+ */
+
+ function getChannel()
+ {
+ return array('url' => '',
+ 'title' => '',
+ 'link' => '',
+ 'description' => '');
+ }
+
+ function getImage()
+ {
+ return null;
+ }
+
+ function showPage()
+ {
+ $this->initRss();
+ $this->showChannel();
+ $this->showImage();
+
+ if (count($this->notices)) {
+ foreach ($this->notices as $n) {
+ try {
+ $this->showItem($n);
+ } catch (Exception $e) {
+ // log exceptions and continue
+ common_log(LOG_ERR, $e->getMessage());
+ continue;
+ }
+ }
+ }
+
+ $this->showCreators();
+ $this->endRss();
+ }
+
+ function showChannel()
+ {
+
+ $channel = $this->getChannel();
+ $image = $this->getImage();
+
+ $this->elementStart('channel', array('rdf:about' => $channel['url']));
+ $this->element('title', null, $channel['title']);
+ $this->element('link', null, $channel['link']);
+ $this->element('description', null, $channel['description']);
+ $this->element('cc:licence', array('rdf:resource' => common_config('license','url')));
+
+ if ($image) {
+ $this->element('image', array('rdf:resource' => $image));
+ }
+
+ $this->elementStart('items');
+ $this->elementStart('rdf:Seq');
+
+ if (count($this->notices)) {
+ foreach ($this->notices as $notice) {
+ $this->element('rdf:li', array('rdf:resource' => $notice->uri));
+ }
+ }
+
+ $this->elementEnd('rdf:Seq');
+ $this->elementEnd('items');
+
+ $this->elementEnd('channel');
+ }
+
+ function showImage()
+ {
+ $image = $this->getImage();
+ if ($image) {
+ $channel = $this->getChannel();
+ $this->elementStart('image', array('rdf:about' => $image));
+ $this->element('title', null, $channel['title']);
+ $this->element('link', null, $channel['link']);
+ $this->element('url', null, $image);
+ $this->elementEnd('image');
+ }
+ }
+
+ function showItem($notice)
+ {
+ $profile = $notice->getProfile();
+ $nurl = common_local_url('shownotice', array('notice' => $notice->id));
+ $creator_uri = common_profile_uri($profile);
+ $this->elementStart('item', array('rdf:about' => $notice->uri,
+ 'rdf:type' => 'http://rdfs.org/sioc/types#MicroblogPost'));
+ $title = $profile->nickname . ': ' . common_xml_safe_str(trim($notice->content));
+ $this->element('title', null, $title);
+ $this->element('link', null, $nurl);
+ $this->element('description', null, $profile->nickname."'s status on ".common_exact_date($notice->created));
+ if ($notice->rendered) {
+ $this->element('content:encoded', null, common_xml_safe_str($notice->rendered));
+ }
+ $this->element('dc:date', null, common_date_w3dtf($notice->created));
+ $this->element('dc:creator', null, ($profile->fullname) ? $profile->fullname : $profile->nickname);
+ $this->element('foaf:maker', array('rdf:resource' => $creator_uri));
+ $this->element('sioc:has_creator', array('rdf:resource' => $creator_uri.'#acct'));
+ $location = $notice->getLocation();
+ if ($location && isset($location->lat) && isset($location->lon)) {
+ $location_uri = $location->getRdfURL();
+ $attrs = array('geo:lat' => $location->lat,
+ 'geo:long' => $location->lon);
+ if (strlen($location_uri)) {
+ $attrs['rdf:resource'] = $location_uri;
+ }
+ $this->element('statusnet:origin', $attrs);
+ }
+ $this->element('statusnet:postIcon', array('rdf:resource' => $profile->avatarUrl()));
+ $this->element('cc:licence', array('rdf:resource' => common_config('license', 'url')));
+ if ($notice->reply_to) {
+ $replyurl = common_local_url('shownotice', array('notice' => $notice->reply_to));
+ $this->element('sioc:reply_of', array('rdf:resource' => $replyurl));
+ }
+ if (!empty($notice->conversation)) {
+ $conversationurl = common_local_url('conversation',
+ array('id' => $notice->conversation));
+ $this->element('sioc:has_discussion', array('rdf:resource' => $conversationurl));
+ }
+ $attachments = $notice->attachments();
+ if($attachments){
+ foreach($attachments as $attachment){
+ try {
+ $enclosure = $attachment->getEnclosure();
+ $attribs = array('rdf:resource' => $enclosure->url);
+ if ($enclosure->title) {
+ $attribs['dc:title'] = $enclosure->title;
+ }
+ if ($enclosure->modified) {
+ $attribs['dc:date'] = common_date_w3dtf($enclosure->modified);
+ }
+ if ($enclosure->size) {
+ $attribs['enc:length'] = $enclosure->size;
+ }
+ if ($enclosure->mimetype) {
+ $attribs['enc:type'] = $enclosure->mimetype;
+ }
+ $this->element('enc:enclosure', $attribs);
+ } catch (ServerException $e) {
+ // There was not enough metadata available
+ }
+ $this->element('sioc:links_to', array('rdf:resource'=>$attachment->url));
+ }
+ }
+
+ $tag = new Notice_tag();
+ $tag->notice_id = $notice->id;
+ if ($tag->find()) {
+ $entry['tags']=array();
+ while ($tag->fetch()) {
+ $tagpage = common_local_url('tag', array('tag' => $tag->tag));
+
+ if ( in_array($tag, $this->tags_already_output) ) {
+ $this->element('ctag:tagged', array('rdf:resource'=>$tagpage.'#concept'));
+ continue;
+ }
+
+ $tagrss = common_local_url('tagrss', array('tag' => $tag->tag));
+ $this->elementStart('ctag:tagged');
+ $this->elementStart('ctag:Tag', array('rdf:about'=>$tagpage.'#concept', 'ctag:label'=>$tag->tag));
+ $this->element('foaf:page', array('rdf:resource'=>$tagpage));
+ $this->element('rdfs:seeAlso', array('rdf:resource'=>$tagrss));
+ $this->elementEnd('ctag:Tag');
+ $this->elementEnd('ctag:tagged');
+
+ $this->tags_already_output[] = $tag->tag;
+ }
+ }
+ $this->elementEnd('item');
+ $this->creators[$creator_uri] = $profile;
+ }
+
+ function showCreators()
+ {
+ foreach ($this->creators as $uri => $profile) {
+ $id = $profile->id;
+ $nickname = $profile->nickname;
+ $this->elementStart('foaf:Agent', array('rdf:about' => $uri));
+ $this->element('foaf:nick', null, $nickname);
+ if ($profile->fullname) {
+ $this->element('foaf:name', null, $profile->fullname);
+ }
+ $this->element('foaf:holdsAccount', array('rdf:resource' => $uri.'#acct'));
+ $avatar = $profile->avatarUrl();
+ $this->element('foaf:depiction', array('rdf:resource' => $avatar));
+ $this->elementEnd('foaf:Agent');
+ }
+ }
+
+ function initRss()
+ {
+ $channel = $this->getChannel();
+ header('Content-Type: application/rdf+xml');
+
+ $this->startXml();
+ $this->elementStart('rdf:RDF', array('xmlns:rdf' =>
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
+ 'xmlns:dc' =>
+ 'http://purl.org/dc/elements/1.1/',
+ 'xmlns:cc' =>
+ 'http://creativecommons.org/ns#',
+ 'xmlns:content' =>
+ 'http://purl.org/rss/1.0/modules/content/',
+ 'xmlns:ctag' =>
+ 'http://commontag.org/ns#',
+ 'xmlns:foaf' =>
+ 'http://xmlns.com/foaf/0.1/',
+ 'xmlns:enc' =>
+ 'http://purl.oclc.org/net/rss_2.0/enc#',
+ 'xmlns:sioc' =>
+ 'http://rdfs.org/sioc/ns#',
+ 'xmlns:sioct' =>
+ 'http://rdfs.org/sioc/types#',
+ 'xmlns:rdfs' =>
+ 'http://www.w3.org/2000/01/rdf-schema#',
+ 'xmlns:geo' =>
+ 'http://www.w3.org/2003/01/geo/wgs84_pos#',
+ 'xmlns:statusnet' =>
+ 'http://status.net/ont/',
+ 'xmlns' => 'http://purl.org/rss/1.0/'));
+ $this->elementStart('sioc:Site', array('rdf:about' => common_root_url()));
+ $this->element('sioc:name', null, common_config('site', 'name'));
+ $this->elementStart('sioc:space_of');
+ $this->element('sioc:Container', array('rdf:about' =>
+ $channel['url']));
+ $this->elementEnd('sioc:space_of');
+ $this->elementEnd('sioc:Site');
+ }
+
+ function endRss()
+ {
+ $this->elementEnd('rdf:RDF');
+ }
+
+ /**
+ * When was this page last modified?
+ *
+ */
+
+ function lastModified()
+ {
+ if (empty($this->notices)) {
+ return null;
+ }
+
+ if (count($this->notices) == 0) {
+ return null;
+ }
+
+ // FIXME: doesn't handle modified profiles, avatars, deleted notices
+
+ return strtotime($this->notices[0]->created);
+ }
+}
+
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Base class for RSS 1.0 feed actions
- *
- * 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 Mail
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @author Earle Martin <earle@downlode.org>
- * @copyright 2008-9 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') && !defined('LACONICA')) { exit(1); }
-
-define('DEFAULT_RSS_LIMIT', 48);
-
-class Rss10Action extends Action
-{
- // This will contain the details of each feed item's author and be used to generate SIOC data.
-
- var $creators = array();
- var $limit = DEFAULT_RSS_LIMIT;
- var $notices = null;
- var $tags_already_output = array();
-
- /**
- * Constructor
- *
- * Just wraps the Action constructor.
- *
- * @param string $output URI to output to, default = stdout
- * @param boolean $indent Whether to indent output, default true
- *
- * @see Action::__construct
- */
-
- function __construct($output='php://output', $indent=null)
- {
- parent::__construct($output, $indent);
- }
-
- /**
- * Do we need to write to the database?
- *
- * @return boolean true
- */
-
- function isReadonly()
- {
- return true;
- }
-
- /**
- * Read arguments and initialize members
- *
- * @param array $args Arguments from $_REQUEST
- * @return boolean success
- */
-
- function prepare($args)
- {
- parent::prepare($args);
-
- $this->limit = (int) $this->trimmed('limit');
-
- if ($this->limit == 0) {
- $this->limit = DEFAULT_RSS_LIMIT;
- }
-
- if (common_config('site', 'private')) {
- if (!isset($_SERVER['PHP_AUTH_USER'])) {
-
- // This header makes basic auth go
- header('WWW-Authenticate: Basic realm="GNU social RSS"');
-
- // If the user hits cancel -- bam!
- $this->show_basic_auth_error();
- return;
- } else {
- $nickname = $_SERVER['PHP_AUTH_USER'];
- $password = $_SERVER['PHP_AUTH_PW'];
-
- if (!common_check_user($nickname, $password)) {
- // basic authentication failed
- list($proxy, $ip) = common_client_ip();
-
- common_log(LOG_WARNING, "Failed RSS auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip.");
- $this->show_basic_auth_error();
- return;
- }
- }
- }
-
- return true;
- }
-
- /**
- * Handle a request
- *
- * @param array $args Arguments from $_REQUEST
- *
- * @return void
- */
-
- function handle($args)
- {
- // Parent handling, including cache check
- parent::handle($args);
- $this->showRss();
- }
-
- function show_basic_auth_error()
- {
- header('HTTP/1.1 401 Unauthorized');
- header('Content-Type: application/xml; charset=utf-8');
- $this->startXML();
- $this->elementStart('hash');
- $this->element('error', null, 'Could not authenticate you.');
- $this->element('request', null, $_SERVER['REQUEST_URI']);
- $this->elementEnd('hash');
- $this->endXML();
- }
-
- /**
- * Get the notices to output in this stream.
- *
- * @return array an array of Notice objects sorted in reverse chron
- */
-
- function getNotices()
- {
- return array();
- }
-
- /**
- * Get a description of the channel
- *
- * Returns an array with the following
- * @return array
- */
-
- function getChannel()
- {
- return array('url' => '',
- 'title' => '',
- 'link' => '',
- 'description' => '');
- }
-
- function getImage()
- {
- return null;
- }
-
- function showRss()
- {
- $this->initRss();
- $this->showChannel();
- $this->showImage();
-
- if (count($this->notices)) {
- foreach ($this->notices as $n) {
- try {
- $this->showItem($n);
- } catch (Exception $e) {
- // log exceptions and continue
- common_log(LOG_ERR, $e->getMessage());
- continue;
- }
- }
- }
-
- $this->showCreators();
- $this->endRss();
- }
-
- function showChannel()
- {
-
- $channel = $this->getChannel();
- $image = $this->getImage();
-
- $this->elementStart('channel', array('rdf:about' => $channel['url']));
- $this->element('title', null, $channel['title']);
- $this->element('link', null, $channel['link']);
- $this->element('description', null, $channel['description']);
- $this->element('cc:licence', array('rdf:resource' => common_config('license','url')));
-
- if ($image) {
- $this->element('image', array('rdf:resource' => $image));
- }
-
- $this->elementStart('items');
- $this->elementStart('rdf:Seq');
-
- if (count($this->notices)) {
- foreach ($this->notices as $notice) {
- $this->element('rdf:li', array('rdf:resource' => $notice->uri));
- }
- }
-
- $this->elementEnd('rdf:Seq');
- $this->elementEnd('items');
-
- $this->elementEnd('channel');
- }
-
- function showImage()
- {
- $image = $this->getImage();
- if ($image) {
- $channel = $this->getChannel();
- $this->elementStart('image', array('rdf:about' => $image));
- $this->element('title', null, $channel['title']);
- $this->element('link', null, $channel['link']);
- $this->element('url', null, $image);
- $this->elementEnd('image');
- }
- }
-
- function showItem($notice)
- {
- $profile = $notice->getProfile();
- $nurl = common_local_url('shownotice', array('notice' => $notice->id));
- $creator_uri = common_profile_uri($profile);
- $this->elementStart('item', array('rdf:about' => $notice->uri,
- 'rdf:type' => 'http://rdfs.org/sioc/types#MicroblogPost'));
- $title = $profile->nickname . ': ' . common_xml_safe_str(trim($notice->content));
- $this->element('title', null, $title);
- $this->element('link', null, $nurl);
- $this->element('description', null, $profile->nickname."'s status on ".common_exact_date($notice->created));
- if ($notice->rendered) {
- $this->element('content:encoded', null, common_xml_safe_str($notice->rendered));
- }
- $this->element('dc:date', null, common_date_w3dtf($notice->created));
- $this->element('dc:creator', null, ($profile->fullname) ? $profile->fullname : $profile->nickname);
- $this->element('foaf:maker', array('rdf:resource' => $creator_uri));
- $this->element('sioc:has_creator', array('rdf:resource' => $creator_uri.'#acct'));
- $location = $notice->getLocation();
- if ($location && isset($location->lat) && isset($location->lon)) {
- $location_uri = $location->getRdfURL();
- $attrs = array('geo:lat' => $location->lat,
- 'geo:long' => $location->lon);
- if (strlen($location_uri)) {
- $attrs['rdf:resource'] = $location_uri;
- }
- $this->element('statusnet:origin', $attrs);
- }
- $this->element('statusnet:postIcon', array('rdf:resource' => $profile->avatarUrl()));
- $this->element('cc:licence', array('rdf:resource' => common_config('license', 'url')));
- if ($notice->reply_to) {
- $replyurl = common_local_url('shownotice', array('notice' => $notice->reply_to));
- $this->element('sioc:reply_of', array('rdf:resource' => $replyurl));
- }
- if (!empty($notice->conversation)) {
- $conversationurl = common_local_url('conversation',
- array('id' => $notice->conversation));
- $this->element('sioc:has_discussion', array('rdf:resource' => $conversationurl));
- }
- $attachments = $notice->attachments();
- if($attachments){
- foreach($attachments as $attachment){
- try {
- $enclosure = $attachment->getEnclosure();
- $attribs = array('rdf:resource' => $enclosure->url);
- if ($enclosure->title) {
- $attribs['dc:title'] = $enclosure->title;
- }
- if ($enclosure->modified) {
- $attribs['dc:date'] = common_date_w3dtf($enclosure->modified);
- }
- if ($enclosure->size) {
- $attribs['enc:length'] = $enclosure->size;
- }
- if ($enclosure->mimetype) {
- $attribs['enc:type'] = $enclosure->mimetype;
- }
- $this->element('enc:enclosure', $attribs);
- } catch (ServerException $e) {
- // There was not enough metadata available
- }
- $this->element('sioc:links_to', array('rdf:resource'=>$attachment->url));
- }
- }
-
- $tag = new Notice_tag();
- $tag->notice_id = $notice->id;
- if ($tag->find()) {
- $entry['tags']=array();
- while ($tag->fetch()) {
- $tagpage = common_local_url('tag', array('tag' => $tag->tag));
-
- if ( in_array($tag, $this->tags_already_output) ) {
- $this->element('ctag:tagged', array('rdf:resource'=>$tagpage.'#concept'));
- continue;
- }
-
- $tagrss = common_local_url('tagrss', array('tag' => $tag->tag));
- $this->elementStart('ctag:tagged');
- $this->elementStart('ctag:Tag', array('rdf:about'=>$tagpage.'#concept', 'ctag:label'=>$tag->tag));
- $this->element('foaf:page', array('rdf:resource'=>$tagpage));
- $this->element('rdfs:seeAlso', array('rdf:resource'=>$tagrss));
- $this->elementEnd('ctag:Tag');
- $this->elementEnd('ctag:tagged');
-
- $this->tags_already_output[] = $tag->tag;
- }
- }
- $this->elementEnd('item');
- $this->creators[$creator_uri] = $profile;
- }
-
- function showCreators()
- {
- foreach ($this->creators as $uri => $profile) {
- $id = $profile->id;
- $nickname = $profile->nickname;
- $this->elementStart('foaf:Agent', array('rdf:about' => $uri));
- $this->element('foaf:nick', null, $nickname);
- if ($profile->fullname) {
- $this->element('foaf:name', null, $profile->fullname);
- }
- $this->element('foaf:holdsAccount', array('rdf:resource' => $uri.'#acct'));
- $avatar = $profile->avatarUrl();
- $this->element('foaf:depiction', array('rdf:resource' => $avatar));
- $this->elementEnd('foaf:Agent');
- }
- }
-
- function initRss()
- {
- $channel = $this->getChannel();
- header('Content-Type: application/rdf+xml');
-
- $this->startXml();
- $this->elementStart('rdf:RDF', array('xmlns:rdf' =>
- 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
- 'xmlns:dc' =>
- 'http://purl.org/dc/elements/1.1/',
- 'xmlns:cc' =>
- 'http://creativecommons.org/ns#',
- 'xmlns:content' =>
- 'http://purl.org/rss/1.0/modules/content/',
- 'xmlns:ctag' =>
- 'http://commontag.org/ns#',
- 'xmlns:foaf' =>
- 'http://xmlns.com/foaf/0.1/',
- 'xmlns:enc' =>
- 'http://purl.oclc.org/net/rss_2.0/enc#',
- 'xmlns:sioc' =>
- 'http://rdfs.org/sioc/ns#',
- 'xmlns:sioct' =>
- 'http://rdfs.org/sioc/types#',
- 'xmlns:rdfs' =>
- 'http://www.w3.org/2000/01/rdf-schema#',
- 'xmlns:geo' =>
- 'http://www.w3.org/2003/01/geo/wgs84_pos#',
- 'xmlns:statusnet' =>
- 'http://status.net/ont/',
- 'xmlns' => 'http://purl.org/rss/1.0/'));
- $this->elementStart('sioc:Site', array('rdf:about' => common_root_url()));
- $this->element('sioc:name', null, common_config('site', 'name'));
- $this->elementStart('sioc:space_of');
- $this->element('sioc:Container', array('rdf:about' =>
- $channel['url']));
- $this->elementEnd('sioc:space_of');
- $this->elementEnd('sioc:Site');
- }
-
- function endRss()
- {
- $this->elementEnd('rdf:RDF');
- }
-
- /**
- * When was this page last modified?
- *
- */
-
- function lastModified()
- {
- if (empty($this->notices)) {
- return null;
- }
-
- if (count($this->notices) == 0) {
- return null;
- }
-
- // FIXME: doesn't handle modified profiles, avatars, deleted notices
-
- return strtotime($this->notices[0]->created);
- }
-}
-
class SelftagsWidget extends PeopletagsWidget
{
- function url($tag)
+ public function url()
{
// link to self tag page
- return common_local_url('selftag', array('tag' => $tag));
+ return common_local_url('selftag', array('tag' => $this->tag->tag));
}
function label()
function tagUrl($tag)
{
- if ('showstream' === $this->out->trimmed('action')) {
- return common_local_url('showstream', array('nickname' => $this->out->profile->nickname, 'tag' => $tag));
- } else {
- return common_local_url('tag', array('tag' => $tag));
+ if ($this->out instanceof ShowstreamAction) {
+ return common_local_url('showstream', array('nickname' => $this->out->getTarget()->getNickname(), 'tag' => $tag));
}
+ return common_local_url('tag', array('tag' => $tag));
}
function divId()
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Base class for RSS 1.0 feed actions
+ *
+ * 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 Mail
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Earle Martin <earle@downlode.org>
+ * @copyright 2008-9 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('GNUSOCIAL')) { exit(1); }
+
+class TargetedRss10Action extends Rss10Action
+{
+ protected $target = null;
+
+ protected function doStreamPreparation()
+ {
+ $this->target = User::getByNickname($this->trimmed('nickname'))->getProfile();
+ }
+
+ function getImage()
+ {
+ return $this->target->avatarUrl(AVATAR_PROFILE_SIZE);
+ }
+}
$choices['public:everyone'] = _m('SENDTO','Everyone');
$default = 'public:everyone';
}
- // XXX: better name...?
// TRANS: Option in drop-down of potential addressees.
// TRANS: %s is a StatusNet sitename.
- $choices['public:site'] = sprintf(_('My colleagues at %s'), common_config('site', 'name'));
+ $choices['public:site'] = sprintf(_('Everyone at %s'), common_config('site', 'name'));
$groups = $this->user->getGroups();
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/rssaction.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* RSS feed for user bookmarks action class.
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*/
-class BookmarksrssAction extends Rss10Action
+class BookmarksrssAction extends TargetedRss10Action
{
- /** The user whose bookmarks to display */
-
- var $user = null;
-
- /**
- * Find the user to display by supplied nickname
- *
- * @param array $args Arguments from $_REQUEST
- *
- * @return boolean success
- */
- function prepare($args)
- {
- parent::prepare($args);
-
- $nickname = $this->trimmed('nickname');
- $this->user = User::getKV('nickname', $nickname);
-
- if (!$this->user) {
- // TRANS: Client error displayed when trying to get the RSS feed with bookmarks of a user that does not exist.
- $this->clientError(_('No such user.'));
- } else {
- $this->notices = $this->getNotices($this->limit);
- return true;
- }
- }
-
- /**
- * Get notices
- *
- * @param integer $limit max number of notices to return
- *
- * @return array notices
- */
- function getNotices($limit=0)
+ protected function getNotices()
{
- $user = $this->user;
-
- $notice = new BookmarksNoticeStream($this->user->id, true);
- $notice = $notice->getNotices(0, NOTICES_PER_PAGE);
-
- $notices = array();
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
- return $notices;
+ $stream = new BookmarksNoticeStream($this->target->getID(), true);
+ return $stream->getNotices(0, $this->limit)->fetchAll();
}
/**
*/
function getChannel()
{
- $user = $this->user;
$c = array('url' => common_local_url('bookmarksrss',
array('nickname' =>
- $user->nickname)),
+ $this->target->getNickname())),
// TRANS: Title of RSS feed with bookmarks of a user.
// TRANS: %s is a user's nickname.
- 'title' => sprintf(_("%s's bookmarks"), $user->nickname),
+ 'title' => sprintf(_("%s's bookmarks"), $this->target->getNickname()),
'link' => common_local_url('bookmarks',
array('nickname' =>
- $user->nickname)),
+ $this->target->getNickname())),
// TRANS: Desciption of RSS feed with bookmarks of a user.
// TRANS: %1$s is a user's nickname, %2$s is the name of the StatusNet site.
'description' => sprintf(_('Bookmarks posted by %1$s on %2$s!'),
- $user->nickname, common_config('site', 'name')));
+ $this->target->getNickname(), common_config('site', 'name')));
return $c;
}
-
- /**
- * Get image.
- *
- * @return void
- */
- function getImage()
- {
- return null;
- }
-
}
* @link http://status.net/
*/
-if (!defined('STATUSNET')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Show a list of direct messages from or to the authenticating user
*
* @return boolean success flag
*/
- function prepare($args)
+ protected function prepare(array $args=array())
{
parent::prepare($args);
- $this->user = $this->auth_user;
-
- if (empty($this->user)) {
+ if (!$this->scoped instanceof Profile) {
// TRANS: Client error given when a user was not found (404).
$this->clientError(_('No such user.'), 404);
}
$this->title = sprintf(
// TRANS: Title. %s is a user nickname.
_("Direct messages from %s"),
- $this->user->nickname
+ $this->scoped->getNickname()
);
$this->subtitle = sprintf(
// TRANS: Subtitle. %s is a user nickname.
_("All the direct messages sent from %s"),
- $this->user->nickname
+ $this->scoped->getNickname()
);
- $this->link = $server . $this->user->nickname . '/outbox';
+ $this->link = $server . $this->scoped->getNickname() . '/outbox';
$this->selfuri_base = common_root_url() . 'api/direct_messages/sent';
- $this->id = "tag:$taguribase:SentDirectMessages:" . $this->user->id;
+ $this->id = "tag:$taguribase:SentDirectMessages:" . $this->scoped->getID();
} else {
$this->title = sprintf(
// TRANS: Title. %s is a user nickname.
_("Direct messages to %s"),
- $this->user->nickname
+ $this->scoped->getNickname()
);
$this->subtitle = sprintf(
// TRANS: Subtitle. %s is a user nickname.
_("All the direct messages sent to %s"),
- $this->user->nickname
+ $this->scoped->getNickname()
);
- $this->link = $server . $this->user->nickname . '/inbox';
+ $this->link = $server . $this->scoped->getNickname() . '/inbox';
$this->selfuri_base = common_root_url() . 'api/direct_messages';
- $this->id = "tag:$taguribase:DirectMessages:" . $this->user->id;
+ $this->id = "tag:$taguribase:DirectMessages:" . $this->scoped->getID();
}
$this->messages = $this->getMessages();
return true;
}
- /**
- * Handle the request
- *
- * Show the messages
- *
- * @param array $args $_REQUEST data (unused)
- *
- * @return void
- */
- function handle($args)
+ protected function handle()
{
- parent::handle($args);
+ parent::handle();
$this->showMessages();
}
$message = new Message();
if ($this->arg('sent')) {
- $message->from_profile = $this->user->id;
+ $message->from_profile = $this->scoped->getID();
} else {
- $message->to_profile = $this->user->id;
+ $message->to_profile = $this->scoped->getID();
}
if (!empty($this->max_id)) {
* @link http://status.net/
*/
-if (!defined('STATUSNET')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Creates a new direct message from the authenticating user to
{
parent::prepare($args);
- if (empty($this->user)) {
+ if (!$this->scoped instanceof Profile) {
// TRANS: Client error when user not found for an API direct message action.
$this->clientError(_('No such user.'), 404);
}
if (!$this->other instanceof Profile) {
// TRANS: Client error displayed if a recipient user could not be found (403).
$this->clientError(_('Recipient user not found.'), 403);
- } else if (!$this->user->mutuallySubscribed($this->other)) {
+ } else if (!$this->scoped->mutuallySubscribed($this->other)) {
// TRANS: Client error displayed trying to direct message another user who's not a friend (403).
$this->clientError(_('Cannot send direct messages to users who aren\'t your friend.'), 403);
- } else if ($this->user->id == $this->other->id) {
+ } else if ($this->scoped->getID() === $this->other->getID()) {
// Note: sending msgs to yourself is allowed by Twitter
}
$message = Message::saveNew(
- $this->user->id,
- $this->other->id,
+ $this->scoped->getID(),
+ $this->other->getID(),
html_entity_decode($this->content, ENT_NOQUOTES, 'UTF-8'),
$this->source
);
$nav->out->menuItem(
common_local_url('userdirectory'),
// TRANS: Menu item text for user directory.
- _m('MENU','Directory'),
+ _m('MENU','People'),
// TRANS: Menu item title for user directory.
- _m('User Directory.'),
+ _m('People.'),
$actionName == 'userdirectory',
'nav_directory'
);
float: none;
}
-table.profile_list tr.alt {
- background-color: #def; /* zebra stripe */
-}
-
table.profie_list td {
width: 100%;
padding: 0;
background-image: url(../images/control_arrow_up.gif);
background-repeat: no-repeat;
background-position: 60% 2px;
-}
\ No newline at end of file
+}
* @link http://status.net/
*/
-if (!defined('STATUSNET')) {
- exit(1);
-}
-
-require_once INSTALLDIR . '/lib/subscriptionlist.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Widget to show a sortable list of subscriptions
*/
class SortableGroupList extends SortableSubscriptionList
{
- /** Owner of this list */
- var $owner = null;
-
- function __construct($profile, $owner=null, $action=null)
- {
- parent::__construct($profile, $owner, $action);
-
- $this->owner = $owner;
- }
-
function startList()
{
$this->out->elementStart('table', array('class' => 'profile_list xoxo'));
$this->out->elementStart('tbody');
}
- function newListItem($profile, $odd)
+ function newListItem($profile)
{
- return new SortableGroupListItem($profile, $this->owner, $this->action, $odd);
+ return new SortableGroupListItem($profile, $this->owner, $this->action);
}
}
class SortableGroupListItem extends SortableSubscriptionListItem
{
- /** Owner of this list */
- var $owner = null;
-
- function __construct($profile, $owner, $action, $alt)
- {
- parent::__construct($profile, $owner, $action, $alt);
-
- $this->alt = $alt; // is this row alternate?
- $this->owner = $owner;
- }
-
function showHomepage()
{
if (!empty($this->profile->homepage)) {
* @link http://status.net/
*/
-if (!defined('STATUSNET')) {
- exit(1);
-}
-
-require_once INSTALLDIR . '/lib/subscriptionlist.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Widget to show a sortable list of subscriptions
*/
class SortableSubscriptionList extends SubscriptionList
{
- /** Owner of this list */
- var $owner = null;
-
- function __construct($profile, $owner=null, $action=null)
- {
- parent::__construct($profile, $owner, $action);
-
- $this->owner = $owner;
- }
-
function startList()
{
$this->out->elementStart('table', array('class' => 'profile_list xoxo'));
$this->out->elementEnd('table');
}
- function showProfiles()
+ function newListItem($profile)
{
- // Note: we don't use fetchAll() because it's borked with query()
-
- $profiles = array();
-
- while ($this->profile->fetch()) {
- $profiles[] = clone($this->profile);
- }
-
- $cnt = count($profiles);
-
- $max = min($cnt, $this->maxProfiles());
-
- for ($i = 0; $i < $max; $i++) {
- $odd = ($i % 2 == 0); // for zebra striping
- $pli = $this->newListItem($profiles[$i], $odd);
- $pli->show();
- }
-
- return $cnt;
- }
-
- function newListItem($profile, $odd)
- {
- return new SortableSubscriptionListItem($profile, $this->owner, $this->action, $odd);
+ return new SortableSubscriptionListItem($profile, $this->owner, $this->action);
}
}
class SortableSubscriptionListItem extends SubscriptionListItem
{
- /** Owner of this list */
- var $owner = null;
-
- function __construct($profile, $owner, $action, $alt)
- {
- parent::__construct($profile, $owner, $action);
-
- $this->alt = $alt; // is this row alternate?
- $this->owner = $owner;
- }
-
function startItem()
{
$attr = array(
'id' => 'profile-' . $this->profile->id
);
- if ($this->alt) {
- $attr['class'] .= ' alt';
- }
-
$this->out->elementStart('tr', $attr);
}
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
class ProfileDetailAction extends ShowstreamAction
{
-
function isReadOnly($args)
{
return true;
function title()
{
- return $this->profile->getFancyName();
+ return $this->target->getFancyName();
}
function showStylesheets() {
function showContent()
{
$cur = common_current_user();
- if ($cur && $cur->id == $this->profile->id) { // your own page
+ if ($this->scoped instanceof Profile && $this->scoped->sameAs($this->target)) {
$this->elementStart('div', 'entity_actions');
$this->elementStart('ul');
$this->elementStart('li', 'entity_edit');
$this->elementEnd('div');
}
- $widget = new ExtendedProfileWidget($this, $this->profile);
+ $widget = new ExtendedProfileWidget($this, $this->target);
$widget->show();
}
}
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/rssaction.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* RSS feed for user favorites action class.
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*/
-class FavoritesrssAction extends Rss10Action
+class FavoritesrssAction extends TargetedRss10Action
{
- /** The user whose favorites to display */
-
- var $user = null;
-
- /**
- * Find the user to display by supplied nickname
- *
- * @param array $args Arguments from $_REQUEST
- *
- * @return boolean success
- */
- function prepare($args)
+ protected function getNotices()
{
- parent::prepare($args);
-
- $nickname = $this->trimmed('nickname');
- $this->user = User::getKV('nickname', $nickname);
+ // is this our own stream?
+ $own = $this->scoped instanceof Profile ? $this->target->getID() === $this->scoped->getID() : false;
- if (!$this->user) {
- // TRANS: Client error displayed when trying to get the RSS feed with favorites of a user that does not exist.
- $this->clientError(_('No such user.'));
- } else {
- $this->notices = $this->getNotices($this->limit);
- return true;
- }
- }
-
- /**
- * Get notices
- *
- * @param integer $limit max number of notices to return
- *
- * @return array notices
- */
- function getNotices($limit=0)
- {
- $notice = Fave::stream($this->user->id, 0, $limit, $false);
- $notices = array();
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
- return $notices;
+ $stream = Fave::stream($this->target->getID(), 0, $this->limit, $own);
+ return $stream->fetchAll();
}
/**
$user->nickname, common_config('site', 'name')));
return $c;
}
-
- /**
- * Get image.
- *
- * @return void
- */
- function getImage()
- {
- return null;
- }
-
}
* @link http://status.net/
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/personalgroupnav.php';
-require_once INSTALLDIR.'/lib/noticelist.php';
-require_once INSTALLDIR.'/lib/feedlist.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* List of replies
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
-class ShowfavoritesAction extends Action
+class ShowfavoritesAction extends ShowstreamAction
{
- /** User we're getting the faves of */
- var $user = null;
- /** Page of the faves we're on */
- var $page = null;
-
- /**
- * Is this a read-only page?
- *
- * @return boolean true
- */
- function isReadOnly($args)
- {
- return true;
- }
-
- /**
- * Title of the page
- *
- * Includes name of user and page number.
- *
- * @return string title of page
- */
function title()
{
if ($this->page == 1) {
// TRANS: Title for first page of favourite notices of a user.
// TRANS: %s is the user for whom the favourite notices are displayed.
- return sprintf(_('%s\'s favorite notices'), $this->user->nickname);
+ return sprintf(_('%s\'s favorite notices'), $this->getTarget()->getNickname());
} else {
// TRANS: Title for all but the first page of favourite notices of a user.
// TRANS: %1$s is the user for whom the favourite notices are displayed, %2$d is the page number.
return sprintf(_('%1$s\'s favorite notices, page %2$d'),
- $this->user->nickname,
+ $this->getTarget()->getNickname(),
$this->page);
}
}
- /**
- * Prepare the object
- *
- * Check the input values and initialize the object.
- * Shows an error page on bad input.
- *
- * @param array $args $_REQUEST data
- *
- * @return boolean success flag
- */
- function prepare($args)
+ public function getStream()
{
- parent::prepare($args);
-
- $nickname = common_canonical_nickname($this->arg('nickname'));
-
- $this->user = User::getKV('nickname', $nickname);
-
- if (!$this->user) {
- // TRANS: Client error displayed when trying to display favourite notices for a non-existing user.
- $this->clientError(_('No such user.'));
- }
-
- $this->page = $this->trimmed('page');
-
- if (!$this->page) {
- $this->page = 1;
- }
-
- common_set_returnto($this->selfUrl());
-
- $cur = common_current_user();
-
- // Show imported/gateway notices as well as local if
- // the user is looking at their own favorites, otherwise not.
- $this->notice = Fave::stream($this->user->id,
- ($this->page-1)*NOTICES_PER_PAGE, // offset
- NOTICES_PER_PAGE + 1, // limit
- (!empty($cur) && $cur->id == $this->user->id) // own feed?
- );
-
- if (empty($this->notice)) {
- // TRANS: Server error displayed when favourite notices could not be retrieved from the database.
- $this->serverError(_('Could not retrieve favorite notices.'));
- }
-
- if($this->page > 1 && $this->notice->N == 0){
- // TRANS: Client error when page not found (404)
- $this->clientError(_('No such page.'), 404);
- }
-
- return true;
- }
-
- /**
- * Handle a request
- *
- * Just show the page. All args already handled.
- *
- * @param array $args $_REQUEST data
- *
- * @return void
- */
- function handle($args)
- {
- parent::handle($args);
- $this->showPage();
+ $own = $this->scoped instanceof Profile ? $this->scoped->sameAs($this->getTarget()) : false;
+ return new FaveNoticeStream($this->getTarget()->getID(), $own);
}
- /**
- * Feeds for the <head> section
- *
- * @return array Feed objects to show
- */
function getFeeds()
{
return array(new Feed(Feed::JSON,
*
* @return void
*/
- function showContent()
+ function showNotices()
{
$nl = new FavoritesNoticeList($this->notice, $this);
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
$this->page, 'showfavorites',
- array('nickname' => $this->user->nickname));
+ array('nickname' => $this->getTarget()->getNickname()));
}
function showPageNotice() {
return $result;
}
- function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $own=false, $since_id=0, $max_id=0)
+ static function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $own=false, $since_id=0, $max_id=0)
{
$stream = new FaveNoticeStream($user_id, $own);
*
* @return boolean event handler flag
*/
- function onEndShowHeadElements($action)
+ function onEndShowHeadElements(Action $action)
{
$name = $action->trimmed('action');
$location = null;
- if ($name == 'showstream') {
- $profile = $action->profile;
- if (!empty($profile) && !empty($profile->lat) && !empty($profile->lon)) {
+ if ($action instanceof ShowstreamAction) {
+ $profile = $action->getTarget();
+ if (!empty($profile->lat) && !empty($profile->lon)) {
$location = $profile->lat . ', ' . $profile->lon;
}
- } else if ($name == 'shownotice') {
- $notice = $action->profile;
- if (!empty($notice) && !empty($notice->lat) && !empty($notice->lon)) {
+ } elseif ($action instanceof ShownoticeAction) {
+ // FIXME: getNotice in ShownoticeAction will do a new lookup, we should fix those classes
+ // so they can reliably just get a pre-stored notice object which was fetched in Shownotice prepare()...
+ $notice = $action->notice;
+ if ($notice instanceof Notice && !empty($notice->lat) && !empty($notice->lon)) {
$location = $notice->lat . ', ' . $notice->lon;
}
}
- if (!empty($location)) {
+ if (!is_null($location)) {
$action->element('meta', array('name' => 'ICBM',
'content' => $location));
$action->element('meta', array('name' => 'DC.title',
+++ /dev/null
-<?php
-/*
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2009,2011 StatusNet, Inc.
- *
- * 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/>.
- */
-
-/**
- * @package GravatarPlugin
- * @maintainer Eric Helgeson <erichelgeson@gmail.com>
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- // This check helps protect against security problems;
- // your code file can't be executed directly from the web.
- exit(1);
-}
-
-class GravatarPlugin extends Plugin
-{
- function onEndProfileGetAvatar($profile, $size, &$avatar)
- {
- if (empty($avatar)) {
- try {
- $user = $profile->getUser();
- if (!empty($user->email)) {
- // Fake one!
- $avatar = new Avatar();
- $avatar->width = $avatar->height = $size;
- $avatar->url = $this->gravatar_url($user->email, $size);
- return false;
- }
- } catch (NoSuchUserException $e) {
- return true;
- }
- }
-
- return true;
- }
-
- function gravatar_url($email, $size)
- {
- $url = "https://secure.gravatar.com/avatar.php?gravatar_id=".
- md5(strtolower($email)).
- "&default=".urlencode(Avatar::defaultImage($size)).
- "&size=".$size;
- return $url;
- }
-
- function onPluginVersion(array &$versions)
- {
- $versions[] = array('name' => 'Gravatar',
- 'version' => GNUSOCIAL_VERSION,
- 'author' => 'Eric Helgeson, Evan Prodromou',
- 'homepage' => 'http://status.net/wiki/Plugin:Gravatar',
- 'rawdescription' =>
- // TRANS: Plugin decsription.
- _m('The Gravatar plugin allows users to use their <a href="http://www.gravatar.com/">Gravatar</a> with StatusNet.'));
-
- return true;
- }
-}
+++ /dev/null
-GravatarPlugin 0.1
-
-About:
-This will allow users to use their Gravatar Avatar with your StatusNet install.
-
-Configuration:
-add this to your config.php:
-addPlugin('Gravatar', array());
-
-To do:
-Site default all on for gravatar by default
-Migration Script
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-27 16:31+0100\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
-"Language: \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=CHARSET\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a href=\"http://www.gravatar."
-"com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Afrikaans (http://www.transifex.com/projects/p/gnu-social/language/af/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: af\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Arabic (http://www.transifex.com/projects/p/gnu-social/language/ar/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ar\n"
-"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Arabic (Egypt) (http://www.transifex.com/projects/p/gnu-social/language/ar_EG/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ar_EG\n"
-"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Asturian (http://www.transifex.com/projects/p/gnu-social/language/ast/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ast\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Belarusian (Tarask) (http://www.transifex.com/projects/p/gnu-social/language/be@tarask/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: be@tarask\n"
-"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Bulgarian (http://www.transifex.com/projects/p/gnu-social/language/bg/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: bg\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Breton (http://www.transifex.com/projects/p/gnu-social/language/br/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: br\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Catalan (http://www.transifex.com/projects/p/gnu-social/language/ca/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ca\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "El connector del Gravatar permet als usuaris fer servir llur <a href=\"http://www.gravatar.com/\">Gravatar</a> amb l'StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Czech (http://www.transifex.com/projects/p/gnu-social/language/cs/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: cs\n"
-"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Danish (http://www.transifex.com/projects/p/gnu-social/language/da/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: da\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: German (http://www.transifex.com/projects/p/gnu-social/language/de/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: de\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Das Gravatar-Plugin erlaubt es Benutzern, ihr <a href=\"http://www.gravatar.com/\">Gravatar</a> mit StatusNet zu verwenden."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Greek (http://www.transifex.com/projects/p/gnu-social/language/el/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: el\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/gnu-social/language/en_GB/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: en_GB\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Esperanto (http://www.transifex.com/projects/p/gnu-social/language/eo/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: eo\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-# Juan Riquelme González <soulchainer@gmail.com>, 2015
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-27 12:21+0000\n"
-"Last-Translator: Juan Riquelme González <soulchainer@gmail.com>\n"
-"Language-Team: Spanish (http://www.transifex.com/projects/p/gnu-social/language/es/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: es\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "El complemento Gravatar permite a los usuarios utilizar su <a href=\"http://www.gravatar.com/\">Gravatar</a> en GNU social."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Basque (http://www.transifex.com/projects/p/gnu-social/language/eu/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: eu\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Gravatar pluginak erabiltzaileei heuren <a href=\"http://www.gravatar.com/\">Gravatar</a>ra StatusNet-en erabiltzen uzten die."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Persian (http://www.transifex.com/projects/p/gnu-social/language/fa/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fa\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Finnish (http://www.transifex.com/projects/p/gnu-social/language/fi/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fi\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: French (http://www.transifex.com/projects/p/gnu-social/language/fr/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fr\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Le greffon Gravatar permet aux utilisateurs d’utiliser leur image <a href=\"http://www.gravatar.com/\">Gravatar</a> avec StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Friulian (http://www.transifex.com/projects/p/gnu-social/language/fur/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fur\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Galician (http://www.transifex.com/projects/p/gnu-social/language/gl/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: gl\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "O complemento Gravatar permite aos usuarios usar o seu <a href=\"http://www.gravatar.com/\">Gravatar</a> co StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Hebrew (http://www.transifex.com/projects/p/gnu-social/language/he/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: he\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "תוסף Gravatar מאפשר למשתמשים להציג את ה־<a href=\"http://www.gravatar.com/\">Gravatar</a> שלהם בסטטוסנט."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Upper Sorbian (http://www.transifex.com/projects/p/gnu-social/language/hsb/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: hsb\n"
-"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Hungarian (http://www.transifex.com/projects/p/gnu-social/language/hu/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: hu\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Interlingua (http://www.transifex.com/projects/p/gnu-social/language/ia/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ia\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Le plug-in Gravatar permitte al usatores de usar lor <a href=\"http://www.gravatar.com/\">Gravatar</a> con StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Indonesian (http://www.transifex.com/projects/p/gnu-social/language/id/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: id\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Icelandic (http://www.transifex.com/projects/p/gnu-social/language/is/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: is\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Italian (http://www.transifex.com/projects/p/gnu-social/language/it/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: it\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Il plugin Gravatar consente agli utenti di utilizzare i loro <a href=\"http://www.gravatar.com/\">Gravatar</a> con StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Japanese (http://www.transifex.com/projects/p/gnu-social/language/ja/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ja\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Georgian (http://www.transifex.com/projects/p/gnu-social/language/ka/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ka\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Korean (http://www.transifex.com/projects/p/gnu-social/language/ko/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ko\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Colognian (http://www.transifex.com/projects/p/gnu-social/language/ksh/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ksh\n"
-"Plural-Forms: nplurals=3; plural=(n==0) ? 0 : (n==1) ? 1 : 2;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/gnu-social/language/lb/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: lb\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Lithuanian (http://www.transifex.com/projects/p/gnu-social/language/lt/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: lt\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-07 09:39+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Latvian (http://www.transifex.com/projects/p/gnu-social/language/lv/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: lv\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Malagasy (http://www.transifex.com/projects/p/gnu-social/language/mg/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: mg\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Macedonian (http://www.transifex.com/projects/p/gnu-social/language/mk/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: mk\n"
-"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Приклучокот Gravatar им овозможува на корисниците да го користат својот <a href=\"http://www.gravatar.com/\">Gravatar</a> со StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Malayalam (http://www.transifex.com/projects/p/gnu-social/language/ml/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ml\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Malay (http://www.transifex.com/projects/p/gnu-social/language/ms/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ms\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Burmese (http://www.transifex.com/projects/p/gnu-social/language/my/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: my\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Norwegian Bokmål (http://www.transifex.com/projects/p/gnu-social/language/nb/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: nb\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-07 09:30+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Nepali (http://www.transifex.com/projects/p/gnu-social/language/ne/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ne\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Dutch (http://www.transifex.com/projects/p/gnu-social/language/nl/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: nl\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "De plug-in Gravatar maak het mogelijk dat gebruikers hun <a href=\"http://www.gravatar.com/\">Gravatar</a> gebruiken in StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Norwegian Nynorsk (http://www.transifex.com/projects/p/gnu-social/language/nn/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: nn\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Polish (http://www.transifex.com/projects/p/gnu-social/language/pl/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: pl\n"
-"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Wtyczka Gravatar umożliwia użytkownikom używanie obrazów <a href=\"http://www.gravatar.com/\">Gravatar</a> w StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Portuguese (http://www.transifex.com/projects/p/gnu-social/language/pt/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: pt\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "O plugin Gravatar permite que os utilizadores usem o seu <a href=\"http://www.gravatar.com/\">Gravatar</a> com o StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/gnu-social/language/pt_BR/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: pt_BR\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Russian (http://www.transifex.com/projects/p/gnu-social/language/ru/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ru\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Serbian (http://www.transifex.com/projects/p/gnu-social/language/sr/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: sr\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Swedish (http://www.transifex.com/projects/p/gnu-social/language/sv/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: sv\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Gravatar-tillägget låter användare använda deras <a href=\"http://www.gravatar.com/\">Gravatar</a> med StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-07 08:48+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Tamil (http://www.transifex.com/projects/p/gnu-social/language/ta/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ta\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Telugu (http://www.transifex.com/projects/p/gnu-social/language/te/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: te\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Tagalog (http://www.transifex.com/projects/p/gnu-social/language/tl/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: tl\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Ang pamasak na Gravatar ay nagpapahintulot sa mga tagagamit na gamitin ang kanilang <a href=\"http://www.gravatar.com/\">Gravatar</a> na may StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Turkish (http://www.transifex.com/projects/p/gnu-social/language/tr/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: tr\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Ukrainian (http://www.transifex.com/projects/p/gnu-social/language/uk/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: uk\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Додаток Gravatar дозволяє користувачам встановлювати аватарки з <a href=\"http://www.gravatar.com/\">Gravatar</a> для сайту StatusNet."
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Urdu (Pakistan) (http://www.transifex.com/projects/p/gnu-social/language/ur_PK/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ur_PK\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Vietnamese (http://www.transifex.com/projects/p/gnu-social/language/vi/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: vi\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:43+0000\n"
-"Last-Translator: digitaldreamer <digitaldreamer@email.cz>\n"
-"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/gnu-social/language/zh_CN/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: zh_CN\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr "Gravatar 插件可以让用户在 StatusNet 站点使用自己的 <a href=\"http://www.gravatar.com/\">Gravatar</a>。"
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: GNU social\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-02 17:47+0100\n"
-"PO-Revision-Date: 2015-02-06 16:27+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/gnu-social/language/zh_TW/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: zh_TW\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. TRANS: Plugin decsription.
-#: GravatarPlugin.php:70
-msgid ""
-"The Gravatar plugin allows users to use their <a "
-"href=\"http://www.gravatar.com/\">Gravatar</a> with StatusNet."
-msgstr ""
$modlog->profile_id = $profile->id;
- $cur = common_current_user();
+ $scoped = Profile::current();
- if (!empty($cur)) {
- $modlog->moderator_id = $cur->id;
+ if ($scoped instanceof Profile) {
+ $modlog->moderator_id = $scoped->getID();
}
$modlog->role = $role;
function onEndShowSections(Action $action)
{
- if ($action->arg('action') != 'showstream') {
+ if (!$action instanceof ShowstreamAction) {
+ // early return for actions we're not interested in
return true;
}
- $cur = common_current_user();
-
- if (empty($cur) || !$cur->hasRight(self::VIEWMODLOG)) {
+ $scoped = $action->getScoped();
+ if (!$scoped instanceof Profile || !$scoped->hasRight(self::VIEWMODLOG)) {
+ // only continue if we are allowed to VIEWMODLOG
return true;
}
- $profile = $action->profile;
+ $profile = $action->getTarget();
$ml = new ModLog();
- $ml->profile_id = $profile->id;
+ $ml->profile_id = $profile->getID();
$ml->orderBy("created");
$cnt = $ml->find();
$action->element('td', null, sprintf(($ml->is_grant) ? _('+%s') : _('-%s'), $ml->role));
$action->elementStart('td');
if ($ml->moderator_id) {
- $mod = Profile::getKV('id', $ml->moderator_id);
+ $mod = Profile::getByID($ml->moderator_id);
if (empty($mod)) {
$action->text(_('[unknown]'));
} else {
- $action->element('a', array('href' => $mod->profileurl,
- 'title' => $mod->fullname),
- $mod->nickname);
+ $action->element('a', array('href' => $mod->getUrl(),
+ 'title' => $mod->getFullname()),
+ $mod->getNickname());
}
} else {
$action->text(_('[unknown]'));
function showEntityRemoteSubscribe($action, $target='ostatussub')
{
- $user = common_current_user();
- if ($user && ($user->id == $action->profile->id)) {
+ if (!$action->getScoped() instanceof Profile) {
+ // early return if we're not logged in
+ return true;
+ }
+
+ if ($action->getScoped()->sameAs($action->getTarget())) {
$action->elementStart('div', 'entity_actions');
$action->elementStart('p', array('id' => 'entity_remote_subscribe',
'class' => 'entity_subscribe'));
return true;
}
- function onStartProfileListItemActionElements($item, $profile=null)
+ // FIXME: This one can accept both an Action and a Widget. Confusing! Refactor to (HTMLOutputter $out, Profile $target)!
+ function onStartProfileListItemActionElements($item)
{
- if (!common_logged_in()) {
-
- $profileUser = User::getKV('id', $item->profile->id);
-
- if (!empty($profileUser)) {
-
- if ($item instanceof Action) {
- $output = $item;
- $profile = $item->profile;
- } else {
- $output = $item->out;
- }
+ if (common_logged_in()) {
+ // only non-logged in users get to see the "remote subscribe" form
+ return true;
+ } elseif (!$item->getTarget()->isLocal()) {
+ // we can (for now) only provide remote subscribe forms for local users
+ return true;
+ }
- // Add an OStatus subscribe
- $output->elementStart('li', 'entity_subscribe');
- $url = common_local_url('ostatusinit',
- array('nickname' => $profileUser->nickname));
- $output->element('a', array('href' => $url,
- 'class' => 'entity_remote_subscribe'),
- // TRANS: Link text for a user to subscribe to an OStatus user.
- _m('Subscribe'));
- $output->elementEnd('li');
-
- $output->elementStart('li', 'entity_tag');
- $url = common_local_url('ostatustag',
- array('nickname' => $profileUser->nickname));
- $output->element('a', array('href' => $url,
- 'class' => 'entity_remote_tag'),
- // TRANS: Link text for a user to list an OStatus user.
- _m('List'));
- $output->elementEnd('li');
- }
+ if ($item instanceof ProfileAction) {
+ $output = $item;
+ } elseif ($item instanceof Widget) {
+ $output = $item->out;
+ } else {
+ // Bad $item class, don't know how to use this for outputting!
+ throw new ServerException('Bad item type for onStartProfileListItemActionElements');
}
+ // Add an OStatus subscribe
+ $output->elementStart('li', 'entity_subscribe');
+ $url = common_local_url('ostatusinit',
+ array('nickname' => $item->getTarget()->getNickname()));
+ $output->element('a', array('href' => $url,
+ 'class' => 'entity_remote_subscribe'),
+ // TRANS: Link text for a user to subscribe to an OStatus user.
+ _m('Subscribe'));
+ $output->elementEnd('li');
+
+ $output->elementStart('li', 'entity_tag');
+ $url = common_local_url('ostatustag',
+ array('nickname' => $item->getTarget()->getNickname()));
+ $output->element('a', array('href' => $url,
+ 'class' => 'entity_remote_tag'),
+ // TRANS: Link text for a user to list an OStatus user.
+ _m('List'));
+ $output->elementEnd('li');
+
return true;
}
*/
public function __construct($xml=null) {
if (!empty($xml)) {
- $dom = DOMDocument::loadXML($xml);
- if (!$dom instanceof DOMDocument) {
+ $dom = new DOMDocument();
+ if (!$dom->loadXML($xml)) {
throw new ServerException('Tried to load malformed XML as DOM');
} elseif (!$this->fromDom($dom)) {
throw new ServerException('Could not load MagicEnvelope from DOM');
$action->element('link', array('rel' => 'openid2.provider',
'href' => common_local_url('openidserver')));
$action->element('link', array('rel' => 'openid2.local_id',
- 'href' => $action->profile->profileurl));
+ 'href' => $action->getTarget()->getUrl()));
$action->element('link', array('rel' => 'openid.server',
'href' => common_local_url('openidserver')));
$action->element('link', array('rel' => 'openid.delegate',
- 'href' => $action->profile->profileurl));
+ 'href' => $action->getTarget()->getUrl()));
}
if ($action instanceof SitestreamAction) {
+++ /dev/null
-Several example plugins are included in the plugins/ directory. You
-can enable a plugin with the following line in config.php:
-
- addPlugin('Example', array('param1' => 'value1',
- 'param2' => 'value2'));
-
-This will look for and load files named 'ExamplePlugin.php' or
-'Example/ExamplePlugin.php' either in the plugins/ directory (for
-plugins that ship with StatusNet) or in the local/ directory (for
-plugins you write yourself or that you get from somewhere else) or
-local/plugins/.
-
-Plugins are documented in their own directories.
-
-
-Additional information on using and developing plugins can be found
-on the StatusNet wiki:
-
-http://status.net/wiki/Plugins
-http://status.net/wiki/Plugin_development
-
--- /dev/null
+Several example plugins are included in the plugins/ directory. You
+can enable a plugin with the following line in config.php:
+
+```php
+ addPlugin('Example', array('param1' => 'value1',
+ 'param2' => 'value2'));
+```
+
+This will look for and load files named 'ExamplePlugin.php' or
+'Example/ExamplePlugin.php' either in the plugins/ directory (for
+plugins that ship with StatusNet) or in the local/ directory (for
+plugins you write yourself or that you get from somewhere else) or
+local/plugins/.
+
+Plugins are documented in their own directories.
+
+Additional information on using and developing plugins can be found
+at the following locations:
+
+* [Plugin Development](doc/Plugin_development.md)
+* [Community Plugins](http://www.skilledtests.com/wiki/GNU_social_plugins)
+
*/
public $disallowLogin = false;
- function onRouterInitialized($m)
+ public function onRouterInitialized(URLMapper $m)
{
$m->connect('main/confirmfirst/:code',
array('action' => 'confirmfirstemail'));
*
* @return bool hook result code
*/
- function onStartNoticeSave($notice)
+ public function onStartNoticeSave(Notice $notice)
{
- $user = User::getKV('id', $notice->profile_id);
- if (!empty($user)) { // it's a remote notice
- if (!$this->validated($user)) {
- // TRANS: Client exception thrown when trying to post notices before validating an e-mail address.
- $msg = _m('You must validate your email address before posting.');
- throw new ClientException($msg);
- }
+ $author = $notice->getProfile();
+ if (!$author->isLocal()) {
+ // remote notice
+ return true;
+ }
+ $user = $author->getUser();
+ if (!$this->validated($user)) {
+ // TRANS: Client exception thrown when trying to post notices before validating an e-mail address.
+ $msg = _m('You must validate your email address before posting.');
+ throw new ClientException($msg);
}
return true;
}
*
* @return bool
*/
- protected function validated($user)
+ protected function validated(User $user)
{
// The email field is only stored after validation...
// Until then you'll find them in confirm_address.
*
* @return bool true if user is grandfathered
*/
- protected function grandfathered($user)
+ protected function grandfathered(User $user)
{
if ($this->grandfatherCutoff) {
$created = strtotime($user->created . " GMT");
*
* @return bool true if user has a trusted OpenID.
*/
- function hasTrustedOpenID($user)
+ function hasTrustedOpenID(User $user)
{
if ($this->trustedOpenIDs && class_exists('User_openid')) {
foreach ($this->trustedOpenIDs as $regex) {
* @link http://status.net/
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* A list of the user's subscriptions
if ($this->page == 1) {
// TRANS: Header for subscriptions overview for a user (first page).
// TRANS: %s is a user nickname.
- return sprintf(_m('%s\'s search subscriptions'), $this->user->nickname);
+ return sprintf(_m('%s\'s search subscriptions'), $this->getTarget()->getNickname());
} else {
// TRANS: Header for subscriptions overview for a user (not first page).
// TRANS: %1$s is a user nickname, %2$d is the page number.
return sprintf(_m('%1$s\'s search subscriptions, page %2$d'),
- $this->user->nickname,
+ $this->getTarget()->getNickname(),
$this->page);
}
}
function showPageNotice()
{
- $user = common_current_user();
- if ($user && ($user->id == $this->profile->id)) {
+ if ($this->scoped instanceof Profile && $this->scoped->sameAs($this->getTarget())) {
$this->element('p', null,
// TRANS: Page notice for page with an overview of all search subscriptions
// TRANS: of the logged in user's own profile.
// TRANS: Page notice for page with an overview of all subscriptions of a user other
// TRANS: than the logged in user. %s is the user nickname.
sprintf(_m('%s has subscribed to receive all notices on this site matching the following searches:'),
- $this->profile->nickname));
+ $this->getTarget()->getNickname()));
}
}
$cnt = 0;
$searchsub = new SearchSub();
- $searchsub->profile_id = $this->user->id;
+ $searchsub->profile_id = $this->getTarget()->getID();
$searchsub->limit($limit, $offset);
$searchsub->find();
if ($searchsub->N) {
- $list = new SearchSubscriptionsList($searchsub, $this->user, $this);
+ $list = new SearchSubscriptionsList($searchsub, $this->getTarget(), $this);
$cnt = $list->show();
if (0 == $cnt) {
$this->showEmptyListMessage();
$this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
$this->page, 'searchsubs',
- array('nickname' => $this->user->nickname));
+ array('nickname' => $this->getTarget()->getNickname()));
Event::handle('EndShowTagSubscriptionsContent', array($this));
function showEmptyListMessage()
{
if (common_logged_in()) {
- $current_user = common_current_user();
- if ($this->user->id === $current_user->id) {
+ if ($this->scoped->sameAs($this->getTarget())) {
// TRANS: Search subscription list text when the logged in user has no search subscriptions.
$message = _m('You are not subscribed to any text searches right now. You can push the "Subscribe" button ' .
'on any notice text search to automatically receive any public messages on this site that match that ' .
} else {
// TRANS: Search subscription list text when looking at the subscriptions for a of a user other
// TRANS: than the logged in user that has no search subscriptions. %s is the user nickname.
- $message = sprintf(_m('%s is not subscribed to any searches.'), $this->user->nickname);
+ $message = sprintf(_m('%s is not subscribed to any searches.'), $this->getTarget()->getNickname());
}
}
else {
// TRANS: Subscription list text when looking at the subscriptions for a of a user that has none
// TRANS: as an anonymous user. %s is the user nickname.
- $message = sprintf(_m('%s is not subscribed to any searches.'), $this->user->nickname);
+ $message = sprintf(_m('%s is not subscribed to any searches.'), $this->getTarget()->getNickname());
}
$this->elementStart('div', 'guide');
return $items;
}
- function item($actionName, $args, $label, $description, $id=null, $cls=null)
+ function item($actionName, array $args, $label, $description, $id=null, $cls=null)
{
if (empty($id)) {
$id = $this->menuItemID($actionName, $args);
{
$this->out->submit('repeat-submit-' . $this->notice->id,
// TRANS: Button text to repeat a notice on notice repeat form.
- _m('BUTTON','Yes'), 'submit', null,
+ _m('BUTTON','Confirm repeat'), 'submit', null,
// TRANS: Button title to repeat a notice on notice repeat form.
_('Repeat this notice.'));
}
* @link http://status.net/
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
/**
* A list of the user's subscriptions
if ($this->page == 1) {
// TRANS: Header for subscriptions overview for a user (first page).
// TRANS: %s is a user nickname.
- return sprintf(_m('%s\'s tag subscriptions'), $this->user->nickname);
+ return sprintf(_m('%s\'s tag subscriptions'), $this->getTarget()->getNickname());
} else {
// TRANS: Header for subscriptions overview for a user (not first page).
// TRANS: %1$s is a user nickname, %2$d is the page number.
return sprintf(_m('%1$s\'s tag subscriptions, page %2$d'),
- $this->user->nickname,
+ $this->getTarget()->getNickname(),
$this->page);
}
}
function showPageNotice()
{
- $user = common_current_user();
- if ($user && ($user->id == $this->profile->id)) {
+ if ($this->scoped instanceof Profile && $this->scoped->sameAs($this->getTarget())) {
$this->element('p', null,
// TRANS: Page notice for page with an overview of all tag subscriptions
// TRANS: of the logged in user's own profile.
// TRANS: Page notice for page with an overview of all subscriptions of a user other
// TRANS: than the logged in user. %s is the user nickname.
sprintf(_m('%s has subscribed to receive all notices on this site containing the following tags:'),
- $this->profile->nickname));
+ $this->getTarget()->getNickname()));
}
}
$cnt = 0;
$tagsub = new TagSub();
- $tagsub->profile_id = $this->user->id;
+ $tagsub->profile_id = $this->getTarget()->getID();
$tagsub->limit($limit, $offset);
$tagsub->find();
if ($tagsub->N) {
- $list = new TagSubscriptionsList($tagsub, $this->user, $this);
+ $list = new TagSubscriptionsList($tagsub, $this->getTarget(), $this);
$cnt = $list->show();
if (0 == $cnt) {
$this->showEmptyListMessage();
$this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
$this->page, 'tagsubs',
- array('nickname' => $this->user->nickname));
+ array('nickname' => $this->getTarget()->getNickname()));
Event::handle('EndShowTagSubscriptionsContent', array($this));
function showEmptyListMessage()
{
if (common_logged_in()) {
- $current_user = common_current_user();
- if ($this->user->id === $current_user->id) {
+ if ($this->scoped->sameAs($this->getTarget())) {
// TRANS: Tag subscription list text when the logged in user has no tag subscriptions.
$message = _m('You are not listening to any hash tags right now. You can push the "Subscribe" button ' .
'on any hashtag page to automatically receive any public messages on this site that use that ' .
} else {
// TRANS: Tag subscription list text when looking at the subscriptions for a of a user other
// TRANS: than the logged in user that has no tag subscriptions. %s is the user nickname.
- $message = sprintf(_m('%s is not following any tags.'), $this->user->nickname);
+ $message = sprintf(_m('%s is not following any tags.'), $this->getTarget()->getNickname());
}
}
else {
// TRANS: Subscription list text when looking at the subscriptions for a of a user that has none
// TRANS: as an anonymous user. %s is the user nickname.
- $message = sprintf(_m('%s is not following any tags.'), $this->user->nickname);
+ $message = sprintf(_m('%s is not following any tags.'), $this->getTarget()->getNickname());
}
$this->elementStart('div', 'guide');
public function onStartShowHTML($action)
{
if ($action instanceof ShowstreamAction) {
- $acct = 'acct:'. $action->profile->nickname .'@'. common_config('site', 'server');
+ $acct = 'acct:'. $action->getTarget()->getNickname() .'@'. common_config('site', 'server');
$url = common_local_url('webfinger') . '?resource='.$acct;
foreach (array(Discovery::JRD_MIMETYPE, Discovery::XRD_MIMETYPE) as $type) {
--- /dev/null
+Plugin Development
+=======================
+
+SamplePlugin.php
+-----------------------
+
+Each plugin requires a main class to interact with the GNU social system.
+
+The main class usually extends the Plugin class that comes with GNU social.
+
+The class has standard-named methods that will be called when certain events
+happen in the code base. These methods have names like 'onX' where X is an
+event name (see EVENTS.txt for the list of available events). Event handlers
+have pre-defined arguments, based on which event they're handling. A typical
+event handler:
+
+```php
+function onSomeEvent($paramA, &$paramB)
+{
+ if ($paramA == 'jed') {
+ throw new Exception(sprintf(_m("Invalid parameter %s"), $paramA));
+ }
+ $paramB = 'spock';
+ return true;
+}
+```
+
+Event Handlers
+-----------------------
+
+Event handlers must return a Boolean value.
+
+If they return false, all other event handlers for this event (in other plug-in)
+will be skipped, and in some cases the default processing for that event would
+be skipped. This is great for replacing the default action of an event.
+
+If the handler returns true, processing of other event handlers and the default
+processing will continue. This is great for extending existing functionality.
+
+If the handler throws an exception, processing will stop, and the exception's
+error will be shown to the user.
+
+Installation
+------------------
+
+To install a plugin (like this one), site admins add the following code to their
+config.php file:
+
+```php
+addPlugin('Sample');
+```
+
+Plugins must be installed in one of the following directories:
+
+* local/plugins/{$pluginclass}.php
+* local/plugins/{$name}/{$pluginclass}.php
+* local/{$pluginclass}.php
+* local/{$name}/{$pluginclass}.php
+* plugins/{$pluginclass}.php
+* plugins/{$name}/{$pluginclass}.php
+
+Here, `{$name}` is the name of the plugin, like 'Sample', and `{$pluginclass}`
+is the name of the main class, like 'SamplePlugin'. Plugins that are part of
+the main GNU social distribution go in 'plugins' and third-party or local ones
+go in 'local'.
+
+Simple plugins can be implemented as a single module. Others are more complex
+and require additional modules; these should use their own directory, like
+'local/plugins/{$name}/'. All files related to the plugin, including images,
+JavaScript, CSS, external libraries or PHP modules should go in the plugin
+directory.
+
+Plugin Configuration
+------------------
+
+Plugins are configured using public instance attributes. To set their values,
+site administrators use this syntax:
+
+```php
+addPlugin('Sample', array('attr1' => 'foo', 'attr2' => 'bar'));
+```
+
+The same plugin class can be initialized multiple times with different arguments:
+
+```php
+addPlugin('EmailNotify', array('sendTo' => 'evan@status.net'));
+addPlugin('EmailNotify', array('sendTo' => 'brionv@status.net'));
+```
+
+```php
+class SamplePlugin extends Plugin
+{
+ public $attr1 = null;
+ public $attr2 = null;
+}
+```
+
+Initialization
+------------------
+
+Plugins overload this method to do any initialization they need, like connecting
+to remote servers or creating paths or so on. @return boolean hook value; true
+means continue processing, false means stop.
+
+```php
+function initialize()
+{
+ return true;
+}
+```
+
+Clean Up
+------------------
+
+Plugins overload this method to do any cleanup they need, like disconnecting from
+remote servers or deleting temp files or so on.
+
+```php
+function cleanup()
+{
+ return true;
+}
+```
+
+Database schema setup
+------------------
+
+Plugins can add their own tables to the GNU social database. Plugins should use
+GNU social's schema interface to add or delete tables. The ensureTable() method
+provides an easy way to ensure a table's structure and availability.
+
+By default, the schema is checked every time GNU social is run (say, when a Web
+page is hit). Admins can configure their systems to only check the schema when
+the checkschema.php script is run, greatly improving performance. However, they
+need to remember to run that script after installing or upgrading a plugin!
+
+```php
+function onCheckSchema()
+{
+ $schema = Schema::get();
+
+ // '''For storing user-submitted flags on profiles'''
+
+ $schema->ensureTable('user_greeting_count',
+ array(new ColumnDef('user_id', 'integer', null,
+ true, 'PRI'),
+ new ColumnDef('greeting_count', 'integer')));
+
+ return true;
+}
+```
+
+Load related modules when needed
+------------------
+
+Most non-trivial plugins will require extra modules to do their work. Typically
+these include data classes, action classes, widget classes, or external libraries.
+
+This method receives a class name and loads the PHP file related to that class.
+By tradition, action classes typically have files named for the action, all
+lower-case. Data classes are in files with the data class name, initial letter
+capitalized.
+
+Note that this method will be called for *all* overloaded classes, not just ones
+in this plugin! So, make sure to return true by default to let other plugins,
+and the core code, get a chance.
+
+```php
+function onAutoload($cls)
+{
+ $dir = dirname(__FILE__);
+
+ switch ($cls)
+ {
+ case 'HelloAction':
+ include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
+ return false;
+ case 'User_greeting_count':
+ include_once $dir . '/'.$cls.'.php';
+ return false;
+ default:
+ return true;
+ }
+}
+```
+
+Map URLs to actions
+------------------
+
+This event handler lets the plugin map URLs on the site to actions (and thus an
+action handler class). Note that the action handler class for an action will be
+named 'FoobarAction', where action = 'foobar'. The class must be loaded in the
+onAutoload() method.
+
+```php
+function onRouterInitialized($m)
+{
+ $m->connect('main/hello',
+ array('action' => 'hello'));
+ return true;
+}
+```
+
+Modify the default menu to link to our custom action
+------------------
+
+Using event handlers, it's possible to modify the default UI for pages almost
+without limit. In this method, we add a menu item to the default primary menu
+for the interface to link to our action.
+
+Action Class
+------------------
+
+The Action class provides a rich set of events to hook, as well as output methods.
+
+```php
+function onEndPrimaryNav($action)
+{
+ // '''common_local_url()''' gets the correct URL for the action name we provide
+
+ $action->menuItem(common_local_url('hello'),
+ _m('Hello'), _m('A warm greeting'), false, 'nav_hello');
+ return true;
+}
+
+function onPluginVersion(&$versions)
+{
+ $versions[] = array('name' => 'Sample',
+ 'version' => STATUSNET_VERSION,
+ 'author' => 'Brion Vibber, Evan Prodromou',
+ 'homepage' => 'http://example.org/plugin',
+ 'rawdescription' =>
+ _m('A sample plugin to show basics of development for new hackers.'));
+ return true;
+}
+```
+
+hello.php
+------------------
+
+This section is taken directly from the 'hello.php'. ( plugins/Sample/hello.php )
+
+Give a warm greeting to our friendly user.
+
+This sample action shows some basic ways of doing output in an action class.
+
+Action classes have several output methods that they override from the parent class.
+
+```php
+class HelloAction extends Action
+{
+ var $user = null;
+ var $gc = null;
+}
+```
+
+Take arguments for running
+------------------
+
+This method is called first, and it lets the action class get all its arguments
+and validate them. It's also the time to fetch any relevant data from the database.
+
+Action classes should run parent::prepare($args) as the first line of this
+method to make sure the default argument-processing happens.
+
+```php
+function prepare($args)
+{
+ parent::prepare($args);
+
+ $this->user = common_current_user();
+
+ if (!empty($this->user)) {
+ $this->gc = User_greeting_count::inc($this->user->id);
+ }
+
+ return true;
+}
+```
+
+Handle request
+------------------
+
+This is the main method for handling a request. Note that most preparation
+should be done in the prepare() method; by the time handle() is called the
+action should be more or less ready to go.
+
+```php
+function handle($args)
+{
+ parent::handle($args);
+
+ $this->showPage();
+}
+```
+
+Title of this page
+------------------
+
+Override this method to show a custom title.
+
+```php
+function title()
+{
+ if (empty($this->user)) {
+ return _m('Hello');
+ } else {
+ return sprintf(_m('Hello, %s'), $this->user->nickname);
+ }
+}
+```
+
+Show content in the content area
+------------------
+
+The default GNU social page has a lot of decorations: menus, logos, tabs, all
+that jazz. This method is used to show content in the content area of the
+page; it's the main thing you want to overload. This method also demonstrates
+use of a plural localized string.
+
+```php
+function showContent()
+{
+ if (empty($this->user)) {
+ $this->element('p', array('class' => 'greeting'),
+ _m('Hello, stranger!'));
+ } else {
+ $this->element('p', array('class' => 'greeting'),
+ sprintf(_m('Hello, %s'), $this->user->nickname));
+ $this->element('p', array('class' => 'greeting_count'),
+ sprintf(_m('I have greeted you %d time.',
+ 'I have greeted you %d times.',
+ $this->gc->greeting_count),
+ $this->gc->greeting_count));
+ }
+}
+```
+
+Return true if read only.
+------------------
+
+Some actions only read from the database; others read and write. The simple
+database load-balancer built into GNU social will direct read-only actions to
+database mirrors (if they are configured) and read-write actions to the master database.
+
+This defaults to false to avoid data integrity issues, but you should make sure
+to overload it for performance gains.
+
+```php
+function isReadOnly($args)
+{
+ return false;
+}
+```
+
--- /dev/null
+#!/usr/bin/env php
+<?php
+/*
+ * StatusNet - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
+ *
+ * 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/>.
+ */
+
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+
+$shortoptions = 'i::n::u::y';
+$longoptions = array('id=', 'nickname=', 'uri=', 'yes');
+
+$helptext = <<<END_OF_HELP
+delete_notice.php [options]
+deletes a notice (but not related File objects) from the database
+
+ -i --id Local ID of the notice
+ -u --uri Notice URI
+ -y --yes do not wait for confirmation
+
+END_OF_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+if (have_option('i', 'id')) {
+ $id = get_option_value('i', 'id');
+ $notice = Notice::getByID($id);
+ if (!$notice instanceof Notice) {
+ print "Can't find notice with ID $id\n";
+ exit(1);
+ }
+} else if (have_option('u', 'uri')) {
+ $uri = get_option_value('u', 'uri');
+ $notice = Notice::getKV('uri', $uri);
+ if (!$notice instanceof Notice) {
+ print "Can't find notice with URI '$uri'\n";
+ exit(1);
+ }
+} else {
+ print "You must provide either an ID, a URI or a nickname.\n";
+ exit(1);
+}
+
+if (!have_option('y', 'yes')) {
+ print "About to PERMANENTLY delete notice ".$notice->getID()." by '".$notice->getProfile()->getNickname()."'. Are you sure? [y/N] ";
+ $response = fgets(STDIN);
+ if (strtolower(trim($response)) != 'y') {
+ print "Aborting.\n";
+ exit(0);
+ }
+}
+
+print "Deleting...";
+$notice->delete();
+print "DONE.\n";
}
.threaded-replies .form_notice .count {
- top: 60px;
+ bottom: 60px;
right: 50px;
}
display: block;
}
+table.profile_list tbody tr:nth-child(2n+1) {
+ background-color: #fafafa !important;
+ border: none !important;
+}
+
.entity_profile .entity_nickname,
.entity_profile .entity_fn {
margin-left:0;
background: url(../images/bluearrow_up.png) no-repeat top right;
}
-table.profile_list tr.alt {
- background-color: #fafafa !important;
- border: none !important;
-}
-
td.entity_profile {
width: auto;
min-width: 250px;
background: url(../images/bluearrow_up.png) no-repeat top right;
}
-table.profile_list tr.alt {
- background-color: #fafafa !important;
- border: none !important;
-}
-
td.entity_profile {
width: auto;
min-width: 250px;