summaryrefslogtreecommitdiff
path: root/actions
diff options
context:
space:
mode:
Diffstat (limited to 'actions')
-rw-r--r--actions/accesstoken.php2
-rw-r--r--actions/all.php10
-rw-r--r--actions/allrss.php10
-rw-r--r--actions/api.php69
-rw-r--r--actions/attachment.php172
-rw-r--r--actions/attachment_ajax.php83
-rw-r--r--actions/attachment_thumbnail.php84
-rw-r--r--actions/avatarbynickname.php2
-rw-r--r--actions/block.php19
-rw-r--r--actions/blockedfromgroup.php315
-rw-r--r--actions/conversation.php294
-rw-r--r--actions/deletenotice.php4
-rw-r--r--actions/disfavor.php4
-rw-r--r--actions/doc.php2
-rw-r--r--actions/editgroup.php65
-rw-r--r--actions/facebookhome.php62
-rw-r--r--actions/facebookinvite.php2
-rw-r--r--actions/facebooklogin.php2
-rw-r--r--actions/facebookremove.php2
-rw-r--r--actions/facebooksettings.php4
-rw-r--r--actions/favor.php2
-rw-r--r--actions/favorited.php2
-rw-r--r--actions/favoritesrss.php2
-rw-r--r--actions/featured.php5
-rw-r--r--actions/file.php72
-rw-r--r--actions/finishopenidlogin.php2
-rw-r--r--actions/finishremotesubscribe.php2
-rw-r--r--actions/foaf.php129
-rw-r--r--actions/groupblock.php215
-rw-r--r--actions/groupdesignsettings.php315
-rw-r--r--actions/grouplogo.php2
-rw-r--r--actions/groupmembers.php336
-rw-r--r--actions/grouprss.php1
-rw-r--r--actions/groups.php13
-rw-r--r--actions/groupsearch.php2
-rw-r--r--actions/groupunblock.php149
-rw-r--r--actions/invite.php8
-rw-r--r--actions/joingroup.php5
-rw-r--r--actions/logout.php18
-rw-r--r--actions/makeadmin.php166
-rw-r--r--actions/microsummary.php2
-rw-r--r--actions/newgroup.php51
-rw-r--r--actions/newnotice.php194
-rw-r--r--actions/noticesearch.php2
-rw-r--r--actions/noticesearchrss.php15
-rw-r--r--actions/nudge.php2
-rw-r--r--actions/openidlogin.php2
-rw-r--r--actions/opensearch.php2
-rw-r--r--actions/othersettings.php11
-rw-r--r--actions/peoplesearch.php46
-rw-r--r--actions/peopletag.php2
-rw-r--r--actions/postnotice.php2
-rw-r--r--actions/public.php14
-rw-r--r--actions/publicrss.php2
-rw-r--r--actions/publicxrds.php2
-rw-r--r--actions/recoverpassword.php2
-rw-r--r--actions/register.php13
-rw-r--r--actions/remotesubscribe.php2
-rw-r--r--actions/replies.php3
-rw-r--r--actions/repliesrss.php2
-rw-r--r--actions/requesttoken.php2
-rw-r--r--actions/showfavorites.php19
-rw-r--r--actions/showgroup.php64
-rw-r--r--actions/shownotice.php53
-rw-r--r--actions/showstream.php16
-rw-r--r--actions/subedit.php2
-rw-r--r--actions/subscribe.php2
-rw-r--r--actions/subscribers.php32
-rw-r--r--actions/subscriptions.php37
-rw-r--r--actions/sup.php6
-rw-r--r--actions/tag.php7
-rw-r--r--actions/tagother.php2
-rw-r--r--actions/tagrss.php2
-rw-r--r--actions/twitapiaccount.php21
-rw-r--r--actions/twitapiblocks.php12
-rw-r--r--actions/twitapidirect_messages.php78
-rw-r--r--actions/twitapifavorites.php147
-rw-r--r--actions/twitapifriendships.php121
-rw-r--r--actions/twitapihelp.php6
-rw-r--r--actions/twitapinotifications.php2
-rw-r--r--actions/twitapisearchatom.php28
-rw-r--r--actions/twitapisearchjson.php9
-rw-r--r--actions/twitapistatuses.php421
-rw-r--r--actions/twitapiusers.php12
-rw-r--r--actions/twittersettings.php28
-rw-r--r--actions/unblock.php2
-rw-r--r--actions/unsubscribe.php2
-rw-r--r--actions/updateprofile.php2
-rw-r--r--actions/userauthorization.php2
-rw-r--r--actions/userbyid.php2
-rw-r--r--actions/userdesignsettings.php285
-rw-r--r--actions/usergroups.php3
-rw-r--r--actions/userrss.php26
-rw-r--r--actions/xrds.php2
94 files changed, 3861 insertions, 618 deletions
diff --git a/actions/accesstoken.php b/actions/accesstoken.php
index 46b43c702..2a8cd1713 100644
--- a/actions/accesstoken.php
+++ b/actions/accesstoken.php
@@ -12,7 +12,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/all.php b/actions/all.php
index 03179a246..f06ead2a8 100644
--- a/actions/all.php
+++ b/actions/all.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -98,7 +98,13 @@ class AllAction extends ProfileAction
function showContent()
{
- $notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+ $cur = common_current_user();
+
+ if (!empty($cur) && $cur->id == $this->user->id) {
+ $notice = $this->user->noticeInbox(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+ } else {
+ $notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+ }
$nl = new NoticeList($notice, $this);
diff --git a/actions/allrss.php b/actions/allrss.php
index 45f3946a6..885a67f61 100644
--- a/actions/allrss.php
+++ b/actions/allrss.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -81,6 +81,14 @@ class AllrssAction extends Rss10Action
*/
function getNotices($limit=0)
{
+ $cur = common_current_user();
+
+ if (!empty($cur) && $cur->id == $user->id) {
+ $notice = $this->user->noticeInbox(0, $limit);
+ } else {
+ $notice = $this->user->noticesWithFriends(0, $limit);
+ }
+
$user = $this->user;
$notice = $user->noticesWithFriends(0, $limit);
$notices = array();
diff --git a/actions/api.php b/actions/api.php
index b8da852b5..18c3b68d4 100644
--- a/actions/api.php
+++ b/actions/api.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -67,20 +67,22 @@ class ApiAction extends Action
$this->process_command();
} else {
# basic authentication failed
- common_log(LOG_WARNING, "Failed API auth attempt, nickname: $nickname.");
+ list($proxy, $ip) = common_client_ip();
+
+ common_log(LOG_WARNING, "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip.");
$this->show_basic_auth_error();
}
}
} else {
- # Caller might give us a username even if not required
- if (isset($_SERVER['PHP_AUTH_USER'])) {
- $user = User::staticGet('nickname', $_SERVER['PHP_AUTH_USER']);
- if ($user) {
- $this->user = $user;
- }
- # Twitter doesn't throw an error if the user isn't found
- }
+ // Caller might give us a username even if not required
+ if (isset($_SERVER['PHP_AUTH_USER'])) {
+ $user = User::staticGet('nickname', $_SERVER['PHP_AUTH_USER']);
+ if ($user) {
+ $this->user = $user;
+ }
+ # Twitter doesn't throw an error if the user isn't found
+ }
$this->process_command();
}
@@ -115,7 +117,7 @@ class ApiAction extends Action
}
}
- # Whitelist of API methods that don't need authentication
+ // Whitelist of API methods that don't need authentication
function requires_auth()
{
static $noauth = array( 'statuses/public_timeline',
@@ -133,28 +135,61 @@ class ApiAction extends Action
'statuses/replies',
'statuses/mentions',
'statuses/followers',
- 'favorites/favorites');
+ 'favorites/favorites',
+ 'friendships/show');
$fullname = "$this->api_action/$this->api_method";
// If the site is "private", all API methods except laconica/config
// need authentication
+
if (common_config('site', 'private')) {
return $fullname != 'laconica/config' || false;
}
+ // bareauth: only needs auth if without an argument or query param specifying user
+
if (in_array($fullname, $bareauth)) {
- # bareauth: only needs auth if without an argument or query param specifying user
- if ($this->api_arg || $this->arg('id') || is_numeric($this->arg('user_id')) || $this->arg('screen_name')) {
+
+ // Special case: friendships/show only needs auth if source_id or
+ // source_screen_name is not specified as a param
+
+ if ($fullname == 'friendships/show') {
+
+ $source_id = $this->arg('source_id');
+ $source_screen_name = $this->arg('source_screen_name');
+
+ if (empty($source_id) && empty($source_screen_name)) {
+ return true;
+ }
+
return false;
- } else {
+ }
+
+ // if all of these are empty, auth is required
+
+ $id = $this->arg('id');
+ $user_id = $this->arg('user_id');
+ $screen_name = $this->arg('screen_name');
+
+ if (empty($this->api_arg) &&
+ empty($id) &&
+ empty($user_id) &&
+ empty($screen_name)) {
return true;
+ } else {
+ return false;
}
+
} else if (in_array($fullname, $noauth)) {
- # noauth: never needs auth
+
+ // noauth: never needs auth
+
return false;
} else {
- # everybody else needs auth
+
+ // everybody else needs auth
+
return true;
}
}
diff --git a/actions/attachment.php b/actions/attachment.php
new file mode 100644
index 000000000..ee4cd9640
--- /dev/null
+++ b/actions/attachment.php
@@ -0,0 +1,172 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Show notice attachments
+ *
+ * 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 Personal
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2008-2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/attachmentlist.php';
+
+/**
+ * Show notice attachments
+ *
+ * @category Personal
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class AttachmentAction extends Action
+{
+ /**
+ * Attachment object to show
+ */
+
+ var $attachment = null;
+
+ /**
+ * Load attributes based on database arguments
+ *
+ * Loads all the DB stuff
+ *
+ * @param array $args $_REQUEST array
+ *
+ * @return success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ if ($id = $this->trimmed('attachment')) {
+ $this->attachment = File::staticGet($id);
+ }
+
+ if (empty($this->attachment)) {
+ $this->clientError(_('No such attachment.'), 404);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Is this action read-only?
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * Title of the page
+ *
+ * @return string title of the page
+ */
+ function title()
+ {
+ $a = new Attachment($this->attachment);
+ return $a->title();
+ }
+
+ /**
+ * Handle input
+ *
+ * Only handles get, so just show the page.
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (empty($this->attachment->filename)) {
+
+ // if it's not a local file, gtfo
+
+ common_redirect($this->attachment->url, 303);
+
+ } else {
+ $this->showPage();
+ }
+ }
+
+ /**
+ * Don't show local navigation
+ *
+ * @return void
+ */
+
+ function showLocalNavBlock()
+ {
+ }
+
+ /**
+ * Fill the content area of the page
+ *
+ * Shows a single notice list item.
+ *
+ * @return void
+ */
+
+ function showContent()
+ {
+ $ali = new Attachment($this->attachment, $this);
+ $cnt = $ali->show();
+ }
+
+ /**
+ * Don't show page notice
+ *
+ * @return void
+ */
+
+ function showPageNoticeBlock()
+ {
+ }
+
+ /**
+ * Show aside: this attachments appears in what notices
+ *
+ * @return void
+ */
+ function showSections() {
+ $ns = new AttachmentNoticeSection($this);
+ $ns->show();
+ $atcs = new AttachmentTagCloudSection($this);
+ $atcs->show();
+ }
+}
+
diff --git a/actions/attachment_ajax.php b/actions/attachment_ajax.php
new file mode 100644
index 000000000..4caa159f3
--- /dev/null
+++ b/actions/attachment_ajax.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Show notice attachments
+ *
+ * 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 Personal
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2008-2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/actions/attachment.php';
+
+/**
+ * Show notice attachments
+ *
+ * @category Personal
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class Attachment_ajaxAction extends AttachmentAction
+{
+ /**
+ * Show page, a template method.
+ *
+ * @return nothing
+ */
+ function showPage()
+ {
+ if (Event::handle('StartShowBody', array($this))) {
+ $this->showCore();
+ Event::handle('EndShowBody', array($this));
+ }
+ }
+
+ function handle($args)
+ {
+ $this->showPage();
+ }
+
+ /**
+ * Show core.
+ *
+ * Shows local navigation, content block and aside.
+ *
+ * @return nothing
+ */
+ function showCore()
+ {
+ $this->elementStart('div', array('id' => 'core'));
+ if (Event::handle('StartShowContentBlock', array($this))) {
+ $this->showContentBlock();
+ Event::handle('EndShowContentBlock', array($this));
+ }
+ $this->elementEnd('div');
+ }
+}
+
diff --git a/actions/attachment_thumbnail.php b/actions/attachment_thumbnail.php
new file mode 100644
index 000000000..248d16e38
--- /dev/null
+++ b/actions/attachment_thumbnail.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Show notice attachments
+ *
+ * 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 Personal
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2008-2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/actions/attachment.php';
+
+/**
+ * Show notice attachments
+ *
+ * @category Personal
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class Attachment_thumbnailAction extends AttachmentAction
+{
+
+ function handle($args)
+ {
+ $this->showPage();
+ }
+
+ /**
+ * Show page, a template method.
+ *
+ * @return nothing
+ */
+ function showPage()
+ {
+ if (Event::handle('StartShowBody', array($this))) {
+ $this->showCore();
+ Event::handle('EndShowBody', array($this));
+ }
+ }
+
+ /**
+ * Show core.
+ *
+ * Shows local navigation, content block and aside.
+ *
+ * @return nothing
+ */
+ function showCore()
+ {
+ $file_thumbnail = File_thumbnail::staticGet('file_id', $this->attachment->id);
+ if (empty($file_thumbnail->url)) {
+ return;
+ }
+ $this->element('img', array('src' => $file_thumbnail->url, 'alt' => 'Thumbnail'));
+ }
+
+}
+
diff --git a/actions/avatarbynickname.php b/actions/avatarbynickname.php
index e92a99372..3e615261f 100644
--- a/actions/avatarbynickname.php
+++ b/actions/avatarbynickname.php
@@ -12,7 +12,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/block.php b/actions/block.php
index 0efee5932..06f92254e 100644
--- a/actions/block.php
+++ b/actions/block.php
@@ -12,7 +12,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -125,16 +125,18 @@ class BlockAction extends Action
function areYouSureForm()
{
$id = $this->profile->id;
+ $this->elementStart('form', array('id' => 'block-' . $id,
+ 'method' => 'post',
+ 'class' => 'form_settings form_entity_block',
+ 'action' => common_local_url('block')));
+ $this->elementStart('fieldset');
+ $this->hidden('token', common_session_token());
+ $this->element('legend', _('Block user'));
$this->element('p', null,
_('Are you sure you want to block this user? '.
'Afterwards, they will be unsubscribed from you, '.
'unable to subscribe to you in the future, and '.
'you will not be notified of any @-replies from them.'));
- $this->elementStart('form', array('id' => 'block-' . $id,
- 'method' => 'post',
- 'class' => 'block',
- 'action' => common_local_url('block')));
- $this->hidden('token', common_session_token());
$this->element('input', array('id' => 'blockto-' . $id,
'name' => 'blockto',
'type' => 'hidden',
@@ -144,8 +146,9 @@ class BlockAction extends Action
$this->hidden($k, $v);
}
}
- $this->submit('no', _('No'));
- $this->submit('yes', _('Yes'));
+ $this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user from this group"));
+ $this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user from this group'));
+ $this->elementEnd('fieldset');
$this->elementEnd('form');
}
diff --git a/actions/blockedfromgroup.php b/actions/blockedfromgroup.php
new file mode 100644
index 000000000..5c1eab354
--- /dev/null
+++ b/actions/blockedfromgroup.php
@@ -0,0 +1,315 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * List of group members
+ *
+ * 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 Group
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2008-2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * List of profiles blocked from this group
+ *
+ * @category Group
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class BlockedfromgroupAction extends GroupDesignAction
+{
+ var $page = null;
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
+
+ $nickname_arg = $this->arg('nickname');
+ $nickname = common_canonical_nickname($nickname_arg);
+
+ // Permanent redirect on non-canonical nickname
+
+ if ($nickname_arg != $nickname) {
+ $args = array('nickname' => $nickname);
+ if ($this->page != 1) {
+ $args['page'] = $this->page;
+ }
+ common_redirect(common_local_url('blockedfromgroup', $args), 301);
+ return false;
+ }
+
+ if (!$nickname) {
+ $this->clientError(_('No nickname'), 404);
+ return false;
+ }
+
+ $this->group = User_group::staticGet('nickname', $nickname);
+
+ if (!$this->group) {
+ $this->clientError(_('No such group'), 404);
+ return false;
+ }
+
+ return true;
+ }
+
+ function title()
+ {
+ if ($this->page == 1) {
+ return sprintf(_('%s blocked profiles'),
+ $this->group->nickname);
+ } else {
+ return sprintf(_('%s blocked profiles, page %d'),
+ $this->group->nickname,
+ $this->page);
+ }
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showPage();
+ }
+
+ function showPageNotice()
+ {
+ $this->element('p', 'instructions',
+ _('A list of the users blocked from joining this group.'));
+ }
+
+ function showLocalNav()
+ {
+ $nav = new GroupNav($this, $this->group);
+ $nav->show();
+ }
+
+ function showContent()
+ {
+ $offset = ($this->page-1) * PROFILES_PER_PAGE;
+ $limit = PROFILES_PER_PAGE + 1;
+
+ $cnt = 0;
+
+ $blocked = $this->group->getBlocked($offset, $limit);
+
+ if ($blocked) {
+ $blocked_list = new GroupBlockList($blocked, $this->group, $this);
+ $cnt = $blocked_list->show();
+ }
+
+ $blocked->free();
+
+ $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
+ $this->page, 'blockedfromgroup',
+ array('nickname' => $this->group->nickname));
+ }
+}
+
+class GroupBlockList extends ProfileList
+{
+ var $group = null;
+
+ function __construct($profile, $group, $action)
+ {
+ parent::__construct($profile, $action);
+
+ $this->group = $group;
+ }
+
+ function newListItem($profile)
+ {
+ return new GroupBlockListItem($profile, $this->group, $this->action);
+ }
+}
+
+class GroupBlockListItem extends ProfileListItem
+{
+ var $group = null;
+
+ function __construct($profile, $group, $action)
+ {
+ parent::__construct($profile, $action);
+
+ $this->group = $group;
+ }
+
+ function showActions()
+ {
+ $this->startActions();
+ $this->showGroupUnblockForm();
+ $this->endActions();
+ }
+
+ function showGroupUnblockForm()
+ {
+ $user = common_current_user();
+
+ if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) {
+ $this->out->elementStart('li', 'entity_block');
+ $bf = new GroupUnblockForm($this->out, $this->profile, $this->group,
+ array('action' => 'blockedfromgroup',
+ 'nickname' => $this->group->nickname));
+ $bf->show();
+ $this->out->elementEnd('li');
+ }
+ }
+}
+
+/**
+ * Form for unblocking a user from a group
+ *
+ * @category Form
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ *
+ * @see UnblockForm
+ */
+
+class GroupUnblockForm extends Form
+{
+ /**
+ * Profile of user to block
+ */
+
+ var $profile = null;
+
+ /**
+ * Group to block the user from
+ */
+
+ var $group = null;
+
+ /**
+ * Return-to args
+ */
+
+ var $args = null;
+
+ /**
+ * Constructor
+ *
+ * @param HTMLOutputter $out output channel
+ * @param Profile $profile profile of user to block
+ * @param User_group $group group to block user from
+ * @param array $args return-to args
+ */
+
+ function __construct($out=null, $profile=null, $group=null, $args=null)
+ {
+ parent::__construct($out);
+
+ $this->profile = $profile;
+ $this->group = $group;
+ $this->args = $args;
+ }
+
+ /**
+ * ID of the form
+ *
+ * @return int ID of the form
+ */
+
+ function id()
+ {
+ // This should be unique for the page.
+ return 'unblock-' . $this->profile->id;
+ }
+
+ /**
+ * class of the form
+ *
+ * @return string class of the form
+ */
+
+ function formClass()
+ {
+ return 'form_group_unblock';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+
+ function action()
+ {
+ return common_local_url('groupunblock');
+ }
+
+ /**
+ * Legend of the Form
+ *
+ * @return void
+ */
+ function formLegend()
+ {
+ $this->out->element('legend', null, _('Unblock user from group'));
+ }
+
+ /**
+ * Data elements of the form
+ *
+ * @return void
+ */
+
+ function formData()
+ {
+ $this->out->hidden('unblockto-' . $this->profile->id,
+ $this->profile->id,
+ 'unblockto');
+ $this->out->hidden('unblockgroup-' . $this->group->id,
+ $this->group->id,
+ 'unblockgroup');
+ if ($this->args) {
+ foreach ($this->args as $k => $v) {
+ $this->out->hidden('returnto-' . $k, $v);
+ }
+ }
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+
+ function formActions()
+ {
+ $this->out->submit('submit', _('Unblock'), 'submit', null, _('Unblock this user'));
+ }
+}
diff --git a/actions/conversation.php b/actions/conversation.php
new file mode 100644
index 000000000..0eb0d86d6
--- /dev/null
+++ b/actions/conversation.php
@@ -0,0 +1,294 @@
+<?php
+/**
+ * Display a conversation in the browser
+ *
+ * PHP version 5
+ *
+ * @category Action
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ *
+ * Laconica - a distributed open-source microblogging tool
+ * Copyright (C) 2009, Control Yourself, 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/>.
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+// XXX: not sure how to do paging yet,
+// so set a 60-notice limit
+
+require_once INSTALLDIR.'/lib/noticelist.php';
+
+/**
+ * Conversation tree in the browser
+ *
+ * @category Action
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ */
+
+class ConversationAction extends Action
+{
+ var $id = null;
+ var $page = null;
+
+ /**
+ * Initialization.
+ *
+ * @param array $args Web and URL arguments
+ *
+ * @return boolean false if id not passed in
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->id = $this->trimmed('id');
+ if (empty($this->id)) {
+ return false;
+ }
+ $this->id = $this->id+0;
+ $this->page = $this->trimmed('page');
+ if (empty($this->page)) {
+ $this->page = 1;
+ }
+ return true;
+ }
+
+ /**
+ * Handle the action
+ *
+ * @param array $args Web and URL arguments
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showPage();
+ }
+
+ /**
+ * Returns the page title
+ *
+ * @return string page title
+ */
+
+ function title()
+ {
+ return _("Conversation");
+ }
+
+ /**
+ * Show content.
+ *
+ * Display a hierarchical unordered list in the content area.
+ * Uses ConversationTree to do most of the heavy lifting.
+ *
+ * @return void
+ */
+
+ function showContent()
+ {
+ $notices = Notice::conversationStream($this->id, null, null);
+
+ $ct = new ConversationTree($notices, $this);
+
+ $cnt = $ct->show();
+ }
+}
+
+/**
+ * Conversation tree
+ *
+ * The widget class for displaying a hierarchical list of notices.
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ */
+
+class ConversationTree extends NoticeList
+{
+ var $tree = null;
+ var $table = null;
+
+ /**
+ * Show the tree of notices
+ *
+ * @return void
+ */
+
+ function show()
+ {
+ $cnt = $this->_buildTree();
+
+ $this->out->elementStart('div', array('id' =>'notices_primary'));
+ $this->out->element('h2', null, _('Notices'));
+ $this->out->elementStart('ol', array('class' => 'notices xoxo'));
+
+ if (array_key_exists('root', $this->tree)) {
+ $rootid = $this->tree['root'][0];
+ $this->showNoticePlus($rootid);
+ }
+
+ $this->out->elementEnd('ol');
+ $this->out->elementEnd('div');
+
+ return $cnt;
+ }
+
+ function _buildTree()
+ {
+ $this->tree = array();
+ $this->table = array();
+
+ while ($this->notice->fetch()) {
+
+ $cnt++;
+
+ $id = $this->notice->id;
+ $notice = clone($this->notice);
+
+ $this->table[$id] = $notice;
+
+ if (is_null($notice->reply_to)) {
+ $this->tree['root'] = array($notice->id);
+ } else if (array_key_exists($notice->reply_to, $this->tree)) {
+ $this->tree[$notice->reply_to][] = $notice->id;
+ } else {
+ $this->tree[$notice->reply_to] = array($notice->id);
+ }
+ }
+
+ return $cnt;
+ }
+
+ /**
+ * Shows a notice plus its list of children.
+ *
+ * @param integer $id ID of the notice to show
+ *
+ * @return void
+ */
+
+ function showNoticePlus($id)
+ {
+ $notice = $this->table[$id];
+
+ // We take responsibility for doing the li
+
+ $this->out->elementStart('li', array('class' => 'hentry notice',
+ 'id' => 'notice-' . $id));
+
+ $item = $this->newListItem($notice);
+ $item->show();
+
+ if (array_key_exists($id, $this->tree)) {
+ $children = $this->tree[$id];
+
+ $this->out->elementStart('ol', array('class' => 'notices'));
+
+ sort($children);
+
+ foreach ($children as $child) {
+ $this->showNoticePlus($child);
+ }
+
+ $this->out->elementEnd('ol');
+ }
+
+ $this->out->elementEnd('li');
+ }
+
+ /**
+ * Override parent class to return our preferred item.
+ *
+ * @param Notice $notice Notice to display
+ *
+ * @return NoticeListItem a list item to show
+ */
+
+ function newListItem($notice)
+ {
+ return new ConversationTreeItem($notice, $this->out);
+ }
+}
+
+/**
+ * Conversation tree list item
+ *
+ * Special class of NoticeListItem for use inside conversation trees.
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ */
+
+class ConversationTreeItem extends NoticeListItem
+{
+ /**
+ * start a single notice.
+ *
+ * The default creates the <li>; we skip, since the ConversationTree
+ * takes care of that.
+ *
+ * @return void
+ */
+
+ function showStart()
+ {
+ return;
+ }
+
+ /**
+ * finish the notice
+ *
+ * The default closes the <li>; we skip, since the ConversationTree
+ * takes care of that.
+ *
+ * @return void
+ */
+
+ function showEnd()
+ {
+ return;
+ }
+
+ /**
+ * show link to notice conversation page
+ *
+ * Since we're only used on the conversation page, we skip this
+ *
+ * @return void
+ */
+
+ function showContext()
+ {
+ return;
+ }
+}
diff --git a/actions/deletenotice.php b/actions/deletenotice.php
index 6c350b33a..e733f9650 100644
--- a/actions/deletenotice.php
+++ b/actions/deletenotice.php
@@ -112,8 +112,8 @@ class DeletenoticeAction extends DeleteAction
$this->hidden('token', common_session_token());
$this->hidden('notice', $this->trimmed('notice'));
$this->element('p', null, _('Are you sure you want to delete this notice?'));
- $this->submit('form_action-yes', _('Yes'), 'submit form_action-primary', 'yes');
- $this->submit('form_action-no', _('No'), 'submit form_action-secondary', 'no');
+ $this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not delete this notice"));
+ $this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Delete this notice'));
$this->elementEnd('fieldset');
$this->elementEnd('form');
}
diff --git a/actions/disfavor.php b/actions/disfavor.php
index bc13b09da..02e01d6e0 100644
--- a/actions/disfavor.php
+++ b/actions/disfavor.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -75,7 +75,7 @@ class DisfavorAction extends Action
return;
}
$fave = new Fave();
- $fave->user_id = $this->id;
+ $fave->user_id = $user->id;
$fave->notice_id = $notice->id;
if (!$fave->find(true)) {
$this->clientError(_('This notice is not a favorite!'));
diff --git a/actions/doc.php b/actions/doc.php
index e6508030b..54ae13803 100644
--- a/actions/doc.php
+++ b/actions/doc.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/editgroup.php b/actions/editgroup.php
index 39dad0465..6aa6f8b11 100644
--- a/actions/editgroup.php
+++ b/actions/editgroup.php
@@ -23,6 +23,7 @@
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @author Zach Copley <zach@controlyourself.ca>
* @copyright 2008-2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
@@ -40,14 +41,15 @@ if (!defined('LACONICA')) {
* @category Group
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
+ * @author Zach Copley <zach@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
-class EditgroupAction extends Action
+class EditgroupAction extends GroupDesignAction
{
+
var $msg;
- var $group = null;
function title()
{
@@ -171,6 +173,7 @@ class EditgroupAction extends Action
$homepage = $this->trimmed('homepage');
$description = $this->trimmed('description');
$location = $this->trimmed('location');
+ $aliasstring = $this->trimmed('aliases');
if (!Validate::string($nickname, array('min_length' => 1,
'max_length' => 64,
@@ -201,6 +204,39 @@ class EditgroupAction extends Action
return;
}
+ if (!empty($aliasstring)) {
+ $aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring)));
+ } else {
+ $aliases = array();
+ }
+
+ if (count($aliases) > common_config('group', 'maxaliases')) {
+ $this->showForm(sprintf(_('Too many aliases! Maximum %d.'),
+ common_config('group', 'maxaliases')));
+ return;
+ }
+
+ foreach ($aliases as $alias) {
+ if (!Validate::string($alias, array('min_length' => 1,
+ 'max_length' => 64,
+ 'format' => NICKNAME_FMT))) {
+ $this->showForm(sprintf(_('Invalid alias: "%s"'), $alias));
+ return;
+ }
+ if ($this->nicknameExists($alias)) {
+ $this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'),
+ $alias));
+ return;
+ }
+ // XXX assumes alphanum nicknames
+ if (strcmp($alias, $nickname) == 0) {
+ $this->showForm(_('Alias can\'t be the same as nickname.'));
+ return;
+ }
+ }
+
+ $this->group->query('BEGIN');
+
$orig = clone($this->group);
$this->group->nickname = $nickname;
@@ -217,6 +253,14 @@ class EditgroupAction extends Action
$this->serverError(_('Could not update group.'));
}
+ $result = $this->group->setAliases($aliases);
+
+ if (!$result) {
+ $this->serverError(_('Could not create aliases.'));
+ }
+
+ $this->group->query('COMMIT');
+
if ($this->group->nickname != $orig->nickname) {
common_redirect(common_local_url('editgroup',
array('nickname' => $nickname)),
@@ -229,9 +273,20 @@ class EditgroupAction extends Action
function nicknameExists($nickname)
{
$group = User_group::staticGet('nickname', $nickname);
- return (!is_null($group) &&
- $group != false &&
- $group->id != $this->group->id);
+
+ if (!empty($group) &&
+ $group->id != $this->group->id) {
+ return true;
+ }
+
+ $alias = Group_alias::staticGet('alias', $nickname);
+
+ if (!empty($alias) &&
+ $alias->group_id != $this->group->id) {
+ return true;
+ }
+
+ return false;
}
}
diff --git a/actions/facebookhome.php b/actions/facebookhome.php
index 4c2b26355..34989c978 100644
--- a/actions/facebookhome.php
+++ b/actions/facebookhome.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -21,29 +21,28 @@ if (!defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/lib/facebookaction.php';
-
class FacebookhomeAction extends FacebookAction
{
var $page = null;
-
+
function prepare($argarray)
- {
+ {
parent::prepare($argarray);
-
+
$this->page = $this->trimmed('page');
-
+
if (!$this->page) {
$this->page = 1;
}
-
+
return true;
}
function handle($args)
{
- parent::handle($args);
-
+ parent::handle($args);
+
// If the user has opted not to initially allow the app to have
// Facebook status update permission, store that preference. Only
// promt the user the first time she uses the app
@@ -73,7 +72,7 @@ class FacebookhomeAction extends FacebookAction
$this->updateProfileBox($notice);
}
- if ($this->arg('status_submit') == 'Send') {
+ if ($this->arg('status_submit') == 'Send') {
$this->saveNewNotice();
}
@@ -81,7 +80,7 @@ class FacebookhomeAction extends FacebookAction
// Facebook status update permission? Then show the main page
// of the app
$this->showPage();
-
+
} else {
// User hasn't authenticated yet, prompt for creds
@@ -89,12 +88,12 @@ class FacebookhomeAction extends FacebookAction
}
}
-
+
function login()
{
-
+
$this->showStylesheets();
-
+
$nickname = common_canonical_nickname($this->trimmed('nickname'));
$password = $this->arg('password');
@@ -115,7 +114,7 @@ class FacebookhomeAction extends FacebookAction
$flink->foreign_id = $this->fbuid;
$flink->service = FACEBOOK_SERVICE;
$flink->created = common_sql_now();
- $flink->set_flags(true, false, false);
+ $flink->set_flags(true, false, false, false);
$flink_id = $flink->insert();
@@ -141,13 +140,12 @@ class FacebookhomeAction extends FacebookAction
$this->facebook->api_client->data_setUserPreference(
FACEBOOK_PROMPTED_UPDATE_PREF, 'false');
}
-
function showNoticeForm()
{
$post_action = "$this->app_uri/index.php";
-
- $notice_form = new FacebookNoticeForm($this, $post_action, null,
+
+ $notice_form = new FacebookNoticeForm($this, $post_action, null,
$post_action, $this->user);
$notice_form->show();
}
@@ -163,9 +161,8 @@ class FacebookhomeAction extends FacebookAction
function showContent()
{
- $notice = $this->user->noticesWithFriends(($this->page-1) *
- NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
-
+ $notice = $this->user->noticeInbox(($this->page-1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+
$nl = new NoticeList($notice, $this);
$cnt = $nl->show();
@@ -176,7 +173,7 @@ class FacebookhomeAction extends FacebookAction
function showNoticeList($notice)
{
-
+
$nl = new NoticeList($notice, $this);
return $nl->show();
}
@@ -201,16 +198,16 @@ class FacebookhomeAction extends FacebookAction
$this->elementStart('ul', array('id' => 'fb-permissions-list'));
$this->elementStart('li', array('id' => 'fb-permissions-item'));
-
+
$next = urlencode("$this->app_uri/index.php");
$api_key = common_config('facebook', 'apikey');
-
+
$auth_url = 'http://www.facebook.com/authorize.php?api_key=' .
- $api_key . '&v=1.0&ext_perm=status_update&next=' . $next .
+ $api_key . '&v=1.0&ext_perm=status_update&next=' . $next .
'&next_cancel=' . $next . '&submit=skip';
-
+
$this->elementStart('span', array('class' => 'facebook-button'));
- $this->element('a', array('href' => $auth_url),
+ $this->element('a', array('href' => $auth_url),
sprintf(_('Okay, do it!'), $this->app_name));
$this->elementEnd('span');
@@ -225,7 +222,7 @@ class FacebookhomeAction extends FacebookAction
$this->elementEnd('div');
}
-
+
/**
* Generate pagination links
*
@@ -239,11 +236,11 @@ class FacebookhomeAction extends FacebookAction
*/
function pagination($have_before, $have_after, $page, $action, $args=null)
{
-
+
// Does a little before-after block for next/prev page
-
+
// XXX: Fix so this uses common_local_url() if possible.
-
+
if ($have_before || $have_after) {
$this->elementStart('div', array('class' => 'pagination'));
$this->elementStart('dl', null);
@@ -254,7 +251,7 @@ class FacebookhomeAction extends FacebookAction
if ($have_before) {
$pargs = array('page' => $page-1);
$newargs = $args ? array_merge($args, $pargs) : $pargs;
- $this->elementStart('li', array('class' => 'nav_prev'));
+ $this->elementStart('li', array('class' => 'nav_prev'));
$this->element('a', array('href' => "$action?page=$newargs[page]", 'rel' => 'prev'),
_('After'));
$this->elementEnd('li');
@@ -274,6 +271,5 @@ class FacebookhomeAction extends FacebookAction
$this->elementEnd('div');
}
}
-
}
diff --git a/actions/facebookinvite.php b/actions/facebookinvite.php
index 2207580f7..f43d04e27 100644
--- a/actions/facebookinvite.php
+++ b/actions/facebookinvite.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/facebooklogin.php b/actions/facebooklogin.php
index 94d494a82..22007da4f 100644
--- a/actions/facebooklogin.php
+++ b/actions/facebooklogin.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/facebookremove.php b/actions/facebookremove.php
index 376e12a2e..9ca7a77a8 100644
--- a/actions/facebookremove.php
+++ b/actions/facebookremove.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/facebooksettings.php b/actions/facebooksettings.php
index 236460c1c..ee2c279ab 100644
--- a/actions/facebooksettings.php
+++ b/actions/facebooksettings.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -55,7 +55,7 @@ class FacebooksettingsAction extends FacebookAction
$prefix = $this->trimmed('prefix');
$original = clone($this->flink);
- $this->flink->set_flags($noticesync, $replysync, false);
+ $this->flink->set_flags($noticesync, $replysync, false, false);
$result = $this->flink->update($original);
$this->facebook->api_client->data_setUserPreference(FACEBOOK_NOTICE_PREFIX,
diff --git a/actions/favor.php b/actions/favor.php
index a7aff87f2..fe51e34a2 100644
--- a/actions/favor.php
+++ b/actions/favor.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/favorited.php b/actions/favorited.php
index c902d80f5..156c7a700 100644
--- a/actions/favorited.php
+++ b/actions/favorited.php
@@ -194,7 +194,7 @@ class FavoritedAction extends Action
$qry = 'SELECT notice.*, '.
$weightexpr . ' as weight ' .
'FROM notice JOIN fave ON notice.id = fave.notice_id ' .
- 'GROUP BY id,profile_id,uri,content,rendered,url,created,notice.modified,reply_to,is_local,source ' .
+ 'GROUP BY id,profile_id,uri,content,rendered,url,created,notice.modified,reply_to,is_local,source,notice.conversation ' .
'ORDER BY weight DESC';
$offset = ($this->page - 1) * NOTICES_PER_PAGE;
diff --git a/actions/favoritesrss.php b/actions/favoritesrss.php
index 6b46b8dec..c439a9a62 100644
--- a/actions/favoritesrss.php
+++ b/actions/favoritesrss.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/featured.php b/actions/featured.php
index 79eba2aa6..04365687d 100644
--- a/actions/featured.php
+++ b/actions/featured.php
@@ -32,7 +32,7 @@ if (!defined('LACONICA')) {
exit(1);
}
-require_once(INSTALLDIR.'/lib/profilelist.php');
+require_once INSTALLDIR.'/lib/profilelist.php';
require_once INSTALLDIR.'/lib/publicgroupnav.php';
/**
@@ -107,7 +107,6 @@ class FeaturedAction extends Action
$featured_nicks = common_config('nickname', 'featured');
-
if (count($featured_nicks) > 0) {
$quoted = array();
@@ -136,7 +135,7 @@ class FeaturedAction extends Action
$cnt = $profile->find();
if ($cnt > 0) {
- $featured = new ProfileList($profile, null, $this);
+ $featured = new ProfileList($profile, $this);
$featured->show();
}
diff --git a/actions/file.php b/actions/file.php
new file mode 100644
index 000000000..8310e48df
--- /dev/null
+++ b/actions/file.php
@@ -0,0 +1,72 @@
+<?php
+/*
+ * Laconica - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, Control Yourself, 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/>.
+ */
+
+if (!defined('LACONICA')) { exit(1); }
+
+require_once(INSTALLDIR.'/actions/shownotice.php');
+
+class FileAction extends Action
+{
+ var $id = null;
+ var $filerec = null;
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->id = $this->trimmed('notice');
+ if (empty($this->id)) {
+ $this->clientError(_('No notice id'));
+ }
+ $notice = Notice::staticGet('id', $this->id);
+ if (empty($notice)) {
+ $this->clientError(_('No notice'));
+ }
+ $atts = $notice->attachments();
+ if (empty($atts)) {
+ $this->clientError(_('No attachments'));
+ }
+ foreach ($atts as $att) {
+ if (!empty($att->filename)) {
+ $this->filerec = $att;
+ break;
+ }
+ }
+ if (empty($this->filerec)) {
+ $this->clientError(_('No uploaded attachments'));
+ }
+ return true;
+ }
+
+ function handle() {
+ common_redirect($this->filerec->url);
+ }
+
+ /**
+ * Is this action read-only?
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+}
+
diff --git a/actions/finishopenidlogin.php b/actions/finishopenidlogin.php
index b08b96df6..e9f7c746b 100644
--- a/actions/finishopenidlogin.php
+++ b/actions/finishopenidlogin.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/finishremotesubscribe.php b/actions/finishremotesubscribe.php
index 3e3a81715..5c764aeb0 100644
--- a/actions/finishremotesubscribe.php
+++ b/actions/finishremotesubscribe.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/foaf.php b/actions/foaf.php
index 2d5b78d12..b481b2437 100644
--- a/actions/foaf.php
+++ b/actions/foaf.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -82,14 +82,18 @@ class FoafAction extends Action
'http://www.w3.org/2000/01/rdf-schema#',
'xmlns:geo' =>
'http://www.w3.org/2003/01/geo/wgs84_pos#',
+ 'xmlns:bio' =>
+ 'http://purl.org/vocab/bio/0.1/',
+ 'xmlns:sioc' =>
+ 'http://rdfs.org/sioc/ns#',
'xmlns' => 'http://xmlns.com/foaf/0.1/'));
// This is the document about the user
$this->showPpd('', $this->user->uri);
- // XXX: might not be a person
- $this->elementStart('Person', array('rdf:about' =>
+ // Would be nice to tell if they were a Person or not (e.g. a #person usertag?)
+ $this->elementStart('Agent', array('rdf:about' =>
$this->user->uri));
$this->element('mbox_sha1sum', null, sha1('mailto:' . $this->user->email));
if ($this->profile->fullname) {
@@ -98,8 +102,11 @@ class FoafAction extends Action
if ($this->profile->homepage) {
$this->element('homepage', array('rdf:resource' => $this->profile->homepage));
}
+ if ($this->profile->profileurl) {
+ $this->element('weblog', array('rdf:resource' => $this->profile->profileurl));
+ }
if ($this->profile->bio) {
- $this->element('rdfs:comment', null, $this->profile->bio);
+ $this->element('bio:olb', null, $this->profile->bio);
}
// XXX: more structured location data
if ($this->profile->location) {
@@ -110,10 +117,7 @@ class FoafAction extends Action
$this->elementEnd('based_near');
}
- $this->showMicrobloggingAccount($this->profile, common_root_url());
-
$avatar = $this->profile->getOriginalAvatar();
-
if ($avatar) {
$this->elementStart('img');
$this->elementStart('Image', array('rdf:about' => $avatar->url));
@@ -129,39 +133,8 @@ class FoafAction extends Action
$this->elementEnd('img');
}
- // Get people user is subscribed to
-
- $person = array();
-
- $sub = new Subscription();
- $sub->subscriber = $this->profile->id;
- $sub->whereAdd('subscriber != subscribed');
-
- if ($sub->find()) {
- while ($sub->fetch()) {
- if (!empty($sub->token)) {
- $other = Remote_profile::staticGet('id', $sub->subscribed);
- } else {
- $other = User::staticGet('id', $sub->subscribed);
- }
- if (empty($other)) {
- common_debug('Got a bad subscription: '.print_r($sub,true));
- continue;
- }
- $this->element('knows', array('rdf:resource' => $other->uri));
- $person[$other->uri] = array(LISTENEE,
- $other->id,
- $other->nickname,
- (empty($sub->token)) ? 'User' : 'Remote_profile');
- $other->free();
- $other = null;
- unset($other);
- }
- }
-
- $sub->free();
- $sub = null;
- unset($sub);
+ $person = $this->showMicrobloggingAccount($this->profile,
+ common_root_url(), $this->user->uri, false);
// Get people who subscribe to user
@@ -198,7 +171,15 @@ class FoafAction extends Action
$sub = null;
unset($sub);
- $this->elementEnd('Person');
+ foreach ($person as $uri => $p) {
+ list($type, $id, $nickname, $cls) = $p;
+ if ($type == BOTH) {
+ $this->element('knows', array('rdf:resource' => $uri));
+ }
+ }
+
+ $this->elementEnd('Agent');
+
foreach ($person as $uri => $p) {
$foaf_url = null;
@@ -207,16 +188,18 @@ class FoafAction extends Action
$foaf_url = common_local_url('foaf', array('nickname' => $nickname));
}
$profile = Profile::staticGet($id);
- $this->elementStart('Person', array('rdf:about' => $uri));
- if ($type == LISTENER || $type == BOTH) {
+ $this->elementStart('Agent', array('rdf:about' => $uri));
+ if ($type == BOTH) {
$this->element('knows', array('rdf:resource' => $this->user->uri));
}
- $this->showMicrobloggingAccount($profile, ($cls == 'User') ?
- common_root_url() : null);
+ $this->showMicrobloggingAccount($profile,
+ ($cls == 'User') ? common_root_url() : null,
+ $uri,
+ true);
if ($foaf_url) {
$this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url));
}
- $this->elementEnd('Person');
+ $this->elementEnd('Agent');
if ($foaf_url) {
$this->showPpd($foaf_url, $uri);
}
@@ -237,18 +220,66 @@ class FoafAction extends Action
$this->elementEnd('PersonalProfileDocument');
}
- function showMicrobloggingAccount($profile, $service=null)
+ function showMicrobloggingAccount($profile, $service=null, $useruri=null, $isSubscriber=false)
{
+ $attr = array();
+ if ($useruri) {
+ $attr['rdf:about'] = $useruri . '#acct';
+ }
+
// Their account
$this->elementStart('holdsAccount');
- $this->elementStart('OnlineAccount');
+ $this->elementStart('OnlineAccount', $attr);
if ($service) {
$this->element('accountServiceHomepage', array('rdf:resource' =>
$service));
}
$this->element('accountName', null, $profile->nickname);
- $this->element('homepage', array('rdf:resource' => $profile->profileurl));
+ $this->element('accountProfilePage', array('rdf:resource' => $profile->profileurl));
+ if ($useruri) {
+ $this->element('sioc:account_of', array('rdf:resource'=>$useruri));
+ }
+
+ $person = array();
+
+ if ($isSubscriber) {
+ $this->element('sioc:follows', array('rdf:resource'=>$this->user->uri . '#acct'));
+ } else {
+ // Get people user is subscribed to
+ $sub = new Subscription();
+ $sub->subscriber = $profile->id;
+ $sub->whereAdd('subscriber != subscribed');
+
+ if ($sub->find()) {
+ while ($sub->fetch()) {
+ if (!empty($sub->token)) {
+ $other = Remote_profile::staticGet('id', $sub->subscribed);
+ } else {
+ $other = User::staticGet('id', $sub->subscribed);
+ }
+ if (empty($other)) {
+ common_debug('Got a bad subscription: '.print_r($sub,true));
+ continue;
+ }
+ $this->element('sioc:follows', array('rdf:resource' => $other->uri.'#acct'));
+ $person[$other->uri] = array(LISTENEE,
+ $other->id,
+ $other->nickname,
+ (empty($sub->token)) ? 'User' : 'Remote_profile');
+ $other->free();
+ $other = null;
+ unset($other);
+ }
+ }
+
+ $sub->free();
+ $sub = null;
+ unset($sub);
+ }
+
$this->elementEnd('OnlineAccount');
$this->elementEnd('holdsAccount');
+
+ return $person;
}
}
diff --git a/actions/groupblock.php b/actions/groupblock.php
new file mode 100644
index 000000000..ce2c6c144
--- /dev/null
+++ b/actions/groupblock.php
@@ -0,0 +1,215 @@
+<?php
+/**
+ * Block a user from a group action class.
+ *
+ * PHP version 5
+ *
+ * @category Action
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ *
+ * Laconica - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, Control Yourself, 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/>.
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Block a user from a group
+ *
+ * @category Action
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ */
+
+class GroupblockAction extends Action
+{
+ var $profile = null;
+ var $group = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ if (!common_logged_in()) {
+ $this->clientError(_('Not logged in.'));
+ return false;
+ }
+ $token = $this->trimmed('token');
+ if (empty($token) || $token != common_session_token()) {
+ $this->clientError(_('There was a problem with your session token. Try again, please.'));
+ return;
+ }
+ $id = $this->trimmed('blockto');
+ if (empty($id)) {
+ $this->clientError(_('No profile specified.'));
+ return false;
+ }
+ $this->profile = Profile::staticGet('id', $id);
+ if (empty($this->profile)) {
+ $this->clientError(_('No profile with that ID.'));
+ return false;
+ }
+ $group_id = $this->trimmed('blockgroup');
+ if (empty($group_id)) {
+ $this->clientError(_('No group specified.'));
+ return false;
+ }
+ $this->group = User_group::staticGet('id', $group_id);
+ if (empty($this->group)) {
+ $this->clientError(_('No such group.'));
+ return false;
+ }
+ $user = common_current_user();
+ if (!$user->isAdmin($this->group)) {
+ $this->clientError(_('Only an admin can block group members.'), 401);
+ return false;
+ }
+ if (Group_block::isBlocked($this->group, $this->profile)) {
+ $this->clientError(_('User is already blocked from group.'));
+ return false;
+ }
+ // XXX: could have proactive blocks, but we don't have UI for it.
+ if (!$this->profile->isMember($this->group)) {
+ $this->clientError(_('User is not a member of group.'));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Handle request
+ *
+ * Shows a page with list of favorite notices
+ *
+ * @param array $args $_REQUEST args; handled in prepare()
+ *
+ * @return void
+ */
+ function handle($args)
+ {
+ parent::handle($args);
+ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ if ($this->arg('no')) {
+ common_redirect(common_local_url('groupmembers',
+ array('nickname' => $this->group->nickname)),
+ 303);
+ } elseif ($this->arg('yes')) {
+ $this->blockProfile();
+ } elseif ($this->arg('blockto')) {
+ $this->showPage();
+ }
+ }
+ }
+
+ function showContent() {
+ $this->areYouSureForm();
+ }
+
+ function title() {
+ return _('Block user from group');
+ }
+
+ function showNoticeForm() {
+ // nop
+ }
+
+ /**
+ * Confirm with user.
+ *
+ * Shows a confirmation form.
+ *
+ * @return void
+ */
+
+ function areYouSureForm()
+ {
+ $id = $this->profile->id;
+ $this->element('p', null,
+ sprintf(_('Are you sure you want to block user "%s" from the group "%s"? '.
+ 'They will be removed from the group, unable to post, and '.
+ 'unable to subscribe to the group in the future.'),
+ $this->profile->getBestName(),
+ $this->group->getBestName()));
+ $this->elementStart('form', array('id' => 'block-' . $id,
+ 'method' => 'post',
+ 'class' => 'block',
+ 'action' => common_local_url('groupblock')));
+ $this->hidden('token', common_session_token());
+ $this->hidden('blockto-' . $this->profile->id,
+ $this->profile->id,
+ 'blockto');
+ $this->hidden('blockgroup-' . $this->group->id,
+ $this->group->id,
+ 'blockgroup');
+ foreach ($this->args as $k => $v) {
+ if (substr($k, 0, 9) == 'returnto-') {
+ $this->hidden($k, $v);
+ }
+ }
+ $this->submit('no', _('No'));
+ $this->submit('yes', _('Yes'));
+ $this->elementEnd('form');
+ }
+
+ /**
+ * Actually block a user.
+ *
+ * @return void
+ */
+
+ function blockProfile()
+ {
+ $block = Group_block::blockProfile($this->group, $this->profile,
+ common_current_user());
+
+ if (empty($block)) {
+ $this->serverError(_("Database error blocking user from group."));
+ return false;
+ }
+
+ // Now, gotta figure where we go back to
+ foreach ($this->args as $k => $v) {
+ if ($k == 'returnto-action') {
+ $action = $v;
+ } elseif (substr($k, 0, 9) == 'returnto-') {
+ $args[substr($k, 9)] = $v;
+ }
+ }
+
+ if ($action) {
+ common_redirect(common_local_url($action, $args), 303);
+ } else {
+ common_redirect(common_local_url('groupmembers',
+ array('nickname' => $this->group->nickname)),
+ 303);
+ }
+ }
+}
+
diff --git a/actions/groupdesignsettings.php b/actions/groupdesignsettings.php
new file mode 100644
index 000000000..bb01243c6
--- /dev/null
+++ b/actions/groupdesignsettings.php
@@ -0,0 +1,315 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Change user password
+ *
+ * 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 Settings
+ * @package Laconica
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @author Zach Copley <zach@controlyourself.ca>
+ * @copyright 2008-2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/designsettings.php';
+
+/**
+ * Set a group's design
+ *
+ * Saves a design for a given group
+ *
+ * @category Settings
+ * @package Laconica
+ * @author Zach Copley <zach@controlyourself.ca>
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class GroupDesignSettingsAction extends DesignSettingsAction
+{
+ var $group = null;
+
+ /**
+ * Sets the right action for the form, and passes request args into
+ * the base action
+ *
+ * @param array $args misc. arguments
+ *
+ * @return boolean true
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ if (!common_config('inboxes', 'enabled')) {
+ $this->serverError(_('Inboxes must be enabled for groups to work'));
+ return false;
+ }
+
+ if (!common_logged_in()) {
+ $this->clientError(_('You must be logged in to edit a group.'));
+ return false;
+ }
+
+ $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);
+ common_redirect(common_local_url('groupdesignsettings', $args), 301);
+ return false;
+ }
+
+ if (!$nickname) {
+ $this->clientError(_('No nickname'), 404);
+ return false;
+ }
+
+ $groupid = $this->trimmed('groupid');
+
+ if ($groupid) {
+ $this->group = User_group::staticGet('id', $groupid);
+ } else {
+ $this->group = User_group::staticGet('nickname', $nickname);
+ }
+
+ if (!$this->group) {
+ $this->clientError(_('No such group'), 404);
+ return false;
+ }
+
+ $cur = common_current_user();
+
+ if (!$cur->isAdmin($this->group)) {
+ $this->clientError(_('You must be an admin to edit the group'), 403);
+ return false;
+ }
+
+ $this->submitaction = common_local_url('groupdesignsettings',
+ array('nickname' => $this->group->nickname));
+
+ return true;
+ }
+
+ /**
+ * A design for this action
+ *
+ * if the group attribute has been set, returns that group's
+ * design.
+ *
+ * @return Design a design object to use
+ */
+
+ function getDesign()
+ {
+
+ if (empty($this->group)) {
+ return null;
+ }
+
+ return $this->group->getDesign();
+ }
+
+ /**
+ * Title of the page
+ *
+ * @return string Title of the page
+ */
+
+ function title()
+ {
+ return _('Group design');
+ }
+
+ /**
+ * Instructions for use
+ *
+ * @return instructions for use
+ */
+
+ function getInstructions()
+ {
+ return _('Customize the way your group looks ' .
+ 'with a background image and a colour palette of your choice.');
+ }
+
+ /**
+ * Override to show group nav stuff
+ *
+ * @return nothing
+ */
+
+ function showLocalNav()
+ {
+ $nav = new GroupNav($this, $this->group);
+ $nav->show();
+ }
+
+ /**
+ * Get the design we want to edit
+ *
+ * @return Design
+ */
+
+ function getWorkingDesign()
+ {
+
+ $design = null;
+
+ if (isset($this->group)) {
+ $design = $this->group->getDesign();
+ }
+
+ if (empty($design)) {
+ $design = $this->defaultDesign();
+ }
+
+ return $design;
+ }
+
+ /**
+ * Content area of the page
+ *
+ * Shows a form for changing the design
+ *
+ * @return void
+ */
+
+ function showContent()
+ {
+ $this->showDesignForm($this->getWorkingDesign());
+ }
+
+ /**
+ * Save or update the group's design settings
+ *
+ * @return void
+ */
+
+ function saveDesign()
+ {
+ try {
+
+ $bgcolor = new WebColor($this->trimmed('design_background'));
+ $ccolor = new WebColor($this->trimmed('design_content'));
+ $sbcolor = new WebColor($this->trimmed('design_sidebar'));
+ $tcolor = new WebColor($this->trimmed('design_text'));
+ $lcolor = new WebColor($this->trimmed('design_links'));
+
+ } catch (WebColorException $e) {
+ $this->showForm($e->getMessage());
+ return;
+ }
+
+ $onoff = $this->arg('design_background-image_onoff');
+
+ $on = false;
+ $off = false;
+ $tile = false;
+
+ if ($onoff == 'on') {
+ $on = true;
+ } else {
+ $off = true;
+ }
+
+ $repeat = $this->boolean('design_background-image_repeat');
+
+ if ($repeat) {
+ $tile = true;
+ }
+
+ $design = $this->group->getDesign();
+
+ if (!empty($design)) {
+
+ // update design
+
+ $original = clone($design);
+
+ $design->backgroundcolor = $bgcolor->intValue();
+ $design->contentcolor = $ccolor->intValue();
+ $design->sidebarcolor = $sbcolor->intValue();
+ $design->textcolor = $tcolor->intValue();
+ $design->linkcolor = $lcolor->intValue();
+
+ $design->setDisposition($on, $off, $tile);
+
+ $result = $design->update($original);
+
+ if ($result === false) {
+ common_log_db_error($design, 'UPDATE', __FILE__);
+ $this->showForm(_('Couldn\'t update your design.'));
+ return;
+ }
+
+ } else {
+
+ $this->group->query('BEGIN');
+
+ // save new design
+
+ $design = new Design();
+
+ $design->backgroundcolor = $bgcolor->intValue();
+ $design->contentcolor = $ccolor->intValue();
+ $design->sidebarcolor = $sbcolor->intValue();
+ $design->textcolor = $tcolor->intValue();
+ $design->linkcolor = $lcolor->intValue();
+
+ $design->setDisposition($on, $off, $tile);
+
+ $id = $design->insert();
+
+ if (empty($id)) {
+ common_log_db_error($id, 'INSERT', __FILE__);
+ $this->showForm(_('Unable to save your design settings!'));
+ return;
+ }
+
+ $original = clone($this->group);
+ $this->group->design_id = $id;
+ $result = $this->group->update($original);
+
+ if (empty($result)) {
+ common_log_db_error($original, 'UPDATE', __FILE__);
+ $this->showForm(_('Unable to save your design settings!'));
+ $this->group->query('ROLLBACK');
+ return;
+ }
+
+ $this->group->query('COMMIT');
+
+ }
+
+ $this->saveBackgroundImage($design);
+
+ $this->showForm(_('Design preferences saved.'), true);
+ }
+
+}
diff --git a/actions/grouplogo.php b/actions/grouplogo.php
index fe6127da2..8f6158dac 100644
--- a/actions/grouplogo.php
+++ b/actions/grouplogo.php
@@ -50,7 +50,7 @@ define('MAX_ORIGINAL', 480);
* @link http://laconi.ca/
*/
-class GrouplogoAction extends Action
+class GrouplogoAction extends GroupDesignAction
{
var $mode = null;
var $imagefile = null;
diff --git a/actions/groupmembers.php b/actions/groupmembers.php
index 21e5ebbaa..14256526a 100644
--- a/actions/groupmembers.php
+++ b/actions/groupmembers.php
@@ -44,7 +44,7 @@ require_once INSTALLDIR.'/lib/publicgroupnav.php';
* @link http://laconi.ca/
*/
-class GroupmembersAction extends Action
+class GroupmembersAction extends GroupDesignAction
{
var $page = null;
@@ -127,7 +127,7 @@ class GroupmembersAction extends Action
$members = $this->group->getMembers($offset, $limit);
if ($members) {
- $member_list = new ProfileList($members, null, $this);
+ $member_list = new GroupMemberList($members, $this->group, $this);
$cnt = $member_list->show();
}
@@ -138,3 +138,335 @@ class GroupmembersAction extends Action
array('nickname' => $this->group->nickname));
}
}
+
+class GroupMemberList extends ProfileList
+{
+ var $group = null;
+
+ function __construct($profile, $group, $action)
+ {
+ parent::__construct($profile, $action);
+
+ $this->group = $group;
+ }
+
+ function newListItem($profile)
+ {
+ return new GroupMemberListItem($profile, $this->group, $this->action);
+ }
+}
+
+class GroupMemberListItem extends ProfileListItem
+{
+ var $group = null;
+
+ function __construct($profile, $group, $action)
+ {
+ parent::__construct($profile, $action);
+
+ $this->group = $group;
+ }
+
+ function showFullName()
+ {
+ parent::showFullName();
+ if ($this->profile->isAdmin($this->group)) {
+ $this->out->text(' ');
+ $this->out->element('span', 'role', _('Admin'));
+ }
+ }
+
+ function showActions()
+ {
+ $this->startActions();
+ $this->showSubscribeButton();
+ $this->showMakeAdminForm();
+ $this->showGroupBlockForm();
+ $this->endActions();
+ }
+
+ function showMakeAdminForm()
+ {
+ $user = common_current_user();
+
+ if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group) &&
+ !$this->profile->isAdmin($this->group)) {
+ $this->out->elementStart('li', 'entity_make_admin');
+ $maf = new MakeAdminForm($this->out, $this->profile, $this->group,
+ array('action' => 'groupmembers',
+ 'nickname' => $this->group->nickname));
+ $maf->show();
+ $this->out->elementEnd('li');
+ }
+
+ }
+ function showGroupBlockForm()
+ {
+ $user = common_current_user();
+
+ if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) {
+ $this->out->elementStart('li', 'entity_block');
+ $bf = new GroupBlockForm($this->out, $this->profile, $this->group,
+ array('action' => 'groupmembers',
+ 'nickname' => $this->group->nickname));
+ $bf->show();
+ $this->out->elementEnd('li');
+ }
+
+ }
+}
+
+/**
+ * Form for blocking a user from a group
+ *
+ * @category Form
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ *
+ * @see BlockForm
+ */
+
+class GroupBlockForm extends Form
+{
+ /**
+ * Profile of user to block
+ */
+
+ var $profile = null;
+
+ /**
+ * Group to block the user from
+ */
+
+ var $group = null;
+
+ /**
+ * Return-to args
+ */
+
+ var $args = null;
+
+ /**
+ * Constructor
+ *
+ * @param HTMLOutputter $out output channel
+ * @param Profile $profile profile of user to block
+ * @param User_group $group group to block user from
+ * @param array $args return-to args
+ */
+
+ function __construct($out=null, $profile=null, $group=null, $args=null)
+ {
+ parent::__construct($out);
+
+ $this->profile = $profile;
+ $this->group = $group;
+ $this->args = $args;
+ }
+
+ /**
+ * ID of the form
+ *
+ * @return int ID of the form
+ */
+
+ function id()
+ {
+ // This should be unique for the page.
+ return 'block-' . $this->profile->id;
+ }
+
+ /**
+ * class of the form
+ *
+ * @return string class of the form
+ */
+
+ function formClass()
+ {
+ return 'form_group_block';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+
+ function action()
+ {
+ return common_local_url('groupblock');
+ }
+
+ /**
+ * Legend of the Form
+ *
+ * @return void
+ */
+ function formLegend()
+ {
+ $this->out->element('legend', null, _('Block user from group'));
+ }
+
+ /**
+ * Data elements of the form
+ *
+ * @return void
+ */
+
+ function formData()
+ {
+ $this->out->hidden('blockto-' . $this->profile->id,
+ $this->profile->id,
+ 'blockto');
+ $this->out->hidden('blockgroup-' . $this->group->id,
+ $this->group->id,
+ 'blockgroup');
+ if ($this->args) {
+ foreach ($this->args as $k => $v) {
+ $this->out->hidden('returnto-' . $k, $v);
+ }
+ }
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+
+ function formActions()
+ {
+ $this->out->submit('submit', _('Block'), 'submit', null, _('Block this user'));
+ }
+}
+
+/**
+ * Form for making a user an admin for a group
+ *
+ * @category Form
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class MakeAdminForm extends Form
+{
+ /**
+ * Profile of user to block
+ */
+
+ var $profile = null;
+
+ /**
+ * Group to block the user from
+ */
+
+ var $group = null;
+
+ /**
+ * Return-to args
+ */
+
+ var $args = null;
+
+ /**
+ * Constructor
+ *
+ * @param HTMLOutputter $out output channel
+ * @param Profile $profile profile of user to block
+ * @param User_group $group group to block user from
+ * @param array $args return-to args
+ */
+
+ function __construct($out=null, $profile=null, $group=null, $args=null)
+ {
+ parent::__construct($out);
+
+ $this->profile = $profile;
+ $this->group = $group;
+ $this->args = $args;
+ }
+
+ /**
+ * ID of the form
+ *
+ * @return int ID of the form
+ */
+
+ function id()
+ {
+ // This should be unique for the page.
+ return 'makeadmin-' . $this->profile->id;
+ }
+
+ /**
+ * class of the form
+ *
+ * @return string class of the form
+ */
+
+ function formClass()
+ {
+ return 'form_make_admin';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+
+ function action()
+ {
+ return common_local_url('makeadmin', array('nickname' => $this->group->nickname));
+ }
+
+ /**
+ * Legend of the Form
+ *
+ * @return void
+ */
+
+ function formLegend()
+ {
+ $this->out->element('legend', null, _('Make user an admin of the group'));
+ }
+
+ /**
+ * Data elements of the form
+ *
+ * @return void
+ */
+
+ function formData()
+ {
+ $this->out->hidden('profileid-' . $this->profile->id,
+ $this->profile->id,
+ 'profileid');
+ $this->out->hidden('groupid-' . $this->group->id,
+ $this->group->id,
+ 'groupid');
+ if ($this->args) {
+ foreach ($this->args as $k => $v) {
+ $this->out->hidden('returnto-' . $k, $v);
+ }
+ }
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+
+ function formActions()
+ {
+ $this->out->submit('submit', _('Make Admin'), 'submit', null, _('Make this user an admin'));
+ }
+}
diff --git a/actions/grouprss.php b/actions/grouprss.php
index 0b7280a11..2bdcaafb2 100644
--- a/actions/grouprss.php
+++ b/actions/grouprss.php
@@ -116,6 +116,7 @@ class groupRssAction extends Rss10Action
return null;
}
+ $notices = array();
$notice = $group->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
while ($notice->fetch()) {
diff --git a/actions/groups.php b/actions/groups.php
index 26b52a5fc..3d62843ed 100644
--- a/actions/groups.php
+++ b/actions/groups.php
@@ -100,11 +100,13 @@ class GroupsAction extends Action
function showContent()
{
- $this->elementStart('p', array('id' => 'new_group'));
- $this->element('a', array('href' => common_local_url('newgroup'),
- 'class' => 'more'),
- _('Create a new group'));
- $this->elementEnd('p');
+ if (common_logged_in()) {
+ $this->elementStart('p', array('id' => 'new_group'));
+ $this->element('a', array('href' => common_local_url('newgroup'),
+ 'class' => 'more'),
+ _('Create a new group'));
+ $this->elementEnd('p');
+ }
$offset = ($this->page-1) * GROUPS_PER_PAGE;
$limit = GROUPS_PER_PAGE + 1;
@@ -113,6 +115,7 @@ class GroupsAction extends Action
$groups->orderBy('created DESC');
$groups->limit($offset, $limit);
+ $cnt = 0;
if ($groups->find()) {
$gl = new GroupList($groups, null, $this);
$cnt = $gl->show();
diff --git a/actions/groupsearch.php b/actions/groupsearch.php
index 06b4a7755..c50466ce6 100644
--- a/actions/groupsearch.php
+++ b/actions/groupsearch.php
@@ -12,7 +12,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/groupunblock.php b/actions/groupunblock.php
new file mode 100644
index 000000000..6beb46352
--- /dev/null
+++ b/actions/groupunblock.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * Block a user from a group action class.
+ *
+ * PHP version 5
+ *
+ * @category Action
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ *
+ * Laconica - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, Control Yourself, 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/>.
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Unlock a user from a group
+ *
+ * @category Action
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ */
+
+class GroupunblockAction extends Action
+{
+ var $profile = null;
+ var $group = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ if (!common_logged_in()) {
+ $this->clientError(_('Not logged in.'));
+ return false;
+ }
+ $token = $this->trimmed('token');
+ if (empty($token) || $token != common_session_token()) {
+ $this->clientError(_('There was a problem with your session token. Try again, please.'));
+ return;
+ }
+ $id = $this->trimmed('unblockto');
+ if (empty($id)) {
+ $this->clientError(_('No profile specified.'));
+ return false;
+ }
+ $this->profile = Profile::staticGet('id', $id);
+ if (empty($this->profile)) {
+ $this->clientError(_('No profile with that ID.'));
+ return false;
+ }
+ $group_id = $this->trimmed('unblockgroup');
+ if (empty($group_id)) {
+ $this->clientError(_('No group specified.'));
+ return false;
+ }
+ $this->group = User_group::staticGet('id', $group_id);
+ if (empty($this->group)) {
+ $this->clientError(_('No such group.'));
+ return false;
+ }
+ $user = common_current_user();
+ if (!$user->isAdmin($this->group)) {
+ $this->clientError(_('Only an admin can unblock group members.'), 401);
+ return false;
+ }
+ if (!Group_block::isBlocked($this->group, $this->profile)) {
+ $this->clientError(_('User is not blocked from group.'));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Handle request
+ *
+ * @param array $args $_REQUEST args; handled in prepare()
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ $this->unblockProfile();
+ }
+ }
+
+ /**
+ * Unblock a user.
+ *
+ * @return void
+ */
+
+ function unblockProfile()
+ {
+ $result = Group_block::unblockProfile($this->group, $this->profile);
+
+ if (!$result) {
+ $this->serverError(_('Error removing the block.'));
+ return;
+ }
+
+ foreach ($this->args as $k => $v) {
+ if ($k == 'returnto-action') {
+ $action = $v;
+ } else if (substr($k, 0, 9) == 'returnto-') {
+ $args[substr($k, 9)] = $v;
+ }
+ }
+
+ if ($action) {
+ common_redirect(common_local_url($action, $args), 303);
+ } else {
+ common_redirect(common_local_url('blockedfromgroup',
+ array('nickname' => $this->group->nickname)),
+ 303);
+ }
+ }
+}
+
diff --git a/actions/invite.php b/actions/invite.php
index 7e52cdbcc..bdea4807d 100644
--- a/actions/invite.php
+++ b/actions/invite.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -19,7 +19,7 @@
if (!defined('LACONICA')) { exit(1); }
-class InviteAction extends Action
+class InviteAction extends CurrentUserDesignAction
{
var $mode = null;
var $error = null;
@@ -35,7 +35,9 @@ class InviteAction extends Action
function handle($args)
{
parent::handle($args);
- if (!common_logged_in()) {
+ if (!common_config('invite', 'enabled')) {
+ $this->clientError(_('Invites have been disabled.'));
+ } else if (!common_logged_in()) {
$this->clientError(sprintf(_('You must be logged in to invite other users to use %s'),
common_config('site', 'name')));
return;
diff --git a/actions/joingroup.php b/actions/joingroup.php
index a5d82ddc7..0e4f96eaf 100644
--- a/actions/joingroup.php
+++ b/actions/joingroup.php
@@ -96,6 +96,11 @@ class JoingroupAction extends Action
return false;
}
+ if (Group_block::isBlocked($this->group, $cur->getProfile())) {
+ $this->clientError(_('You have been blocked from that group by the admin.'), 403);
+ return false;
+ }
+
return true;
}
diff --git a/actions/logout.php b/actions/logout.php
index 9f3bfe247..3fcfb4f4e 100644
--- a/actions/logout.php
+++ b/actions/logout.php
@@ -12,7 +12,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -70,10 +70,20 @@ class LogoutAction extends Action
if (!common_logged_in()) {
$this->clientError(_('Not logged in.'));
} else {
- common_set_user(null);
- common_real_login(false); // not logged in
- common_forgetme(); // don't log back in!
+ if (Event::handle('StartLogout', array($this))) {
+ $this->logout();
+ }
+ Event::handle('EndLogout', array($this));
+
common_redirect(common_local_url('public'), 303);
}
}
+
+ function logout()
+ {
+ common_set_user(null);
+ common_real_login(false); // not logged in
+ common_forgetme(); // don't log back in!
+ }
+
}
diff --git a/actions/makeadmin.php b/actions/makeadmin.php
new file mode 100644
index 000000000..6fc2cf9ab
--- /dev/null
+++ b/actions/makeadmin.php
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Make another user an admin of a group
+ *
+ * PHP version 5
+ *
+ * @category Action
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ *
+ * Laconica - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, Control Yourself, 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/>.
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Make another user an admin of a group
+ *
+ * @category Action
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ */
+
+class MakeadminAction extends Action
+{
+ var $profile = null;
+ var $group = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ if (!common_logged_in()) {
+ $this->clientError(_('Not logged in.'));
+ return false;
+ }
+ $token = $this->trimmed('token');
+ if (empty($token) || $token != common_session_token()) {
+ $this->clientError(_('There was a problem with your session token. Try again, please.'));
+ return;
+ }
+ $id = $this->trimmed('profileid');
+ if (empty($id)) {
+ $this->clientError(_('No profile specified.'));
+ return false;
+ }
+ $this->profile = Profile::staticGet('id', $id);
+ if (empty($this->profile)) {
+ $this->clientError(_('No profile with that ID.'));
+ return false;
+ }
+ $group_id = $this->trimmed('groupid');
+ if (empty($group_id)) {
+ $this->clientError(_('No group specified.'));
+ return false;
+ }
+ $this->group = User_group::staticGet('id', $group_id);
+ if (empty($this->group)) {
+ $this->clientError(_('No such group.'));
+ return false;
+ }
+ $user = common_current_user();
+ if (!$user->isAdmin($this->group)) {
+ $this->clientError(_('Only an admin can make another user an admin.'), 401);
+ return false;
+ }
+ if ($this->profile->isAdmin($this->group)) {
+ $this->clientError(sprintf(_('%s is already an admin for group "%s".'),
+ $this->profile->getBestName(),
+ $this->group->getBestName()),
+ 401);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Handle request
+ *
+ * @param array $args $_REQUEST args; handled in prepare()
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ $this->makeAdmin();
+ }
+ }
+
+ /**
+ * Make user an admin
+ *
+ * @return void
+ */
+
+ function makeAdmin()
+ {
+ $member = Group_member::pkeyGet(array('group_id' => $this->group->id,
+ 'profile_id' => $this->profile->id));
+
+ if (empty($member)) {
+ $this->serverError(_('Can\'t get membership record for %s in group %s'),
+ $this->profile->getBestName(),
+ $this->group->getBestName());
+ }
+
+ $orig = clone($member);
+
+ $member->is_admin = 1;
+
+ $result = $member->update($orig);
+
+ if (!$result) {
+ common_log_db_error($member, 'UPDATE', __FILE__);
+ $this->serverError(_('Can\'t make %s an admin for group %s'),
+ $this->profile->getBestName(),
+ $this->group->getBestName());
+ }
+
+ foreach ($this->args as $k => $v) {
+ if ($k == 'returnto-action') {
+ $action = $v;
+ } else if (substr($k, 0, 9) == 'returnto-') {
+ $args[substr($k, 9)] = $v;
+ }
+ }
+
+ if ($action) {
+ common_redirect(common_local_url($action, $args), 303);
+ } else {
+ common_redirect(common_local_url('groupmembers',
+ array('nickname' => $this->group->nickname)),
+ 303);
+ }
+ }
+}
diff --git a/actions/microsummary.php b/actions/microsummary.php
index 0b408ec95..6884a919a 100644
--- a/actions/microsummary.php
+++ b/actions/microsummary.php
@@ -12,7 +12,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/newgroup.php b/actions/newgroup.php
index 67cd6b2f1..0289e77c2 100644
--- a/actions/newgroup.php
+++ b/actions/newgroup.php
@@ -123,6 +123,7 @@ class NewgroupAction extends Action
$homepage = $this->trimmed('homepage');
$description = $this->trimmed('description');
$location = $this->trimmed('location');
+ $aliasstring = $this->trimmed('aliases');
if (!Validate::string($nickname, array('min_length' => 1,
'max_length' => 64,
@@ -153,6 +154,37 @@ class NewgroupAction extends Action
return;
}
+ if (!empty($aliasstring)) {
+ $aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring)));
+ } else {
+ $aliases = array();
+ }
+
+ if (count($aliases) > common_config('group', 'maxaliases')) {
+ $this->showForm(sprintf(_('Too many aliases! Maximum %d.'),
+ common_config('group', 'maxaliases')));
+ return;
+ }
+
+ foreach ($aliases as $alias) {
+ if (!Validate::string($alias, array('min_length' => 1,
+ 'max_length' => 64,
+ 'format' => NICKNAME_FMT))) {
+ $this->showForm(sprintf(_('Invalid alias: "%s"'), $alias));
+ return;
+ }
+ if ($this->nicknameExists($alias)) {
+ $this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'),
+ $alias));
+ return;
+ }
+ // XXX assumes alphanum nicknames
+ if (strcmp($alias, $nickname) == 0) {
+ $this->showForm(_('Alias can\'t be the same as nickname.'));
+ return;
+ }
+ }
+
$cur = common_current_user();
// Checked in prepare() above
@@ -177,6 +209,12 @@ class NewgroupAction extends Action
$this->serverError(_('Could not create group.'));
}
+ $result = $group->setAliases($aliases);
+
+ if (!$result) {
+ $this->serverError(_('Could not create aliases.'));
+ }
+
$member = new Group_member();
$member->group_id = $group->id;
@@ -199,7 +237,18 @@ class NewgroupAction extends Action
function nicknameExists($nickname)
{
$group = User_group::staticGet('nickname', $nickname);
- return (!is_null($group) && $group != false);
+
+ if (!empty($group)) {
+ return true;
+ }
+
+ $alias = Group_alias::staticGet('alias', $nickname);
+
+ if (!empty($alias)) {
+ return true;
+ }
+
+ return false;
}
}
diff --git a/actions/newnotice.php b/actions/newnotice.php
index cbd04c58b..e254eac49 100644
--- a/actions/newnotice.php
+++ b/actions/newnotice.php
@@ -84,20 +84,24 @@ class NewnoticeAction extends Action
function handle($args)
{
- parent::handle($args);
-
if (!common_logged_in()) {
$this->clientError(_('Not logged in.'));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ // check for this before token since all POST and FILES data
+ // is losts when size is exceeded
+ if (empty($_POST) && $_SERVER['CONTENT_LENGTH']) {
+ $this->clientError(sprintf(_('The server was unable to handle ' .
+ 'that much POST data (%s bytes) due to its current configuration.'),
+ $_SERVER['CONTENT_LENGTH']));
+ }
+ parent::handle($args);
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$this->clientError(_('There was a problem with your session token. '.
'Try again, please.'));
- return;
}
-
try {
$this->saveNewNotice();
} catch (Exception $e) {
@@ -109,6 +113,33 @@ class NewnoticeAction extends Action
}
}
+ function getUploadedFileType() {
+ require_once 'MIME/Type.php';
+
+ $cmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd');
+ $cmd = common_config('attachments', 'filecommand');
+
+ $filetype = MIME_Type::autoDetect($_FILES['attach']['tmp_name']);
+ if (in_array($filetype, common_config('attachments', 'supported'))) {
+ return $filetype;
+ }
+ $media = MIME_Type::getMedia($filetype);
+ if ('application' !== $media) {
+ $hint = sprintf(_(' Try using another %s format.'), $media);
+ } else {
+ $hint = '';
+ }
+ $this->clientError(sprintf(
+ _('%s is not a supported filetype on this server.'), $filetype) . $hint);
+ }
+
+ function isRespectsQuota($user) {
+ $file = new File;
+ $ret = $file->isRespectsQuota($user,$_FILES['attach']['size']);
+ if (true === $ret) return true;
+ $this->clientError($ret);
+ }
+
/**
* Save a new notice, based on arguments
*
@@ -131,7 +162,6 @@ class NewnoticeAction extends Action
$this->clientError(_('No content!'));
} else {
$content_shortened = common_shorten_links($content);
-
if (mb_strlen($content_shortened) > 140) {
$this->clientError(_('That\'s too long. '.
'Max notice size is 140 chars.'));
@@ -158,12 +188,80 @@ class NewnoticeAction extends Action
$replyto = 'false';
}
- $notice = Notice::saveNew($user->id, $content, 'web', 1,
+ if (isset($_FILES['attach']['error'])) {
+ switch ($_FILES['attach']['error']) {
+ case UPLOAD_ERR_NO_FILE:
+ // no file uploaded, nothing to do
+ break;
+
+ case UPLOAD_ERR_OK:
+ $mimetype = $this->getUploadedFileType();
+ if (!$this->isRespectsQuota($user)) {
+ die('clientError() should trigger an exception before reaching here.');
+ }
+ break;
+
+ case UPLOAD_ERR_INI_SIZE:
+ $this->clientError(_('The uploaded file exceeds the upload_max_filesize directive in php.ini.'));
+
+ case UPLOAD_ERR_FORM_SIZE:
+ $this->clientError(_('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'));
+
+ case UPLOAD_ERR_PARTIAL:
+ $this->clientError(_('The uploaded file was only partially uploaded.'));
+
+ case UPLOAD_ERR_NO_TMP_DIR:
+ $this->clientError(_('Missing a temporary folder.'));
+
+ case UPLOAD_ERR_CANT_WRITE:
+ $this->clientError(_('Failed to write file to disk.'));
+
+ case UPLOAD_ERR_EXTENSION:
+ $this->clientError(_('File upload stopped by extension.'));
+
+ default:
+ die('Should never reach here.');
+ }
+ }
+
+ if (isset($mimetype)) {
+ $filename = $this->saveFile($mimetype);
+ if (empty($filename)) {
+ $this->clientError(_('Couldn\'t save file.'));
+ }
+
+ $fileRecord = $this->storeFile($filename, $mimetype);
+
+ $fileurl = common_local_url('attachment',
+ array('attachment' => $fileRecord->id));
+
+ // not sure this is necessary -- Zach
+ $this->maybeAddRedir($fileRecord->id, $fileurl);
+
+ $short_fileurl = common_shorten_url($fileurl);
+ $content_shortened .= ' ' . $short_fileurl;
+
+ if (mb_strlen($content_shortened) > 140) {
+ $this->deleteFile($filename);
+ $this->clientError(_('Max notice size is 140 chars, including attachment URL.'));
+ }
+
+ // Also, not sure this is necessary -- Zach
+ $this->maybeAddRedir($fileRecord->id, $short_fileurl);
+ }
+
+ $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1,
($replyto == 'false') ? null : $replyto);
if (is_string($notice)) {
+ if (isset($filename)) {
+ $this->deleteFile($filename);
+ }
$this->clientError($notice);
- return;
+ }
+
+ if (isset($mimetype)) {
+ $this->attachFile($notice, $fileRecord);
}
common_broadcast_notice($notice);
@@ -191,6 +289,87 @@ class NewnoticeAction extends Action
}
}
+ function saveFile($mimetype) {
+
+ $cur = common_current_user();
+
+ if (empty($cur)) {
+ $this->serverError(_('Somehow lost the login in saveFile'));
+ }
+
+ $basename = basename($_FILES['attach']['name']);
+
+ $filename = File::filename($cur->getProfile(), $basename, $mimetype);
+
+ $filepath = File::path($filename);
+
+ if (move_uploaded_file($_FILES['attach']['tmp_name'], $filepath)) {
+ return $filename;
+ } else {
+ $this->clientError(_('File could not be moved to destination directory.'));
+ }
+ }
+
+ function deleteFile($filename)
+ {
+ $filepath = File::path($filename);
+ @unlink($filepath);
+ }
+
+ function storeFile($filename, $mimetype) {
+
+ $file = new File;
+ $file->filename = $filename;
+
+ $file->url = File::url($filename);
+
+ $filepath = File::path($filename);
+
+ $file->size = filesize($filepath);
+ $file->date = time();
+ $file->mimetype = $mimetype;
+
+ $file_id = $file->insert();
+
+ if (!$file_id) {
+ common_log_db_error($file, "INSERT", __FILE__);
+ $this->clientError(_('There was a database error while saving your file. Please try again.'));
+ }
+
+ return $file;
+ }
+
+ function rememberFile($file, $short)
+ {
+ $this->maybeAddRedir($file->id, $short);
+ }
+
+ function maybeAddRedir($file_id, $url)
+ {
+ $file_redir = File_redirection::staticGet('url', $url);
+
+ if (empty($file_redir)) {
+ $file_redir = new File_redirection;
+ $file_redir->url = $url;
+ $file_redir->file_id = $file_id;
+
+ $result = $file_redir->insert();
+
+ if (!$result) {
+ common_log_db_error($file_redir, "INSERT", __FILE__);
+ $this->clientError(_('There was a database error while saving your file. Please try again.'));
+ }
+ }
+ }
+
+ function attachFile($notice, $filerec)
+ {
+ File_to_post::processNew($filerec->id, $notice->id);
+
+ $this->maybeAddRedir($filerec->id,
+ common_local_url('file', array('notice' => $notice->id)));
+ }
+
/**
* Show an Ajax-y error message
*
@@ -295,3 +474,4 @@ class NewnoticeAction extends Action
$nli->show();
}
}
+
diff --git a/actions/noticesearch.php b/actions/noticesearch.php
index d996998fc..49b473d9e 100644
--- a/actions/noticesearch.php
+++ b/actions/noticesearch.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/noticesearchrss.php b/actions/noticesearchrss.php
index f6da969ee..2a4b2060d 100644
--- a/actions/noticesearchrss.php
+++ b/actions/noticesearchrss.php
@@ -12,7 +12,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -67,11 +67,16 @@ class NoticesearchrssAction extends Rss10Action
if (!$limit) $limit = 20;
$search_engine->limit(0, $limit, true);
- $search_engine->query($q);
- $notice->find();
+ if (false === $search_engine->query($q)) {
+ $cnt = 0;
+ } else {
+ $cnt = $notice->find();
+ }
- while ($notice->fetch()) {
- $notices[] = clone($notice);
+ if ($cnt > 0) {
+ while ($notice->fetch()) {
+ $notices[] = clone($notice);
+ }
}
return $notices;
diff --git a/actions/nudge.php b/actions/nudge.php
index c23d3e643..78c0ee566 100644
--- a/actions/nudge.php
+++ b/actions/nudge.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/openidlogin.php b/actions/openidlogin.php
index 1a4372d73..a8d052096 100644
--- a/actions/openidlogin.php
+++ b/actions/openidlogin.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/opensearch.php b/actions/opensearch.php
index d1f4895ce..4fe95c93b 100644
--- a/actions/opensearch.php
+++ b/actions/opensearch.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/othersettings.php b/actions/othersettings.php
index b542233ca..1277f8052 100644
--- a/actions/othersettings.php
+++ b/actions/othersettings.php
@@ -83,14 +83,12 @@ class OthersettingsAction extends AccountSettingsAction
{
$user = common_current_user();
-
$this->elementStart('form', array('method' => 'post',
'id' => 'form_settings_other',
'class' => 'form_settings',
'action' =>
common_local_url('othersettings')));
$this->elementStart('fieldset');
- $this->element('legend', null, _('URL Auto-shortening'));
$this->hidden('token', common_session_token());
// I18N
@@ -109,10 +107,14 @@ class OthersettingsAction extends AccountSettingsAction
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
- $this->dropdown('urlshorteningservice', _('Service'),
+ $this->dropdown('urlshorteningservice', _('Shorten URLs with'),
$services, _('Automatic shortening service to use.'),
false, $user->urlshorteningservice);
$this->elementEnd('li');
+ $this->elementStart('li');
+ $this->checkbox('viewdesigns', _('View profile designs'),
+ $user->viewdesigns, _('Show or hide profile designs.'));
+ $this->elementEnd('li');
$this->elementEnd('ul');
$this->submit('save', _('Save'));
$this->elementEnd('fieldset');
@@ -145,6 +147,8 @@ class OthersettingsAction extends AccountSettingsAction
return;
}
+ $viewdesigns = $this->boolean('viewdesigns');
+
$user = common_current_user();
assert(!is_null($user)); // should already be checked
@@ -154,6 +158,7 @@ class OthersettingsAction extends AccountSettingsAction
$original = clone($user);
$user->urlshorteningservice = $urlshorteningservice;
+ $user->viewdesigns = $viewdesigns;
$result = $user->update($original);
diff --git a/actions/peoplesearch.php b/actions/peoplesearch.php
index 65d970dd1..60ddb6a82 100644
--- a/actions/peoplesearch.php
+++ b/actions/peoplesearch.php
@@ -12,7 +12,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -87,3 +87,47 @@ class PeoplesearchAction extends SearchAction
}
}
+/**
+ * People search results class
+ *
+ * Derivative of ProfileList with specialization for highlighting search terms.
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @author Robin Millette <millette@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://laconi.ca/
+ *
+ * @see PeoplesearchAction
+ */
+
+class PeopleSearchResults extends ProfileList
+{
+ var $terms = null;
+ var $pattern = null;
+
+ function __construct($profile, $terms, $action)
+ {
+ parent::__construct($profile, $action);
+
+ $this->terms = array_map('preg_quote',
+ array_map('htmlspecialchars', $terms));
+
+ $this->pattern = '/('.implode('|',$terms).')/i';
+ }
+
+ function newProfileItem($profile)
+ {
+ return new PeopleSearchResultItem($profile, $this->action);
+ }
+}
+
+class PeopleSearchResultItem extends ProfileListItem
+{
+ function highlight($text)
+ {
+ return preg_replace($this->pattern, '<strong>\\1</strong>', htmlspecialchars($text));
+ }
+}
+
diff --git a/actions/peopletag.php b/actions/peopletag.php
index 5add75485..dd3c1c089 100644
--- a/actions/peopletag.php
+++ b/actions/peopletag.php
@@ -124,7 +124,7 @@ class PeopletagAction extends Action
$profile->query(sprintf($qry, $this->tag, $lim));
- $pl = new ProfileList($profile, null, $this);
+ $pl = new ProfileList($profile, $this);
$cnt = $pl->show();
$this->pagination($this->page > 1,
diff --git a/actions/postnotice.php b/actions/postnotice.php
index 3e98b3cd5..eb2d63b61 100644
--- a/actions/postnotice.php
+++ b/actions/postnotice.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/public.php b/actions/public.php
index 27153f131..ef9ef0d1a 100644
--- a/actions/public.php
+++ b/actions/public.php
@@ -35,6 +35,10 @@ require_once INSTALLDIR.'/lib/publicgroupnav.php';
require_once INSTALLDIR.'/lib/noticelist.php';
require_once INSTALLDIR.'/lib/feedlist.php';
+// Farther than any human will go
+
+define('MAX_PUBLIC_PAGE', 100);
+
/**
* Action for displaying the public stream
*
@@ -74,6 +78,10 @@ class PublicAction extends Action
parent::prepare($args);
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
+ if ($this->page > MAX_PUBLIC_PAGE) {
+ $this->clientError(sprintf(_("Beyond the page limit (%s)"), MAX_PUBLIC_PAGE));
+ }
+
common_set_returnto($this->selfUrl());
return true;
@@ -174,8 +182,10 @@ class PublicAction extends Action
$message .= _('Be the first to post!');
}
else {
- $message .= _('Why not [register an account](%%action.register%%) and be the first to post!');
- }
+ if (! (common_config('site','closed') || common_config('site','inviteonly'))) {
+ $message .= _('Why not [register an account](%%action.register%%) and be the first to post!');
+ }
+ }
$this->elementStart('div', 'guide');
$this->raw(common_markup_to_html($message));
diff --git a/actions/publicrss.php b/actions/publicrss.php
index bc52f2952..7e8df9625 100644
--- a/actions/publicrss.php
+++ b/actions/publicrss.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/publicxrds.php b/actions/publicxrds.php
index 283a932ca..0a1421550 100644
--- a/actions/publicxrds.php
+++ b/actions/publicxrds.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/recoverpassword.php b/actions/recoverpassword.php
index 82263fcd5..2afd052a7 100644
--- a/actions/recoverpassword.php
+++ b/actions/recoverpassword.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/register.php b/actions/register.php
index 033cf557f..dcbbbdb6a 100644
--- a/actions/register.php
+++ b/actions/register.php
@@ -382,6 +382,19 @@ class RegisterAction extends Action
function showFormContent()
{
+ $code = $this->trimmed('code');
+
+ $invite = null;
+
+ if ($code) {
+ $invite = Invitation::staticGet($code);
+ }
+
+ if (common_config('site', 'inviteonly') && !($code && $invite)) {
+ $this->clientError(_('Sorry, only invited people can register.'));
+ return;
+ }
+
$this->elementStart('form', array('method' => 'post',
'id' => 'form_register',
'class' => 'form_settings',
diff --git a/actions/remotesubscribe.php b/actions/remotesubscribe.php
index 0b1174896..e658f8d37 100644
--- a/actions/remotesubscribe.php
+++ b/actions/remotesubscribe.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/replies.php b/actions/replies.php
index eac4d0a3a..d7ed440e9 100644
--- a/actions/replies.php
+++ b/actions/replies.php
@@ -45,9 +45,8 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @link http://laconi.ca/
*/
-class RepliesAction extends Action
+class RepliesAction extends OwnerDesignAction
{
- var $user = null;
var $page = null;
/**
diff --git a/actions/repliesrss.php b/actions/repliesrss.php
index 2017c4309..a87e2870d 100644
--- a/actions/repliesrss.php
+++ b/actions/repliesrss.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/requesttoken.php b/actions/requesttoken.php
index 9507e3d6c..8d1e3f004 100644
--- a/actions/requesttoken.php
+++ b/actions/requesttoken.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/showfavorites.php b/actions/showfavorites.php
index 865045337..8efe9d30a 100644
--- a/actions/showfavorites.php
+++ b/actions/showfavorites.php
@@ -45,7 +45,7 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @link http://laconi.ca/
*/
-class ShowfavoritesAction extends Action
+class ShowfavoritesAction extends OwnerDesignAction
{
/** User we're getting the faves of */
var $user = null;
@@ -191,10 +191,21 @@ class ShowfavoritesAction extends Action
function showContent()
{
- $notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE,
- NOTICES_PER_PAGE + 1);
+ $cur = common_current_user();
- if (!$notice) {
+ if (!empty($cur) && $cur->id == $this->user->id) {
+
+ // Show imported/gateway notices as well as local if
+ // the user is looking at his own favorites
+
+ $notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE,
+ NOTICES_PER_PAGE + 1, true);
+ } else {
+ $notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE,
+ NOTICES_PER_PAGE + 1, false);
+ }
+
+ if (empty($notice)) {
$this->serverError(_('Could not retrieve favorite notices.'));
return;
}
diff --git a/actions/showgroup.php b/actions/showgroup.php
index 29b6fa1e6..ce11d574e 100644
--- a/actions/showgroup.php
+++ b/actions/showgroup.php
@@ -47,10 +47,9 @@ define('MEMBERS_PER_SECTION', 27);
* @link http://laconi.ca/
*/
-class ShowgroupAction extends Action
+class ShowgroupAction extends GroupDesignAction
{
- /** group we're viewing. */
- var $group = null;
+
/** page we're viewing. */
var $page = null;
@@ -272,6 +271,17 @@ class ShowgroupAction extends Action
$this->elementEnd('dl');
}
+ if (common_config('group', 'maxaliases') > 0) {
+ $aliases = $this->group->getAliases();
+
+ if (!empty($aliases)) {
+ $this->elementStart('dl', 'entity_aliases');
+ $this->element('dt', null, _('Aliases'));
+ $this->element('dd', 'aliases', implode(' ', $aliases));
+ $this->elementEnd('dl');
+ }
+ }
+
$this->elementEnd('div');
$this->elementStart('div', 'entity_actions');
@@ -283,7 +293,7 @@ class ShowgroupAction extends Action
if ($cur->isMember($this->group)) {
$lf = new LeaveForm($this, $this->group);
$lf->show();
- } else {
+ } else if (!Group_block::isBlocked($this->group, $cur->getProfile())) {
$jf = new JoinForm($this, $this->group);
$jf->show();
}
@@ -321,6 +331,7 @@ class ShowgroupAction extends Action
{
$this->showMembers();
$this->showStatistics();
+ $this->showAdmins();
$cloud = new GroupTagCloudSection($this, $this->group);
$cloud->show();
}
@@ -344,7 +355,7 @@ class ShowgroupAction extends Action
$this->element('h2', null, _('Members'));
- $pml = new ProfileMiniList($member, null, $this);
+ $pml = new ProfileMiniList($member, $this);
$cnt = $pml->show();
if ($cnt == 0) {
$this->element('p', null, _('(None)'));
@@ -360,6 +371,18 @@ class ShowgroupAction extends Action
}
/**
+ * Show list of admins
+ *
+ * @return void
+ */
+
+ function showAdmins()
+ {
+ $adminSection = new GroupAdminSection($this, $this->group);
+ $adminSection->show();
+ }
+
+ /**
* Show some statistics
*
* @return void
@@ -413,3 +436,34 @@ class ShowgroupAction extends Action
$this->elementEnd('div');
}
}
+
+class GroupAdminSection extends ProfileSection
+{
+ var $group;
+
+ function __construct($out, $group)
+ {
+ parent::__construct($out);
+ $this->group = $group;
+ }
+
+ function getProfiles()
+ {
+ return $this->group->getAdmins();
+ }
+
+ function title()
+ {
+ return _('Admins');
+ }
+
+ function divId()
+ {
+ return 'group_admins';
+ }
+
+ function moreUrl()
+ {
+ return null;
+ }
+} \ No newline at end of file
diff --git a/actions/shownotice.php b/actions/shownotice.php
index 1be1e2414..1ec38a76b 100644
--- a/actions/shownotice.php
+++ b/actions/shownotice.php
@@ -45,7 +45,7 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @link http://laconi.ca/
*/
-class ShownoticeAction extends Action
+class ShownoticeAction extends OwnerDesignAction
{
/**
* Notice object to show
@@ -83,18 +83,25 @@ class ShownoticeAction extends Action
$this->notice = Notice::staticGet($id);
- if (!$this->notice) {
+ if (empty($this->notice)) {
$this->clientError(_('No such notice.'), 404);
return false;
}
$this->profile = $this->notice->getProfile();
- if (!$this->profile) {
+ if (empty($this->profile)) {
$this->serverError(_('Notice has no profile'), 500);
return false;
}
+ $this->user = User::staticGet('id', $this->profile->id);
+
+ if (empty($this->user)) {
+ $this->serverError(_('Not a local notice'), 500);
+ return false;
+ }
+
$this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
return true;
@@ -158,8 +165,14 @@ class ShownoticeAction extends Action
function title()
{
+ if (!empty($this->profile->fullname)) {
+ $base = $this->profile->fullname . ' (' . $this->user->nickname . ') ';
+ } else {
+ $base = $this->user->nickname;
+ }
+
return sprintf(_('%1$s\'s status on %2$s'),
- $this->profile->nickname,
+ $base,
common_exact_date($this->notice->created));
}
@@ -208,10 +221,10 @@ class ShownoticeAction extends Action
function showContent()
{
- $this->elementStart('ul', array('class' => 'notices'));
- $nli = new NoticeListItem($this->notice, $this);
+ $this->elementStart('ol', array('class' => 'notices xoxo'));
+ $nli = new SingleNoticeItem($this->notice, $this);
$nli->show();
- $this->elementEnd('ul');
+ $this->elementEnd('ol');
}
/**
@@ -264,3 +277,29 @@ class ShownoticeAction extends Action
}
}
}
+
+class SingleNoticeItem extends NoticeListItem
+{
+ /**
+ * recipe function for displaying a single notice.
+ *
+ * We overload to show attachments.
+ *
+ * @return void
+ */
+
+ function show()
+ {
+ $this->showStart();
+ $this->showNotice();
+ $this->showNoticeAttachments();
+ $this->showNoticeInfo();
+ $this->showNoticeOptions();
+ $this->showEnd();
+ }
+
+ function showNoticeAttachments() {
+ $al = new AttachmentList($this->notice, $this->out);
+ $al->show();
+ }
+}
diff --git a/actions/showstream.php b/actions/showstream.php
index 641228bc7..cd5d4bb70 100644
--- a/actions/showstream.php
+++ b/actions/showstream.php
@@ -68,6 +68,9 @@ class ShowstreamAction extends ProfileAction
} else {
$base = $this->user->nickname;
}
+ if (!empty($this->tag)) {
+ $base .= sprintf(_(' tagged %s'), $this->tag);
+ }
if ($this->page == 1) {
return $base;
@@ -110,6 +113,15 @@ class ShowstreamAction extends ProfileAction
function getFeeds()
{
+ if (!empty($this->tag)) {
+ return array(new Feed(Feed::RSS1,
+ common_local_url('userrss',
+ array('nickname' => $this->user->nickname,
+ 'tag' => $this->tag)),
+ sprintf(_('Notice feed for %s tagged %s (RSS 1.0)'),
+ $this->user->nickname, $this->tag)));
+ }
+
return array(new Feed(Feed::RSS1,
common_local_url('userrss',
array('nickname' => $this->user->nickname)),
@@ -356,7 +368,9 @@ class ShowstreamAction extends ProfileAction
function showNotices()
{
- $notice = $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+ $notice = empty($this->tag)
+ ? $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1)
+ : $this->user->getTaggedNotices($this->tag, ($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1, 0, 0, null);
$pnl = new ProfileNoticeList($notice, $this);
$cnt = $pnl->show();
diff --git a/actions/subedit.php b/actions/subedit.php
index 8ca2d7914..2e1bf5538 100644
--- a/actions/subedit.php
+++ b/actions/subedit.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/subscribe.php b/actions/subscribe.php
index 0bc522867..15b89a312 100644
--- a/actions/subscribe.php
+++ b/actions/subscribe.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/subscribers.php b/actions/subscribers.php
index 4482de9a7..66ac00fb1 100644
--- a/actions/subscribers.php
+++ b/actions/subscribers.php
@@ -130,18 +130,34 @@ class SubscribersAction extends GalleryAction
}
}
-class SubscribersList extends ProfileList
+class SubscribersList extends SubscriptionList
{
- function showBlockForm()
+ function newListItem($profile)
{
- $bf = new BlockForm($this->out, $this->profile,
- array('action' => 'subscribers',
- 'nickname' => $this->owner->nickname));
- $bf->show();
+ return new SubscribersListItem($profile, $this->owner, $this->action);
}
+}
- function isReadOnly($args)
+class SubscribersListItem extends SubscriptionListItem
+{
+ function showActions()
{
- return true;
+ $this->startActions();
+ $this->showSubscribeButton();
+ // Relevant code!
+ $this->showBlockForm();
+ $this->endActions();
+ }
+
+ function showBlockForm()
+ {
+ $user = common_current_user();
+
+ if (!empty($user) && $this->owner->id == $user->id) {
+ $bf = new BlockForm($this->out, $this->profile,
+ array('action' => 'subscribers',
+ 'nickname' => $this->owner->nickname));
+ $bf->show();
+ }
}
}
diff --git a/actions/subscriptions.php b/actions/subscriptions.php
index 095b18ad8..42bdae10f 100644
--- a/actions/subscriptions.php
+++ b/actions/subscriptions.php
@@ -137,22 +137,49 @@ class SubscriptionsAction extends GalleryAction
}
}
-class SubscriptionsList extends ProfileList
+// XXX SubscriptionsList and SubscriptionList are dangerously close
+
+class SubscriptionsList extends SubscriptionList
+{
+ function newListItem($profile)
+ {
+ return new SubscriptionsListItem($profile, $this->owner, $this->action);
+ }
+}
+
+class SubscriptionsListItem extends SubscriptionListItem
{
- function showOwnerControls($profile)
+ function showProfile()
+ {
+ $this->startProfile();
+ $this->showAvatar();
+ $this->showFullName();
+ $this->showLocation();
+ $this->showHomepage();
+ $this->showBio();
+ $this->showTags();
+ // Relevant portion!
+ $cur = common_current_user();
+ if (!empty($cur) && $cur->id == $this->owner->id) {
+ $this->showOwnerControls();
+ }
+ $this->endProfile();
+ }
+
+ function showOwnerControls()
{
$sub = Subscription::pkeyGet(array('subscriber' => $this->owner->id,
- 'subscribed' => $profile->id));
+ 'subscribed' => $this->profile->id));
if (!$sub) {
return;
}
- $this->out->elementStart('form', array('id' => 'subedit-' . $profile->id,
+ $this->out->elementStart('form', array('id' => 'subedit-' . $this->profile->id,
'method' => 'post',
'class' => 'form_subscription_edit',
'action' => common_local_url('subedit')));
$this->out->hidden('token', common_session_token());
- $this->out->hidden('profile', $profile->id);
+ $this->out->hidden('profile', $this->profile->id);
$this->out->checkbox('jabber', _('Jabber'), $sub->jabber);
$this->out->checkbox('sms', _('SMS'), $sub->sms);
$this->out->submit('save', _('Save'));
diff --git a/actions/sup.php b/actions/sup.php
index 691153d6a..a5b665562 100644
--- a/actions/sup.php
+++ b/actions/sup.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -63,11 +63,13 @@ class SupAction extends Action
# XXX: cache this. Depends on how big this protocol becomes;
# Re-doing this query every 15 seconds isn't the end of the world.
+ $divider = common_sql_date(time() - $seconds);
+
$notice->query('SELECT profile_id, max(id) AS max_id ' .
'FROM notice ' .
((common_config('db','type') == 'pgsql') ?
'WHERE extract(epoch from created) > (extract(epoch from now()) - ' . $seconds . ') ' :
- 'WHERE created > (now() - ' . $seconds . ') ' ) .
+ 'WHERE created > "'.$divider.'" ' ) .
'GROUP BY profile_id');
$updates = array();
diff --git a/actions/tag.php b/actions/tag.php
index f5ca06f05..888aba062 100644
--- a/actions/tag.php
+++ b/actions/tag.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -76,11 +76,6 @@ class TagAction extends Action
sprintf(_('Feed for tag %s'), $this->tag)));
}
- function showPageNotice()
- {
- return sprintf(_('Messages tagged "%s", most recent first'), $this->tag);
- }
-
function showContent()
{
$notice = Notice_tag::getStream($this->tag, (($this->page-1)*NOTICES_PER_PAGE), NOTICES_PER_PAGE + 1);
diff --git a/actions/tagother.php b/actions/tagother.php
index 0c5bb7cf3..96246f799 100644
--- a/actions/tagother.php
+++ b/actions/tagother.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/tagrss.php b/actions/tagrss.php
index 83cf3afe2..f69374fca 100644
--- a/actions/tagrss.php
+++ b/actions/tagrss.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/twitapiaccount.php b/actions/twitapiaccount.php
index 8b956f897..f2a7534a2 100644
--- a/actions/twitapiaccount.php
+++ b/actions/twitapiaccount.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
require_once(INSTALLDIR.'/lib/twitterapi.php');
@@ -51,7 +53,8 @@ class TwitapiaccountAction extends TwitterapiAction
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- $this->clientError(_('This method requires a POST.'), 400, $apidata['content-type']);
+ $this->clientError(_('This method requires a POST.'),
+ 400, $apidata['content-type']);
return;
}
@@ -60,24 +63,20 @@ class TwitapiaccountAction extends TwitterapiAction
if (!is_null($location) && mb_strlen($location) > 255) {
// XXX: But Twitter just truncates and runs with it. -- Zach
- $this->clientError(_('That\'s too long. Max notice size is 255 chars.'), 406, $apidate['content-type']);
+ $this->clientError(_('That\'s too long. Max notice size is 255 chars.'),
+ 406, $apidate['content-type']);
return;
}
- $user = $apidata['user'];
+ $user = $apidata['user']; // Always the auth user
$profile = $user->getProfile();
- if (!$profile) {
- $this->serverError(_('User has no profile.'));
- return;
- }
-
$orig_profile = clone($profile);
$profile->location = $location;
$result = $profile->update($orig_profile);
- if (!$result) {
+ if (empty($result)) {
common_log_db_error($profile, 'UPDATE', __FILE__);
$this->serverError(_('Couldn\'t save profile.'));
return;
diff --git a/actions/twitapiblocks.php b/actions/twitapiblocks.php
index 8135adef3..d8e72efb1 100644
--- a/actions/twitapiblocks.php
+++ b/actions/twitapiblocks.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
require_once(INSTALLDIR.'/lib/twitterapi.php');
@@ -31,12 +33,12 @@ class TwitapiblocksAction extends TwitterapiAction
$blockee = $this->get_user($apidata['api_arg'], $apidata);
- if (!$blockee) {
+ if (empty($blockee)) {
$this->clientError('Not Found', 404, $apidata['content-type']);
return;
}
- $user = $apidata['user'];
+ $user = $apidata['user']; // Always the auth user
if ($user->hasBlocked($blockee) || $user->block($blockee)) {
$type = $apidata['content-type'];
@@ -53,7 +55,7 @@ class TwitapiblocksAction extends TwitterapiAction
parent::handle($args);
$blockee = $this->get_user($apidata['api_arg'], $apidata);
- if (!$blockee) {
+ if (empty($blockee)) {
$this->clientError('Not Found', 404, $apidata['content-type']);
return;
}
diff --git a/actions/twitapidirect_messages.php b/actions/twitapidirect_messages.php
index d2dbdb619..bd27e9d20 100644
--- a/actions/twitapidirect_messages.php
+++ b/actions/twitapidirect_messages.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
require_once(INSTALLDIR.'/lib/twitterapi.php');
@@ -38,42 +40,34 @@ class Twitapidirect_messagesAction extends TwitterapiAction
function show_messages($args, $apidata, $type)
{
- $user = $apidata['user'];
-
- $count = $this->arg('count');
- $since = $this->arg('since');
- $since_id = $this->arg('since_id');
- $max_id = $this->arg('max_id');
-
- $page = $this->arg('page');
-
- if (!$page) {
- $page = 1;
- }
+ $user = $apidata['user']; // Always the auth user
- if (!$count) {
- $count = 20;
- }
-
- $message = new Message();
-
- $title = null;
+ $message = new Message();
+ $title = null;
$subtitle = null;
- $link = null;
- $server = common_root_url();
+ $link = null;
+ $server = common_root_url();
if ($type == 'received') {
$message->to_profile = $user->id;
$title = sprintf(_("Direct messages to %s"), $user->nickname);
- $subtitle = sprintf(_("All the direct messages sent to %s"), $user->nickname);
+ $subtitle = sprintf(_("All the direct messages sent to %s"),
+ $user->nickname);
$link = $server . $user->nickname . '/inbox';
} else {
$message->from_profile = $user->id;
$title = _('Direct Messages You\'ve Sent');
- $subtitle = sprintf(_("All the direct messages sent from %s"), $user->nickname);
+ $subtitle = sprintf(_("All the direct messages sent from %s"),
+ $user->nickname);
$link = $server . $user->nickname . '/outbox';
}
+ $page = (int)$this->arg('page', 1);
+ $count = (int)$this->arg('count', 20);
+ $max_id = (int)$this->arg('max_id', 0);
+ $since_id = (int)$this->arg('since_id', 0);
+ $since = $this->arg('since');
+
if ($max_id) {
$message->whereAdd("id <= $max_id");
}
@@ -82,25 +76,23 @@ class Twitapidirect_messagesAction extends TwitterapiAction
$message->whereAdd("id > $since_id");
}
- $since = strtotime($this->arg('since'));
-
if ($since) {
$d = date('Y-m-d H:i:s', $since);
$message->whereAdd("created > '$d'");
}
$message->orderBy('created DESC, id DESC');
- $message->limit((($page-1)*20), $count);
+ $message->limit((($page-1)*$count), $count);
$message->find();
switch($apidata['content-type']) {
- case 'xml':
+ case 'xml':
$this->show_xml_dmsgs($message);
break;
- case 'rss':
+ case 'rss':
$this->show_rss_dmsgs($message, $title, $link, $subtitle);
break;
- case 'atom':
+ case 'atom':
$selfuri = common_root_url() . 'api/direct_messages';
$selfuri .= ($type == 'received') ? '.atom' : '/sent.atom';
$taguribase = common_config('integration', 'taguri');
@@ -111,12 +103,13 @@ class Twitapidirect_messagesAction extends TwitterapiAction
$id = "tag:$taguribase:DirectMessages:" . $user->id;
}
- $this->show_atom_dmsgs($message, $title, $link, $subtitle, $selfuri, $id);
+ $this->show_atom_dmsgs($message, $title, $link, $subtitle,
+ $selfuri, $id);
break;
- case 'json':
+ case 'json':
$this->show_json_dmsgs($message);
break;
- default:
+ default:
$this->clientError(_('API method not found!'), $code = 404);
}
@@ -128,22 +121,24 @@ class Twitapidirect_messagesAction extends TwitterapiAction
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- $this->clientError(_('This method requires a POST.'), 400, $apidata['content-type']);
+ $this->clientError(_('This method requires a POST.'),
+ 400, $apidata['content-type']);
return;
}
$user = $apidata['user'];
- $source = $this->trimmed('source'); // Not supported by Twitter.
+ $source = $this->trimmed('source'); // Not supported by Twitter.
$reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
- if (!$source || in_array($source, $reserved_sources)) {
+ if (empty($source) || in_array($source, $reserved_sources)) {
$source = 'api';
}
$content = $this->trimmed('text');
- if (!$content) {
- $this->clientError(_('No message text!'), $code = 406, $apidata['content-type']);
+ if (empty($content)) {
+ $this->clientError(_('No message text!'),
+ $code = 406, $apidata['content-type']);
} else {
$content_shortened = common_shorten_links($content);
if (mb_strlen($content_shortened) > 140) {
@@ -155,8 +150,9 @@ class Twitapidirect_messagesAction extends TwitterapiAction
$other = $this->get_user($this->trimmed('user'));
- if (!$other) {
- $this->clientError(_('Recipient user not found.'), $code = 403, $apidata['content-type']);
+ if (empty($other)) {
+ $this->clientError(_('Recipient user not found.'),
+ $code = 403, $apidata['content-type']);
return;
} else if (!$user->mutuallySubscribed($other)) {
$this->clientError(_('Can\'t send direct messages to users who aren\'t your friend.'),
diff --git a/actions/twitapifavorites.php b/actions/twitapifavorites.php
index 31dce341b..8256668f3 100644
--- a/actions/twitapifavorites.php
+++ b/actions/twitapifavorites.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
require_once(INSTALLDIR.'/lib/twitterapi.php');
@@ -31,50 +33,48 @@ class TwitapifavoritesAction extends TwitterapiAction
$this->auth_user = $apidata['user'];
$user = $this->get_user($apidata['api_arg'], $apidata);
- if (!$user) {
+ if (empty($user)) {
+ if ($apidata['content-type'] == 'xml') {
+ $this->show_single_xml_status($notice);
+ } elseif ($apidata['content-type'] == 'json') {
+ $this->show_single_json_status($notice);
+ }
$this->clientError('Not Found', 404, $apidata['content-type']);
return;
}
$profile = $user->getProfile();
- if (!$profile) {
- $this->serverError(_('User has no profile.'));
- return;
- }
-
- $page = $this->arg('page');
-
- if (!$page) {
- $page = 1;
- }
-
- if (!$count) {
- $count = 20;
- }
-
- $notice = $user->favoriteNotices((($page-1)*20), $count);
-
- if (!$notice) {
- $this->serverError(_('Could not retrieve favorite notices.'));
- return;
- }
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_('%s / Favorites from %s'), $sitename, $user->nickname);
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_('%s / Favorites from %s'), $sitename,
+ $user->nickname);
$taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:Favorites:".$user->id;
- $link = common_local_url('favorites', array('nickname' => $user->nickname));
- $subtitle = sprintf(_('%s updates favorited by %s / %s.'), $sitename, $profile->getBestName(), $user->nickname);
+ $id = "tag:$taguribase:Favorites:".$user->id;
+ $link = common_local_url('favorites',
+ array('nickname' => $user->nickname));
+ $subtitle = sprintf(_('%s updates favorited by %s / %s.'), $sitename,
+ $profile->getBestName(), $user->nickname);
+
+ $page = (int)$this->arg('page', 1);
+ $count = (int)$this->arg('count', 20);
+ $max_id = (int)$this->arg('max_id', 0);
+ $since_id = (int)$this->arg('since_id', 0);
+ $since = $this->arg('since');
+
+ if (!empty($this->auth_user) && $this->auth_user->id == $user->id) {
+ $notice = $user->favoriteNotices(($page-1)*$count, $count, true);
+ } else {
+ $notice = $user->favoriteNotices(($page-1)*$count, $count, false);
+ }
switch($apidata['content-type']) {
- case 'xml':
+ case 'xml':
$this->show_xml_timeline($notice);
break;
- case 'rss':
+ case 'rss':
$this->show_rss_timeline($notice, $title, $link, $subtitle);
break;
- case 'atom':
+ case 'atom':
if (isset($apidata['api_arg'])) {
$selfuri = $selfuri = common_root_url() .
'api/favorites/' . $apidata['api_arg'] . '.atom';
@@ -82,12 +82,13 @@ class TwitapifavoritesAction extends TwitterapiAction
$selfuri = $selfuri = common_root_url() .
'api/favorites.atom';
}
- $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri);
+ $this->show_atom_timeline($notice, $title, $id, $link,
+ $subtitle, null, $selfuri);
break;
- case 'json':
+ case 'json':
$this->show_json_timeline($notice);
break;
- default:
+ default:
$this->clientError(_('API method not found!'), $code = 404);
}
@@ -99,8 +100,8 @@ class TwitapifavoritesAction extends TwitterapiAction
// Check for RESTfulness
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
- // XXX: Twitter just prints the err msg, no XML / JSON.
- $this->clientError(_('This method requires a POST or DELETE.'), 400, $apidata['content-type']);
+ $this->clientError(_('This method requires a POST or DELETE.'),
+ 400, $apidata['content-type']);
return;
}
@@ -109,26 +110,27 @@ class TwitapifavoritesAction extends TwitterapiAction
return;
}
- $this->auth_user = $apidata['user'];
- $user = $this->auth_user;
+ $user = $apidata['user']; // Always the auth user
$notice_id = $apidata['api_arg'];
- $notice = Notice::staticGet($notice_id);
+ $notice = Notice::staticGet($notice_id);
- if (!$notice) {
- $this->clientError(_('No status found with that ID.'), 404, $apidata['content-type']);
+ if (empty($notice)) {
+ $this->clientError(_('No status found with that ID.'),
+ 404, $apidata['content-type']);
return;
}
// XXX: Twitter lets you fave things repeatedly via api.
if ($user->hasFave($notice)) {
- $this->clientError(_('This notice is already a favorite!'), 403, $apidata['content-type']);
+ $this->clientError(_('This status is already a favorite!'),
+ 403, $apidata['content-type']);
return;
}
$fave = Fave::addNew($user, $notice);
- if (!$fave) {
- $this->serverError(_('Could not create favorite.'));
+ if (empty($fave)) {
+ $this->clientError(_('Could not create favorite.'));
return;
}
@@ -146,10 +148,59 @@ class TwitapifavoritesAction extends TwitterapiAction
function destroy($args, $apidata)
{
parent::handle($args);
- $this->serverError(_('API method under construction.'), $code=501);
+
+ // Check for RESTfulness
+ if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
+ $this->clientError(_('This method requires a POST or DELETE.'),
+ 400, $apidata['content-type']);
+ return;
+ }
+
+ if (!in_array($apidata['content-type'], array('xml', 'json'))) {
+ $this->clientError(_('API method not found!'), $code = 404);
+ return;
+ }
+
+ $user = $apidata['user']; // Always the auth user
+ $notice_id = $apidata['api_arg'];
+ $notice = Notice::staticGet($notice_id);
+
+ if (empty($notice)) {
+ $this->clientError(_('No status found with that ID.'),
+ 404, $apidata['content-type']);
+ return;
+ }
+
+ $fave = new Fave();
+ $fave->user_id = $this->id;
+ $fave->notice_id = $notice->id;
+
+ if (!$fave->find(true)) {
+ $this->clientError(_('That status is not a favorite!'),
+ 403, $apidata['content-type']);
+ return;
+ }
+
+ $result = $fave->delete();
+
+ if (!$result) {
+ common_log_db_error($fave, 'DELETE', __FILE__);
+ $this->clientError(_('Could not delete favorite.'), 404);
+ return;
+ }
+
+ $user->blowFavesCache();
+
+ if ($apidata['content-type'] == 'xml') {
+ $this->show_single_xml_status($notice);
+ } elseif ($apidata['content-type'] == 'json') {
+ $this->show_single_json_status($notice);
+ }
+
}
- // XXX: these two funcs swiped from faves. Maybe put in util.php, or some common base class?
+ // XXX: these two funcs swiped from faves.
+ // Maybe put in util.php, or some common base class?
function notify($fave, $notice, $user)
{
diff --git a/actions/twitapifriendships.php b/actions/twitapifriendships.php
index 2f8250e0d..5fb55e9ff 100644
--- a/actions/twitapifriendships.php
+++ b/actions/twitapifriendships.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
require_once(INSTALLDIR.'/lib/twitterapi.php');
@@ -29,23 +31,25 @@ class TwitapifriendshipsAction extends TwitterapiAction
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- $this->clientError(_('This method requires a POST.'), 400, $apidata['content-type']);
+ $this->clientError(_('This method requires a POST.'),
+ 400, $apidata['content-type']);
return;
}
- $id = $apidata['api_arg'];
-
+ $id = $apidata['api_arg'];
$other = $this->get_user($id);
- if (!$other) {
- $this->clientError(_('Could not follow user: User not found.'), 403, $apidata['content-type']);
+ if (empty($other)) {
+ $this->clientError(_('Could not follow user: User not found.'),
+ 403, $apidata['content-type']);
return;
}
$user = $apidata['user'];
if ($user->isSubscribed($other)) {
- $errmsg = sprintf(_('Could not follow user: %s is already on your list.'), $other->nickname);
+ $errmsg = sprintf(_('Could not follow user: %s is already on your list.'),
+ $other->nickname);
$this->clientError($errmsg, 403, $apidata['content-type']);
return;
}
@@ -60,8 +64,9 @@ class TwitapifriendshipsAction extends TwitterapiAction
$result = $sub->insert();
- if (!$result) {
- $errmsg = sprintf(_('Could not follow user: %s is already on your list.'), $other->nickname);
+ if (empty($result)) {
+ $errmsg = sprintf(_('Could not follow user: %s is already on your list.'),
+ $other->nickname);
$this->clientError($errmsg, 400, $apidata['content-type']);
return;
}
@@ -82,7 +87,8 @@ class TwitapifriendshipsAction extends TwitterapiAction
parent::handle($args);
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
- $this->clientError(_('This method requires a POST or DELETE.'), 400, $apidata['content-type']);
+ $this->clientError(_('This method requires a POST or DELETE.'),
+ 400, $apidata['content-type']);
return;
}
@@ -91,7 +97,7 @@ class TwitapifriendshipsAction extends TwitterapiAction
# We can't subscribe to a remote person, but we can unsub
$other = $this->get_profile($id);
- $user = $apidata['user'];
+ $user = $apidata['user']; // Alwyas the auth user
$sub = new Subscription();
$sub->subscriber = $user->id;
@@ -102,7 +108,8 @@ class TwitapifriendshipsAction extends TwitterapiAction
$sub->delete();
$sub->query('COMMIT');
} else {
- $this->clientError(_('You are not friends with the specified user.'), 403, $apidata['content-type']);
+ $this->clientError(_('You are not friends with the specified user.'),
+ 403, $apidata['content-type']);
return;
}
@@ -128,8 +135,9 @@ class TwitapifriendshipsAction extends TwitterapiAction
$user_a = $this->get_user($user_a_id);
$user_b = $this->get_user($user_b_id);
- if (!$user_a || !$user_b) {
- $this->clientError(_('Two user ids or screen_names must be supplied.'), 400, $apidata['content-type']);
+ if (empty($user_a) || empty($user_b)) {
+ $this->clientError(_('Two user ids or screen_names must be supplied.'),
+ 400, $apidata['content-type']);
return;
}
@@ -152,4 +160,85 @@ class TwitapifriendshipsAction extends TwitterapiAction
}
-} \ No newline at end of file
+ function show($args, $apidata)
+ {
+ parent::handle($args);
+
+ if (!in_array($apidata['content-type'], array('xml', 'json'))) {
+ $this->clientError(_('API method not found!'), $code = 404);
+ return;
+ }
+
+ $source_id = (int)$this->trimmed('source_id');
+ $source_screen_name = $this->trimmed('source_screen_name');
+
+ // If the source is not specified for an unauthenticated request,
+ // the method will return an HTTP 403.
+
+ if (empty($source_id) && empty($source_screen_name)) {
+ if (empty($apidata['user'])) {
+ $this->clientError(_('Could not determine source user.'),
+ $code = 403);
+ return;
+ }
+ }
+
+ $source = null;
+
+ if (!empty($source_id)) {
+ $source = User::staticGet($source_id);
+ } elseif (!empty($source_screen_name)) {
+ $source = User::staticGet('nickname', $source_screen_name);
+ } else {
+ $source = $apidata['user'];
+ }
+
+ // If a source or target is specified but does not exist,
+ // the method will return an HTTP 404.
+
+ if (empty($source)) {
+ $this->clientError(_('Could not determine source user.'),
+ $code = 404);
+ return;
+ }
+
+ $target_id = (int)$this->trimmed('target_id');
+ $target_screen_name = $this->trimmed('target_screen_name');
+
+ $target = null;
+
+ if (!empty($target_id)) {
+ $target = User::staticGet($target_id);
+ } elseif (!empty($target_screen_name)) {
+ $target = User::staticGet('nickname', $target_screen_name);
+ } else {
+ $this->clientError(_('Target user not specified.'),
+ $code = 403);
+ return;
+ }
+
+ if (empty($target)) {
+ $this->clientError(_('Could not find target user.'),
+ $code = 404);
+ return;
+ }
+
+ $result = $this->twitter_relationship_array($source, $target);
+
+ switch ($apidata['content-type']) {
+ case 'xml':
+ $this->init_document('xml');
+ $this->show_twitter_xml_relationship($result[relationship]);
+ $this->end_document('xml');
+ break;
+ case 'json':
+ $this->init_document('json');
+ print json_encode($result);
+ $this->end_document('json');
+ break;
+ default:
+ break;
+ }
+ }
+
+}
diff --git a/actions/twitapihelp.php b/actions/twitapihelp.php
index db5892baf..dab2b34f9 100644
--- a/actions/twitapihelp.php
+++ b/actions/twitapihelp.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
require_once(INSTALLDIR.'/lib/twitterapi.php');
diff --git a/actions/twitapinotifications.php b/actions/twitapinotifications.php
index 411971af1..09b11766b 100644
--- a/actions/twitapinotifications.php
+++ b/actions/twitapinotifications.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/twitapisearchatom.php b/actions/twitapisearchatom.php
index eb9ab5d8e..3678213c3 100644
--- a/actions/twitapisearchatom.php
+++ b/actions/twitapisearchatom.php
@@ -165,24 +165,30 @@ class TwitapisearchatomAction extends TwitterapiAction
$search_engine->set_sort_mode('chron');
$search_engine->limit(($this->page - 1) * $this->rpp,
$this->rpp + 1, true);
- $search_engine->query($q);
- $this->cnt = $notice->find();
+ if (false === $search_engine->query($q)) {
+ $this->cnt = 0;
+ } else {
+ $this->cnt = $notice->find();
+ }
$cnt = 0;
+ $this->max_id = 0;
- while ($notice->fetch()) {
+ if ($this->cnt > 0) {
+ while ($notice->fetch()) {
- ++$cnt;
+ ++$cnt;
- if (!$this->max_id) {
- $this->max_id = $notice->id;
- }
+ if (!$this->max_id) {
+ $this->max_id = $notice->id;
+ }
- if ($cnt > $this->rpp) {
- break;
- }
+ if ($cnt > $this->rpp) {
+ break;
+ }
- $notices[] = clone($notice);
+ $notices[] = clone($notice);
+ }
}
return $notices;
diff --git a/actions/twitapisearchjson.php b/actions/twitapisearchjson.php
index b0e3be687..27a717bfc 100644
--- a/actions/twitapisearchjson.php
+++ b/actions/twitapisearchjson.php
@@ -124,8 +124,11 @@ class TwitapisearchjsonAction extends TwitterapiAction
$search_engine = $notice->getSearchEngine('identica_notices');
$search_engine->set_sort_mode('chron');
$search_engine->limit(($this->page - 1) * $this->rpp, $this->rpp + 1, true);
- $search_engine->query($q);
- $cnt = $notice->find();
+ if (false === $search_engine->query($q)) {
+ $cnt = 0;
+ } else {
+ $cnt = $notice->find();
+ }
// TODO: since_id, lang, geocode
@@ -146,4 +149,4 @@ class TwitapisearchjsonAction extends TwitterapiAction
{
return true;
}
-} \ No newline at end of file
+}
diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php
index 1fbde6639..c9943698d 100644
--- a/actions/twitapistatuses.php
+++ b/actions/twitapistatuses.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
require_once(INSTALLDIR.'/lib/twitterapi.php');
@@ -26,64 +28,45 @@ class TwitapistatusesAction extends TwitterapiAction
function public_timeline($args, $apidata)
{
- parent::handle($args);
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_("%s public timeline"), $sitename);
-
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:PublicTimeline";
- $link = common_root_url();
-
- $subtitle = sprintf(_("%s updates from everyone!"), $sitename);
-
- // Number of public statuses to return by default -- Twitter sends 20
- $MAX_PUBSTATUSES = 20;
-
- // FIXME: To really live up to the spec we need to build a list
+ // XXX: To really live up to the spec we need to build a list
// of notices by users who have custom avatars, so fix this SQL -- Zach
- $page = $this->arg('page');
- $since_id = $this->arg('since_id');
- $max_id = $this->arg('max_id');
-
- if (!$page) {
- $page = 1;
- }
- if (!$since_id) {
- $since_id = 0;
- }
- if (!$max_id) {
- $max_id = 0;
- }
-
- $since = strtotime($this->arg('since'));
+ parent::handle($args);
- $notice = Notice::publicStream((($page-1)*$MAX_PUBSTATUSES), $MAX_PUBSTATUSES, $since_id, $max_id, $since);
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s public timeline"), $sitename);
+ $taguribase = common_config('integration', 'taguri');
+ $id = "tag:$taguribase:PublicTimeline";
+ $link = common_root_url();
+ $subtitle = sprintf(_("%s updates from everyone!"), $sitename);
- if ($notice) {
+ $page = (int)$this->arg('page', 1);
+ $count = (int)$this->arg('count', 20);
+ $max_id = (int)$this->arg('max_id', 0);
+ $since_id = (int)$this->arg('since_id', 0);
+ $since = $this->arg('since');
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_timeline($notice);
- break;
- case 'rss':
- $this->show_rss_timeline($notice, $title, $link, $subtitle);
- break;
- case 'atom':
- $selfuri = common_root_url() . 'api/statuses/public_timeline.atom';
- $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri);
- break;
- case 'json':
- $this->show_json_timeline($notice);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- break;
- }
+ $notice = Notice::publicStream(($page-1)*$count, $count, $since_id,
+ $max_id, $since);
- } else {
- $this->serverError(_('Couldn\'t find any statuses.'), $code = 503);
+ switch($apidata['content-type']) {
+ case 'xml':
+ $this->show_xml_timeline($notice);
+ break;
+ case 'rss':
+ $this->show_rss_timeline($notice, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() . 'api/statuses/public_timeline.atom';
+ $this->show_atom_timeline($notice, $title, $id, $link,
+ $subtitle, null, $selfuri);
+ break;
+ case 'json':
+ $this->show_json_timeline($notice);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
}
}
@@ -92,68 +75,62 @@ class TwitapistatusesAction extends TwitterapiAction
{
parent::handle($args);
- $since = $this->arg('since');
- $since_id = $this->arg('since_id');
- $count = $this->arg('count');
- $page = $this->arg('page');
- $max_id = $this->arg('max_id');
-
- if (!$page) {
- $page = 1;
- }
-
- if (!$count) {
- $count = 20;
- }
-
- if (!$since_id) {
- $since_id = 0;
- }
-
- if (!$max_id) {
- $max_id = 0;
- }
-
- $since = strtotime($this->arg('since'));
+ $this->auth_user = $apidata['user'];
$user = $this->get_user($apidata['api_arg'], $apidata);
- $this->auth_user = $user;
if (empty($user)) {
- $this->clientError(_('No such user!'), 404, $apidata['content-type']);
+ $this->clientError(_('No such user!'), 404,
+ $apidata['content-type']);
return;
}
- $profile = $user->getProfile();
- $sitename = common_config('site', 'name');
- $title = sprintf(_("%s and friends"), $user->nickname);
+ $profile = $user->getProfile();
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s and friends"), $user->nickname);
$taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:FriendsTimeline:" . $user->id;
- $link = common_local_url('all', array('nickname' => $user->nickname));
- $subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'), $user->nickname, $sitename);
-
- $notice = $user->noticesWithFriends(($page-1)*20, $count, $since_id, $max_id, $since);
+ $id = "tag:$taguribase:FriendsTimeline:" . $user->id;
+ $link = common_local_url('all',
+ array('nickname' => $user->nickname));
+ $subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'),
+ $user->nickname, $sitename);
+
+ $page = (int)$this->arg('page', 1);
+ $count = (int)$this->arg('count', 20);
+ $max_id = (int)$this->arg('max_id', 0);
+ $since_id = (int)$this->arg('since_id', 0);
+ $since = $this->arg('since');
+
+ if (!empty($this->auth_user) && $this->auth_user->id == $user->id) {
+ $notice = $user->noticeInbox(($page-1)*$count,
+ $count, $since_id, $max_id, $since);
+ } else {
+ $notice = $user->noticesWithFriends(($page-1)*$count,
+ $count, $since_id, $max_id, $since);
+ }
switch($apidata['content-type']) {
- case 'xml':
+ case 'xml':
$this->show_xml_timeline($notice);
break;
- case 'rss':
+ case 'rss':
$this->show_rss_timeline($notice, $title, $link, $subtitle);
break;
- case 'atom':
+ case 'atom':
if (isset($apidata['api_arg'])) {
$selfuri = common_root_url() .
- 'api/statuses/friends_timeline/' . $apidata['api_arg'] . '.atom';
+ 'api/statuses/friends_timeline/' .
+ $apidata['api_arg'] . '.atom';
} else {
$selfuri = common_root_url() .
'api/statuses/friends_timeline.atom';
}
- $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri);
+ $this->show_atom_timeline($notice, $title, $id, $link,
+ $subtitle, null, $selfuri);
break;
- case 'json':
+ case 'json':
$this->show_json_timeline($notice);
break;
- default:
+ default:
$this->clientError(_('API method not found!'), $code = 404);
}
@@ -166,48 +143,21 @@ class TwitapistatusesAction extends TwitterapiAction
$this->auth_user = $apidata['user'];
$user = $this->get_user($apidata['api_arg'], $apidata);
- if (!$user) {
+ if (empty($user)) {
$this->clientError('Not Found', 404, $apidata['content-type']);
return;
}
$profile = $user->getProfile();
- if (!$profile) {
- $this->serverError(_('User has no profile.'));
- return;
- }
-
- $count = $this->arg('count');
- $since = $this->arg('since');
- $since_id = $this->arg('since_id');
- $page = $this->arg('page');
- $max_id = $this->arg('max_id');
-
- if (!$page) {
- $page = 1;
- }
-
- if (!$count) {
- $count = 20;
- }
-
- if (!$since_id) {
- $since_id = 0;
- }
-
- if (!$max_id) {
- $max_id = 0;
- }
-
- $since = strtotime($this->arg('since'));
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_("%s timeline"), $user->nickname);
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s timeline"), $user->nickname);
$taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:UserTimeline:".$user->id;
- $link = common_local_url('showstream', array('nickname' => $user->nickname));
- $subtitle = sprintf(_('Updates from %1$s on %2$s!'), $user->nickname, $sitename);
+ $id = "tag:$taguribase:UserTimeline:".$user->id;
+ $link = common_local_url('showstream',
+ array('nickname' => $user->nickname));
+ $subtitle = sprintf(_('Updates from %1$s on %2$s!'),
+ $user->nickname, $sitename);
# FriendFeed's SUP protocol
# Also added RSS and Atom feeds
@@ -215,26 +165,34 @@ class TwitapistatusesAction extends TwitterapiAction
$suplink = common_local_url('sup', null, null, $user->id);
header('X-SUP-ID: '.$suplink);
- # XXX: since
+ $page = (int)$this->arg('page', 1);
+ $count = (int)$this->arg('count', 20);
+ $max_id = (int)$this->arg('max_id', 0);
+ $since_id = (int)$this->arg('since_id', 0);
+ $since = $this->arg('since');
- $notice = $user->getNotices((($page-1)*20), $count, $since_id, $max_id, $since);
+ $notice = $user->getNotices(($page-1)*$count,
+ $count, $since_id, $max_id, $since);
switch($apidata['content-type']) {
case 'xml':
$this->show_xml_timeline($notice);
break;
case 'rss':
- $this->show_rss_timeline($notice, $title, $link, $subtitle, $suplink);
+ $this->show_rss_timeline($notice, $title, $link,
+ $subtitle, $suplink);
break;
case 'atom':
if (isset($apidata['api_arg'])) {
$selfuri = common_root_url() .
- 'api/statuses/user_timeline/' . $apidata['api_arg'] . '.atom';
+ 'api/statuses/user_timeline/' .
+ $apidata['api_arg'] . '.atom';
} else {
$selfuri = common_root_url() .
'api/statuses/user_timeline.atom';
}
- $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, $suplink, $selfuri);
+ $this->show_atom_timeline($notice, $title, $id, $link,
+ $subtitle, $suplink, $selfuri);
break;
case 'json':
$this->show_json_timeline($notice);
@@ -247,7 +205,6 @@ class TwitapistatusesAction extends TwitterapiAction
function update($args, $apidata)
{
-
parent::handle($args);
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
@@ -256,21 +213,24 @@ class TwitapistatusesAction extends TwitterapiAction
}
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- $this->clientError(_('This method requires a POST.'), 400, $apidata['content-type']);
+ $this->clientError(_('This method requires a POST.'),
+ 400, $apidata['content-type']);
return;
}
- $this->auth_user = $apidata['user'];
- $user = $this->auth_user;
+ $user = $apidata['user']; // Always the auth user
+
$status = $this->trimmed('status');
$source = $this->trimmed('source');
- $in_reply_to_status_id = intval($this->trimmed('in_reply_to_status_id'));
+ $in_reply_to_status_id =
+ intval($this->trimmed('in_reply_to_status_id'));
$reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
- if (!$source || in_array($source, $reserved_sources)) {
+
+ if (empty($source) || in_array($source, $reserved_sources)) {
$source = 'api';
}
- if (!$status) {
+ if (empty($status)) {
// XXX: Note: In this case, Twitter simply returns '200 OK'
// No error is given, but the status is not posted to the
@@ -288,9 +248,9 @@ class TwitapistatusesAction extends TwitterapiAction
// as "truncated." Sending this error may screw up some clients
// that assume Twitter will truncate for them. Should we just
// truncate too? -- Zach
- $this->clientError(_('That\'s too long. Max notice size is 140 chars.'), $code = 406, $apidata['content-type']);
+ $this->clientError(_('That\'s too long. Max notice size is 140 chars.'),
+ $code = 406, $apidata['content-type']);
return;
-
}
}
@@ -321,13 +281,15 @@ class TwitapistatusesAction extends TwitterapiAction
if ($reply) {
$reply_to = $in_reply_to_status_id;
} else {
- $this->clientError(_('Not found'), $code = 404, $apidata['content-type']);
+ $this->clientError(_('Not found'), $code = 404,
+ $apidata['content-type']);
return;
}
}
- $notice = Notice::saveNew($user->id, html_entity_decode($status, ENT_NOQUOTES, 'UTF-8'),
- $source, 1, $reply_to);
+ $notice = Notice::saveNew($user->id,
+ html_entity_decode($status, ENT_NOQUOTES, 'UTF-8'),
+ $source, 1, $reply_to);
if (is_string($notice)) {
$this->serverError($notice);
@@ -343,71 +305,55 @@ class TwitapistatusesAction extends TwitterapiAction
function mentions($args, $apidata)
{
-
parent::handle($args);
- $since = $this->arg('since');
- $count = $this->arg('count');
- $page = $this->arg('page');
- $since_id = $this->arg('since_id');
- $max_id = $this->arg('max_id');
-
$user = $this->get_user($apidata['api_arg'], $apidata);
$this->auth_user = $apidata['user'];
+
+ if (empty($user)) {
+ $this->clientError(_('No such user!'), 404,
+ $apidata['content-type']);
+ return;
+ }
+
$profile = $user->getProfile();
- $sitename = common_config('site', 'name');
- $title = sprintf(_('%1$s / Updates mentioning %2$s'),
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_('%1$s / Updates mentioning %2$s'),
$sitename, $user->nickname);
$taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:Mentions:".$user->id;
- $link = common_local_url('replies', array('nickname' => $user->nickname));
- $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'),
+ $id = "tag:$taguribase:Mentions:".$user->id;
+ $link = common_local_url('replies',
+ array('nickname' => $user->nickname));
+ $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'),
$sitename, $user->nickname, $profile->getBestName());
- if (!$page) {
- $page = 1;
- }
-
- if (!$count) {
- $count = 20;
- }
-
- if (!$since_id) {
- $since_id = 0;
- }
+ $page = (int)$this->arg('page', 1);
+ $count = (int)$this->arg('count', 20);
+ $max_id = (int)$this->arg('max_id', 0);
+ $since_id = (int)$this->arg('since_id', 0);
+ $since = $this->arg('since');
- if (!$max_id) {
- $max_id = 0;
- }
-
- $since = strtotime($this->arg('since'));
-
- $notice = $user->getReplies((($page-1)*20),
+ $notice = $user->getReplies(($page-1)*$count,
$count, $since_id, $max_id, $since);
- $notices = array();
-
- while ($notice->fetch()) {
- $notices[] = clone($notice);
- }
switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_timeline($notices);
+ case 'xml':
+ $this->show_xml_timeline($notice);
break;
- case 'rss':
- $this->show_rss_timeline($notices, $title, $link, $subtitle);
+ case 'rss':
+ $this->show_rss_timeline($notice, $title, $link, $subtitle);
break;
- case 'atom':
+ case 'atom':
$selfuri = common_root_url() .
ltrim($_SERVER['QUERY_STRING'], 'p=');
- $this->show_atom_timeline($notices, $title, $id, $link, $subtitle,
+ $this->show_atom_timeline($notice, $title, $id, $link, $subtitle,
null, $selfuri);
break;
- case 'json':
- $this->show_json_timeline($notices);
+ case 'json':
+ $this->show_json_timeline($notice);
break;
- default:
+ default:
$this->clientError(_('API method not found!'), $code = 404);
}
@@ -427,9 +373,19 @@ class TwitapistatusesAction extends TwitterapiAction
return;
}
+ // 'id' is an undocumented parameter in Twitter's API. Several
+ // clients make use of it, so we support it too.
+
+ // show.json?id=12345 takes precedence over /show/12345.json
+
$this->auth_user = $apidata['user'];
- $notice_id = $apidata['api_arg'];
- $notice = Notice::staticGet($notice_id);
+ $notice_id = $this->trimmed('id');
+
+ if (empty($notice_id)) {
+ $notice_id = $apidata['api_arg'];
+ }
+
+ $notice = Notice::staticGet((int)$notice_id);
if ($notice) {
if ($apidata['content-type'] == 'xml') {
@@ -438,15 +394,15 @@ class TwitapistatusesAction extends TwitterapiAction
$this->show_single_json_status($notice);
}
} else {
- // XXX: Twitter just sets a 404 header and doens't bother to return an err msg
- $this->clientError(_('No status with that ID found.'), 404, $apidata['content-type']);
+ // XXX: Twitter just sets a 404 header and doens't bother
+ // to return an err msg
+ $this->clientError(_('No status with that ID found.'),
+ 404, $apidata['content-type']);
}
-
}
function destroy($args, $apidata)
{
-
parent::handle($args);
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
@@ -457,17 +413,18 @@ class TwitapistatusesAction extends TwitterapiAction
// Check for RESTfulness
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
// XXX: Twitter just prints the err msg, no XML / JSON.
- $this->clientError(_('This method requires a POST or DELETE.'), 400, $apidata['content-type']);
+ $this->clientError(_('This method requires a POST or DELETE.'),
+ 400, $apidata['content-type']);
return;
}
- $this->auth_user = $apidata['user'];
- $user = $this->auth_user;
+ $user = $apidata['user']; // Always the auth user
$notice_id = $apidata['api_arg'];
- $notice = Notice::staticGet($notice_id);
+ $notice = Notice::staticGet($notice_id);
- if (!$notice) {
- $this->clientError(_('No status found with that ID.'), 404, $apidata['content-type']);
+ if (empty($notice)) {
+ $this->clientError(_('No status found with that ID.'),
+ 404, $apidata['content-type']);
return;
}
@@ -483,7 +440,8 @@ class TwitapistatusesAction extends TwitterapiAction
$this->show_single_json_status($notice);
}
} else {
- $this->clientError(_('You may not delete another user\'s status.'), 403, $apidata['content-type']);
+ $this->clientError(_('You may not delete another user\'s status.'),
+ 403, $apidata['content-type']);
}
}
@@ -514,42 +472,41 @@ class TwitapistatusesAction extends TwitterapiAction
function subscriptions($apidata, $other_attr, $user_attr, $onlyIDs=false)
{
-
$this->auth_user = $apidata['user'];
$user = $this->get_user($apidata['api_arg'], $apidata);
- if (!$user) {
+ if (empty($user)) {
$this->clientError('Not Found', 404, $apidata['content-type']);
return;
}
- $page = $this->trimmed('page');
-
- if (!$page || !is_numeric($page)) {
- $page = 1;
- }
-
$profile = $user->getProfile();
- if (!$profile) {
- $this->serverError(_('User has no profile.'));
- return;
- }
-
$sub = new Subscription();
$sub->$user_attr = $profile->id;
- $since = strtotime($this->trimmed('since'));
-
- if ($since) {
- $d = date('Y-m-d H:i:s', $since);
- $sub->whereAdd("created > '$d'");
- }
-
$sub->orderBy('created DESC');
+ // Normally, page 100 friends at a time
+
if (!$onlyIDs) {
- $sub->limit(($page-1)*100, 100);
+ $page = $this->arg('page', 1);
+ $count = $this->arg('count', 100);
+ $sub->limit(($page-1)*$count, $count);
+ } else {
+
+ // If we're just looking at IDs, return
+ // ALL of them, unless the user specifies a page,
+ // in which case, return 500 per page.
+
+ $page = $this->arg('page');
+ if (!empty($page)) {
+ if ($page < 1) {
+ $page = 1;
+ }
+ $count = 500;
+ $sub->limit(($page-1)*$count, $count);
+ }
}
$others = array();
@@ -578,21 +535,21 @@ class TwitapistatusesAction extends TwitterapiAction
function show_profiles($profiles, $type)
{
switch ($type) {
- case 'xml':
+ case 'xml':
$this->elementStart('users', array('type' => 'array'));
foreach ($profiles as $profile) {
$this->show_profile($profile);
}
$this->elementEnd('users');
break;
- case 'json':
+ case 'json':
$arrays = array();
foreach ($profiles as $profile) {
$arrays[] = $this->twitter_user_array($profile, true);
}
print json_encode($arrays);
break;
- default:
+ default:
$this->clientError(_('unsupported file type'));
}
}
@@ -600,21 +557,21 @@ class TwitapistatusesAction extends TwitterapiAction
function showIDs($profiles, $type)
{
switch ($type) {
- case 'xml':
+ case 'xml':
$this->elementStart('ids');
foreach ($profiles as $profile) {
$this->element('id', null, $profile->id);
}
$this->elementEnd('ids');
break;
- case 'json':
+ case 'json':
$ids = array();
foreach ($profiles as $profile) {
$ids[] = (int)$profile->id;
}
print json_encode($ids);
break;
- default:
+ default:
$this->clientError(_('unsupported file type'));
}
}
@@ -627,8 +584,8 @@ class TwitapistatusesAction extends TwitterapiAction
function supported($cmd)
{
-
- $cmdlist = array('MessageCommand', 'SubCommand', 'UnsubCommand', 'FavCommand', 'OnCommand', 'OffCommand');
+ $cmdlist = array('MessageCommand', 'SubCommand', 'UnsubCommand',
+ 'FavCommand', 'OnCommand', 'OffCommand');
if (in_array(get_class($cmd), $cmdlist)) {
return true;
diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php
index a47fdfbc3..fea41b397 100644
--- a/actions/twitapiusers.php
+++ b/actions/twitapiusers.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
require_once(INSTALLDIR.'/lib/twitterapi.php');
@@ -41,10 +43,10 @@ class TwitapiusersAction extends TwitterapiAction
if ($email) {
$user = User::staticGet('email', $email);
} else {
- $user = $this->get_user($apidata['api_arg']);
+ $user = $this->get_user($apidata['api_arg'], $apidata);
}
- if (!$user) {
+ if (empty($user)) {
$this->clientError(_('Not found.'), 404, $apidata['content-type']);
return;
}
@@ -56,7 +58,7 @@ class TwitapiusersAction extends TwitterapiAction
return;
}
- $twitter_user = $this->twitter_user_array($profile, true);
+ $twitter_user = $this->twitter_user_array($user->getProfile(), true);
if ($apidata['content-type'] == 'xml') {
$this->init_document('xml');
diff --git a/actions/twittersettings.php b/actions/twittersettings.php
index 0b98eef59..2b742788e 100644
--- a/actions/twittersettings.php
+++ b/actions/twittersettings.php
@@ -138,7 +138,7 @@ class TwittersettingsAction extends ConnectSettingsAction
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
- $this->checkbox('noticesync',
+ $this->checkbox('noticesend',
_('Automatically send my notices to Twitter.'),
($flink) ?
($flink->noticesync & FOREIGN_NOTICE_SEND) :
@@ -158,6 +158,22 @@ class TwittersettingsAction extends ConnectSettingsAction
($flink->friendsync & FOREIGN_FRIEND_RECV) :
false);
$this->elementEnd('li');
+
+ if (common_config('twitterbridge','enabled')) {
+ $this->elementStart('li');
+ $this->checkbox('noticerecv',
+ _('Import my Friends Timeline.'),
+ ($flink) ?
+ ($flink->noticesync & FOREIGN_NOTICE_RECV) :
+ false);
+ $this->elementEnd('li');
+ } else {
+ // preserve setting even if bidrection bridge toggled off
+ if ($flink && ($flink->noticesync & FOREIGN_NOTICE_RECV)) {
+ $this->hidden('noticerecv', true, 'noticerecv');
+ }
+ }
+
$this->elementEnd('ul');
if ($flink) {
@@ -320,7 +336,8 @@ class TwittersettingsAction extends ConnectSettingsAction
{
$screen_name = $this->trimmed('twitter_username');
$password = $this->trimmed('twitter_password');
- $noticesync = $this->boolean('noticesync');
+ $noticesend = $this->boolean('noticesend');
+ $noticerecv = $this->boolean('noticerecv');
$replysync = $this->boolean('replysync');
$friendsync = $this->boolean('friendsync');
@@ -363,7 +380,7 @@ class TwittersettingsAction extends ConnectSettingsAction
$flink->credentials = $password;
$flink->created = common_sql_now();
- $flink->set_flags($noticesync, $replysync, $friendsync);
+ $flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync);
$flink_id = $flink->insert();
@@ -421,7 +438,8 @@ class TwittersettingsAction extends ConnectSettingsAction
function savePreferences()
{
- $noticesync = $this->boolean('noticesync');
+ $noticesend = $this->boolean('noticesend');
+ $noticerecv = $this->boolean('noticerecv');
$friendsync = $this->boolean('friendsync');
$replysync = $this->boolean('replysync');
@@ -450,7 +468,7 @@ class TwittersettingsAction extends ConnectSettingsAction
$original = clone($flink);
- $flink->set_flags($noticesync, $replysync, $friendsync);
+ $flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync);
$result = $flink->update($original);
diff --git a/actions/unblock.php b/actions/unblock.php
index 6e671c9dd..05d57c60d 100644
--- a/actions/unblock.php
+++ b/actions/unblock.php
@@ -12,7 +12,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/unsubscribe.php b/actions/unsubscribe.php
index 7dcab04c0..19275041a 100644
--- a/actions/unsubscribe.php
+++ b/actions/unsubscribe.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/updateprofile.php b/actions/updateprofile.php
index 08cb31ae0..d8b62fb09 100644
--- a/actions/updateprofile.php
+++ b/actions/updateprofile.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/userauthorization.php b/actions/userauthorization.php
index 168019149..8dc2c808d 100644
--- a/actions/userauthorization.php
+++ b/actions/userauthorization.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/userbyid.php b/actions/userbyid.php
index 4a985fcd7..8b686ae10 100644
--- a/actions/userbyid.php
+++ b/actions/userbyid.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
diff --git a/actions/userdesignsettings.php b/actions/userdesignsettings.php
new file mode 100644
index 000000000..d7949951a
--- /dev/null
+++ b/actions/userdesignsettings.php
@@ -0,0 +1,285 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Change user password
+ *
+ * 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 Settings
+ * @package Laconica
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @author Zach Copley <zach@controlyourself.ca>
+ * @copyright 2008-2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/designsettings.php';
+
+/**
+ * Set a user's design
+ *
+ * Saves a design for a given user
+ *
+ * @category Settings
+ * @package Laconica
+ * @author Zach Copley <zach@controlyourself.ca>
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class UserDesignSettingsAction extends DesignSettingsAction
+{
+ /**
+ * Sets the right action for the form, and passes request args into
+ * the base action
+ *
+ * @param array $args misc. arguments
+ *
+ * @return boolean true
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->submitaction = common_local_url('userdesignsettings');
+ return true;
+ }
+
+ /**
+ * Title of the page
+ *
+ * @return string Title of the page
+ */
+
+ function title()
+ {
+ return _('Profile design');
+ }
+
+ /**
+ * Instructions for use
+ *
+ * @return instructions for use
+ */
+
+ function getInstructions()
+ {
+ return _('Customize the way your profile looks ' .
+ 'with a background image and a colour palette of your choice.');
+ }
+
+ /**
+ * Get the design we want to edit
+ *
+ * @return Design
+ */
+
+ function getWorkingDesign()
+ {
+
+ $user = common_current_user();
+ $design = $user->getDesign();
+
+ if (empty($design)) {
+ $design = $this->defaultDesign();
+ }
+
+ return $design;
+ }
+
+ /**
+ * Content area of the page
+ *
+ * Shows a form for changing the design
+ *
+ * @return void
+ */
+
+ function showContent()
+ {
+ $this->showDesignForm($this->getWorkingDesign());
+ }
+
+ /**
+ * Save or update the user's design settings
+ *
+ * @return void
+ */
+
+ function saveDesign()
+ {
+ foreach ($this->args as $key => $val) {
+ if (preg_match('/(#ho|ho)Td.*g/i', $val)) {
+ $this->sethd();
+ return;
+ }
+ }
+
+ try {
+ $bgcolor = new WebColor($this->trimmed('design_background'));
+ $ccolor = new WebColor($this->trimmed('design_content'));
+ $sbcolor = new WebColor($this->trimmed('design_sidebar'));
+ $tcolor = new WebColor($this->trimmed('design_text'));
+ $lcolor = new WebColor($this->trimmed('design_links'));
+ } catch (WebColorException $e) {
+ $this->showForm($e->getMessage());
+ return;
+ }
+
+ $onoff = $this->arg('design_background-image_onoff');
+
+ $on = false;
+ $off = false;
+ $tile = false;
+
+ if ($onoff == 'on') {
+ $on = true;
+ } else {
+ $off = true;
+ }
+
+ $repeat = $this->boolean('design_background-image_repeat');
+
+ if ($repeat) {
+ $tile = true;
+ }
+
+ $user = common_current_user();
+ $design = $user->getDesign();
+
+ if (!empty($design)) {
+
+ $original = clone($design);
+
+ $design->backgroundcolor = $bgcolor->intValue();
+ $design->contentcolor = $ccolor->intValue();
+ $design->sidebarcolor = $sbcolor->intValue();
+ $design->textcolor = $tcolor->intValue();
+ $design->linkcolor = $lcolor->intValue();
+
+ $design->setDisposition($on, $off, $tile);
+
+ $result = $design->update($original);
+
+ if ($result === false) {
+ common_log_db_error($design, 'UPDATE', __FILE__);
+ $this->showForm(_('Couldn\'t update your design.'));
+ return;
+ }
+
+ // update design
+ } else {
+
+ $user->query('BEGIN');
+
+ // save new design
+ $design = new Design();
+
+ $design->backgroundcolor = $bgcolor->intValue();
+ $design->contentcolor = $ccolor->intValue();
+ $design->sidebarcolor = $sbcolor->intValue();
+ $design->textcolor = $tcolor->intValue();
+ $design->linkcolor = $lcolor->intValue();
+
+ $design->setDisposition($on, $off, $tile);
+
+ $id = $design->insert();
+
+ if (empty($id)) {
+ common_log_db_error($id, 'INSERT', __FILE__);
+ $this->showForm(_('Unable to save your design settings!'));
+ return;
+ }
+
+ $original = clone($user);
+ $user->design_id = $id;
+ $result = $user->update($original);
+
+ if (empty($result)) {
+ common_log_db_error($original, 'UPDATE', __FILE__);
+ $this->showForm(_('Unable to save your design settings!'));
+ $user->query('ROLLBACK');
+ return;
+ }
+
+ $user->query('COMMIT');
+
+ }
+
+ $this->saveBackgroundImage($design);
+
+ $this->showForm(_('Design preferences saved.'), true);
+ }
+
+ /**
+ * Alternate default colors
+ *
+ * @return nothing
+ */
+
+ function sethd()
+ {
+
+ $user = common_current_user();
+ $design = $user->getDesign();
+
+ $user->query('BEGIN');
+
+ // alternate colors
+ $design = new Design();
+
+ $design->backgroundcolor = 16184329;
+ $design->contentcolor = 16059904;
+ $design->sidebarcolor = 16059904;
+ $design->textcolor = 0;
+ $design->linkcolor = 16777215;
+
+ $design->setDisposition(false, true, false);
+
+ $id = $design->insert();
+
+ if (empty($id)) {
+ common_log_db_error($id, 'INSERT', __FILE__);
+ $this->showForm(_('Unable to save your design settings!'));
+ return;
+ }
+
+ $original = clone($user);
+ $user->design_id = $id;
+ $result = $user->update($original);
+
+ if (empty($result)) {
+ common_log_db_error($original, 'UPDATE', __FILE__);
+ $this->showForm(_('Unable to save your design settings!'));
+ $user->query('ROLLBACK');
+ return;
+ }
+
+ $user->query('COMMIT');
+
+ $this->saveBackgroundImage($design);
+
+ $this->showForm(_('Enjoy your hotdog!'), true);
+ }
+
+}
diff --git a/actions/usergroups.php b/actions/usergroups.php
index e3088dcbd..7ead6e6e4 100644
--- a/actions/usergroups.php
+++ b/actions/usergroups.php
@@ -46,9 +46,8 @@ require_once INSTALLDIR.'/lib/grouplist.php';
* @link http://laconi.ca/
*/
-class UsergroupsAction extends Action
+class UsergroupsAction extends OwnerDesignAction
{
- var $user = null;
var $page = null;
var $profile = null;
diff --git a/actions/userrss.php b/actions/userrss.php
index 5861d9ee3..8a940865f 100644
--- a/actions/userrss.php
+++ b/actions/userrss.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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
@@ -25,14 +25,15 @@ require_once(INSTALLDIR.'/lib/rssaction.php');
class UserrssAction extends Rss10Action
{
-
var $user = null;
+ var $tag = null;
function prepare($args)
{
parent::prepare($args);
- $nickname = $this->trimmed('nickname');
+ $nickname = $this->trimmed('nickname');
$this->user = User::staticGet('nickname', $nickname);
+ $this->tag = $this->trimmed('tag');
if (!$this->user) {
$this->clientError(_('No such user.'));
@@ -42,6 +43,25 @@ class UserrssAction extends Rss10Action
}
}
+ function getTaggedNotices($tag = null, $limit=0)
+ {
+ $user = $this->user;
+
+ if (is_null($user)) {
+ return null;
+ }
+
+ $notice = $user->getTaggedNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit, 0, 0, null, $tag);
+
+ $notices = array();
+ while ($notice->fetch()) {
+ $notices[] = clone($notice);
+ }
+
+ return $notices;
+ }
+
+
function getNotices($limit=0)
{
diff --git a/actions/xrds.php b/actions/xrds.php
index 1335b6b80..9327a3c83 100644
--- a/actions/xrds.php
+++ b/actions/xrds.php
@@ -13,7 +13,7 @@
* @link http://laconi.ca/
*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, 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