summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/accountsettingsaction.php3
-rw-r--r--lib/action.php8
-rw-r--r--lib/common.php5
-rw-r--r--lib/noticelist.php17
-rw-r--r--lib/queuehandler.php72
-rw-r--r--lib/router.php8
-rw-r--r--lib/theme.php29
-rw-r--r--lib/twitter.php2
-rw-r--r--lib/util.php98
9 files changed, 191 insertions, 51 deletions
diff --git a/lib/accountsettingsaction.php b/lib/accountsettingsaction.php
index 46090b8c1..86800d2a3 100644
--- a/lib/accountsettingsaction.php
+++ b/lib/accountsettingsaction.php
@@ -115,6 +115,9 @@ class AccountSettingsNav extends Widget
'openidsettings' =>
array(_('OpenID'),
_('Add or remove OpenIDs')),
+ 'designsettings' =>
+ array(_('Design'),
+ _('Design your profile')),
'othersettings' =>
array(_('Other'),
_('Other options')));
diff --git a/lib/action.php b/lib/action.php
index 6b130b6d5..bab987de6 100644
--- a/lib/action.php
+++ b/lib/action.php
@@ -861,10 +861,12 @@ class Action extends HTMLOutputter // lawsuit
}
if ($lm) {
header('Last-Modified: ' . date(DATE_RFC1123, $lm));
- if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
- $ims = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
+ if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) {
+ $if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
+ $ims = strtotime($if_modified_since);
if ($lm <= $ims) {
- $if_none_match = $_SERVER['HTTP_IF_NONE_MATCH'];
+ $if_none_match = (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) ?
+ $_SERVER['HTTP_IF_NONE_MATCH'] : null;
if (!$if_none_match ||
!$etag ||
$this->_hasEtag($etag, $if_none_match)) {
diff --git a/lib/common.php b/lib/common.php
index f983c4d16..3feba1d8b 100644
--- a/lib/common.php
+++ b/lib/common.php
@@ -19,7 +19,7 @@
if (!defined('LACONICA')) { exit(1); }
-define('LACONICA_VERSION', '0.7.3');
+define('LACONICA_VERSION', '0.8.0dev');
define('AVATAR_PROFILE_SIZE', 96);
define('AVATAR_STREAM_SIZE', 48);
@@ -71,6 +71,7 @@ $config =
array('name' => 'Just another Laconica microblog',
'server' => $_server,
'theme' => 'default',
+ 'skin' => 'default',
'path' => $_path,
'logfile' => null,
'logo' => null,
@@ -142,6 +143,8 @@ $config =
array('piddir' => '/var/run',
'user' => false,
'group' => false),
+ 'twitterbridge' =>
+ array('enabled' => false),
'integration' =>
array('source' => 'Laconica', # source attribute for Twitter
'taguri' => $_server.',2009'), # base for tag URIs
diff --git a/lib/noticelist.php b/lib/noticelist.php
index 4182d8808..8fccba73e 100644
--- a/lib/noticelist.php
+++ b/lib/noticelist.php
@@ -197,7 +197,7 @@ class NoticeListItem extends Widget
$this->out->elementStart('div', 'entry-content');
$this->showNoticeLink();
$this->showNoticeSource();
- $this->showReplyTo();
+ $this->showContext();
$this->out->elementEnd('div');
}
@@ -421,17 +421,18 @@ class NoticeListItem extends Widget
* @return void
*/
- function showReplyTo()
+ function showContext()
{
- if ($this->notice->reply_to) {
- $replyurl = common_local_url('shownotice',
- array('notice' => $this->notice->reply_to));
+ // XXX: also show context if there are replies to this notice
+ if (!empty($this->notice->conversation)
+ && $this->notice->conversation != $this->notice->id) {
+ $convurl = common_local_url('conversation',
+ array('id' => $this->notice->conversation));
$this->out->elementStart('dl', 'response');
$this->out->element('dt', null, _('To'));
$this->out->elementStart('dd');
- $this->out->element('a', array('href' => $replyurl,
- 'rel' => 'in-reply-to'),
- _('in reply to'));
+ $this->out->element('a', array('href' => $convurl),
+ _('in context'));
$this->out->elementEnd('dd');
$this->out->elementEnd('dl');
}
diff --git a/lib/queuehandler.php b/lib/queuehandler.php
index fde650d9e..f76f16e07 100644
--- a/lib/queuehandler.php
+++ b/lib/queuehandler.php
@@ -75,15 +75,9 @@ class QueueHandler extends Daemon
return true;
}
- function run()
- {
- if (!$this->start()) {
- return false;
- }
- $transport = $this->transport();
- $this->log(LOG_INFO, 'checking for queued notices for "' . $transport . '"');
+ function db_dispatch() {
do {
- $qi = Queue_item::top($transport);
+ $qi = Queue_item::top($this->transport());
if ($qi) {
$this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($qi->created));
$notice = Notice::staticGet($qi->notice_id);
@@ -115,6 +109,67 @@ class QueueHandler extends Daemon
$this->idle(5);
}
} while (true);
+ }
+
+ function stomp_dispatch() {
+ require("Stomp.php");
+ $con = new Stomp(common_config('queue','stomp_server'));
+ if (!$con->connect()) {
+ $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());
+
+ do {
+ $frame = $con->readFrame();
+ if ($frame) {
+ $this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($frame->headers['created']));
+
+ // XXX: Now the queue handler receives only the ID of the
+ // notice, and it has to get it from the DB
+ // A massive improvement would be avoid DB query by transmitting
+ // all the notice details via queue server...
+ $notice = Notice::staticGet($frame->body);
+
+ if ($notice) {
+ $this->log(LOG_INFO, 'broadcasting notice ID = ' . $notice->id);
+ $result = $this->handle_notice($notice);
+ if ($result) {
+ // if the msg has been handled positively, ack it
+ // and the queue server will remove it from the queue
+ $con->ack($frame);
+ $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id);
+ }
+ else {
+ // no ack
+ $this->log(LOG_WARNING, 'Failed broadcast for notice ID = ' . $notice->id);
+ }
+ $notice->free();
+ unset($notice);
+ $notice = null;
+ } else {
+ $this->log(LOG_WARNING, 'queue item for notice that does not exist');
+ }
+ }
+ } while (true);
+
+ $con->disconnect();
+ }
+
+ function run()
+ {
+ if (!$this->start()) {
+ return false;
+ }
+ $this->log(LOG_INFO, 'checking for queued notices');
+ if (common_config('queue','subsystem') == 'stomp') {
+ $this->stomp_dispatch();
+ }
+ else {
+ $this->db_dispatch();
+ }
if (!$this->finish()) {
return false;
}
@@ -143,3 +198,4 @@ class QueueHandler extends Daemon
common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg);
}
}
+
diff --git a/lib/router.php b/lib/router.php
index 12590b790..9308c818a 100644
--- a/lib/router.php
+++ b/lib/router.php
@@ -131,7 +131,7 @@ class Router
// settings
foreach (array('profile', 'avatar', 'password', 'openid', 'im',
- 'email', 'sms', 'twitter', 'other') as $s) {
+ 'email', 'sms', 'twitter', 'design', 'other') as $s) {
$m->connect('settings/'.$s, array('action' => $s.'settings'));
}
@@ -165,6 +165,12 @@ class Router
array('action' => 'deletenotice'),
array('notice' => '[0-9]+'));
+ // conversation
+
+ $m->connect('conversation/:id',
+ array('action' => 'conversation'),
+ array('id' => '[0-9]+'));
+
$m->connect('message/new', array('action' => 'newmessage'));
$m->connect('message/new?to=:to', array('action' => 'newmessage'), array('to' => '[A-Za-z0-9_-]+'));
$m->connect('message/:message',
diff --git a/lib/theme.php b/lib/theme.php
index 95030affe..bef660cbf 100644
--- a/lib/theme.php
+++ b/lib/theme.php
@@ -69,4 +69,31 @@ function theme_path($relative, $theme=null)
} else {
return common_path('theme/'.$theme.'/'.$relative);
}
-} \ No newline at end of file
+}
+
+/**
+ * Gets the full URL of a file in a skin dir based on its relative name
+ *
+ * @param string $relative relative path within the theme, skin directory
+ * @param string $theme name of the theme; defaults to current theme
+ * @param string $skin name of the skin; defaults to current theme
+ *
+ * @return string URL of the file
+ */
+
+function skin_path($relative, $theme=null, $skin=null)
+{
+ if (!$theme) {
+ $theme = common_config('site', 'theme');
+ }
+ if (!$skin) {
+ $skin = common_config('site', 'skin');
+ }
+ $server = common_config('theme', 'server');
+ if ($server) {
+ return 'http://'.$server.'/'.$theme.'/skin/'.$skin.'/'.$relative;
+ } else {
+ return common_path('theme/'.$theme.'/skin/'.$skin.'/'.$relative);
+ }
+}
+
diff --git a/lib/twitter.php b/lib/twitter.php
index ccc6c93ca..c1d0dc254 100644
--- a/lib/twitter.php
+++ b/lib/twitter.php
@@ -346,7 +346,7 @@ function save_twitter_friends($user, $twitter_id, $screen_name, $password)
function is_twitter_bound($notice, $flink) {
// Check to see if notice should go to Twitter
- if ($flink->noticesync & FOREIGN_NOTICE_SEND) {
+ if (!empty($flink) && ($flink->noticesync & FOREIGN_NOTICE_SEND)) {
// If it's not a Twitter-style reply, or if the user WANTS to send replies.
if (!preg_match('/^@[a-zA-Z0-9_]{1,15}\b/u', $notice->content) ||
diff --git a/lib/util.php b/lib/util.php
index f862d7fcc..198185338 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -879,34 +879,76 @@ function common_broadcast_notice($notice, $remote=false)
function common_enqueue_notice($notice)
{
- $transports = array('omb', 'sms', 'twitter', 'facebook', 'ping');
-
- if (common_config('xmpp', 'enabled')) {
- $transports = array_merge($transports, array('jabber', 'public'));
- }
-
- if (common_config('memcached', 'enabled')) {
- // Note: limited to 8 chars
- $transports[] = 'memcache';
- }
-
- if (common_config('inboxes', 'enabled') === true ||
- common_config('inboxes', 'enabled') === 'transitional') {
- $transports[] = 'inbox';
- }
-
- foreach ($transports 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;
+ 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;
+ }
+ 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_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport);
}
return $result;
}
@@ -1115,7 +1157,7 @@ function common_accept_to_prefs($accept, $def = '*/*')
foreach($parts as $part) {
// FIXME: doesn't deal with params like 'text/html; level=1'
- @list($value, $qpart) = explode(';', $part);
+ @list($value, $qpart) = explode(';', trim($part));
$match = array();
if(!isset($qpart)) {
$prefs[$value] = 1;