diff --git a/actions/showstream.php b/actions/showstream.php
index c736c99b5d..65482167e1 100644
--- a/actions/showstream.php
+++ b/actions/showstream.php
@@ -292,11 +292,11 @@ class ShowstreamAction extends Action
$this->elementStart('ul', 'tags xoxo');
foreach ($tags as $tag) {
$this->elementStart('li');
- $this->element('span', 'mark_hash', '#');
- $this->element('a', array('rel' => 'tag',
- 'href' => common_local_url('peopletag',
- array('tag' => $tag))),
- $tag);
+ // Avoid space by using raw output.
+ $pt = '#' . $tag . '';
+ $this->raw($pt);
$this->elementEnd('li');
}
$this->elementEnd('ul');
diff --git a/config.php.sample b/config.php.sample
index da31545074..6e55eaffc8 100644
--- a/config.php.sample
+++ b/config.php.sample
@@ -18,6 +18,8 @@ $config['site']['server'] = 'localhost';
$config['site']['path'] = 'laconica';
#$config['site']['fancy'] = false;
#$config['site']['theme'] = 'default';
+#To enable the built-in mobile style sheet, defaults to false.
+#$config['site']['mobile'] = true;
#For contact email, defaults to $_SERVER["SERVER_ADMIN"]
#$config['site']['email'] = 'admin@example.net';
#Brought by...
diff --git a/lib/action.php b/lib/action.php
index 79e8c95471..b1e700b670 100644
--- a/lib/action.php
+++ b/lib/action.php
@@ -158,8 +158,6 @@ class Action extends HTMLOutputter // lawsuit
'type' => 'text/css',
'href' => theme_path('css/display.css', 'base') . '?version=' . LACONICA_VERSION,
'media' => 'screen, projection, tv'));
-
-
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
'href' => theme_path('css/modal.css', 'base') . '?version=' . LACONICA_VERSION,
@@ -168,6 +166,13 @@ class Action extends HTMLOutputter // lawsuit
'type' => 'text/css',
'href' => theme_path('css/display.css', null) . '?version=' . LACONICA_VERSION,
'media' => 'screen, projection, tv'));
+ if (common_config('site', 'mobile')) {
+ $this->element('link', array('rel' => 'stylesheet',
+ 'type' => 'text/css',
+ 'href' => theme_path('css/mobile.css', 'base') . '?version=' . LACONICA_VERSION,
+ // TODO: "handheld" CSS for other mobile devices
+ 'media' => 'only screen and (max-device-width: 480px)')); // Mobile WebKit
+ }
Event::handle('EndShowLaconicaStyles', array($this));
}
if (Event::handle('StartShowUAStyles', array($this))) {
@@ -204,12 +209,10 @@ class Action extends HTMLOutputter // lawsuit
'src' => common_path('js/jquery.form.js')),
' ');
-
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/jquery.simplemodal-1.2.2.pack.js')),
' ');
-
Event::handle('EndShowJQueryScripts', array($this));
}
if (Event::handle('StartShowLaconicaScripts', array($this))) {
@@ -219,7 +222,9 @@ class Action extends HTMLOutputter // lawsuit
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/util.js?version='.LACONICA_VERSION)),
' ');
-
+ // Frame-busting code to avoid clickjacking attacks.
+ $this->element('script', array('type' => 'text/javascript'),
+ 'if (window.top !== window.self) { window.top.location.href = window.self.location.href; }');
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/flowplayer-3.0.5.min.js')),
@@ -228,9 +233,6 @@ class Action extends HTMLOutputter // lawsuit
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/video.js')),
' ');
-
-
-
Event::handle('EndShowLaconicaScripts', array($this));
}
Event::handle('EndShowScripts', array($this));
@@ -809,8 +811,10 @@ class Action extends HTMLOutputter // lawsuit
if ($if_modified_since) {
$ims = strtotime($if_modified_since);
if ($lm <= $ims) {
- if (!$etag ||
- $this->_hasEtag($etag, $_SERVER['HTTP_IF_NONE_MATCH'])) {
+ $if_none_match = $_SERVER['HTTP_IF_NONE_MATCH'];
+ if (!$if_none_match ||
+ !$etag ||
+ $this->_hasEtag($etag, $if_none_match)) {
header('HTTP/1.1 304 Not Modified');
// Better way to do this?
exit(0);
@@ -828,9 +832,11 @@ class Action extends HTMLOutputter // lawsuit
*
* @return boolean
*/
+
function _hasEtag($etag, $if_none_match)
{
- return ($if_none_match) && in_array($etag, explode(',', $if_none_match));
+ $etags = explode(',', $if_none_match);
+ return in_array($etag, $etags) || in_array('*', $etags);
}
/**
diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php
index 01fe8914f1..ef3f8c63d8 100755
--- a/scripts/xmppdaemon.php
+++ b/scripts/xmppdaemon.php
@@ -208,6 +208,8 @@ class XMPPDaemon extends Daemon
{
if (preg_match('/[\[\(]?[Aa]uto[-\s]?[Rr]e(ply|sponse)[\]\)]/', $txt)) {
return true;
+ } else if (preg_match('/^System: Message wasn\'t delivered. Offline storage size was exceeded.$/', $txt)) {
+ return true;
} else {
return false;
}
diff --git a/theme/base/css/mobile.css b/theme/base/css/mobile.css
new file mode 100644
index 0000000000..3d0455a673
--- /dev/null
+++ b/theme/base/css/mobile.css
@@ -0,0 +1,72 @@
+/** theme: base
+ *
+ * @package Laconica
+ * @author Meitar Moscovitz
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+/* Go linear. */
+#header,
+#header address,
+#site_nav_global_primary,
+#anon_notice,
+#site_nav_local_views .nav,
+#form_notice,
+#form_notice .form_data li,
+#core,
+#content_inner,
+#notices_primary,
+.notice,
+.notice .entry-title,
+.notice div.entry-content,
+.notice-options,
+.notice .notice-options a,
+.pagination,
+.pagination .nav,
+.aside .section { float: none; }
+
+.notice-options .notice_reply,
+.notice-options .notice_delete,
+.notice-options .form_favor,
+.notice-options .form_disfavor { position: static; }
+
+#form_notice,
+#anon_notice,
+#content_inner,
+#footer { width: auto; }
+
+/* And liquid. */
+#wrap { width: 95%; }
+
+/* Make things bigger on smaller screens. */
+body { font-size: 2em; }
+.notices { font-size: 1.5em; }
+
+#site_nav_global_primary, #site_nav_global_secondary { text-align: center; }
+
+.notice div.entry-content { margin-left: 0; }
+address { margin: 0; }
+
+#anon_notice, #footer { clear: left; font-size: .5em; }
+
+#form_notice textarea { width: 80%; height: 5em; }
+#form_notice .form_note { right: 20%; top: 6em; }
+#form_notice .form_actions input.submit { width: auto; }
+
+#content { padding: 18px 0; width: 100%; }
+#content h1, #page_notice, #content_inner { padding: 0 18px; }
+.notices .entry-title, .notices div.entry-content { width: 90%; }
+.notice .author .photo { height: 4.5em; width: 4.5em; } /* about double physical size; TODO: do this scaling better */
+.notice-options { position: absolute; top: 0; right: 0; padding-left: 7%; width: 3%; }
+.notice-options .notice_delete a { float: left; } /* Works, but feels like it shouldn't. */
+/* TODO: Make the icons of the notice options bigger. Probably with mobile-specific images. */
+.pagination .nav { overflow: auto; }
+
+#aside_primary { margin: 10px 0 0 0; border: none; padding: 0; width: 100%; }
+#popular_notices { float: none; width: auto; }
+/* Columns for supplemental info. */
+.aside .section { clear: none; padding: 9px; width: 45%; }
+#top_groups_by_post { float: left; }
+#featured_users { float: right; }
+#export_data { display: none; }