summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README26
-rw-r--r--actions/attachment.php12
-rw-r--r--actions/attachment_ajax.php22
-rw-r--r--actions/attachment_thumbnail.php (renamed from actions/attachments_ajax.php)87
-rw-r--r--actions/attachments.php292
-rw-r--r--actions/tag.php2
-rw-r--r--config.php.sample9
-rw-r--r--db/notice_source.sql1
-rw-r--r--index.php4
-rw-r--r--install.php18
-rw-r--r--js/util.js50
-rw-r--r--lib/attachmentlist.php31
-rw-r--r--lib/attachmentsection.php80
-rw-r--r--lib/common.php4
-rw-r--r--lib/facebookaction.php8
-rw-r--r--lib/frequentattachmentsection.php66
-rw-r--r--lib/noticelist.php52
-rw-r--r--lib/router.php17
-rw-r--r--lib/snapshot.php227
-rw-r--r--lib/util.php21
-rw-r--r--scripts/reportsnapshot.php37
-rw-r--r--theme/base/css/display.css35
-rw-r--r--theme/base/css/facebookapp.css3
-rw-r--r--theme/base/images/icons/clip-inline.pngbin0 -> 1646 bytes
-rw-r--r--theme/default/css/display.css12
-rw-r--r--theme/identica/css/display.css12
26 files changed, 492 insertions, 636 deletions
diff --git a/README b/README
index 4f9382960..9207f3e90 100644
--- a/README
+++ b/README
@@ -1136,6 +1136,32 @@ welcome: nickname of a user account that sends welcome messages to new
If either of these special user accounts are specified, the users should
be created before the configuration is updated.
+snapshot
+--------
+
+The software will, by default, send statistical snapshots about the
+local installation to a stats server on the laconi.ca Web site. This
+data is used by the developers to prioritize development decisions. No
+identifying data about users or organizations is collected. The data
+is available to the public for review. Participating in this survey
+helps Laconica developers take your needs into account when updating
+the software.
+
+run: string indicating when to run the statistics. Values can be 'web'
+ (run occasionally at Web time), 'cron' (run from a cron script),
+ or 'never' (don't ever run). If you set it to 'cron', remember to
+ schedule the script to run on a regular basis.
+frequency: if run value is 'web', how often to report statistics.
+ Measured in Web hits; depends on how active your site is.
+ Default is 10000 -- that is, one report every 10000 Web hits,
+ on average.
+reporturl: URL to post statistics to. Defaults to Laconica developers'
+ report system, but if they go evil or disappear you may
+ need to update this to another value. Note: if you
+ don't want to report stats, it's much better to
+ set 'run' to 'never' than to set this value to something
+ nonsensical.
+
Troubleshooting
===============
diff --git a/actions/attachment.php b/actions/attachment.php
index b9187ff08..16ee723d9 100644
--- a/actions/attachment.php
+++ b/actions/attachment.php
@@ -31,8 +31,6 @@ if (!defined('LACONICA')) {
exit(1);
}
-//require_once INSTALLDIR.'/lib/personalgroupnav.php';
-//require_once INSTALLDIR.'/lib/feedlist.php';
require_once INSTALLDIR.'/lib/attachmentlist.php';
/**
@@ -67,11 +65,11 @@ class AttachmentAction extends Action
{
parent::prepare($args);
- $id = $this->arg('attachment');
-
- $this->attachment = File::staticGet($id);
+ if ($id = $this->trimmed('attachment')) {
+ $this->attachment = File::staticGet($id);
+ }
- if (!$this->attachment) {
+ if (empty($this->attachment)) {
$this->clientError(_('No such attachment.'), 404);
return false;
}
@@ -178,10 +176,8 @@ class AttachmentAction extends Action
function showContent()
{
- $this->elementStart('ul', array('class' => 'attachments'));
$ali = new Attachment($this->attachment, $this);
$cnt = $ali->show();
- $this->elementEnd('ul');
}
/**
diff --git a/actions/attachment_ajax.php b/actions/attachment_ajax.php
index 1620b27dd..3d83393c5 100644
--- a/actions/attachment_ajax.php
+++ b/actions/attachment_ajax.php
@@ -46,26 +46,6 @@ require_once INSTALLDIR.'/actions/attachment.php';
class Attachment_ajaxAction extends AttachmentAction
{
/**
- * 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 (!$this->attachment) {
- $this->clientError(_('No such attachment.'), 404);
- return false;
- }
- return true;
- }
-
- /**
* Show page, a template method.
*
* @return nothing
@@ -95,8 +75,6 @@ class Attachment_ajaxAction extends AttachmentAction
$this->elementEnd('div');
}
-
-
/**
* Last-modified date for page
*
diff --git a/actions/attachments_ajax.php b/actions/attachment_thumbnail.php
index 402d8b5e7..b4070e747 100644
--- a/actions/attachments_ajax.php
+++ b/actions/attachment_thumbnail.php
@@ -31,9 +31,7 @@ if (!defined('LACONICA')) {
exit(1);
}
-//require_once INSTALLDIR.'/lib/personalgroupnav.php';
-//require_once INSTALLDIR.'/lib/feedlist.php';
-require_once INSTALLDIR.'/actions/attachments.php';
+require_once INSTALLDIR.'/actions/attachment.php';
/**
* Show notice attachments
@@ -45,39 +43,8 @@ require_once INSTALLDIR.'/actions/attachments.php';
* @link http://laconi.ca/
*/
-class Attachments_ajaxAction extends AttachmentsAction
+class Attachment_thumbnailAction extends AttachmentAction
{
- function showContent()
- {
- }
-
- /**
- * Fill the content area of the page
- *
- * Shows a single notice list item.
- *
- * @return void
- */
-
- function showContentBlock()
- {
- $al = new AttachmentList($this->notice, $this);
- $cnt = $al->show();
- }
-
- /**
- * Extra <head> content
- *
- * We show the microid(s) for the author, if any.
- *
- * @return void
- */
-
- function extraHead()
- {
- }
-
-
/**
* Show page, a template method.
*
@@ -100,16 +67,52 @@ class Attachments_ajaxAction extends AttachmentsAction
*/
function showCore()
{
- $this->elementStart('div', array('id' => 'core'));
- if (Event::handle('StartShowContentBlock', array($this))) {
- $this->showContentBlock();
- Event::handle('EndShowContentBlock', array($this));
+ $file_thumbnail = File_thumbnail::staticGet('file_id', $this->attachment->id);
+ if (empty($file_thumbnail->url)) {
+ return;
}
- $this->elementEnd('div');
+ $this->element('img', array('src' => $file_thumbnail->url, 'alt' => 'Thumbnail'));
}
+ /**
+ * Last-modified date for page
+ *
+ * When was the content of this page last modified? Based on notice,
+ * profile, avatar.
+ *
+ * @return int last-modified date as unix timestamp
+ */
+/*
+ function lastModified()
+ {
+ return max(strtotime($this->notice->created),
+ strtotime($this->profile->modified),
+ ($this->avatar) ? strtotime($this->avatar->modified) : 0);
+ }
+*/
-
-
+ /**
+ * An entity tag for this page
+ *
+ * Shows the ETag for the page, based on the notice ID and timestamps
+ * for the notice, profile, and avatar. It's weak, since we change
+ * the date text "one hour ago", etc.
+ *
+ * @return string etag
+ */
+/*
+ function etag()
+ {
+ $avtime = ($this->avatar) ?
+ strtotime($this->avatar->modified) : 0;
+
+ return 'W/"' . implode(':', array($this->arg('action'),
+ common_language(),
+ $this->notice->id,
+ strtotime($this->notice->created),
+ strtotime($this->profile->modified),
+ $avtime)) . '"';
+ }
+*/
}
diff --git a/actions/attachments.php b/actions/attachments.php
deleted file mode 100644
index 6b31c839d..000000000
--- a/actions/attachments.php
+++ /dev/null
@@ -1,292 +0,0 @@
-<?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/personalgroupnav.php';
-//require_once INSTALLDIR.'/lib/feedlist.php';
-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 AttachmentsAction extends Action
-{
- /**
- * Notice object to show
- */
-
- var $notice = null;
-
- /**
- * Profile of the notice object
- */
-
- var $profile = null;
-
- /**
- * Avatar of the profile of the notice object
- */
-
- var $avatar = null;
-
- /**
- * Is this action read-only?
- *
- * @return boolean true
- */
-
- function isReadOnly($args)
- {
- return true;
- }
-
- /**
- * Last-modified date for page
- *
- * When was the content of this page last modified? Based on notice,
- * profile, avatar.
- *
- * @return int last-modified date as unix timestamp
- */
-
- function lastModified()
- {
- return max(strtotime($this->notice->created),
- strtotime($this->profile->modified),
- ($this->avatar) ? strtotime($this->avatar->modified) : 0);
- }
-
- /**
- * An entity tag for this page
- *
- * Shows the ETag for the page, based on the notice ID and timestamps
- * for the notice, profile, and avatar. It's weak, since we change
- * the date text "one hour ago", etc.
- *
- * @return string etag
- */
-
- function etag()
- {
- $avtime = ($this->avatar) ?
- strtotime($this->avatar->modified) : 0;
-
- return 'W/"' . implode(':', array($this->arg('action'),
- common_language(),
- $this->notice->id,
- strtotime($this->notice->created),
- strtotime($this->profile->modified),
- $avtime)) . '"';
- }
-
- /**
- * Title of the page
- *
- * @return string title of the page
- */
-
- function title()
- {
- return sprintf(_('%1$s\'s status on %2$s'),
- $this->profile->nickname,
- common_exact_date($this->notice->created));
- }
-
-
- /**
- * 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);
-
- $id = $this->arg('notice');
-
- $this->notice = Notice::staticGet($id);
-
- if (!$this->notice) {
- $this->clientError(_('No such notice.'), 404);
- return false;
- }
-
-
-/*
-// STOP if there are no attachments
-// maybe even redirect if there's a single one
-// RYM FIXME TODO
- $this->clientError(_('No such attachment.'), 404);
- return false;
-
-*/
-
-
-
-
- $this->profile = $this->notice->getProfile();
-
- if (!$this->profile) {
- $this->serverError(_('Notice has no profile'), 500);
- return false;
- }
-
- $this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
- return true;
- }
-
-
-
- /**
- * 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 ($this->notice->is_local == 0) {
- if (!empty($this->notice->url)) {
- common_redirect($this->notice->url, 301);
- } else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) {
- common_redirect($this->notice->uri, 301);
- }
- } else {
- $f2p = new File_to_post;
- $f2p->post_id = $this->notice->id;
- $file = new File;
- $file->joinAdd($f2p);
- $file->selectAdd();
- $file->selectAdd('file.id as id');
- $count = $file->find(true);
- if (!$count) return;
- if (1 === $count) {
- common_redirect(common_local_url('attachment', array('attachment' => $file->id)), 301);
- } 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()
- {
- $al = new AttachmentList($this->notice, $this);
- $cnt = $al->show();
- }
-
- /**
- * Don't show page notice
- *
- * @return void
- */
-
- function showPageNoticeBlock()
- {
- }
-
- /**
- * Don't show aside
- *
- * @return void
- */
-
- function showAside() {
- }
-
- /**
- * Extra <head> content
- *
- * We show the microid(s) for the author, if any.
- *
- * @return void
- */
-
- function extraHead()
- {
- $user = User::staticGet($this->profile->id);
-
- if (!$user) {
- return;
- }
-
- if ($user->emailmicroid && $user->email && $this->notice->uri) {
- $id = new Microid('mailto:'. $user->email,
- $this->notice->uri);
- $this->element('meta', array('name' => 'microid',
- 'content' => $id->toString()));
- }
-
- if ($user->jabbermicroid && $user->jabber && $this->notice->uri) {
- $id = new Microid('xmpp:', $user->jabber,
- $this->notice->uri);
- $this->element('meta', array('name' => 'microid',
- 'content' => $id->toString()));
- }
- }
-}
-
diff --git a/actions/tag.php b/actions/tag.php
index 47420e4c3..e9351d241 100644
--- a/actions/tag.php
+++ b/actions/tag.php
@@ -49,8 +49,6 @@ class TagAction extends Action
{
$pop = new PopularNoticeSection($this);
$pop->show();
- $freqatt = new FrequentAttachmentSection($this);
- $freqatt->show();
}
function title()
diff --git a/config.php.sample b/config.php.sample
index 4f438dc5e..282826a7f 100644
--- a/config.php.sample
+++ b/config.php.sample
@@ -206,3 +206,12 @@ $config['sphinx']['port'] = 3312;
// print "Error\n";
// exit(1);
// }
+
+// How often to send snapshots; in # of web hits. Ideally,
+// try to do this once per month (that is, make this equal to number
+// of hits per month)
+// $config['snapshot']['frequency'] = 10000;
+// If you don't want to report statistics to the central server, uncomment.
+// $config['snapshot']['run'] = 'never';
+// If you want to report statistics in a cron job instead.
+// $config['snapshot']['run'] = 'cron';
diff --git a/db/notice_source.sql b/db/notice_source.sql
index f026679d5..f351bb066 100644
--- a/db/notice_source.sql
+++ b/db/notice_source.sql
@@ -9,6 +9,7 @@ VALUES
('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()),
('Facebook','Facebook','http://apps.facebook.com/identica/', now()),
('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()),
+ ('gravity', 'Gravity', 'http://mobileways.de/gravity', now()),
('Gwibber','Gwibber','http://launchpad.net/gwibber', now()),
('HelloTxt','HelloTxt','http://hellotxt.com/', now()),
('identicatools','Laconica Tools','http://bitbucketlabs.net/laconica-tools/', now()),
diff --git a/index.php b/index.php
index 9ff1c2c56..4eff99dff 100644
--- a/index.php
+++ b/index.php
@@ -64,11 +64,13 @@ function handleError($error)
function main()
{
// quick check for fancy URL auto-detection support in installer.
- if (isset($_SERVER['REDIRECT_URL']) && ('/check-fancy' === $_SERVER['REDIRECT_URL'])) {
+ if (isset($_SERVER['REDIRECT_URL']) && ((dirname($_SERVER['REQUEST_URI']) . '/check-fancy') === $_SERVER['REDIRECT_URL'])) {
die("Fancy URL support detection succeeded. We suggest you enable this to get fancy (pretty) URLs.");
}
global $user, $action, $config;
+ Snapshot::check();
+
if (!_have_config()) {
$msg = sprintf(_("No configuration file found. Try running ".
"the installation program first."));
diff --git a/install.php b/install.php
index bc82e5e37..133f2b30f 100644
--- a/install.php
+++ b/install.php
@@ -117,16 +117,16 @@ function showForm()
<p class="form_guide" id='fancy-form_guide'>Enable fancy (pretty) URLs. Auto-detection failed, it depends on Javascript.</p>
</li>
<li>
- <label for="host">Hostname</label>
- <input type="text" id="host" name="host" />
- <p class="form_guide">Database hostname</p>
- </li>
- <li>
<label for="host">Site path</label>
<input type="text" id="path" name="path" value="$config_path" />
<p class="form_guide">Site path, following the "/" after the domain name in the URL. Empty is fine. Field should be filled automatically.</p>
</li>
<li>
+ <label for="host">Hostname</label>
+ <input type="text" id="host" name="host" />
+ <p class="form_guide">Database hostname</p>
+ </li>
+ <li>
<label for="host">Database</label>
<input type="text" id="database" name="database" />
<p class="form_guide">Database name</p>
@@ -295,13 +295,13 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
<head>
<title>Install Laconica</title>
- <link rel="stylesheet" type="text/css" href="theme/base/css/display.css?version=0.8" media="screen, projection, tv"/>
+ <link rel="shortcut icon" href="favicon.ico"/>
<link rel="stylesheet" type="text/css" href="theme/default/css/display.css?version=0.8" media="screen, projection, tv"/>
<!--[if IE]><link rel="stylesheet" type="text/css" href="theme/base/css/ie.css?version=0.8" /><![endif]-->
<!--[if lte IE 6]><link rel="stylesheet" type="text/css" theme/base/css/ie6.css?version=0.8" /><![endif]-->
- <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/earthy/css/ie.css?version=0.8" /><![endif]-->
- <script src='js/jquery.min.js'></script>
- <script src='js/install.js'></script>
+ <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/default/css/ie.css?version=0.8" /><![endif]-->
+ <script src="js/jquery.min.js"></script>
+ <script src="js/install.js"></script>
</head>
<body id="install">
<div id="wrap">
diff --git a/js/util.js b/js/util.js
index 31d9eb4f5..b1b6ec82b 100644
--- a/js/util.js
+++ b/js/util.js
@@ -17,9 +17,29 @@
*/
$(document).ready(function(){
- $('.attachments').click(function() {$().jOverlay({zIndex:999, success:function(html) {$('.attachment').click(function() {$().jOverlay({url:$(this).attr('href') + '/ajax'}); return false; });
- }, url:$(this).attr('href') + '/ajax'}); return false; });
- $('.attachment').click(function() {$().jOverlay({url:$(this).attr('href') + '/ajax'}); return false; });
+ $('a.attachment').click(function() {$().jOverlay({url: $('address .url')[0].href+'/attachment/' + ($(this).attr('id').substring('attachment'.length + 1)) + '/ajax'}); return false; });
+ $("a.thumbnail").hover(
+ function() {
+ var anchor = $(this);
+ $("a.thumbnail").children('img').remove();
+
+ setTimeout(function() {
+ anchor.closest(".entry-title").addClass('ov');
+ $.get($('address .url')[0].href+'/attachment/' + (anchor.attr('id').substring('attachment'.length + 1)) + '/thumbnail', null, function(data) {
+ anchor.append(data);
+ });
+ }, 250);
+
+ setTimeout(function() {
+ anchor.children('img').remove();
+ anchor.closest(".entry-title").removeClass('ov');
+ }, 3000);
+ },
+ function() {
+ $(this).children('img').remove();
+ $(this).closest(".entry-title").removeClass('ov');
+ }
+ );
// count character on keyup
function counter(event){
@@ -203,7 +223,6 @@ $(document).ready(function(){
$("#notices_primary .notices").prepend(document._importNode(li, true));
$("#notices_primary .notice:first").css({display:"none"});
$("#notices_primary .notice:first").fadeIn(2500);
- NoticeHover();
NoticeReply();
}
}
@@ -221,24 +240,23 @@ $(document).ready(function(){
NoticeReply();
});
+
function NoticeHover() {
- $("#content .notice").hover(
- function () {
- $(this).addClass('hover');
- },
- function () {
- $(this).removeClass('hover');
- }
- );
+ function mouseHandler(e) {
+ $(e.target).closest('li.hentry')[(e.type === 'mouseover') ? 'addClass' : 'removeClass']('hover');
+ };
+ $('#content .notices').mouseover(mouseHandler);
+ $('#content .notices').mouseout(mouseHandler);
}
+
function NoticeReply() {
if ($('#notice_data-text').length > 0) {
$('#content .notice').each(function() {
- var notice = $(this);
- $('.notice_reply', $(this)).click(function() {
- var nickname = ($('.author .nickname', notice).length > 0) ? $('.author .nickname', notice) : $('.author .nickname');
- NoticeReplySet(nickname.text(), $('.notice_id', notice).text());
+ var notice = $(this)[0];
+ $($('.notice_reply', notice)[0]).click(function() {
+ var nickname = ($('.author .nickname', notice).length > 0) ? $($('.author .nickname', notice)[0]) : $('.author .nickname');
+ NoticeReplySet(nickname.text(), $($('.notice_id', notice)[0]).text());
return false;
});
});
diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php
index 8d6d19f2a..dcf59b1bc 100644
--- a/lib/attachmentlist.php
+++ b/lib/attachmentlist.php
@@ -79,9 +79,9 @@ class AttachmentList extends Widget
function show()
{
-// $this->out->elementStart('div', array('id' =>'attachments_primary'));
- $this->out->elementStart('div', array('id' =>'content'));
- $this->out->element('h2', null, _('Attachments'));
+ $this->out->elementStart('dl', array('id' =>'attachment'));
+ $this->out->element('dt', null, _('Attachments'));
+ $this->out->elementStart('dd');
$this->out->elementStart('ul', array('class' => 'attachments'));
$atts = new File;
@@ -91,8 +91,9 @@ class AttachmentList extends Widget
$item->show();
}
+ $this->out->elementEnd('dd');
$this->out->elementEnd('ul');
- $this->out->elementEnd('div');
+ $this->out->elementEnd('dl');
return count($att);
}
@@ -170,7 +171,7 @@ class AttachmentListItem extends Widget
}
function linkTitle() {
- return 'Our page for ' . $this->title();
+ return $this->title();
}
/**
@@ -190,33 +191,25 @@ class AttachmentListItem extends Widget
}
function linkAttr() {
- return array('class' => 'attachment', 'href' => common_local_url('attachment', array('attachment' => $this->attachment->id)));
+ return array('class' => 'attachment', 'href' => $this->attachment->url, 'id' => 'attachment-' . $this->attachment->id);
}
function showLink() {
- $attr = $this->linkAttr();
- $text = $this->linkTitle();
- $this->out->elementStart('h4');
- $this->out->element('a', $attr, $text);
-
- if ($this->attachment->url !== $this->title())
- $this->out->element('span', null, " ({$this->attachment->url})");
-
- $this->out->elementEnd('h4');
+ $this->out->elementStart('a', $this->linkAttr());
+ $this->out->element('span', null, $this->linkTitle());
+ $this->showRepresentation();
+ $this->out->elementEnd('a');
}
function showNoticeAttachment()
{
$this->showLink();
- $this->showRepresentation();
}
function showRepresentation() {
$thumbnail = File_thumbnail::staticGet('file_id', $this->attachment->id);
if (!empty($thumbnail)) {
- $this->out->elementStart('a', $this->linkAttr()/*'href' => $this->linkTo()*/);
$this->out->element('img', array('alt' => 'nothing to say', 'src' => $thumbnail->url, 'width' => $thumbnail->width, 'height' => $thumbnail->height));
- $this->out->elementEnd('a');
}
}
@@ -258,7 +251,7 @@ class Attachment extends AttachmentListItem
}
function linkTitle() {
- return 'Direct link to ' . $this->title();
+ return $this->attachment->url;
}
function showRepresentation() {
diff --git a/lib/attachmentsection.php b/lib/attachmentsection.php
deleted file mode 100644
index 20e620b9b..000000000
--- a/lib/attachmentsection.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-/**
- * Laconica, the distributed open-source microblogging tool
- *
- * Base class for sections showing lists of 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 Widget
- * @package Laconica
- * @author Evan Prodromou <evan@controlyourself.ca>
- * @copyright 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);
-}
-
-define('ATTACHMENTS_PER_SECTION', 6);
-
-/**
- * Base class for sections showing lists of attachments
- *
- * These are the widgets that show interesting data about a person
- * group, or site.
- *
- * @category Widget
- * @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 AttachmentSection extends Section
-{
- function showContent()
- {
- $attachments = $this->getAttachments();
-
- $cnt = 0;
-
- $this->out->elementStart('ul', 'attachments');
-
- while ($attachments->fetch() && ++$cnt <= ATTACHMENTS_PER_SECTION) {
- $this->showAttachment($attachments);
- }
-
- $this->out->elementEnd('ul');
-
- return ($cnt > ATTACHMENTS_PER_SECTION);
- }
-
- function getAttachments()
- {
- return null;
- }
-
- function showAttachment($attachment)
- {
- $this->out->elementStart('li');
- $this->out->element('a', array('class' => 'attachment', 'href' => common_local_url('attachment', array('attachment' => $attachment->file_id))), "Attachment tagged {$attachment->c} times");
- $this->out->elementEnd('li');
- }
-}
-
diff --git a/lib/common.php b/lib/common.php
index 3feba1d8b..0ce46442d 100644
--- a/lib/common.php
+++ b/lib/common.php
@@ -159,6 +159,10 @@ $config =
'newuser' =>
array('subscribe' => null,
'welcome' => null),
+ 'snapshot' =>
+ array('run' => 'web',
+ 'frequency' => 10000,
+ 'reporturl' => 'http://laconi.ca/stats/report'),
);
$config['db'] = &PEAR::getStaticProperty('DB_DataObject','options');
diff --git a/lib/facebookaction.php b/lib/facebookaction.php
index 043a078cd..637a6284d 100644
--- a/lib/facebookaction.php
+++ b/lib/facebookaction.php
@@ -97,11 +97,11 @@ class FacebookAction extends Action
{
// Add a timestamp to the file so Facebook cache wont ignore our changes
$ts = filemtime(INSTALLDIR.'/theme/base/css/display.css');
+
+ $this->element('link', array('rel' => 'stylesheet',
+ 'type' => 'text/css',
+ 'href' => theme_path('css/display.css', 'base') . '?ts=' . $ts));
- $this->element('link', array('rel' => 'stylesheet',
- 'type' => 'text/css',
- 'href' => theme_path('css/display.css', 'base') . '?ts=' . $ts));
-
$theme = common_config('site', 'theme');
$ts = filemtime(INSTALLDIR. '/theme/' . $theme .'/css/display.css');
diff --git a/lib/frequentattachmentsection.php b/lib/frequentattachmentsection.php
deleted file mode 100644
index 0ce0d1871..000000000
--- a/lib/frequentattachmentsection.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/**
- * Laconica, the distributed open-source microblogging tool
- *
- * FIXME
- *
- * 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 Widget
- * @package Laconica
- * @author Evan Prodromou <evan@controlyourself.ca>
- * @copyright 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);
-}
-
-/**
- * FIXME
- *
- * These are the widgets that show interesting data about a person
- * group, or site.
- *
- * @category Widget
- * @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 FrequentAttachmentSection extends AttachmentSection
-{
- function getAttachments() {
- $notice_tag = new Notice_tag;
- $query = 'select file_id, count(file_id) as c from notice_tag join file_to_post on post_id = notice_id where tag="' . $notice_tag->escape($this->out->tag) . '" group by file_id order by c desc';
- $notice_tag->query($query);
- return $notice_tag;
- }
-
- function title()
- {
- return sprintf(_('Attachments frequently tagged with %s'), $this->out->tag);
- }
-
- function divId()
- {
- return 'frequent_attachments';
- }
-}
-
diff --git a/lib/noticelist.php b/lib/noticelist.php
index ba3526509..8aab83433 100644
--- a/lib/noticelist.php
+++ b/lib/noticelist.php
@@ -34,6 +34,7 @@ if (!defined('LACONICA')) {
require_once INSTALLDIR.'/lib/favorform.php';
require_once INSTALLDIR.'/lib/disfavorform.php';
+require_once INSTALLDIR.'/lib/attachmentlist.php';
/**
* widget for displaying a list of notices
@@ -192,45 +193,24 @@ class NoticeListItem extends Widget
$this->out->elementEnd('div');
}
- function showNoticeAttachments()
- {
- $f2p = new File_to_post;
- $f2p->post_id = $this->notice->id;
- $file = new File;
- $file->joinAdd($f2p);
- $file->selectAdd();
- $file->selectAdd('file.id as id');
- $count = $file->find(true);
- if (!$count) return;
- if (1 === $count) {
- $href = common_local_url('attachment', array('attachment' => $file->id));
- $att_class = 'attachment';
- } else {
- $href = common_local_url('attachments', array('notice' => $this->notice->id));
- $att_class = 'attachments';
+ function showNoticeAttachments() {
+ if ($this->isUsedInList()) {
+ return;
}
+ $al = new AttachmentList($this->notice, $this->out);
+ $al->show();
+ }
- $clip = theme_path('images/icons/clip', 'base');
- if ('shownotice' === $this->out->args['action']) {
- $height = '96px';
- $width = '83%';
- $width_att = '15%';
- $clip .= '-big.png';
- $top = '70px';
- } else {
- $height = '48px';
- $width = '90%';
- $width_att = '8%';
- $clip .= '.png';
- $top = '20px';
- }
-if(0)
- $this->out->elementStart('div', 'entry-attachments');
-else
- $this->out->elementStart('p', array('class' => 'entry-attachments', 'style' => "float: right; width: $width_att; background: url($clip) no-repeat; text-align: right; height: $height;"));
- $this->out->element('a', array('class' => $att_class, 'style' => "text-decoration: none; padding-top: $top; display: block; height: $height;", 'href' => $href, 'title' => "# of attachments: $count"), $count === 1 ? '' : $count);
+ function isUsedInList() {
+ return 'shownotice' !== $this->out->args['action'];
+ }
- $this->out->elementEnd('p');
+ function attachmentCount($discriminant = true) {
+ $file_oembed = new File_oembed;
+ $query = "select count(*) as c from file_oembed join file_to_post on file_oembed.file_id = file_to_post.file_id where post_id=" . $this->notice->id;
+ $file_oembed->query($query);
+ $file_oembed->fetch();
+ return intval($file_oembed->c);
}
function showNoticeInfo()
diff --git a/lib/router.php b/lib/router.php
index 70ee0f3fb..fc119821b 100644
--- a/lib/router.php
+++ b/lib/router.php
@@ -153,24 +153,17 @@ class Router
$m->connect('attachment/:attachment/ajax',
array('action' => 'attachment_ajax'),
- array('notice' => '[0-9]+'));
-
- $m->connect('attachment/:attachment',
- array('action' => 'attachment'),
- array('notice' => '[0-9]+'));
+ array('attachment' => '[0-9]+'));
- // notice
+ $m->connect('attachment/:attachment/thumbnail',
+ array('action' => 'attachment_thumbnail'),
+ array('attachment' => '[0-9]+'));
$m->connect('notice/new', array('action' => 'newnotice'));
$m->connect('notice/new?replyto=:replyto',
array('action' => 'newnotice'),
array('replyto' => '[A-Za-z0-9_-]+'));
- $m->connect('notice/:notice/attachments/ajax',
- array('action' => 'attachments_ajax'),
- array('notice' => '[0-9]+'));
- $m->connect('notice/:notice/attachments',
- array('action' => 'attachments'),
- array('notice' => '[0-9]+'));
+
$m->connect('notice/:notice',
array('action' => 'shownotice'),
array('notice' => '[0-9]+'));
diff --git a/lib/snapshot.php b/lib/snapshot.php
new file mode 100644
index 000000000..4b05b502d
--- /dev/null
+++ b/lib/snapshot.php
@@ -0,0 +1,227 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * A snapshot of site stats that can report itself to headquarters
+ *
+ * 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 Stats
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 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);
+}
+
+/**
+ * A snapshot of site stats that can report itself to headquarters
+ *
+ * This class will collect statistics on the site and report them to
+ * a statistics server of the admin's choice. (Default is the big one
+ * at laconi.ca.)
+ *
+ * It can either be called from a cron job, or run occasionally by the
+ * Web site.
+ *
+ * @category Stats
+ * @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 Snapshot
+{
+ var $stats = null;
+
+ /**
+ * Constructor for a snapshot
+ */
+
+ function __construct()
+ {
+ }
+
+ /**
+ * Static function for reporting statistics
+ *
+ * This function checks whether it should report statistics, based on
+ * the current configuation settings. If it should, it creates a new
+ * Snapshot object, takes a snapshot, and reports it to headquarters.
+ *
+ * @return void
+ */
+
+ static function check()
+ {
+ switch (common_config('snapshot', 'run')) {
+ case 'web':
+ // skip if we're not running on the Web.
+ if (!isset($_SERVER) || !array_key_exists('REQUEST_METHOD', $_SERVER)) {
+ break;
+ }
+ // Run once every frequency hits
+ // XXX: do frequency by time (once a week, etc.) rather than
+ // hits
+ if (rand() % common_config('snapshot', 'frequency') == 0) {
+ $snapshot = new Snapshot();
+ $snapshot->take();
+ $snapshot->report();
+ }
+ break;
+ case 'cron':
+ // skip if we're running on the Web
+ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
+ break;
+ }
+ common_log(LOG_INFO, 'Running snapshot from cron job');
+ // We're running from the command line; assume
+
+ $snapshot = new Snapshot();
+ $snapshot->take();
+ common_log(LOG_INFO, count($snapshot->stats) . " statistics being uploaded.");
+ $snapshot->report();
+
+ break;
+ case 'never':
+ break;
+ default:
+ common_log(LOG_WARNING, "Unrecognized value for snapshot run config.");
+ }
+ }
+
+ /**
+ * Take a snapshot of the server
+ *
+ * Builds an array of statistical and configuration data based
+ * on the local database and config files. We avoid grabbing any
+ * information that could be personal or private.
+ *
+ * @return void
+ */
+
+ function take()
+ {
+ $this->stats = array();
+
+ // Some basic identification stuff
+
+ $this->stats['version'] = LACONICA_VERSION;
+ $this->stats['phpversion'] = phpversion();
+ $this->stats['name'] = common_config('site', 'name');
+ $this->stats['root'] = common_root_url();
+
+ // non-identifying stats on various tables. Primary
+ // interest is size and rate of activity of service.
+
+ $tables = array('user',
+ 'notice',
+ 'subscription',
+ 'remote_profile',
+ 'user_group');
+
+ foreach ($tables as $table) {
+ $this->tableStats($table);
+ }
+
+ // stats on some important config options
+
+ $this->stats['theme'] = common_config('site', 'theme');
+ $this->stats['dbtype'] = common_config('db', 'type');
+ $this->stats['xmpp'] = common_config('xmpp', 'enabled');
+ $this->stats['inboxes'] = common_config('inboxes', 'enabled');
+ $this->stats['queue'] = common_config('queue', 'enabled');
+ $this->stats['license'] = common_config('license', 'url');
+ $this->stats['fancy'] = common_config('site', 'fancy');
+ $this->stats['private'] = common_config('site', 'private');
+ $this->stats['closed'] = common_config('site', 'closed');
+ $this->stats['memcached'] = common_config('memcached', 'enabled');
+ $this->stats['language'] = common_config('site', 'language');
+ $this->stats['timezone'] = common_config('site', 'timezone');
+
+ }
+
+ /**
+ * Reports statistics to headquarters
+ *
+ * Posts statistics to a reporting server.
+ *
+ * @return void
+ */
+
+ function report()
+ {
+ // XXX: Use OICU2 and OAuth to make authorized requests
+
+ $postdata = http_build_query($this->stats);
+
+ $opts =
+ array('http' =>
+ array(
+ 'method' => 'POST',
+ 'header' => 'Content-type: '.
+ 'application/x-www-form-urlencoded',
+ 'content' => $postdata,
+ 'user_agent' => 'Laconica/'.LACONICA_VERSION
+ )
+ );
+
+ $context = stream_context_create($opts);
+
+ $reporturl = common_config('snapshot', 'reporturl');
+
+ $result = @file_get_contents($reporturl, false, $context);
+
+ return $result;
+ }
+
+ /**
+ * Updates statistics for a single table
+ *
+ * Determines the size of a table and its oldest and newest rows.
+ * Goal here is to see how active a site is. Note that it
+ * fills up the instance stats variable.
+ *
+ * @param string $table name of table to check
+ *
+ * @return void
+ */
+
+ function tableStats($table)
+ {
+ $inst = DB_DataObject::factory($table);
+
+ $inst->selectAdd();
+ $inst->selectAdd('count(*) as cnt, '.
+ 'min(created) as first, '.
+ 'max(created) as last');
+
+ if ($inst->find(true)) {
+ $this->stats[$table.'count'] = $inst->cnt;
+ $this->stats[$table.'first'] = $inst->first;
+ $this->stats[$table.'last'] = $inst->last;
+ }
+
+ $inst->free();
+ unset($inst);
+ }
+}
diff --git a/lib/util.php b/lib/util.php
index fbef8764a..d56f44f7b 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -496,6 +496,27 @@ function common_linkify($url) {
}
$attrs = array('href' => $longurl, 'rel' => 'external');
+
+// 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.
+ $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)) {
+ $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 {
+ $attrs['class'] = 'attachment thumbnail';
+ }
+ $attrs['id'] = "attachment-{$file->file_id}";
+ }
return XMLStringer::estring('a', $attrs, $display);
}
diff --git a/scripts/reportsnapshot.php b/scripts/reportsnapshot.php
new file mode 100644
index 000000000..e332d856c
--- /dev/null
+++ b/scripts/reportsnapshot.php
@@ -0,0 +1,37 @@
+#!/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
+if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
+ print "This script must be run from the command line\n";
+ exit(1);
+}
+
+ini_set("max_execution_time", "0");
+ini_set("max_input_time", "0");
+set_time_limit(0);
+mb_internal_encoding('UTF-8');
+
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+define('LACONICA', true);
+
+require_once(INSTALLDIR . '/lib/common.php');
+
+Snapshot::check();
diff --git a/theme/base/css/display.css b/theme/base/css/display.css
index 5d2b5231c..9bc1417b1 100644
--- a/theme/base/css/display.css
+++ b/theme/base/css/display.css
@@ -742,15 +742,10 @@ border-top-style:dotted;
.notices li {
list-style-type:none;
}
-.notices li.hover {
-border-radius:4px;
--moz-border-radius:4px;
--webkit-border-radius:4px;
-}
.notices .notices {
margin-top:7px;
-margin-left:3%;
-width:97%;
+margin-left:5%;
+width:95%;
float:left;
}
@@ -803,6 +798,9 @@ float:left;
width:100%;
overflow:hidden;
}
+.notice .entry-title.ov {
+overflow:visible;
+}
#shownotice .notice .entry-title {
font-size:2.2em;
}
@@ -827,7 +825,7 @@ clear:left;
float:left;
font-size:0.95em;
margin-left:59px;
-width:65%;
+width:60%;
}
#showstream .notice div.entry-content,
#shownotice .notice div.entry-content {
@@ -857,15 +855,26 @@ display:inline-block;
text-transform:lowercase;
}
+.notice .attachment {
+position:relative;
+}
+.notice .attachment img {
+position:absolute;
+top:18px;
+left:0;
+z-index:99;
+}
+#shownotice .notice .attachment img {
+position:static;
+}
+
.notice-options {
-padding-left:2%;
-float:left;
-width:50%;
position:relative;
font-size:0.95em;
-width:12.5%;
+width:90px;
float:right;
+margin-right:11px;
}
.notice-options a {
@@ -1049,8 +1058,6 @@ margin-left:18px;
}
-
-
/* TOP_POSTERS */
.section tbody td {
padding-right:18px;
diff --git a/theme/base/css/facebookapp.css b/theme/base/css/facebookapp.css
index 163b41fb4..e6b1c9ee5 100644
--- a/theme/base/css/facebookapp.css
+++ b/theme/base/css/facebookapp.css
@@ -1,6 +1,3 @@
-@import url("display.css");
-@import url("../../identica/css/display.css");
-
* {
font-size:14px;
font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif;
diff --git a/theme/base/images/icons/clip-inline.png b/theme/base/images/icons/clip-inline.png
new file mode 100644
index 000000000..870f8b2e8
--- /dev/null
+++ b/theme/base/images/icons/clip-inline.png
Binary files differ
diff --git a/theme/default/css/display.css b/theme/default/css/display.css
index 16c9322a5..737db7ce9 100644
--- a/theme/default/css/display.css
+++ b/theme/default/css/display.css
@@ -193,7 +193,9 @@ background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-r
}
.notices div.entry-content,
-.notices div.notice-options {
+.notices div.notice-options,
+.notices li.hover .notices div.entry-content,
+.notices li.hover .notices div.notice-options {
opacity:0.4;
}
.notices li.hover div.entry-content,
@@ -212,16 +214,16 @@ background-color:#fcfcfc;
}
.notices .notices {
-background-color:rgba(200, 200, 200, 0.025);
+background-color:rgba(200, 200, 200, 0.050);
}
.notices .notices .notices {
-background-color:rgba(200, 200, 200, 0.050);
+background-color:rgba(200, 200, 200, 0.100);
}
.notices .notices .notices .notices {
-background-color:rgba(200, 200, 200, 0.075);
+background-color:rgba(200, 200, 200, 0.150);
}
.notices .notices .notices .notices .notices {
-background-color:rgba(200, 200, 200, 0.100);
+background-color:rgba(200, 200, 200, 0.300);
}
/*END: NOTICES */
diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css
index 2fb123a20..f7abac482 100644
--- a/theme/identica/css/display.css
+++ b/theme/identica/css/display.css
@@ -193,7 +193,9 @@ background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-r
}
.notices div.entry-content,
-.notices div.notice-options {
+.notices div.notice-options,
+.notices li.hover .notices div.entry-content,
+.notices li.hover .notices div.notice-options {
opacity:0.4;
}
.notices li.hover div.entry-content,
@@ -212,16 +214,16 @@ background-color:#fcfcfc;
}
.notices .notices {
-background-color:rgba(200, 200, 200, 0.025);
+background-color:rgba(200, 200, 200, 0.050);
}
.notices .notices .notices {
-background-color:rgba(200, 200, 200, 0.050);
+background-color:rgba(200, 200, 200, 0.100);
}
.notices .notices .notices .notices {
-background-color:rgba(200, 200, 200, 0.075);
+background-color:rgba(200, 200, 200, 0.150);
}
.notices .notices .notices .notices .notices {
-background-color:rgba(200, 200, 200, 0.100);
+background-color:rgba(200, 200, 200, 0.300);
}
/*END: NOTICES */