summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--actions/conversation.php12
-rw-r--r--actions/file.php44
-rw-r--r--actions/groupdesignsettings.php2
-rw-r--r--actions/newnotice.php46
-rw-r--r--actions/public.php8
-rw-r--r--actions/showfavorites.php17
-rw-r--r--actions/twitapifavorites.php6
-rw-r--r--actions/twitapistatuses.php11
-rw-r--r--actions/userdesignsettings.php2
-rw-r--r--classes/Fave.php46
-rw-r--r--classes/File.php5
-rw-r--r--classes/File_redirection.php52
-rw-r--r--classes/File_to_post.php20
-rw-r--r--classes/Foreign_user.php22
-rw-r--r--classes/Group_inbox.php6
-rw-r--r--classes/Notice.php197
-rw-r--r--classes/Notice_inbox.php1
-rw-r--r--classes/Profile.php48
-rw-r--r--classes/User.php50
-rw-r--r--classes/User_group.php24
-rw-r--r--db/074to080.sql109
-rw-r--r--db/laconica.sql2
-rw-r--r--index.php9
-rw-r--r--js/userdesign.go.js5
-rw-r--r--js/util.js19
-rw-r--r--lib/attachmentlist.php8
-rw-r--r--lib/common.php12
-rw-r--r--lib/designsettings.php16
-rw-r--r--lib/imagefile.php3
-rw-r--r--lib/noticelist.php2
-rw-r--r--lib/queuehandler.php15
-rw-r--r--lib/util.php181
-rw-r--r--lib/xmppqueuehandler.php9
-rwxr-xr-xscripts/allsites.php40
-rwxr-xr-xscripts/delete_status_network.sh21
-rwxr-xr-xscripts/getvaliddaemons.php3
-rwxr-xr-xscripts/jabberqueuehandler.php20
-rwxr-xr-xscripts/publicqueuehandler.php20
-rw-r--r--scripts/setup.cfg.sample7
-rwxr-xr-xscripts/setup_status_network.sh10
-rwxr-xr-xscripts/startdaemons.sh23
-rwxr-xr-xscripts/xmppconfirmhandler.php20
-rwxr-xr-xscripts/xmppdaemon.php22
-rw-r--r--theme/base/css/display.css20
-rw-r--r--theme/base/css/ie.css6
-rw-r--r--theme/default/css/display.css26
-rw-r--r--theme/default/css/ie.css6
-rw-r--r--theme/identica/css/display.css2
-rw-r--r--theme/identica/css/ie.css6
49 files changed, 881 insertions, 380 deletions
diff --git a/actions/conversation.php b/actions/conversation.php
index d3fc5b6a9..654a670f5 100644
--- a/actions/conversation.php
+++ b/actions/conversation.php
@@ -63,6 +63,7 @@ class ConversationAction extends Action
if (empty($this->id)) {
return false;
}
+ $this->id = $this->id+0;
$this->page = $this->trimmed('page');
if (empty($this->page)) {
$this->page = 1;
@@ -106,18 +107,10 @@ class ConversationAction extends Action
function showContent()
{
- // FIXME this needs to be a tree, not a list
-
- $qry = 'SELECT * FROM notice WHERE conversation = %s ';
-
$offset = ($this->page-1) * NOTICES_PER_PAGE;
$limit = NOTICES_PER_PAGE + 1;
- $txt = sprintf($qry, $this->id);
-
- $notices = Notice::getStream($txt,
- 'notice:conversation:'.$this->id,
- $offset, $limit);
+ $notices = Notice::conversationStream($this->id, $offset, $limit);
$ct = new ConversationTree($notices, $this);
@@ -126,7 +119,6 @@ class ConversationAction extends Action
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
$this->page, 'conversation', array('id' => $this->id));
}
-
}
/**
diff --git a/actions/file.php b/actions/file.php
index bb245c4a7..271f57ab9 100644
--- a/actions/file.php
+++ b/actions/file.php
@@ -21,20 +21,40 @@ if (!defined('LACONICA')) { exit(1); }
require_once(INSTALLDIR.'/actions/shownotice.php');
-class FileAction extends ShowNoticeAction
+class FileAction extends Action
{
- function showPage() {
- $source_url = common_local_url('file', array('notice' => $this->notice->id));
- $query = "select file_redirection.url as url from file join file_redirection on file.id = file_redirection.file_id where file.url = '$source_url'";
- $file = new File_redirection;
- $file->query($query);
- $file->fetch();
- if (empty($file->url)) {
- die('nothing attached here');
- } else {
- header("Location: {$file->url}");
- die();
+ 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);
}
}
diff --git a/actions/groupdesignsettings.php b/actions/groupdesignsettings.php
index 7270bc8f7..79c192ac4 100644
--- a/actions/groupdesignsettings.php
+++ b/actions/groupdesignsettings.php
@@ -238,7 +238,6 @@ class GroupDesignSettingsAction extends DesignSettingsAction
$design->sidebarcolor = $sbcolor->intValue();
$design->textcolor = $tcolor->intValue();
$design->linkcolor = $lcolor->intValue();
- $design->backgroundimage = $filepath;
$design->setDisposition($on, $off, $tile);
@@ -263,7 +262,6 @@ class GroupDesignSettingsAction extends DesignSettingsAction
$design->sidebarcolor = $sbcolor->intValue();
$design->textcolor = $tcolor->intValue();
$design->linkcolor = $lcolor->intValue();
- $design->backgroundimage = $filepath;
$design->setDisposition($on, $off, $tile);
diff --git a/actions/newnotice.php b/actions/newnotice.php
index 4a2c369f0..15caff6ea 100644
--- a/actions/newnotice.php
+++ b/actions/newnotice.php
@@ -236,6 +236,7 @@ class NewnoticeAction extends Action
$this->deleteFile($filename);
$this->clientError(_('Max notice size is 140 chars, including attachment URL.'));
}
+ $fileRecord = $this->rememberFile($filename, $mimetype, $short_fileurl);
}
$notice = Notice::saveNew($user->id, $content_shortened, 'web', 1,
@@ -249,7 +250,7 @@ class NewnoticeAction extends Action
}
if (isset($mimetype)) {
- $this->attachFile($notice, $filename, $mimetype, $short_fileurl);
+ $this->attachFile($notice, $fileRecord);
}
common_broadcast_notice($notice);
@@ -304,12 +305,12 @@ class NewnoticeAction extends Action
@unlink($filepath);
}
- function attachFile($notice, $filename, $mimetype, $short)
+ function rememberFile($filename, $mimetype, $short)
{
$file = new File;
$file->filename = $filename;
- $file->url = common_local_url('file', array('notice' => $notice->id));
+ $file->url = File::url($filename);
$filepath = File::path($filename);
@@ -324,28 +325,37 @@ class NewnoticeAction extends Action
$this->clientError(_('There was a database error while saving your file. Please try again.'));
}
- $file_redir = new File_redirection;
- $file_redir->url = File::url($filename);
- $file_redir->file_id = $file_id;
+ $this->maybeAddRedir($file_id, $short);
- $result = $file_redir->insert();
+ return $file;
+ }
- 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 maybeAddRedir($file_id, $url)
+ {
+ $file_redir = File_redirection::staticGet('url', $url);
- $f2p = new File_to_post;
- $f2p->file_id = $file_id;
- $f2p->post_id = $notice->id;
- $f2p->insert();
+ if (empty($file_redir)) {
+ $file_redir = new File_redirection;
+ $file_redir->url = $url;
+ $file_redir->file_id = $file_id;
- if (!$result) {
- common_log_db_error($f2p, "INSERT", __FILE__);
- $this->clientError(_('There was a database error while saving your file. Please try again.'));
+ $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
*
diff --git a/actions/public.php b/actions/public.php
index 27153f131..9851285c4 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;
diff --git a/actions/showfavorites.php b/actions/showfavorites.php
index 01f38a892..b723924a5 100644
--- a/actions/showfavorites.php
+++ b/actions/showfavorites.php
@@ -191,10 +191,21 @@ class ShowfavoritesAction extends CurrentUserDesignAction
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/twitapifavorites.php b/actions/twitapifavorites.php
index e40fea91a..8256668f3 100644
--- a/actions/twitapifavorites.php
+++ b/actions/twitapifavorites.php
@@ -61,7 +61,11 @@ class TwitapifavoritesAction extends TwitterapiAction
$since_id = (int)$this->arg('since_id', 0);
$since = $this->arg('since');
- $notice = $user->favoriteNotices(($page-1)*$count, $count);
+ 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':
diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php
index 2bc404063..555c746cb 100644
--- a/actions/twitapistatuses.php
+++ b/actions/twitapistatuses.php
@@ -75,8 +75,8 @@ class TwitapistatusesAction extends TwitterapiAction
{
parent::handle($args);
+ $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,
@@ -100,8 +100,13 @@ class TwitapistatusesAction extends TwitterapiAction
$since_id = (int)$this->arg('since_id', 0);
$since = $this->arg('since');
- $notice = $user->noticesWithFriends(($page-1)*$count,
- $count, $since_id, $max_id,$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':
diff --git a/actions/userdesignsettings.php b/actions/userdesignsettings.php
index d6088aa9d..6e745e96f 100644
--- a/actions/userdesignsettings.php
+++ b/actions/userdesignsettings.php
@@ -149,7 +149,6 @@ class UserDesignSettingsAction extends DesignSettingsAction
$design->sidebarcolor = $sbcolor->intValue();
$design->textcolor = $tcolor->intValue();
$design->linkcolor = $lcolor->intValue();
- $design->backgroundimage = $filepath;
$design->setDisposition($on, $off, $tile);
@@ -174,7 +173,6 @@ class UserDesignSettingsAction extends DesignSettingsAction
$design->sidebarcolor = $sbcolor->intValue();
$design->textcolor = $tcolor->intValue();
$design->linkcolor = $lcolor->intValue();
- $design->backgroundimage = $filepath;
$design->setDisposition($on, $off, $tile);
diff --git a/classes/Fave.php b/classes/Fave.php
index 572334ce4..f4cf6256f 100644
--- a/classes/Fave.php
+++ b/classes/Fave.php
@@ -37,52 +37,62 @@ class Fave extends Memcached_DataObject
return Memcached_DataObject::pkeyGet('Fave', $kv);
}
- function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE)
+ function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $own=false)
{
$ids = Notice::stream(array('Fave', '_streamDirect'),
- array($user_id),
- 'fave:ids_by_user:'.$user_id,
+ array($user_id, $own),
+ ($own) ? 'fave:ids_by_user_own:'.$user_id :
+ 'fave:by_user:'.$user_id,
$offset, $limit);
return $ids;
}
- function _streamDirect($user_id, $offset, $limit, $since_id, $max_id, $since)
+ function _streamDirect($user_id, $own, $offset, $limit, $since_id, $max_id, $since)
{
$fav = new Fave();
-
- $fav->user_id = $user_id;
-
- $fav->selectAdd();
- $fav->selectAdd('notice_id');
+ $qry = null;
+
+ if ($own) {
+ $qry = 'SELECT fave.* FROM fave ';
+ $qry .= 'WHERE fave.user_id = ' . $user_id . ' ';
+ } else {
+ $qry = 'SELECT fave.* FROM fave ';
+ $qry .= 'INNER JOIN notice ON fave.notice_id = notice.id ';
+ $qry .= 'WHERE fave.user_id = ' . $user_id . ' ';
+ $qry .= 'AND notice.is_local != ' . NOTICE_GATEWAY . ' ';
+ }
if ($since_id != 0) {
- $fav->whereAdd('notice_id > ' . $since_id);
+ $qry .= 'AND notice_id > ' . $since_id . ' ';
}
if ($max_id != 0) {
- $fav->whereAdd('notice_id <= ' . $max_id);
+ $qry .= 'AND notice_id <= ' . $max_id . ' ';
}
if (!is_null($since)) {
- $fav->whereAdd('modified > \'' . date('Y-m-d H:i:s', $since) . '\'');
+ $qry .= 'AND modified > \'' . date('Y-m-d H:i:s', $since) . '\' ';
}
// NOTE: we sort by fave time, not by notice time!
- $fav->orderBy('modified DESC');
+ $qry .= 'ORDER BY modified DESC ';
if (!is_null($offset)) {
- $fav->limit($offset, $limit);
+ $qry .= "LIMIT $offset, $limit";
}
+ $fav->query($qry);
+
$ids = array();
- if ($fav->find()) {
- while ($fav->fetch()) {
- $ids[] = $fav->notice_id;
- }
+ while ($fav->fetch()) {
+ $ids[] = $fav->notice_id;
}
+ $fav->free();
+ unset($fav);
+
return $ids;
}
}
diff --git a/classes/File.php b/classes/File.php
index b98c9e665..5dd7cd865 100644
--- a/classes/File.php
+++ b/classes/File.php
@@ -91,9 +91,10 @@ class File extends Memcached_DataObject
$given_url = File_redirection::_canonUrl($given_url);
if (empty($given_url)) return -1; // error, no url to process
$file = File::staticGet('url', $given_url);
- if (empty($file->id)) {
+ if (empty($file)) {
$file_redir = File_redirection::staticGet('url', $given_url);
- if (empty($file_redir->id)) {
+ if (empty($file_redir)) {
+ common_debug("processNew() '$given_url' not a known redirect.\n");
$redir_data = File_redirection::where($given_url);
$redir_url = $redir_data['url'];
if ($redir_url === $given_url) {
diff --git a/classes/File_redirection.php b/classes/File_redirection.php
index c173017e2..d6fa0bcb6 100644
--- a/classes/File_redirection.php
+++ b/classes/File_redirection.php
@@ -66,21 +66,17 @@ class File_redirection extends Memcached_DataObject
// let's see if we know this...
$a = File::staticGet('url', $short_url);
- if (empty($a->id)) {
+
+ if (!empty($a)) {
+ // this is a direct link to $a->url
+ return $a->url;
+ } else {
$b = File_redirection::staticGet('url', $short_url);
- if (empty($b->id)) {
- // we'll have to figure it out
- } else {
+ if (!empty($b)) {
// this is a redirect to $b->file_id
- $a = File::staticGet($b->file_id);
- $url = $a->url;
+ $a = File::staticGet('id', $b->file_id);
+ return $a->url;
}
- } else {
- // this is a direct link to $a->url
- $url = $a->url;
- }
- if (isset($url)) {
- return $url;
}
$curlh = File_redirection::_commonCurl($short_url, $redirs);
@@ -118,28 +114,22 @@ class File_redirection extends Memcached_DataObject
}
function makeShort($long_url) {
- $long_url = File_redirection::_canonUrl($long_url);
- // do we already know this long_url and have a short redirection for it?
- $file = new File;
- $file_redir = new File_redirection;
- $file->url = $long_url;
- $file->joinAdd($file_redir);
- $file->selectAdd('length(file_redirection.url) as len');
- $file->limit(1);
- $file->orderBy('len');
- $file->find(true);
- if (!empty($file->url) && (strlen($file->url) < strlen($long_url))) {
- return $file->url;
- }
- // if yet unknown, we must find a short url according to user settings
- $short_url = File_redirection::_userMakeShort($long_url, common_current_user());
- return $short_url;
+ $canon = File_redirection::_canonUrl($long_url);
+
+ $short_url = File_redirection::_userMakeShort($canon);
+
+ // Did we get one? Is it shorter?
+ if (!empty($short_url) && mb_strlen($short_url) < mb_strlen($long_url)) {
+ return $short_url;
+ } else {
+ return $long_url;
+ }
}
- function _userMakeShort($long_url, $user) {
+ function _userMakeShort($long_url) {
$short_url = common_shorten_url($long_url);
- if ($short_url) {
+ if (!empty($short_url) && $short_url != $long_url) {
$short_url = (string)$short_url;
// store it
$file = File::staticGet('url', $long_url);
@@ -162,7 +152,7 @@ class File_redirection extends Memcached_DataObject
}
return $short_url;
}
- return $long_url;
+ return null;
}
function _canonUrl($in_url, $default_scheme = 'http://') {
diff --git a/classes/File_to_post.php b/classes/File_to_post.php
index db0a8d216..d35febb77 100644
--- a/classes/File_to_post.php
+++ b/classes/File_to_post.php
@@ -25,7 +25,7 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
* Table Definition for file_to_post
*/
-class File_to_post extends Memcached_DataObject
+class File_to_post extends Memcached_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
@@ -44,17 +44,27 @@ class File_to_post extends Memcached_DataObject
function processNew($file_id, $notice_id) {
static $seen = array();
if (empty($seen[$notice_id]) || !in_array($file_id, $seen[$notice_id])) {
- $f2p = new File_to_post;
- $f2p->file_id = $file_id;
- $f2p->post_id = $notice_id;
- $f2p->insert();
+
+ $f2p = File_to_post::pkeyGet(array('post_id' => $notice_id,
+ 'file_id' => $file_id));
+ if (empty($f2p)) {
+ $f2p = new File_to_post;
+ $f2p->file_id = $file_id;
+ $f2p->post_id = $notice_id;
+ $f2p->insert();
+ }
+
if (empty($seen[$notice_id])) {
$seen[$notice_id] = array($file_id);
} else {
$seen[$notice_id][] = $file_id;
}
}
+ }
+ function &pkeyGet($kv)
+ {
+ return Memcached_DataObject::pkeyGet('File_to_post', $kv);
}
}
diff --git a/classes/Foreign_user.php b/classes/Foreign_user.php
index 61727abe5..8b3e03dfb 100644
--- a/classes/Foreign_user.php
+++ b/classes/Foreign_user.php
@@ -4,42 +4,41 @@
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
-class Foreign_user extends Memcached_DataObject
+class Foreign_user extends Memcached_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
public $__table = 'foreign_user'; // table name
- public $id; // int(4) primary_key not_null
+ public $id; // bigint(8) primary_key not_null
public $service; // int(4) primary_key not_null
public $uri; // varchar(255) unique_key not_null
- public $nickname; // varchar(255)
+ public $nickname; // varchar(255)
public $created; // datetime() not_null
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
/* Static get */
- function staticGet($k,$v=null)
- { return Memcached_DataObject::staticGet('Foreign_user',$k,$v); }
+ function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Foreign_user',$k,$v); }
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
-
+
// XXX: This only returns a 1->1 single obj mapping. Change? Or make
// a getForeignUsers() that returns more than one? --Zach
- static function getForeignUser($id, $service) {
+ static function getForeignUser($id, $service) {
$fuser = new Foreign_user();
$fuser->whereAdd("service = $service");
$fuser->whereAdd("id = $id");
$fuser->limit(1);
-
+
if ($fuser->find()) {
$fuser->fetch();
return $fuser;
}
-
- return null;
+
+ return null;
}
-
+
function updateKeys(&$orig)
{
$parts = array();
@@ -68,5 +67,4 @@ class Foreign_user extends Memcached_DataObject
return $result;
}
-
}
diff --git a/classes/Group_inbox.php b/classes/Group_inbox.php
index b80ba4272..1af7439f7 100644
--- a/classes/Group_inbox.php
+++ b/classes/Group_inbox.php
@@ -14,8 +14,14 @@ class Group_inbox extends Memcached_DataObject
public $created; // datetime() not_null
/* Static get */
+
function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Group_inbox',$k,$v); }
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
+
+ function &pkeyGet($kv)
+ {
+ return Memcached_DataObject::pkeyGet('Group_inbox', $kv);
+ }
}
diff --git a/classes/Notice.php b/classes/Notice.php
index b6bbf66ca..fdcef1bc2 100644
--- a/classes/Notice.php
+++ b/classes/Notice.php
@@ -331,6 +331,20 @@ class Notice extends Memcached_DataObject
return $n_attachments;
}
+ function attachments() {
+ // XXX: cache this
+ $att = array();
+ $f2p = new File_to_post;
+ $f2p->post_id = $this->id;
+ if ($f2p->find()) {
+ while ($f2p->fetch()) {
+ $f = File::staticGet($f2p->file_id);
+ $att[] = clone($f);
+ }
+ }
+ return $att;
+ }
+
function blowCaches($blowLast=false)
{
$this->blowSubsCache($blowLast);
@@ -339,6 +353,19 @@ class Notice extends Memcached_DataObject
$this->blowPublicCache($blowLast);
$this->blowTagCache($blowLast);
$this->blowGroupCache($blowLast);
+ $this->blowConversationCache($blowLast);
+ }
+
+ function blowConversationCache($blowLast=false)
+ {
+ $cache = common_memcache();
+ if ($cache) {
+ $ck = common_cache_key('notice:conversation_ids:'.$this->conversation);
+ $cache->delete($ck);
+ if ($blowLast) {
+ $cache->delete($ck.';last');
+ }
+ }
}
function blowGroupCache($blowLast=false)
@@ -471,8 +498,10 @@ class Notice extends Memcached_DataObject
if ($fave->find()) {
while ($fave->fetch()) {
$cache->delete(common_cache_key('fave:ids_by_user:'.$fave->user_id));
+ $cache->delete(common_cache_key('fave:by_user_own:'.$fave->user_id));
if ($blowLast) {
$cache->delete(common_cache_key('fave:ids_by_user:'.$fave->user_id.';last'));
+ $cache->delete(common_cache_key('fave:by_user_own:'.$fave->user_id.';last'));
}
}
}
@@ -675,7 +704,10 @@ class Notice extends Memcached_DataObject
if (!empty($cache)) {
$notices = array();
foreach ($ids as $id) {
- $notices[] = Notice::staticGet('id', $id);
+ $n = Notice::staticGet('id', $id);
+ if (!empty($n)) {
+ $notices[] = $n;
+ }
}
return new ArrayWrapper($notices);
} else {
@@ -744,29 +776,116 @@ class Notice extends Memcached_DataObject
return $ids;
}
+ function conversationStream($id, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
+ {
+ $ids = Notice::stream(array('Notice', '_conversationStreamDirect'),
+ array($id),
+ 'notice:conversation_ids:'.$id,
+ $offset, $limit, $since_id, $max_id, $since);
+
+ return Notice::getStreamByIds($ids);
+ }
+
+ function _conversationStreamDirect($id, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
+ {
+ $notice = new Notice();
+
+ $notice->selectAdd(); // clears it
+ $notice->selectAdd('id');
+
+ $notice->whereAdd('conversation = '.$id);
+
+ $notice->orderBy('id DESC');
+
+ if (!is_null($offset)) {
+ $notice->limit($offset, $limit);
+ }
+
+ if ($since_id != 0) {
+ $notice->whereAdd('id > ' . $since_id);
+ }
+
+ if ($max_id != 0) {
+ $notice->whereAdd('id <= ' . $max_id);
+ }
+
+ if (!is_null($since)) {
+ $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
+ }
+
+ $ids = array();
+
+ if ($notice->find()) {
+ while ($notice->fetch()) {
+ $ids[] = $notice->id;
+ }
+ }
+
+ $notice->free();
+ $notice = NULL;
+
+ return $ids;
+ }
+
function addToInboxes()
{
$enabled = common_config('inboxes', 'enabled');
if ($enabled === true || $enabled === 'transitional') {
- $inbox = new Notice_inbox();
- $UT = common_config('db','type')=='pgsql'?'"user"':'user';
- $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' .
- "SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " .
- "FROM $UT JOIN subscription ON $UT.id = subscription.subscriber " .
- 'WHERE subscription.subscribed = ' . $this->profile_id . ' ' .
- 'AND NOT EXISTS (SELECT user_id, notice_id ' .
- 'FROM notice_inbox ' .
- "WHERE user_id = $UT.id " .
- 'AND notice_id = ' . $this->id . ' )';
- if ($enabled === 'transitional') {
- $qry .= " AND $UT.inboxed = 1";
+
+ $users = $this->getSubscribedUsers();
+
+ // FIXME: kind of ignoring 'transitional'...
+ // we'll probably stop supporting inboxless mode
+ // in 0.9.x
+
+ foreach ($users as $id) {
+ $this->addToUserInbox($id, NOTICE_INBOX_SOURCE_SUB);
}
- $inbox->query($qry);
}
+
return;
}
+ function getSubscribedUsers()
+ {
+ $user = new User();
+
+ $qry =
+ 'SELECT id ' .
+ 'FROM user JOIN subscription '.
+ 'ON user.id = subscription.subscriber ' .
+ 'WHERE subscription.subscribed = %d ';
+
+ $user->query(sprintf($qry, $this->profile_id));
+
+ $ids = array();
+
+ while ($user->fetch()) {
+ $ids[] = $user->id;
+ }
+
+ $user->free();
+
+ return $ids;
+ }
+
+ function addToUserInbox($user_id, $source)
+ {
+ $inbox = Notice_inbox::pkeyGet(array('user_id' => $user_id,
+ 'notice_id' => $this->id));
+ if (empty($inbox)) {
+ $inbox = new Notice_inbox();
+ $inbox->user_id = $user_id;
+ $inbox->notice_id = $this->id;
+ $inbox->source = $source;
+ $inbox->created = $this->created;
+ return $inbox->insert();
+ }
+
+ return true;
+ }
+
function saveGroups()
{
$enabled = common_config('inboxes', 'enabled');
@@ -805,13 +924,7 @@ class Notice extends Memcached_DataObject
if ($profile->isMember($group)) {
- $gi = new Group_inbox();
-
- $gi->group_id = $group->id;
- $gi->notice_id = $this->id;
- $gi->created = common_sql_now();
-
- $result = $gi->insert();
+ $result = $this->addToGroupInbox($group);
if (!$result) {
common_log_db_error($gi, 'INSERT', __FILE__);
@@ -819,27 +932,37 @@ class Notice extends Memcached_DataObject
// FIXME: do this in an offline daemon
- $this->addToGroupInboxes($group);
+ $this->addToGroupMemberInboxes($group);
}
}
}
- function addToGroupInboxes($group)
+ function addToGroupInbox($group)
{
- $inbox = new Notice_inbox();
- $UT = common_config('db','type')=='pgsql'?'"user"':'user';
- $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' .
- "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', " . NOTICE_INBOX_SOURCE_GROUP . " " .
- "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " .
- 'WHERE group_member.group_id = ' . $group->id . ' ' .
- 'AND NOT EXISTS (SELECT user_id, notice_id ' .
- 'FROM notice_inbox ' .
- "WHERE user_id = $UT.id " .
- 'AND notice_id = ' . $this->id . ' )';
- if ($enabled === 'transitional') {
- $qry .= " AND $UT.inboxed = 1";
- }
- $result = $inbox->query($qry);
+ $gi = Group_inbox::pkeyGet(array('group_id' => $group->id,
+ 'notice_id' => $this->id));
+
+ if (empty($gi)) {
+
+ $gi = new Group_inbox();
+
+ $gi->group_id = $group->id;
+ $gi->notice_id = $this->id;
+ $gi->created = $this->created;
+
+ return $gi->insert();
+ }
+
+ return true;
+ }
+
+ function addToGroupMemberInboxes($group)
+ {
+ $users = $group->getUserMembers();
+
+ foreach ($users as $id) {
+ $this->addToUserInbox($id, NOTICE_INBOX_SOURCE_GROUP);
+ }
}
function saveReplies()
diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php
index 4ca2e9ae3..940381f84 100644
--- a/classes/Notice_inbox.php
+++ b/classes/Notice_inbox.php
@@ -27,6 +27,7 @@ define('INBOX_CACHE_WINDOW', 101);
define('NOTICE_INBOX_SOURCE_SUB', 1);
define('NOTICE_INBOX_SOURCE_GROUP', 2);
+define('NOTICE_INBOX_SOURCE_REPLY', 3);
define('NOTICE_INBOX_SOURCE_GATEWAY', -1);
class Notice_inbox extends Memcached_DataObject
diff --git a/classes/Profile.php b/classes/Profile.php
index 6b27c80cb..a0ed6b3ca 100644
--- a/classes/Profile.php
+++ b/classes/Profile.php
@@ -289,4 +289,52 @@ class Profile extends Memcached_DataObject
return Avatar::defaultImage($size);
}
}
+
+ function getSubscriptions($offset=0, $limit=null)
+ {
+ $qry =
+ 'SELECT profile.* ' .
+ 'FROM profile JOIN subscription ' .
+ 'ON profile.id = subscription.subscribed ' .
+ 'WHERE subscription.subscriber = %d ' .
+ 'AND subscription.subscribed != subscription.subscriber ' .
+ 'ORDER BY subscription.created DESC ';
+
+ if (common_config('db','type') == 'pgsql') {
+ $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+ } else {
+ $qry .= ' LIMIT ' . $offset . ', ' . $limit;
+ }
+
+ $profile = new Profile();
+
+ $profile->query(sprintf($qry, $this->id));
+
+ return $profile;
+ }
+
+ function getSubscribers($offset=0, $limit=null)
+ {
+ $qry =
+ 'SELECT profile.* ' .
+ 'FROM profile JOIN subscription ' .
+ 'ON profile.id = subscription.subscriber ' .
+ 'WHERE subscription.subscribed = %d ' .
+ 'AND subscription.subscribed != subscription.subscriber ' .
+ 'ORDER BY subscription.created DESC ';
+
+ if ($offset) {
+ if (common_config('db','type') == 'pgsql') {
+ $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+ } else {
+ $qry .= ' LIMIT ' . $offset . ', ' . $limit;
+ }
+ }
+
+ $profile = new Profile();
+
+ $cnt = $profile->query(sprintf($qry, $this->id));
+
+ return $profile;
+ }
}
diff --git a/classes/User.php b/classes/User.php
index e8c8c5a75..62a3f8a66 100644
--- a/classes/User.php
+++ b/classes/User.php
@@ -424,9 +424,9 @@ class User extends Memcached_DataObject
}
}
- function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE)
+ function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE, $own=false)
{
- $ids = Fave::stream($this->id, $offset, $limit);
+ $ids = Fave::stream($this->id, $offset, $limit, $own);
return Notice::getStreamByIds($ids);
}
@@ -600,50 +600,16 @@ class User extends Memcached_DataObject
function getSubscriptions($offset=0, $limit=null)
{
- $qry =
- 'SELECT profile.* ' .
- 'FROM profile JOIN subscription ' .
- 'ON profile.id = subscription.subscribed ' .
- 'WHERE subscription.subscriber = %d ' .
- 'AND subscription.subscribed != subscription.subscriber ' .
- 'ORDER BY subscription.created DESC ';
-
- if (common_config('db','type') == 'pgsql') {
- $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
- } else {
- $qry .= ' LIMIT ' . $offset . ', ' . $limit;
- }
-
- $profile = new Profile();
-
- $profile->query(sprintf($qry, $this->id));
-
- return $profile;
+ $profile = $this->getProfile();
+ assert(!empty($profile));
+ return $profile->getSubscriptions($offset, $limit);
}
function getSubscribers($offset=0, $limit=null)
{
- $qry =
- 'SELECT profile.* ' .
- 'FROM profile JOIN subscription ' .
- 'ON profile.id = subscription.subscriber ' .
- 'WHERE subscription.subscribed = %d ' .
- 'AND subscription.subscribed != subscription.subscriber ' .
- 'ORDER BY subscription.created DESC ';
-
- if ($offset) {
- if (common_config('db','type') == 'pgsql') {
- $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
- } else {
- $qry .= ' LIMIT ' . $offset . ', ' . $limit;
- }
- }
-
- $profile = new Profile();
-
- $cnt = $profile->query(sprintf($qry, $this->id));
-
- return $profile;
+ $profile = $this->getProfile();
+ assert(!empty($profile));
+ return $profile->getSubscribers($offset, $limit);
}
function getTaggedSubscribers($tag, $offset=0, $limit=null)
diff --git a/classes/User_group.php b/classes/User_group.php
index 8a56b9e52..9b4b01ead 100644
--- a/classes/User_group.php
+++ b/classes/User_group.php
@@ -246,4 +246,28 @@ class User_group extends Memcached_DataObject
return Design::staticGet('id', $this->design_id);
}
+ function getUserMembers()
+ {
+ // XXX: cache this
+
+ $user = new User();
+
+ $qry =
+ 'SELECT id ' .
+ 'FROM user JOIN group_member '.
+ 'ON user.id = group_member.profile_id ' .
+ 'WHERE group_member.group_id = %d ';
+
+ $user->query(sprintf($qry, $this->id));
+
+ $ids = array();
+
+ while ($user->fetch()) {
+ $ids[] = $user->id;
+ }
+
+ $user->free();
+
+ return $ids;
+ }
}
diff --git a/db/074to080.sql b/db/074to080.sql
new file mode 100644
index 000000000..ff0819159
--- /dev/null
+++ b/db/074to080.sql
@@ -0,0 +1,109 @@
+alter table user
+ add column design_id integer comment 'id of a design' references design(id),
+ add column viewdesigns tinyint default 1 comment 'whether to view user-provided designs';
+
+alter table notice add column
+ conversation integer comment 'id of root notice in this conversation' references notice (id),
+ add index notice_conversation_idx (conversation);
+
+alter table foreign_user
+ modify column id bigint not null comment 'unique numeric key on foreign service';
+
+alter table foreign_link
+ modify column foreign_id bigint unsigned comment 'link to user on foreign service, if exists';
+
+alter table user_group
+ add column design_id integer comment 'id of a design' references design(id);
+
+create table file (
+ id integer primary key auto_increment,
+ url varchar(255) comment 'destination URL after following redirections',
+ mimetype varchar(50) comment 'mime type of resource',
+ size integer comment 'size of resource when available',
+ title varchar(255) comment 'title of resource when available',
+ date integer(11) comment 'date of resource according to http query',
+ protected integer(1) comment 'true when URL is private (needs login)',
+ filename varchar(255) comment 'if a local file, name of the file',
+ modified timestamp comment 'date this record was modified',
+
+ unique(url)
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
+
+create table file_oembed (
+ file_id integer primary key comment 'oEmbed for that URL/file' references file (id),
+ version varchar(20) comment 'oEmbed spec. version',
+ type varchar(20) comment 'oEmbed type: photo, video, link, rich',
+ provider varchar(50) comment 'name of this oEmbed provider',
+ provider_url varchar(255) comment 'URL of this oEmbed provider',
+ width integer comment 'width of oEmbed resource when available',
+ height integer comment 'height of oEmbed resource when available',
+ html text comment 'html representation of this oEmbed resource when applicable',
+ title varchar(255) comment 'title of oEmbed resource when available',
+ author_name varchar(50) comment 'author name for this oEmbed resource',
+ author_url varchar(255) comment 'author URL for this oEmbed resource',
+ url varchar(255) comment 'URL for this oEmbed resource when applicable (photo, link)',
+ modified timestamp comment 'date this record was modified'
+
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
+
+create table file_redirection (
+
+ url varchar(255) primary key comment 'short URL (or any other kind of redirect) for file (id)',
+ file_id integer comment 'short URL for what URL/file' references file (id),
+ redirections integer comment 'redirect count',
+ httpcode integer comment 'HTTP status code (20x, 30x, etc.)',
+ modified timestamp comment 'date this record was modified'
+
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
+
+create table file_thumbnail (
+
+ file_id integer primary key comment 'thumbnail for what URL/file' references file (id),
+ url varchar(255) comment 'URL of thumbnail',
+ width integer comment 'width of thumbnail',
+ height integer comment 'height of thumbnail',
+ modified timestamp comment 'date this record was modified',
+
+ unique(url)
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
+
+create table file_to_post (
+
+ file_id integer comment 'id of URL/file' references file (id),
+ post_id integer comment 'id of the notice it belongs to' references notice (id),
+ modified timestamp comment 'date this record was modified',
+
+ constraint primary key (file_id, post_id)
+
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
+
+create table design (
+ id integer primary key auto_increment comment 'design ID',
+ backgroundcolor integer comment 'main background color',
+ contentcolor integer comment 'content area background color',
+ sidebarcolor integer comment 'sidebar background color',
+ textcolor integer comment 'text color',
+ linkcolor integer comment 'link color',
+ backgroundimage varchar(255) comment 'background image, if any',
+ disposition tinyint default 1 comment 'bit 1 = hide background image, bit 2 = display background image, bit 4 = tile background image'
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
+
+create table group_block (
+ group_id integer not null comment 'group profile is blocked from' references user_group (id),
+ blocked integer not null comment 'profile that is blocked' references profile (id),
+ blocker integer not null comment 'user making the block' references user (id),
+ modified timestamp comment 'date of blocking',
+
+ constraint primary key (group_id, blocked)
+
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
+
+create table group_alias (
+
+ alias varchar(64) primary key comment 'additional nickname for the group',
+ group_id integer not null comment 'group profile is blocked from' references user_group (id),
+ modified timestamp comment 'date alias was created',
+
+ index group_alias_group_id_idx (group_id)
+
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
diff --git a/db/laconica.sql b/db/laconica.sql
index 95796d5cc..3f8918de6 100644
--- a/db/laconica.sql
+++ b/db/laconica.sql
@@ -277,7 +277,7 @@ create table foreign_service (
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table foreign_user (
- id int not null comment 'unique numeric key on foreign service',
+ id bigint not null comment 'unique numeric key on foreign service',
service int not null comment 'foreign key to service' references foreign_service(id),
uri varchar(255) not null unique key comment 'identifying URI',
nickname varchar(255) comment 'nickname on foreign service',
diff --git a/index.php b/index.php
index cb26e2196..cb6a0fe60 100644
--- a/index.php
+++ b/index.php
@@ -48,7 +48,14 @@ function handleError($error)
$logmsg .= " : ". $error->getDebugInfo();
}
common_log(LOG_ERR, $logmsg);
- if ($error instanceof DB_DataObject_Error) {
+ if(common_config('site', 'logdebug')) {
+ $bt = $error->getBacktrace();
+ foreach ($bt as $line) {
+ common_log(LOG_ERR, $line);
+ }
+ }
+ if ($error instanceof DB_DataObject_Error ||
+ $error instanceof DB_Error) {
$msg = sprintf(_('The database for %s isn\'t responding correctly, '.
'so the site won\'t work properly. '.
'The site admins probably know about the problem, '.
diff --git a/js/userdesign.go.js b/js/userdesign.go.js
index b54b492cc..833b19adc 100644
--- a/js/userdesign.go.js
+++ b/js/userdesign.go.js
@@ -89,11 +89,10 @@ $(document).ready(function() {
$('body').css({'background-image':'none'});
});
$('#design_background-image_on').focus(function() {
- var bis = $('#design_background-image_onoff img')[0].src;
- $('body').css({'background-image':'url('+bis+')'});
+ $('body').css({'background-image':'url('+$('#design_background-image_onoff img')[0].src+')'});
});
$('#design_background-image_repeat').click(function() {
($(this)[0].checked) ? $('body').css({'background-repeat':'repeat'}) : $('body').css({'background-repeat':'no-repeat'});
});
-}); \ No newline at end of file
+});
diff --git a/js/util.js b/js/util.js
index 65a77960a..e7c54b74a 100644
--- a/js/util.js
+++ b/js/util.js
@@ -222,6 +222,7 @@ $(document).ready(function(){
}
$("#notice_data-text").val("");
$("#notice_data-attach").val("");
+ $('#notice_data-attach_selected').remove();
counter();
}
$("#form_notice").removeClass("processing");
@@ -233,6 +234,7 @@ $(document).ready(function(){
$("#form_notice").each(addAjaxHidden);
NoticeReply();
NoticeAttachments();
+ NoticeDataAttach();
});
function NoticeReply() {
@@ -280,13 +282,13 @@ function NoticeAttachments() {
timeout : 0
};
- $('a.attachment').click(function() {
+ $('#content .notice a.attachment').click(function() {
$().jOverlay({url: $('address .url')[0].href+'/attachment/' + ($(this).attr('id').substring('attachment'.length + 1)) + '/ajax'});
return false;
});
var t;
- $("body:not(#shownotice) a.thumbnail").hover(
+ $("body:not(#shownotice) #content .notice a.thumbnail").hover(
function() {
var anchor = $(this);
$("a.thumbnail").children('img').hide();
@@ -310,3 +312,16 @@ function NoticeAttachments() {
}
);
}
+
+function NoticeDataAttach() {
+ NDA = $('#notice_data-attach');
+ NDA.change(function() {
+ S = '<div id="notice_data-attach_selected" class="success"><code>'+$(this).val()+'</code> <button>&#215;</button></div>';
+ NDAS = $('#notice_data-attach_selected');
+ (NDAS.length > 0) ? NDAS.replaceWith(S) : $('#form_notice').append(S);
+ $('#notice_data-attach_selected button').click(function(){
+ $('#notice_data-attach_selected').remove();
+ NDA.val('');
+ });
+ });
+}
diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php
index a2446a886..f6a1b59d0 100644
--- a/lib/attachmentlist.php
+++ b/lib/attachmentlist.php
@@ -82,7 +82,8 @@ class AttachmentList extends Widget
$atts = new File;
$att = $atts->getAttachments($this->notice->id);
if (empty($att)) return 0;
- $this->out->elementStart('dl', array('id' =>'attachments'));
+ $this->out->elementStart('dl', array('id' =>'attachments',
+ 'class' => 'entry-content'));
$this->out->element('dt', null, _('Attachments'));
$this->out->elementStart('dd');
$this->out->elementStart('ol', array('class' => 'attachments'));
@@ -249,10 +250,13 @@ class Attachment extends AttachmentListItem
$this->out->elementStart('div', 'entry-title');
$this->out->elementStart('a', $this->linkAttr());
$this->out->element('span', null, $this->linkTitle());
- $this->showRepresentation();
$this->out->elementEnd('a');
$this->out->elementEnd('div');
+ $this->out->elementStart('div', 'entry-content');
+ $this->showRepresentation();
+ $this->out->elementEnd('div');
+
if (!empty($this->oembed->author_name) || !empty($this->oembed->provider)) {
$this->out->elementStart('div', array('id' => 'oembed_info',
'class' => 'entry-content'));
diff --git a/lib/common.php b/lib/common.php
index 76eb4a978..bb1a4255d 100644
--- a/lib/common.php
+++ b/lib/common.php
@@ -95,9 +95,9 @@ $config =
'server' => $_server,
'theme' => 'default',
'design' =>
- array('backgroundcolor' => '#F0F2F5',
+ array('backgroundcolor' => '#CEE1E9',
'contentcolor' => '#FFFFFF',
- 'sidebarcolor' => '#CEE1E9',
+ 'sidebarcolor' => '#C8D1D5',
'textcolor' => '#000000',
'linkcolor' => '#002E6E',
'backgroundimage' => null,
@@ -125,7 +125,13 @@ $config =
array('appname' => 'laconica', # for syslog
'priority' => 'debug'), # XXX: currently ignored
'queue' =>
- array('enabled' => false),
+ array('enabled' => false,
+ 'subsystem' => 'db', # default to database, or 'stomp'
+ 'stomp_server' => null,
+ 'queue_basename' => 'laconica',
+ 'stomp_username' => null,
+ 'stomp_password' => null,
+ ),
'license' =>
array('url' => 'http://creativecommons.org/licenses/by/3.0/',
'title' => 'Creative Commons Attribution 3.0',
diff --git a/lib/designsettings.php b/lib/designsettings.php
index 6aa6bb2f1..9650679ac 100644
--- a/lib/designsettings.php
+++ b/lib/designsettings.php
@@ -132,13 +132,13 @@ class DesignSettingsAction extends AccountSettingsAction
_('Off'));
$this->element('p', 'form_guide', _('Turn background image on or off.'));
$this->elementEnd('li');
- }
- $this->elementStart('li');
- $this->checkbox('design_background-image_repeat',
- _('Tile background image'),
- ($design->disposition & BACKGROUND_TILE) ? true : false );
- $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->checkbox('design_background-image_repeat',
+ _('Tile background image'),
+ ($design->disposition & BACKGROUND_TILE) ? true : false );
+ $this->elementEnd('li');
+ }
$this->elementEnd('ul');
$this->elementEnd('fieldset');
@@ -388,7 +388,11 @@ class DesignSettingsAction extends AccountSettingsAction
$original = clone($design);
$design->backgroundimage = $filename;
+
+ // default to on, no tile
+
$design->setDisposition(true, false, false);
+
$result = $design->update($original);
if ($result === false) {
diff --git a/lib/imagefile.php b/lib/imagefile.php
index 0c93b257e..52e4c4b22 100644
--- a/lib/imagefile.php
+++ b/lib/imagefile.php
@@ -72,7 +72,8 @@ class ImageFile
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
- throw new Exception(sprintf(_('That file is too big. The maximum file size is %d.'), $this->maxFileSize()));
+ throw new Exception(sprintf(_('That file is too big. The maximum file size is %d.'),
+ ImageFile::maxFileSize()));
return;
case UPLOAD_ERR_PARTIAL:
@unlink($_FILES[$param]['tmp_name']);
diff --git a/lib/noticelist.php b/lib/noticelist.php
index 6f05c63d6..44726a17b 100644
--- a/lib/noticelist.php
+++ b/lib/noticelist.php
@@ -432,7 +432,7 @@ class NoticeListItem extends Widget
$this->out->elementStart('dl', 'response');
$this->out->element('dt', null, _('To'));
$this->out->elementStart('dd');
- $this->out->element('a', array('href' => $convurl),
+ $this->out->element('a', array('href' => $convurl.'#notice-'.$this->notice->id),
_('in context'));
$this->out->elementEnd('dd');
$this->out->elementEnd('dl');
diff --git a/lib/queuehandler.php b/lib/queuehandler.php
index d5e0150d9..ae403c65e 100644
--- a/lib/queuehandler.php
+++ b/lib/queuehandler.php
@@ -112,12 +112,21 @@ class QueueHandler extends Daemon
}
function stomp_dispatch() {
- require("Stomp.php");
- $con = new Stomp(common_config('queue','stomp_server'));
- if (!$con->connect()) {
+
+ // use an external message queue system via STOMP
+ require_once("Stomp.php");
+
+ $server = common_config('queue','stomp_server');
+ $username = common_config('queue', 'stomp_username');
+ $password = common_config('queue', 'stomp_password');
+
+ $con = new Stomp($server);
+
+ if (!$con->connect($username, $password)) {
$this->log(LOG_ERR, 'Failed to connect to queue server');
return false;
}
+
$queue_basename = common_config('queue','queue_basename');
// subscribe to the relevant queue (format: basename-transport)
$con->subscribe('/queue/'.$queue_basename.'-'.$this->transport());
diff --git a/lib/util.php b/lib/util.php
index d14759001..9a51477f4 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -497,6 +497,22 @@ function common_linkify($url) {
$attrs = array('href' => $longurl, 'rel' => 'external');
+ $is_attachment = false;
+ $attachment_id = null;
+ $has_thumb = false;
+
+ // Check to see whether there's a filename associated with this URL.
+ // If there is, it's an upload and qualifies as an attachment
+
+ $localfile = File::staticGet('url', $longurl);
+
+ if (!empty($localfile)) {
+ if (isset($localfile->filename)) {
+ $is_attachment = true;
+ $attachment_id = $localfile->id;
+ }
+ }
+
// if this URL is an attachment, then we set class='attachment' and id='attahcment-ID'
// where ID is the id of the attachment for the given URL.
//
@@ -504,24 +520,35 @@ function common_linkify($url) {
// we're currently picking up oembeds only.
// I think the best option is another file_view table in the db
// and associated dbobject.
+
$query = "select file_oembed.file_id as file_id from file join file_oembed on file.id = file_oembed.file_id where file.url='$longurl'";
$file = new File;
$file->query($query);
$file->fetch();
if (!empty($file->file_id)) {
+ $is_attachment = true;
+ $attachment_id = $file->file_id;
+
$query = "select file_thumbnail.file_id as file_id from file join file_thumbnail on file.id = file_thumbnail.file_id where file.url='$longurl'";
$file2 = new File;
$file2->query($query);
$file2->fetch();
- if (empty($file2->file_id)) {
- $attrs['class'] = 'attachment';
- } else {
+ if (!empty($file2)) {
+ $has_thumb = true;
+ }
+ }
+
+ // Add clippy
+ if ($is_attachment) {
+ $attrs['class'] = 'attachment';
+ if ($has_thumb) {
$attrs['class'] = 'attachment thumbnail';
}
- $attrs['id'] = "attachment-{$file->file_id}";
+ $attrs['id'] = "attachment-{$attachment_id}";
}
+
return XMLStringer::estring('a', $attrs, $display);
}
@@ -826,89 +853,91 @@ function common_broadcast_notice($notice, $remote=false)
function common_enqueue_notice($notice)
{
+ $transports = array('omb', 'sms', 'public', 'twitter', 'facebook', 'ping');
+
+ if (common_config('xmpp', 'enabled'))
+ {
+ $transports[] = 'jabber';
+ }
+
if (common_config('queue','subsystem') == 'stomp') {
- // use an external message queue system via STOMP
- require_once("Stomp.php");
- $con = new Stomp(common_config('queue','stomp_server'));
- if (!$con->connect()) {
- common_log(LOG_ERR, 'Failed to connect to queue server');
- return false;
- }
- $queue_basename = common_config('queue','queue_basename');
- foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) {
- if (!$con->send(
- '/queue/'.$queue_basename.'-'.$transport, // QUEUE
- $notice->id, // BODY of the message
- array ( // HEADERS of the msg
- 'created' => $notice->created
- ))) {
- common_log(LOG_ERR, 'Error sending to '.$transport.' queue');
- return false;
- }
- common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' . $notice->id . ' for ' . $transport);
- }
-
- //send tags as headers, so they can be used as JMS selectors
- common_log(LOG_DEBUG, 'searching for tags ' . $notice->id);
- $tags = array();
- $tag = new Notice_tag();
- $tag->notice_id = $notice->id;
- if ($tag->find()) {
- while ($tag->fetch()) {
- common_log(LOG_DEBUG, 'tag found = ' . $tag->tag);
- array_push($tags,$tag->tag);
- }
- }
- $tag->free();
-
- $con->send('/topic/laconica.'.$notice->profile_id,
- $notice->content,
- array(
- 'profile_id' => $notice->profile_id,
- 'created' => $notice->created,
- 'tags' => implode($tags,' - ')
- )
- );
- common_log(LOG_DEBUG, 'sent to personal topic ' . $notice->id);
- $con->send('/topic/laconica.allusers',
- $notice->content,
- array(
- 'profile_id' => $notice->profile_id,
- 'created' => $notice->created,
- 'tags' => implode($tags,' - ')
- )
- );
- common_log(LOG_DEBUG, 'sent to catch-all topic ' . $notice->id);
- $result = true;
+ common_enqueue_notice_stomp($notice, $transports);
}
else {
- // in any other case, 'internal'
- foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) {
- $qi = new Queue_item();
- $qi->notice_id = $notice->id;
- $qi->transport = $transport;
- $qi->created = $notice->created;
- $result = $qi->insert();
- if (!$result) {
- $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
- common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message);
- return false;
- }
- common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport);
- }
+ common_enqueue_notice_db($notice, $transports);
}
return $result;
}
-function common_post_inbox_transports()
+function common_enqueue_notice_stomp($notice, $transports)
{
- $transports = array('omb', 'sms');
+ // use an external message queue system via STOMP
+ require_once("Stomp.php");
+
+ $server = common_config('queue','stomp_server');
+ $username = common_config('queue', 'stomp_username');
+ $password = common_config('queue', 'stomp_password');
+
+ $con = new Stomp($server);
+
+ if (!$con->connect($username, $password)) {
+ common_log(LOG_ERR, 'Failed to connect to queue server');
+ return false;
+ }
+
+ $queue_basename = common_config('queue','queue_basename');
- if (common_config('xmpp', 'enabled')) {
- $transports = array_merge($transports, array('jabber', 'public'));
+ foreach ($transports as $transport) {
+ $result = $con->send('/queue/'.$queue_basename.'-'.$transport, // QUEUE
+ $notice->id, // BODY of the message
+ array ('created' => $notice->created));
+ if (!$result) {
+ common_log(LOG_ERR, 'Error sending to '.$transport.' queue');
+ return false;
+ }
+ common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' . $notice->id . ' for ' . $transport);
}
- return $transports;
+ //send tags as headers, so they can be used as JMS selectors
+ common_log(LOG_DEBUG, 'searching for tags ' . $notice->id);
+ $tags = array();
+ $tag = new Notice_tag();
+ $tag->notice_id = $notice->id;
+ if ($tag->find()) {
+ while ($tag->fetch()) {
+ common_log(LOG_DEBUG, 'tag found = ' . $tag->tag);
+ array_push($tags,$tag->tag);
+ }
+ }
+ $tag->free();
+
+ $con->send('/topic/laconica.'.$notice->profile_id,
+ $notice->content,
+ array(
+ 'profile_id' => $notice->profile_id,
+ 'created' => $notice->created,
+ 'tags' => implode($tags,' - ')
+ )
+ );
+ common_log(LOG_DEBUG, 'sent to personal topic ' . $notice->id);
+ $con->send('/topic/laconica.allusers',
+ $notice->content,
+ array(
+ 'profile_id' => $notice->profile_id,
+ 'created' => $notice->created,
+ 'tags' => implode($tags,' - ')
+ )
+ );
+ common_log(LOG_DEBUG, 'sent to catch-all topic ' . $notice->id);
+ $result = true;
+}
+
+function common_enqueue_notice_db($notice, $transports)
+{
+ // in any other case, 'internal'
+ foreach ($transports as $transport) {
+ common_enqueue_notice_transport($notice, $transport);
+ }
}
function common_enqueue_notice_transport($notice, $transport)
diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php
index a078cd9f7..986e09c25 100644
--- a/lib/xmppqueuehandler.php
+++ b/lib/xmppqueuehandler.php
@@ -22,7 +22,7 @@ if (!defined('LACONICA')) { exit(1); }
require_once(INSTALLDIR.'/lib/queuehandler.php');
/**
- * Common superclass for all XMPP-using queue handlers. They all need to
+ * Common superclass for all XMPP-using queue handlers. They all need to
* service their message queues on idle, and forward any incoming messages
* to the XMPP listener connection. So, we abstract out common code to a
* superclass.
@@ -30,12 +30,11 @@ require_once(INSTALLDIR.'/lib/queuehandler.php');
class XmppQueueHandler extends QueueHandler
{
-
function start()
{
# Low priority; we don't want to receive messages
$this->log(LOG_INFO, "INITIALIZE");
- $this->conn = jabber_connect($this->_id);
+ $this->conn = jabber_connect($this->_id.$this->transport());
if ($this->conn) {
$this->conn->addEventHandler('message', 'forward_message', $this);
$this->conn->addEventHandler('reconnect', 'handle_reconnect', $this);
@@ -44,7 +43,7 @@ class XmppQueueHandler extends QueueHandler
}
return !is_null($this->conn);
}
-
+
function handle_reconnect(&$pl)
{
$this->conn->processUntil('session_start');
@@ -63,7 +62,7 @@ class XmppQueueHandler extends QueueHandler
die($e->getMessage());
}
}
-
+
function forward_message(&$pl)
{
if ($pl['type'] != 'chat') {
diff --git a/scripts/allsites.php b/scripts/allsites.php
new file mode 100755
index 000000000..d6768c278
--- /dev/null
+++ b/scripts/allsites.php
@@ -0,0 +1,40 @@
+#!/usr/bin/env php
+<?php
+/*
+ * 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/>.
+ */
+
+# Abort if called from a web server
+
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+
+$helptext = <<<ENDOFHELP
+allsites.php - list all sites configured for multi-site use
+
+returns the nickname of each site configured for multi-site use
+
+ENDOFHELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+$sn = new Status_network();
+
+if ($sn->find()) {
+ while ($sn->fetch()) {
+ print "$sn->nickname\n";
+ }
+} \ No newline at end of file
diff --git a/scripts/delete_status_network.sh b/scripts/delete_status_network.sh
new file mode 100755
index 000000000..32187382c
--- /dev/null
+++ b/scripts/delete_status_network.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+source /etc/laconica/setup.cfg
+
+export nickname=$1
+
+export database=$nickname$DBBASE
+
+# Create the db
+
+mysqladmin -h $DBHOST -u $ADMIN --password=$ADMINPASS -f drop $database
+
+mysql -h $DBHOST -u $ADMIN --password=$ADMINPASS $SITEDB << ENDOFCOMMANDS
+
+delete from status_network where nickname = '$nickname';
+
+ENDOFCOMMANDS
+
+for top in $AVATARBASE $FILEBASE $BACKGROUNDBASE; do
+ rm -Rf $top/$nickname
+done
diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php
index 198ea8fb9..97c230784 100755
--- a/scripts/getvaliddaemons.php
+++ b/scripts/getvaliddaemons.php
@@ -38,9 +38,6 @@ if(common_config('xmpp','enabled')) {
echo "xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php ";
echo "xmppconfirmhandler.php ";
}
-if(common_config('memcached','enabled')) {
- echo "memcachedqueuehandler.php ";
-}
if(common_config('twitterbridge','enabled')) {
echo "twitterstatusfetcher.php ";
}
diff --git a/scripts/jabberqueuehandler.php b/scripts/jabberqueuehandler.php
index a44993236..5b581629d 100755
--- a/scripts/jabberqueuehandler.php
+++ b/scripts/jabberqueuehandler.php
@@ -20,13 +20,13 @@
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
-$shortoptions = 'r::';
-$longoptions = array('resource::');
+$shortoptions = 'i::';
+$longoptions = array('id::');
$helptext = <<<END_OF_JABBER_HELP
Daemon script for pushing new notices to Jabber users.
- -r --resource Jabber Resource ID (default to config)
+ -i --id Identity (default none)
END_OF_JABBER_HELP;
@@ -63,16 +63,16 @@ if (common_config('xmpp','enabled')==false) {
exit();
}
-if (have_option('r')) {
- $resource = get_option_value('r');
-} else if (have_option('--resource')) {
- $resource = get_option_value('--resource');
+if (have_option('i')) {
+ $id = get_option_value('i');
+} else if (have_option('--id')) {
+ $id = get_option_value('--id');
} else if (count($args) > 0) {
- $resource = $args[0];
+ $id = $args[0];
} else {
- $resource = null;
+ $id = null;
}
-$handler = new JabberQueueHandler($resource);
+$handler = new JabberQueueHandler($id);
$handler->runOnce();
diff --git a/scripts/publicqueuehandler.php b/scripts/publicqueuehandler.php
index 58ecc1745..701d50e01 100755
--- a/scripts/publicqueuehandler.php
+++ b/scripts/publicqueuehandler.php
@@ -20,13 +20,13 @@
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
-$shortoptions = 'r::';
-$longoptions = array('resource::');
+$shortoptions = 'i::';
+$longoptions = array('id::');
$helptext = <<<END_OF_PUBLIC_HELP
Daemon script for pushing new notices to public XMPP subscribers.
- -r --resource Jabber Resource ID
+ -i --id Identity (default none)
END_OF_PUBLIC_HELP;
@@ -61,16 +61,16 @@ if (common_config('xmpp','enabled')==false) {
exit();
}
-if (have_option('r')) {
- $resource = get_option_value('r');
-} else if (have_option('--resource')) {
- $resource = get_option_value('--resource');
+if (have_option('i')) {
+ $id = get_option_value('i');
+} else if (have_option('--id')) {
+ $id = get_option_value('--id');
} else if (count($args) > 0) {
- $resource = $args[0];
+ $id = $args[0];
} else {
- $resource = null;
+ $id = null;
}
-$handler = new PublicQueueHandler($resource);
+$handler = new PublicQueueHandler($id);
$handler->runOnce();
diff --git a/scripts/setup.cfg.sample b/scripts/setup.cfg.sample
index dd3c2705f..8d03b06f5 100644
--- a/scripts/setup.cfg.sample
+++ b/scripts/setup.cfg.sample
@@ -1,13 +1,14 @@
# CONFIGURATION FILE for setup_status_network.sh
-# Base database name; full name will include nickname
-
-export DBHOST=masterdb.example.net
+export DBHOST=localhost
+export DBHOSTNAME=masterdb.example.net
export DBBASE=_example_net
export USERBASE=_example_net
export ADMIN=root
export ADMINPASS=yourpassword
export SITEDB=example_net_site
export AVATARBASE=/var/www/avatar.example.net
+export BACKGROUNDBASE=/var/www/background.example.net
+export FILEBASE=/var/www/file.example.net
export PWDGEN="pwgen 20"
diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh
index 29ee010ed..17440640e 100755
--- a/scripts/setup_status_network.sh
+++ b/scripts/setup_status_network.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-source ./setup.cfg
+source /etc/laconica/setup.cfg
export nickname=$1
export sitename=$2
@@ -22,9 +22,11 @@ mysql -h $DBHOST -u $ADMIN --password=$ADMINPASS $SITEDB << ENDOFCOMMANDS
GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'localhost' IDENTIFIED BY '$password';
GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'%' IDENTIFIED BY '$password';
INSERT INTO status_network (nickname, dbhost, dbuser, dbpass, dbname, sitename, created)
-VALUES ('$nickname', '$DBHOST', '$username', '$password', '$database', '$sitename', now());
+VALUES ('$nickname', '$DBHOSTNAME', '$username', '$password', '$database', '$sitename', now());
ENDOFCOMMANDS
-mkdir $AVATARBASE/$nickname
-chmod a+w $AVATARBASE/$nickname
+for top in $AVATARBASE $FILEBASE $BACKGROUNDBASE; do
+ mkdir $top/$nickname
+ chmod a+w $top/$nickname
+done
diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh
index 053c4f8ee..9ead20acd 100755
--- a/scripts/startdaemons.sh
+++ b/scripts/startdaemons.sh
@@ -20,12 +20,27 @@
# This program tries to start the daemons for Laconica.
# Note that the 'maildaemon' needs to run as a mail filter.
+ARGSG=
+ARGSD=
+
+if [ $# -gt 0 ]; then
+ ARGSG="$ARGSG -s$1"
+ ID=`echo $1 | sed s/\\\\./_/g`
+ ARGSD="$ARGSD -s$1 -i$ID"
+fi
+
+if [ $# -gt 1 ]; then
+ ARGSD="$ARGSD -p$2"
+ ARGSG="$ARGSG -p$2"
+fi
+
DIR=`dirname $0`
-DAEMONS=`php $DIR/getvaliddaemons.php`
+DAEMONS=`php $DIR/getvaliddaemons.php $ARGSG`
for f in $DAEMONS; do
- echo -n "Starting $f...";
- php $DIR/$f
- echo "DONE."
+ printf "Starting $f...";
+ php $DIR/$f $ARGSD
+ printf "DONE.\n"
+
done
diff --git a/scripts/xmppconfirmhandler.php b/scripts/xmppconfirmhandler.php
index 883934fd6..d6821ddef 100755
--- a/scripts/xmppconfirmhandler.php
+++ b/scripts/xmppconfirmhandler.php
@@ -20,13 +20,13 @@
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
-$shortoptions = 'r::';
-$longoptions = array('resource::');
+$shortoptions = 'i::';
+$longoptions = array('id::');
$helptext = <<<END_OF_JABBER_HELP
Daemon script for pushing new confirmations to Jabber users.
- -r --resource Jabber Resource ID (default to config)
+ -i --id Identity (default none)
END_OF_JABBER_HELP;
@@ -147,17 +147,17 @@ if (common_config('xmpp','enabled')==false) {
exit();
}
-if (have_option('r')) {
- $resource = get_option_value('r');
-} else if (have_option('--resource')) {
- $resource = get_option_value('--resource');
+if (have_option('i')) {
+ $id = get_option_value('i');
+} else if (have_option('--id')) {
+ $id = get_option_value('--id');
} else if (count($args) > 0) {
- $resource = $args[0];
+ $id = $args[0];
} else {
- $resource = null;
+ $id = null;
}
-$handler = new XmppConfirmHandler($resource);
+$handler = new XmppConfirmHandler($id);
$handler->runOnce();
diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php
index 661631937..3eecfec29 100755
--- a/scripts/xmppdaemon.php
+++ b/scripts/xmppdaemon.php
@@ -20,13 +20,13 @@
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
-$shortoptions = 'r::';
-$longoptions = array('resource::');
+$shortoptions = 'i::';
+$longoptions = array('id::');
$helptext = <<<END_OF_XMPP_HELP
Daemon script for receiving new notices from Jabber users.
- -r --resource Jabber Resource ID (default to config)
+ -i --id Identity (default none)
END_OF_XMPP_HELP;
@@ -52,7 +52,7 @@ class XMPPDaemon extends Daemon
}
if ($resource) {
- $this->resource = $resource;
+ $this->resource = $resource . 'daemon';
} else {
$this->resource = common_config('xmpp', 'resource') . 'daemon';
}
@@ -323,16 +323,16 @@ if (common_config('xmpp','enabled')==false) {
exit();
}
-if (have_option('r')) {
- $resource = get_option_value('r');
-} else if (have_option('--resource')) {
- $resource = get_option_value('--resource');
+if (have_option('i')) {
+ $id = get_option_value('i');
+} else if (have_option('--id')) {
+ $id = get_option_value('--id');
} else if (count($args) > 0) {
- $resource = $args[0];
+ $id = $args[0];
} else {
- $resource = null;
+ $id = null;
}
-$daemon = new XMPPDaemon($resource);
+$daemon = new XMPPDaemon($id);
$daemon->runOnce();
diff --git a/theme/base/css/display.css b/theme/base/css/display.css
index 8957a5b40..78fcd7ece 100644
--- a/theme/base/css/display.css
+++ b/theme/base/css/display.css
@@ -510,13 +510,26 @@ margin-bottom:7px;
margin-left:18px;
float:left;
}
-#form_notice .error {
+#form_notice .error,
+#form_notice .success {
float:left;
clear:both;
-width:96.9%;
+width:81.5%;
margin-bottom:0;
line-height:1.618;
}
+#form_notice #notice_data-attach_selected code {
+float:left;
+width:90%;
+display:block;
+font-size:1.1em;
+line-height:1.8;
+overflow:auto;
+}
+#form_notice #notice_data-attach_selected button {
+float:right;
+font-size:0.8em;
+}
/* entity_profile */
.entity_profile {
@@ -548,7 +561,8 @@ margin-bottom:18px;
.entity_profile .entity_location,
.entity_profile .entity_url,
.entity_profile .entity_note,
-.entity_profile .entity_tags {
+.entity_profile .entity_tags,
+.entity_profile .entity_aliases {
margin-left:113px;
margin-bottom:4px;
}
diff --git a/theme/base/css/ie.css b/theme/base/css/ie.css
index da200388e..43fb01492 100644
--- a/theme/base/css/ie.css
+++ b/theme/base/css/ie.css
@@ -19,6 +19,12 @@ display:block;
width:17%;
max-width:17%;
}
+#form_notice #notice_data-attach_selected {
+width:78.5%;
+}
+#form_notice #notice_data-attach_selected button {
+padding:0 4px;
+}
#anon_notice {
max-width:39%;
}
diff --git a/theme/default/css/display.css b/theme/default/css/display.css
index 7e8b84b4c..89197bddb 100644
--- a/theme/default/css/display.css
+++ b/theme/default/css/display.css
@@ -11,7 +11,7 @@
body,
a:active {
-background-color:#C3D6DF;
+background-color:#CEE1E9;
}
body {
font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
@@ -29,7 +29,7 @@ input, textarea, select,
border-color:#AAAAAA;
}
#filter_tags ul li {
-border-color:#C3D6DF;
+border-color:#DDDDDD;
}
.form_settings input.form_action-primary {
@@ -40,12 +40,12 @@ input.submit,
#form_notice.warning #notice_text-count,
.form_settings .form_note,
.entity_remote_subscribe {
-background-color:#A9BF4F;
+background-color:#9BB43E;
}
input:focus, textarea:focus, select:focus,
#form_notice.warning #notice_data-text {
-border-color:#A9BF4F;
+border-color:#9BB43E;
box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
-moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
-webkit-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
@@ -71,14 +71,14 @@ color:#002E6E;
.notice,
.profile {
-border-top-color:#D1D9E4;
+border-top-color:#C8D1D5;
}
.section .profile {
-border-top-color:#C3D6DF;
+border-top-color:#87B4C8;
}
#aside_primary {
-background-color:#CEE1E9;
+background-color:#C8D1D5;
}
#notice_text-count {
@@ -136,13 +136,13 @@ background-color:#EFF3DC;
}
#anon_notice {
-background-color:#C3D6DF;
+background-color:#87B4C8;
color:#FFFFFF;
border-color:#FFFFFF;
}
#showstream #anon_notice {
-background-color:#A9BF4F;
+background-color:#9BB43E;
}
#export_data li a {
@@ -176,13 +176,13 @@ background-color:transparent;
.form_group_leave input.submit
.form_user_subscribe input.submit,
.form_user_unsubscribe input.submit {
-background-color:#A9BF4F;
+background-color:#9BB43E;
color:#FFFFFF;
}
.form_user_unsubscribe input.submit,
.form_group_leave input.submit,
.form_user_authorization input.reject {
-background-color:#C3D6DF;
+background-color:#87B4C8;
}
.entity_edit a {
@@ -245,7 +245,7 @@ div.notice-options input {
font-family:sans-serif;
}
#content .notices li:hover {
-background-color:#FCFCFC;
+background-color:rgba(240, 240, 240, 0.2);
}
#conversation .notices li:hover {
background-color:transparent;
@@ -272,7 +272,7 @@ background:transparent url(../../base/images/icons/twotone/green/news.gif) no-re
.pagination .nav_prev a,
.pagination .nav_next a {
background-repeat:no-repeat;
-border-color:#D1D9E4;
+border-color:#C8D1D5;
}
.pagination .nav_prev a {
background-image:url(../../base/images/icons/twotone/green/arrow-left.gif);
diff --git a/theme/default/css/ie.css b/theme/default/css/ie.css
index 6501f4e48..cbbd49ce6 100644
--- a/theme/default/css/ie.css
+++ b/theme/default/css/ie.css
@@ -1,14 +1,14 @@
/* IE specific styles */
.notice-options input.submit {
-color:#fff;
+color:#FFFFFF;
}
#site_nav_local_views a {
-background-color:#ACCCDA;
+background-color:#C8D1D5;
}
#form_notice .form_note + label {
background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%;
}
#form_notice #notice_data-attach {
filter: alpha(opacity=0);
-} \ No newline at end of file
+}
diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css
index 09ad4c972..025debf34 100644
--- a/theme/identica/css/display.css
+++ b/theme/identica/css/display.css
@@ -245,7 +245,7 @@ div.notice-options input {
font-family:sans-serif;
}
#content .notices li:hover {
-background-color:#FCFCFC;
+background-color:rgba(240, 240, 240, 0.2);
}
#conversation .notices li:hover {
background-color:transparent;
diff --git a/theme/identica/css/ie.css b/theme/identica/css/ie.css
index 69db16aad..97cabc30a 100644
--- a/theme/identica/css/ie.css
+++ b/theme/identica/css/ie.css
@@ -1,14 +1,14 @@
/* IE specific styles */
.notice-options input.submit {
-color:#fff;
+color:#FFFFFF;
}
#site_nav_local_views a {
-background-color:#D0DFE7;
+background-color:#D9DADB;
}
#form_notice .form_note + label {
background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%;
}
#form_notice #notice_data-attach {
filter: alpha(opacity=0);
-} \ No newline at end of file
+}