Merge branch '0.8.x' into fbconnect
250
actions/attachment.php
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
<?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 AttachmentAction extends Action
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Attachment object to show
|
||||||
|
*/
|
||||||
|
|
||||||
|
var $attachment = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profile of the notice object
|
||||||
|
*/
|
||||||
|
|
||||||
|
// var $profile = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Avatar of the profile of the notice object
|
||||||
|
*/
|
||||||
|
|
||||||
|
// var $avatar = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load attributes based on database arguments
|
||||||
|
*
|
||||||
|
* Loads all the DB stuff
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST array
|
||||||
|
*
|
||||||
|
* @return success flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$id = $this->arg('attachment');
|
||||||
|
|
||||||
|
$this->attachment = File::staticGet($id);
|
||||||
|
|
||||||
|
if (!$this->attachment) {
|
||||||
|
$this->clientError(_('No such attachment.'), 404);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this action read-only?
|
||||||
|
*
|
||||||
|
* @return boolean true
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Title of the page
|
||||||
|
*
|
||||||
|
* @return string title of the page
|
||||||
|
*/
|
||||||
|
function title()
|
||||||
|
{
|
||||||
|
$a = new Attachment($this->attachment);
|
||||||
|
return $a->title();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)) . '"';
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle input
|
||||||
|
*
|
||||||
|
* Only handles get, so just show the page.
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
$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()
|
||||||
|
{
|
||||||
|
$this->elementStart('ul', array('class' => 'attachments'));
|
||||||
|
$ali = new Attachment($this->attachment, $this);
|
||||||
|
$cnt = $ali->show();
|
||||||
|
$this->elementEnd('ul');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't show page notice
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function showPageNoticeBlock()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show aside: this attachments appears in what notices
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function showAside() {
|
||||||
|
$notice = new Notice;
|
||||||
|
$f2p = new File_to_post;
|
||||||
|
$f2p->file_id = $this->attachment->id;
|
||||||
|
$notice->joinAdd($f2p);
|
||||||
|
$notice->orderBy('created desc');
|
||||||
|
$x = $notice->find();
|
||||||
|
$this->elementStart('ol');
|
||||||
|
while($notice->fetch()) {
|
||||||
|
$this->elementStart('li');
|
||||||
|
$profile = $notice->getProfile();
|
||||||
|
$this->element('a', array('href' => $notice->uri), $profile->nickname . ' on ' . $notice->created);
|
||||||
|
$this->elementEnd('li');
|
||||||
|
}
|
||||||
|
$this->elementEnd('ol');
|
||||||
|
$notice->free();
|
||||||
|
$f2p->free();
|
||||||
|
|
||||||
|
$notice_tag = new Notice_tag;
|
||||||
|
$attachment = new File;
|
||||||
|
|
||||||
|
$query = 'select tag,count(tag) as c from notice_tag join file_to_post on (notice_tag.notice_id=post_id) join notice on notice_id = notice.id where file_id=' . $notice_tag->escape($this->attachment->id) . ' group by tag order by c desc';
|
||||||
|
|
||||||
|
$notice_tag->query($query);
|
||||||
|
$this->elementStart('ol');
|
||||||
|
while($notice_tag->fetch()) {
|
||||||
|
$this->elementStart('li');
|
||||||
|
$href = common_local_url('tag', array('tag' => $notice_tag->tag));
|
||||||
|
$this->element('a', array('href' => $href), $notice_tag->tag . ' (' . $notice_tag->c . ')');
|
||||||
|
$this->elementEnd('li');
|
||||||
|
}
|
||||||
|
$this->elementEnd('ol');
|
||||||
|
}
|
||||||
|
}
|
141
actions/attachment_ajax.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Laconica, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Show notice attachments
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category Personal
|
||||||
|
* @package Laconica
|
||||||
|
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||||
|
* @copyright 2008-2009 Control Yourself, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://laconi.ca/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('LACONICA')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/actions/attachment.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show notice attachments
|
||||||
|
*
|
||||||
|
* @category Personal
|
||||||
|
* @package Laconica
|
||||||
|
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://laconi.ca/
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Attachment_ajaxAction extends AttachmentAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
function showPage()
|
||||||
|
{
|
||||||
|
if (Event::handle('StartShowBody', array($this))) {
|
||||||
|
$this->showCore();
|
||||||
|
Event::handle('EndShowBody', array($this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show core.
|
||||||
|
*
|
||||||
|
* Shows local navigation, content block and aside.
|
||||||
|
*
|
||||||
|
* @return nothing
|
||||||
|
*/
|
||||||
|
function showCore()
|
||||||
|
{
|
||||||
|
$this->elementStart('div', array('id' => 'core'));
|
||||||
|
if (Event::handle('StartShowContentBlock', array($this))) {
|
||||||
|
$this->showContentBlock();
|
||||||
|
Event::handle('EndShowContentBlock', array($this));
|
||||||
|
}
|
||||||
|
$this->elementEnd('div');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)) . '"';
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
292
actions/attachments.php
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
<?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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
115
actions/attachments_ajax.php
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<?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.'/actions/attachments.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 Attachments_ajaxAction extends AttachmentsAction
|
||||||
|
{
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @return nothing
|
||||||
|
*/
|
||||||
|
function showPage()
|
||||||
|
{
|
||||||
|
if (Event::handle('StartShowBody', array($this))) {
|
||||||
|
$this->showCore();
|
||||||
|
Event::handle('EndShowBody', array($this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show core.
|
||||||
|
*
|
||||||
|
* Shows local navigation, content block and aside.
|
||||||
|
*
|
||||||
|
* @return nothing
|
||||||
|
*/
|
||||||
|
function showCore()
|
||||||
|
{
|
||||||
|
$this->elementStart('div', array('id' => 'core'));
|
||||||
|
if (Event::handle('StartShowContentBlock', array($this))) {
|
||||||
|
$this->showContentBlock();
|
||||||
|
Event::handle('EndShowContentBlock', array($this));
|
||||||
|
}
|
||||||
|
$this->elementEnd('div');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -158,7 +158,8 @@ class NewnoticeAction extends Action
|
|||||||
$replyto = 'false';
|
$replyto = 'false';
|
||||||
}
|
}
|
||||||
|
|
||||||
$notice = Notice::saveNew($user->id, $content, 'web', 1,
|
// $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1,
|
||||||
|
$notice = Notice::saveNew($user->id, $content_shortened, 'web', 1,
|
||||||
($replyto == 'false') ? null : $replyto);
|
($replyto == 'false') ? null : $replyto);
|
||||||
|
|
||||||
if (is_string($notice)) {
|
if (is_string($notice)) {
|
||||||
@ -166,6 +167,8 @@ class NewnoticeAction extends Action
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->saveUrls($notice);
|
||||||
|
|
||||||
common_broadcast_notice($notice);
|
common_broadcast_notice($notice);
|
||||||
|
|
||||||
if ($this->boolean('ajax')) {
|
if ($this->boolean('ajax')) {
|
||||||
@ -191,6 +194,24 @@ class NewnoticeAction extends Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** save all urls in the notice to the db
|
||||||
|
*
|
||||||
|
* follow redirects and save all available file information
|
||||||
|
* (mimetype, date, size, oembed, etc.)
|
||||||
|
*
|
||||||
|
* @param class $notice Notice to pull URLs from
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function saveUrls($notice) {
|
||||||
|
common_replace_urls_callback($notice->content, array($this, 'saveUrl'), $notice->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveUrl($data) {
|
||||||
|
list($url, $notice_id) = $data;
|
||||||
|
$zzz = File::processNew($url, $notice_id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show an Ajax-y error message
|
* Show an Ajax-y error message
|
||||||
*
|
*
|
||||||
|
@ -49,8 +49,18 @@ class TagAction extends Action
|
|||||||
{
|
{
|
||||||
$pop = new PopularNoticeSection($this);
|
$pop = new PopularNoticeSection($this);
|
||||||
$pop->show();
|
$pop->show();
|
||||||
}
|
|
||||||
|
|
||||||
|
$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->tag) . '" group by file_id order by c desc';
|
||||||
|
$notice_tag->query($query);
|
||||||
|
$this->elementStart('ol');
|
||||||
|
while ($notice_tag->fetch()) {
|
||||||
|
$this->elementStart('li');
|
||||||
|
$this->element('a', array('class' => 'attachment', 'href' => common_local_url('attachment', array('attachment' => $notice_tag->file_id))), "Attachment tagged {$notice_tag->c} times");
|
||||||
|
$this->elementEnd('li');
|
||||||
|
}
|
||||||
|
$this->elementEnd('ol');
|
||||||
|
}
|
||||||
|
|
||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
|
123
classes/File.php
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Laconica - a distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2008, Controlez-Vous, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('LACONICA')) { exit(1); }
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||||
|
require_once INSTALLDIR.'/classes/File_redirection.php';
|
||||||
|
require_once INSTALLDIR.'/classes/File_oembed.php';
|
||||||
|
require_once INSTALLDIR.'/classes/File_thumbnail.php';
|
||||||
|
require_once INSTALLDIR.'/classes/File_to_post.php';
|
||||||
|
//require_once INSTALLDIR.'/classes/File_redirection.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table Definition for file
|
||||||
|
*/
|
||||||
|
|
||||||
|
class File extends Memcached_DataObject
|
||||||
|
{
|
||||||
|
###START_AUTOCODE
|
||||||
|
/* the code below is auto generated do not remove the above tag */
|
||||||
|
|
||||||
|
public $__table = 'file'; // table name
|
||||||
|
public $id; // int(11) not_null primary_key group_by
|
||||||
|
public $url; // varchar(255) unique_key
|
||||||
|
public $mimetype; // varchar(50)
|
||||||
|
public $size; // int(11) group_by
|
||||||
|
public $title; // varchar(255)
|
||||||
|
public $date; // int(11) group_by
|
||||||
|
public $protected; // int(1) group_by
|
||||||
|
|
||||||
|
/* Static get */
|
||||||
|
function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File',$k,$v); }
|
||||||
|
|
||||||
|
/* the code above is auto generated do not remove the tag below */
|
||||||
|
###END_AUTOCODE
|
||||||
|
|
||||||
|
function isProtected($url) {
|
||||||
|
return 'http://www.facebook.com/login.php' === $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAttachments($post_id) {
|
||||||
|
$query = "select file.* from file join file_to_post on (file_id = file.id) join notice on (post_id = notice.id) where post_id = " . $this->escape($post_id);
|
||||||
|
$this->query($query);
|
||||||
|
$att = array();
|
||||||
|
while ($this->fetch()) {
|
||||||
|
$att[] = clone($this);
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $att;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveNew($redir_data, $given_url) {
|
||||||
|
$x = new File;
|
||||||
|
$x->url = $given_url;
|
||||||
|
if (!empty($redir_data['protected'])) $x->protected = $redir_data['protected'];
|
||||||
|
if (!empty($redir_data['title'])) $x->title = $redir_data['title'];
|
||||||
|
if (!empty($redir_data['type'])) $x->mimetype = $redir_data['type'];
|
||||||
|
if (!empty($redir_data['size'])) $x->size = intval($redir_data['size']);
|
||||||
|
if (isset($redir_data['time']) && $redir_data['time'] > 0) $x->date = intval($redir_data['time']);
|
||||||
|
$file_id = $x->insert();
|
||||||
|
|
||||||
|
if (isset($redir_data['type'])
|
||||||
|
&& ('text/html' === substr($redir_data['type'], 0, 9))
|
||||||
|
&& ($oembed_data = File_oembed::_getOembed($given_url))
|
||||||
|
&& isset($oembed_data['json'])) {
|
||||||
|
|
||||||
|
File_oembed::saveNew($oembed_data['json'], $file_id);
|
||||||
|
}
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processNew($given_url, $notice_id) {
|
||||||
|
if (empty($given_url)) return -1; // error, no url to process
|
||||||
|
$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)) {
|
||||||
|
$file_redir = File_redirection::staticGet('url', $given_url);
|
||||||
|
if (empty($file_redir->id)) {
|
||||||
|
$redir_data = File_redirection::where($given_url);
|
||||||
|
$redir_url = $redir_data['url'];
|
||||||
|
if ($redir_url === $given_url) {
|
||||||
|
$x = File::saveNew($redir_data, $given_url);
|
||||||
|
$file_id = $x->id;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$x = File::processNew($redir_url, $notice_id);
|
||||||
|
$file_id = $x->id;
|
||||||
|
File_redirection::saveNew($redir_data, $file_id, $given_url);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$file_id = $file_redir->file_id;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$file_id = $file->id;
|
||||||
|
$x = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($x)) {
|
||||||
|
$x = File::staticGet($file_id);
|
||||||
|
if (empty($x)) die('Impossible!');
|
||||||
|
}
|
||||||
|
|
||||||
|
File_to_post::processNew($file_id, $notice_id);
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
}
|
87
classes/File_oembed.php
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Laconica - a distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2008, Controlez-Vous, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('LACONICA')) { exit(1); }
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table Definition for file_oembed
|
||||||
|
*/
|
||||||
|
|
||||||
|
class File_oembed extends Memcached_DataObject
|
||||||
|
{
|
||||||
|
###START_AUTOCODE
|
||||||
|
/* the code below is auto generated do not remove the above tag */
|
||||||
|
|
||||||
|
public $__table = 'file_oembed'; // table name
|
||||||
|
public $id; // int(11) not_null primary_key group_by
|
||||||
|
public $file_id; // int(11) unique_key group_by
|
||||||
|
public $version; // varchar(20)
|
||||||
|
public $type; // varchar(20)
|
||||||
|
public $provider; // varchar(50)
|
||||||
|
public $provider_url; // varchar(255)
|
||||||
|
public $width; // int(11) group_by
|
||||||
|
public $height; // int(11) group_by
|
||||||
|
public $html; // blob(65535) blob
|
||||||
|
public $title; // varchar(255)
|
||||||
|
public $author_name; // varchar(50)
|
||||||
|
public $author_url; // varchar(255)
|
||||||
|
public $url; // varchar(255)
|
||||||
|
|
||||||
|
/* Static get */
|
||||||
|
function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_oembed',$k,$v); }
|
||||||
|
|
||||||
|
/* the code above is auto generated do not remove the tag below */
|
||||||
|
###END_AUTOCODE
|
||||||
|
|
||||||
|
|
||||||
|
function _getOembed($url, $maxwidth = 500, $maxheight = 400, $format = 'json') {
|
||||||
|
$cmd = 'http://oohembed.com/oohembed/?url=' . urlencode($url);
|
||||||
|
if (is_int($maxwidth)) $cmd .= "&maxwidth=$maxwidth";
|
||||||
|
if (is_int($maxheight)) $cmd .= "&maxheight=$maxheight";
|
||||||
|
if (is_string($format)) $cmd .= "&format=$format";
|
||||||
|
$oe = @file_get_contents($cmd);
|
||||||
|
if (false === $oe) return false;
|
||||||
|
return array($format => (('json' === $format) ? json_decode($oe, true) : $oe));
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveNew($data, $file_id) {
|
||||||
|
$file_oembed = new File_oembed;
|
||||||
|
$file_oembed->file_id = $file_id;
|
||||||
|
$file_oembed->version = $data['version'];
|
||||||
|
$file_oembed->type = $data['type'];
|
||||||
|
if (!empty($data['provider_name'])) $file_oembed->provider = $data['provider_name'];
|
||||||
|
if (!isset($file_oembed->provider) && !empty($data['provide'])) $file_oembed->provider = $data['provider'];
|
||||||
|
if (!empty($data['provide_url'])) $file_oembed->provider_url = $data['provider_url'];
|
||||||
|
if (!empty($data['width'])) $file_oembed->width = intval($data['width']);
|
||||||
|
if (!empty($data['height'])) $file_oembed->height = intval($data['height']);
|
||||||
|
if (!empty($data['html'])) $file_oembed->html = $data['html'];
|
||||||
|
if (!empty($data['title'])) $file_oembed->title = $data['title'];
|
||||||
|
if (!empty($data['author_name'])) $file_oembed->author_name = $data['author_name'];
|
||||||
|
if (!empty($data['author_url'])) $file_oembed->author_url = $data['author_url'];
|
||||||
|
if (!empty($data['url'])) $file_oembed->url = $data['url'];
|
||||||
|
$file_oembed->insert();
|
||||||
|
if (!empty($data['thumbnail_url'])) {
|
||||||
|
File_thumbnail::saveNew($data, $file_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
276
classes/File_redirection.php
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Laconica - a distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2008, Controlez-Vous, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('LACONICA')) { exit(1); }
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||||
|
require_once INSTALLDIR.'/classes/File.php';
|
||||||
|
require_once INSTALLDIR.'/classes/File_oembed.php';
|
||||||
|
|
||||||
|
define('USER_AGENT', 'Laconica user agent / file probe');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table Definition for file_redirection
|
||||||
|
*/
|
||||||
|
|
||||||
|
class File_redirection extends Memcached_DataObject
|
||||||
|
{
|
||||||
|
###START_AUTOCODE
|
||||||
|
/* the code below is auto generated do not remove the above tag */
|
||||||
|
|
||||||
|
public $__table = 'file_redirection'; // table name
|
||||||
|
public $id; // int(11) not_null primary_key group_by
|
||||||
|
public $url; // varchar(255) unique_key
|
||||||
|
public $file_id; // int(11) group_by
|
||||||
|
public $redirections; // int(11) group_by
|
||||||
|
public $httpcode; // int(11) group_by
|
||||||
|
|
||||||
|
/* Static get */
|
||||||
|
function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_redirection',$k,$v); }
|
||||||
|
|
||||||
|
/* the code above is auto generated do not remove the tag below */
|
||||||
|
###END_AUTOCODE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function _commonCurl($url, $redirs) {
|
||||||
|
$curlh = curl_init();
|
||||||
|
curl_setopt($curlh, CURLOPT_URL, $url);
|
||||||
|
curl_setopt($curlh, CURLOPT_AUTOREFERER, true); // # setup referer header when folowing redirects
|
||||||
|
curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 10); // # seconds to wait
|
||||||
|
curl_setopt($curlh, CURLOPT_MAXREDIRS, $redirs); // # max number of http redirections to follow
|
||||||
|
curl_setopt($curlh, CURLOPT_USERAGENT, USER_AGENT);
|
||||||
|
curl_setopt($curlh, CURLOPT_FOLLOWLOCATION, true); // Follow redirects
|
||||||
|
curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($curlh, CURLOPT_FILETIME, true);
|
||||||
|
curl_setopt($curlh, CURLOPT_HEADER, true); // Include header in output
|
||||||
|
return $curlh;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _redirectWhere_imp($short_url, $redirs = 10, $protected = false) {
|
||||||
|
if ($redirs < 0) return false;
|
||||||
|
|
||||||
|
// let's see if we know this...
|
||||||
|
$a = File::staticGet('url', $short_url);
|
||||||
|
if (empty($a->id)) {
|
||||||
|
$b = File_redirection::staticGet('url', $short_url);
|
||||||
|
if (empty($b->id)) {
|
||||||
|
// we'll have to figure it out
|
||||||
|
} else {
|
||||||
|
// this is a redirect to $b->file_id
|
||||||
|
$a = File::staticGet($b->file_id);
|
||||||
|
$url = $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);
|
||||||
|
// Don't include body in output
|
||||||
|
curl_setopt($curlh, CURLOPT_NOBODY, true);
|
||||||
|
curl_exec($curlh);
|
||||||
|
$info = curl_getinfo($curlh);
|
||||||
|
curl_close($curlh);
|
||||||
|
|
||||||
|
if (405 == $info['http_code']) {
|
||||||
|
$curlh = File_redirection::_commonCurl($short_url, $redirs);
|
||||||
|
curl_exec($curlh);
|
||||||
|
$info = curl_getinfo($curlh);
|
||||||
|
curl_close($curlh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($info['redirect_count']) && File::isProtected($info['url'])) {
|
||||||
|
return File_redirection::_redirectWhere_imp($short_url, $info['redirect_count'] - 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = array('code' => $info['http_code']
|
||||||
|
, 'redirects' => $info['redirect_count']
|
||||||
|
, 'url' => $info['url']);
|
||||||
|
|
||||||
|
if (!empty($info['content_type'])) $ret['type'] = $info['content_type'];
|
||||||
|
if ($protected) $ret['protected'] = true;
|
||||||
|
if (!empty($info['download_content_length'])) $ret['size'] = $info['download_content_length'];
|
||||||
|
if (isset($info['filetime']) && ($info['filetime'] > 0)) $ret['time'] = $info['filetime'];
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function where($in_url) {
|
||||||
|
$ret = File_redirection::_redirectWhere_imp($in_url);
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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->id)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _userMakeShort($long_url, $user) {
|
||||||
|
if (empty($user)) {
|
||||||
|
// common current user does not find a user when called from the XMPP daemon
|
||||||
|
// therefore we'll set one here fix, so that XMPP given URLs may be shortened
|
||||||
|
$user->urlshorteningservice = 'ur1.ca';
|
||||||
|
}
|
||||||
|
$curlh = curl_init();
|
||||||
|
curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait
|
||||||
|
curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica');
|
||||||
|
curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
switch($user->urlshorteningservice) {
|
||||||
|
case 'ur1.ca':
|
||||||
|
require_once INSTALLDIR.'/lib/Shorturl_api.php';
|
||||||
|
$short_url_service = new LilUrl;
|
||||||
|
$short_url = $short_url_service->shorten($long_url);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '2tu.us':
|
||||||
|
$short_url_service = new TightUrl;
|
||||||
|
require_once INSTALLDIR.'/lib/Shorturl_api.php';
|
||||||
|
$short_url = $short_url_service->shorten($long_url);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'ptiturl.com':
|
||||||
|
require_once INSTALLDIR.'/lib/Shorturl_api.php';
|
||||||
|
$short_url_service = new PtitUrl;
|
||||||
|
$short_url = $short_url_service->shorten($long_url);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'bit.ly':
|
||||||
|
curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($long_url));
|
||||||
|
$short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'is.gd':
|
||||||
|
curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($long_url));
|
||||||
|
$short_url = curl_exec($curlh);
|
||||||
|
break;
|
||||||
|
case 'snipr.com':
|
||||||
|
curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($long_url));
|
||||||
|
$short_url = curl_exec($curlh);
|
||||||
|
break;
|
||||||
|
case 'metamark.net':
|
||||||
|
curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($long_url));
|
||||||
|
$short_url = curl_exec($curlh);
|
||||||
|
break;
|
||||||
|
case 'tinyurl.com':
|
||||||
|
curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($long_url));
|
||||||
|
$short_url = curl_exec($curlh);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$short_url = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_close($curlh);
|
||||||
|
|
||||||
|
if ($short_url) {
|
||||||
|
$short_url = (string)$short_url;
|
||||||
|
if(1) {
|
||||||
|
// store it
|
||||||
|
$file = File::staticGet('url', $long_url);
|
||||||
|
if (empty($file)) {
|
||||||
|
$redir_data = File_redirection::where($long_url);
|
||||||
|
$file = File::saveNew($redir_data, $long_url);
|
||||||
|
$file_id = $file->id;
|
||||||
|
if (!empty($redir_data['oembed']['json'])) {
|
||||||
|
File_oembed::saveNew($redir_data['oembed']['json'], $file_id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$file_id = $file->id;
|
||||||
|
}
|
||||||
|
$file_redir = File_redirection::staticGet('url', $short_url);
|
||||||
|
if (empty($file_redir)) {
|
||||||
|
$file_redir = new File_redirection;
|
||||||
|
$file_redir->url = $short_url;
|
||||||
|
$file_redir->file_id = $file_id;
|
||||||
|
$file_redir->insert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $short_url;
|
||||||
|
}
|
||||||
|
return $long_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _canonUrl($in_url, $default_scheme = 'http://') {
|
||||||
|
if (empty($in_url)) return false;
|
||||||
|
$out_url = $in_url;
|
||||||
|
$p = parse_url($out_url);
|
||||||
|
if (empty($p['host']) || empty($p['scheme'])) {
|
||||||
|
list($scheme) = explode(':', $in_url, 2);
|
||||||
|
switch ($scheme) {
|
||||||
|
case 'fax':
|
||||||
|
case 'tel':
|
||||||
|
$out_url = str_replace('.-()', '', $out_url);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'mailto':
|
||||||
|
case 'aim':
|
||||||
|
case 'jabber':
|
||||||
|
case 'xmpp':
|
||||||
|
// don't touch anything
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$out_url = $default_scheme . ltrim($out_url, '/');
|
||||||
|
$p = parse_url($out_url);
|
||||||
|
if (empty($p['scheme'])) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (('ftp' == $p['scheme']) || ('http' == $p['scheme']) || ('https' == $p['scheme'])) {
|
||||||
|
if (empty($p['host'])) return false;
|
||||||
|
if (empty($p['path'])) {
|
||||||
|
$out_url .= '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveNew($data, $file_id, $url) {
|
||||||
|
$file_redir = new File_redirection;
|
||||||
|
$file_redir->url = $url;
|
||||||
|
$file_redir->file_id = $file_id;
|
||||||
|
$file_redir->redirections = intval($data['redirects']);
|
||||||
|
$file_redir->httpcode = intval($data['code']);
|
||||||
|
$file_redir->insert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
55
classes/File_thumbnail.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Laconica - a distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2008, Controlez-Vous, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('LACONICA')) { exit(1); }
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table Definition for file_thumbnail
|
||||||
|
*/
|
||||||
|
|
||||||
|
class File_thumbnail extends Memcached_DataObject
|
||||||
|
{
|
||||||
|
###START_AUTOCODE
|
||||||
|
/* the code below is auto generated do not remove the above tag */
|
||||||
|
|
||||||
|
public $__table = 'file_thumbnail'; // table name
|
||||||
|
public $id; // int(11) not_null primary_key group_by
|
||||||
|
public $file_id; // int(11) unique_key group_by
|
||||||
|
public $url; // varchar(255) unique_key
|
||||||
|
public $width; // int(11) group_by
|
||||||
|
public $height; // int(11) group_by
|
||||||
|
|
||||||
|
/* Static get */
|
||||||
|
function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_thumbnail',$k,$v); }
|
||||||
|
|
||||||
|
/* the code above is auto generated do not remove the tag below */
|
||||||
|
###END_AUTOCODE
|
||||||
|
|
||||||
|
function saveNew($data, $file_id) {
|
||||||
|
$tn = new File_thumbnail;
|
||||||
|
$tn->file_id = $file_id;
|
||||||
|
$tn->url = $data['thumbnail_url'];
|
||||||
|
$tn->width = intval($data['thumbnail_width']);
|
||||||
|
$tn->height = intval($data['thumbnail_height']);
|
||||||
|
$tn->insert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
60
classes/File_to_post.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Laconica - a distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2008, Controlez-Vous, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('LACONICA')) { exit(1); }
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table Definition for file_to_post
|
||||||
|
*/
|
||||||
|
|
||||||
|
class File_to_post extends Memcached_DataObject
|
||||||
|
{
|
||||||
|
###START_AUTOCODE
|
||||||
|
/* the code below is auto generated do not remove the above tag */
|
||||||
|
|
||||||
|
public $__table = 'file_to_post'; // table name
|
||||||
|
public $id; // int(11) not_null primary_key group_by
|
||||||
|
public $file_id; // int(11) multiple_key group_by
|
||||||
|
public $post_id; // int(11) group_by
|
||||||
|
|
||||||
|
/* Static get */
|
||||||
|
function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_to_post',$k,$v); }
|
||||||
|
|
||||||
|
/* the code above is auto generated do not remove the tag below */
|
||||||
|
###END_AUTOCODE
|
||||||
|
|
||||||
|
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();
|
||||||
|
if (empty($seen[$notice_id])) {
|
||||||
|
$seen[$notice_id] = array($file_id);
|
||||||
|
} else {
|
||||||
|
$seen[$notice_id][] = $file_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -124,8 +124,6 @@ class Notice extends Memcached_DataObject
|
|||||||
|
|
||||||
$profile = Profile::staticGet($profile_id);
|
$profile = Profile::staticGet($profile_id);
|
||||||
|
|
||||||
$final = common_shorten_links($content);
|
|
||||||
|
|
||||||
if (!$profile) {
|
if (!$profile) {
|
||||||
common_log(LOG_ERR, 'Problem saving notice. Unknown user.');
|
common_log(LOG_ERR, 'Problem saving notice. Unknown user.');
|
||||||
return _('Problem saving notice. Unknown user.');
|
return _('Problem saving notice. Unknown user.');
|
||||||
@ -167,8 +165,8 @@ class Notice extends Memcached_DataObject
|
|||||||
|
|
||||||
$notice->reply_to = $reply_to;
|
$notice->reply_to = $reply_to;
|
||||||
$notice->created = common_sql_now();
|
$notice->created = common_sql_now();
|
||||||
$notice->content = $final;
|
$notice->content = $content;
|
||||||
$notice->rendered = common_render_content($final, $notice);
|
$notice->rendered = common_render_content($content, $notice);
|
||||||
$notice->source = $source;
|
$notice->source = $source;
|
||||||
$notice->uri = $uri;
|
$notice->uri = $uri;
|
||||||
|
|
||||||
@ -279,6 +277,16 @@ class Notice extends Memcached_DataObject
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasAttachments() {
|
||||||
|
$post = clone($this);
|
||||||
|
$query = "select count(file_id) as n_attachments from file join file_to_post on (file_id = file.id) join notice on (post_id = notice.id) where post_id = " . $post->escape($this->id);
|
||||||
|
$post->query($query);
|
||||||
|
$post->fetch();
|
||||||
|
$n_attachments = intval($post->n_attachments);
|
||||||
|
$post->free();
|
||||||
|
return $n_attachments;
|
||||||
|
}
|
||||||
|
|
||||||
function blowCaches($blowLast=false)
|
function blowCaches($blowLast=false)
|
||||||
{
|
{
|
||||||
$this->blowSubsCache($blowLast);
|
$this->blowSubsCache($blowLast);
|
||||||
|
61
classes/laconica.ini
Executable file → Normal file
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[avatar]
|
[avatar]
|
||||||
profile_id = 129
|
profile_id = 129
|
||||||
original = 17
|
original = 17
|
||||||
@ -393,3 +392,63 @@ modified = 384
|
|||||||
[user_openid__keys]
|
[user_openid__keys]
|
||||||
canonical = K
|
canonical = K
|
||||||
display = U
|
display = U
|
||||||
|
|
||||||
|
[file]
|
||||||
|
id = 129
|
||||||
|
url = 2
|
||||||
|
mimetype = 2
|
||||||
|
size = 1
|
||||||
|
title = 2
|
||||||
|
date = 1
|
||||||
|
protected = 1
|
||||||
|
|
||||||
|
[file__keys]
|
||||||
|
id = N
|
||||||
|
|
||||||
|
[file_oembed]
|
||||||
|
id = 129
|
||||||
|
file_id = 129
|
||||||
|
version = 2
|
||||||
|
type = 2
|
||||||
|
provider = 2
|
||||||
|
provider_url = 2
|
||||||
|
width = 1
|
||||||
|
height = 1
|
||||||
|
html = 34
|
||||||
|
title = 2
|
||||||
|
author_name = 2
|
||||||
|
author_url = 2
|
||||||
|
url = 2
|
||||||
|
|
||||||
|
[file_oembed__keys]
|
||||||
|
id = N
|
||||||
|
|
||||||
|
[file_redirection]
|
||||||
|
id = 129
|
||||||
|
url = 2
|
||||||
|
file_id = 129
|
||||||
|
redirections = 1
|
||||||
|
httpcode = 1
|
||||||
|
|
||||||
|
[file_redirection__keys]
|
||||||
|
id = N
|
||||||
|
|
||||||
|
[file_thumbnail]
|
||||||
|
id = 129
|
||||||
|
file_id = 129
|
||||||
|
url = 2
|
||||||
|
width = 1
|
||||||
|
height = 1
|
||||||
|
|
||||||
|
[file_thumbnail__keys]
|
||||||
|
id = N
|
||||||
|
|
||||||
|
[file_to_post]
|
||||||
|
id = 129
|
||||||
|
file_id = 129
|
||||||
|
post_id = 129
|
||||||
|
|
||||||
|
[file_to_post__keys]
|
||||||
|
id = N
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,3 +41,17 @@ subscribed = profile:id
|
|||||||
[fave]
|
[fave]
|
||||||
notice_id = notice:id
|
notice_id = notice:id
|
||||||
user_id = user:id
|
user_id = user:id
|
||||||
|
|
||||||
|
[file_oembed]
|
||||||
|
file_id = file:id
|
||||||
|
|
||||||
|
[file_redirection]
|
||||||
|
file_id = file:id
|
||||||
|
|
||||||
|
[file_thumbnail]
|
||||||
|
file_id = file:id
|
||||||
|
|
||||||
|
[file_to_post]
|
||||||
|
file_id = file:id
|
||||||
|
post_id = notice:id
|
||||||
|
|
||||||
|
@ -425,3 +425,62 @@ create table group_inbox (
|
|||||||
|
|
||||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
|
||||||
|
create table file (
|
||||||
|
id integer primary key auto_increment,
|
||||||
|
url varchar(255), mimetype varchar(50),
|
||||||
|
size integer,
|
||||||
|
title varchar(255),
|
||||||
|
date integer(11),
|
||||||
|
protected integer(1),
|
||||||
|
|
||||||
|
unique(url)
|
||||||
|
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
create table file_oembed (
|
||||||
|
id integer primary key auto_increment,
|
||||||
|
file_id integer,
|
||||||
|
version varchar(20),
|
||||||
|
type varchar(20),
|
||||||
|
provider varchar(50),
|
||||||
|
provider_url varchar(255),
|
||||||
|
width integer,
|
||||||
|
height integer,
|
||||||
|
html text,
|
||||||
|
title varchar(255),
|
||||||
|
author_name varchar(50),
|
||||||
|
author_url varchar(255),
|
||||||
|
url varchar(255),
|
||||||
|
|
||||||
|
unique(file_id)
|
||||||
|
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
create table file_redirection (
|
||||||
|
id integer primary key auto_increment,
|
||||||
|
url varchar(255),
|
||||||
|
file_id integer,
|
||||||
|
redirections integer,
|
||||||
|
httpcode integer,
|
||||||
|
|
||||||
|
unique(url)
|
||||||
|
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
|
||||||
|
create table file_thumbnail (
|
||||||
|
id integer primary key auto_increment,
|
||||||
|
file_id integer,
|
||||||
|
url varchar(255),
|
||||||
|
width integer,
|
||||||
|
height integer,
|
||||||
|
|
||||||
|
unique(file_id),
|
||||||
|
unique(url)
|
||||||
|
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
|
||||||
|
create table file_to_post (
|
||||||
|
id integer primary key auto_increment,
|
||||||
|
file_id integer,
|
||||||
|
post_id integer,
|
||||||
|
|
||||||
|
unique(file_id, post_id)
|
||||||
|
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
|
||||||
|
|
||||||
|
@ -427,6 +427,64 @@ create table group_inbox (
|
|||||||
);
|
);
|
||||||
create index group_inbox_created_idx on group_inbox using btree(created);
|
create index group_inbox_created_idx on group_inbox using btree(created);
|
||||||
|
|
||||||
|
|
||||||
|
/*attachments and URLs stuff */
|
||||||
|
create sequence file_seq;
|
||||||
|
create table file (
|
||||||
|
id bigint default nextval('file_seq') primary key /* comment 'unique identifier' */,
|
||||||
|
url varchar(255) unique,
|
||||||
|
mimetype varchar(50),
|
||||||
|
size integer,
|
||||||
|
title varchar(255),
|
||||||
|
date integer(11),
|
||||||
|
protected integer(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
create sequence file_oembed_seq;
|
||||||
|
create table file_oembed (
|
||||||
|
id bigint default nextval('file_oembed_seq') primary key /* comment 'unique identifier' */,
|
||||||
|
file_id bigint unique,
|
||||||
|
version varchar(20),
|
||||||
|
type varchar(20),
|
||||||
|
provider varchar(50),
|
||||||
|
provider_url varchar(255),
|
||||||
|
width integer,
|
||||||
|
height integer,
|
||||||
|
html text,
|
||||||
|
title varchar(255),
|
||||||
|
author_name varchar(50),
|
||||||
|
author_url varchar(255),
|
||||||
|
url varchar(255),
|
||||||
|
);
|
||||||
|
|
||||||
|
create sequence file_redirection_seq;
|
||||||
|
create table file_redirection (
|
||||||
|
id bigint default nextval('file_redirection_seq') primary key /* comment 'unique identifier' */,
|
||||||
|
url varchar(255) unique,
|
||||||
|
file_id bigint,
|
||||||
|
redirections integer,
|
||||||
|
httpcode integer
|
||||||
|
);
|
||||||
|
|
||||||
|
create sequence file_thumbnail_seq;
|
||||||
|
create table file_thumbnail (
|
||||||
|
id bigint default nextval('file_thumbnail_seq') primary key /* comment 'unique identifier' */,
|
||||||
|
file_id bigint unique,
|
||||||
|
url varchar(255) unique,
|
||||||
|
width integer,
|
||||||
|
height integer
|
||||||
|
);
|
||||||
|
|
||||||
|
create sequence file_to_post_seq;
|
||||||
|
create table file_to_post (
|
||||||
|
id bigint default nextval('file_to_post_seq') primary key /* comment 'unique identifier' */,
|
||||||
|
file_id bigint,
|
||||||
|
post_id bigint,
|
||||||
|
|
||||||
|
unique(file_id, post_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/* Textsearch stuff */
|
/* Textsearch stuff */
|
||||||
|
|
||||||
create index textsearch_idx on profile using gist(textsearch);
|
create index textsearch_idx on profile using gist(textsearch);
|
||||||
|
6
js/jquery.joverlay.min.js
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/* Copyright (c) 2009 Alvaro A. Lima Jr http://alvarojunior.com/jquery/joverlay.html
|
||||||
|
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
||||||
|
* Version: 0.6 (Abr 23, 2009)
|
||||||
|
* Requires: jQuery 1.3+
|
||||||
|
*/
|
||||||
|
(function($){var f=$.browser.msie&&$.browser.version==6.0;var g=null;$.fn.jOverlay=function(b){var b=$.extend({},$.fn.jOverlay.options,b);if(g!=null){clearTimeout(g)}var c=this.is('*')?this:'#jOverlayContent';var d=f?'absolute':'fixed';var e=b.imgLoading?"<img id='jOverlayLoading' src='"+b.imgLoading+"' style='position:"+d+"; z-index:"+(b.zIndex+9)+";'/>":'';$('body').prepend(e+"<div id='jOverlay' />"+"<div id='jOverlayContent' style='position:"+d+"; z-index:"+(b.zIndex+5)+"; display:none;'/>");$('#jOverlayLoading').load(function(){if(b.center){$.center(this)}});if(f){$("select").hide();$("#jOverlayContent select").show()}$('#jOverlay').css({backgroundColor:b.color,position:d,top:'0px',left:'0px',filter:'alpha(opacity='+(b.opacity*100)+')',opacity:b.opacity,zIndex:b.zIndex,width:!f?'100%':$(window).width()+'px',height:!f?'100%':$(document).height()+'px'}).show();if(this.is('*')){$('#jOverlayContent').html(this.addClass('jOverlayChildren').show()).show();if(b.center){$.center('#jOverlayContent')}if(!b.url&&$.isFunction(b.success)){b.success(this.html())}}if(b.url){$.ajax({type:b.method,data:b.data,url:b.url,success:function(a){$('#jOverlayLoading').fadeOut(600);$(c).html(a).show();if(b.center){$.center('#jOverlayContent')}if($.isFunction(b.success)){b.success(a)}}})}if(f){$(window).scroll(function(){if(b.center){$.center('#jOverlayContent')}});$(window).resize(function(){$('#jOverlay').css({width:$(window).width()+'px',height:$(document).height()+'px'});if(b.center){$.center('#jOverlayContent')}})}$(document).keydown(function(a){if(a.keyCode==27){$.closeOverlay()}});if(b.bgClickToClose){$('#jOverlay').click($.closeOverlay)}if(Number(b.timeout)>0){g=setTimeout($.closeOverlay,Number(b.timeout))}};$.center=function(a){var a=$(a);var b=a.height();var c=a.width();a.css({width:c+'px',marginLeft:'-'+(c/2)+'px',marginTop:'-'+b/2+'px',height:'auto',top:!f?'50%':$(window).scrollTop()+($(window).height()/2)+"px",left:'50%'})};$.fn.jOverlay.options={method:'GET',data:'',url:'',color:'#000',opacity:'0.6',zIndex:9999,center:true,imgLoading:'',bgClickToClose:true,success:null,timeout:0};$.closeOverlay=function(){if(f){$("select").show()}$('#jOverlayContent .jOverlayChildren').hide().prependTo($('body'));$('#jOverlayLoading, #jOverlayContent, #jOverlay').remove()}})(jQuery);
|
@ -17,6 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(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; });
|
||||||
|
|
||||||
// count character on keyup
|
// count character on keyup
|
||||||
function counter(event){
|
function counter(event){
|
||||||
var maxLength = 140;
|
var maxLength = 140;
|
||||||
|
@ -22,6 +22,7 @@ if (!defined('LACONICA')) { exit(1); }
|
|||||||
class ShortUrlApi
|
class ShortUrlApi
|
||||||
{
|
{
|
||||||
protected $service_url;
|
protected $service_url;
|
||||||
|
protected $long_limit = 27;
|
||||||
|
|
||||||
function __construct($service_url)
|
function __construct($service_url)
|
||||||
{
|
{
|
||||||
@ -39,7 +40,7 @@ class ShortUrlApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function is_long($url) {
|
private function is_long($url) {
|
||||||
return strlen($url) >= 30;
|
return strlen($url) >= $this->long_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function http_post($data) {
|
protected function http_post($data) {
|
||||||
|
@ -98,15 +98,15 @@ class Action extends HTMLOutputter // lawsuit
|
|||||||
Event::handle('EndShowHTML', array($this));
|
Event::handle('EndShowHTML', array($this));
|
||||||
}
|
}
|
||||||
if (Event::handle('StartShowHead', array($this))) {
|
if (Event::handle('StartShowHead', array($this))) {
|
||||||
$this->showHead();
|
$this->showHead();
|
||||||
Event::handle('EndShowHead', array($this));
|
Event::handle('EndShowHead', array($this));
|
||||||
}
|
}
|
||||||
if (Event::handle('StartShowBody', array($this))) {
|
if (Event::handle('StartShowBody', array($this))) {
|
||||||
$this->showBody();
|
$this->showBody();
|
||||||
Event::handle('EndShowBody', array($this));
|
Event::handle('EndShowBody', array($this));
|
||||||
}
|
}
|
||||||
if (Event::handle('StartEndHTML', array($this))) {
|
if (Event::handle('StartEndHTML', array($this))) {
|
||||||
$this->endHTML();
|
$this->endHTML();
|
||||||
Event::handle('EndEndHTML', array($this));
|
Event::handle('EndEndHTML', array($this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,6 +243,12 @@ class Action extends HTMLOutputter // lawsuit
|
|||||||
$this->element('script', array('type' => 'text/javascript',
|
$this->element('script', array('type' => 'text/javascript',
|
||||||
'src' => common_path('js/jquery.form.js')),
|
'src' => common_path('js/jquery.form.js')),
|
||||||
' ');
|
' ');
|
||||||
|
|
||||||
|
$this->element('script', array('type' => 'text/javascript',
|
||||||
|
'src' => common_path('js/jquery.joverlay.min.js')),
|
||||||
|
' ');
|
||||||
|
|
||||||
|
|
||||||
Event::handle('EndShowJQueryScripts', array($this));
|
Event::handle('EndShowJQueryScripts', array($this));
|
||||||
}
|
}
|
||||||
if (Event::handle('StartShowLaconicaScripts', array($this))) {
|
if (Event::handle('StartShowLaconicaScripts', array($this))) {
|
||||||
|
300
lib/attachmentlist.php
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Laconica, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* widget for displaying a list of 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 UI
|
||||||
|
* @package Laconica
|
||||||
|
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||||
|
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
||||||
|
* @copyright 2008 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* widget for displaying a list of notice attachments
|
||||||
|
*
|
||||||
|
* There are a number of actions that display a list of notices, in
|
||||||
|
* reverse chronological order. This widget abstracts out most of the
|
||||||
|
* code for UI for notice lists. It's overridden to hide some
|
||||||
|
* data for e.g. the profile page.
|
||||||
|
*
|
||||||
|
* @category UI
|
||||||
|
* @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/
|
||||||
|
* @see Notice
|
||||||
|
* @see StreamAction
|
||||||
|
* @see NoticeListItem
|
||||||
|
* @see ProfileNoticeList
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AttachmentList extends Widget
|
||||||
|
{
|
||||||
|
/** the current stream of notices being displayed. */
|
||||||
|
|
||||||
|
var $notice = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
*
|
||||||
|
* @param Notice $notice stream of notices from DB_DataObject
|
||||||
|
*/
|
||||||
|
|
||||||
|
function __construct($notice, $out=null)
|
||||||
|
{
|
||||||
|
parent::__construct($out);
|
||||||
|
$this->notice = $notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* show the list of notices
|
||||||
|
*
|
||||||
|
* "Uses up" the stream by looping through it. So, probably can't
|
||||||
|
* be called twice on the same list.
|
||||||
|
*
|
||||||
|
* @return int count of notices listed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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('ul', array('class' => 'attachments'));
|
||||||
|
|
||||||
|
$atts = new File;
|
||||||
|
$att = $atts->getAttachments($this->notice->id);
|
||||||
|
foreach ($att as $n=>$attachment) {
|
||||||
|
$item = $this->newListItem($attachment);
|
||||||
|
$item->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->out->elementEnd('ul');
|
||||||
|
$this->out->elementEnd('div');
|
||||||
|
|
||||||
|
return count($att);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a new list item for the current notice
|
||||||
|
*
|
||||||
|
* Recipe (factory?) method; overridden by sub-classes to give
|
||||||
|
* a different list item class.
|
||||||
|
*
|
||||||
|
* @param Notice $notice the current notice
|
||||||
|
*
|
||||||
|
* @return NoticeListItem a list item for displaying the notice
|
||||||
|
*/
|
||||||
|
|
||||||
|
function newListItem($attachment)
|
||||||
|
{
|
||||||
|
return new AttachmentListItem($attachment, $this->out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* widget for displaying a single notice
|
||||||
|
*
|
||||||
|
* This widget has the core smarts for showing a single notice: what to display,
|
||||||
|
* where, and under which circumstances. Its key method is show(); this is a recipe
|
||||||
|
* that calls all the other show*() methods to build up a single notice. The
|
||||||
|
* ProfileNoticeListItem subclass, for example, overrides showAuthor() to skip
|
||||||
|
* author info (since that's implicit by the data in the page).
|
||||||
|
*
|
||||||
|
* @category UI
|
||||||
|
* @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/
|
||||||
|
* @see NoticeList
|
||||||
|
* @see ProfileNoticeListItem
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AttachmentListItem extends Widget
|
||||||
|
{
|
||||||
|
/** The attachment this item will show. */
|
||||||
|
|
||||||
|
var $attachment = null;
|
||||||
|
|
||||||
|
var $oembed = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
*
|
||||||
|
* Also initializes the profile attribute.
|
||||||
|
*
|
||||||
|
* @param Notice $notice The notice we'll display
|
||||||
|
*/
|
||||||
|
|
||||||
|
function __construct($attachment, $out=null)
|
||||||
|
{
|
||||||
|
parent::__construct($out);
|
||||||
|
$this->attachment = $attachment;
|
||||||
|
$this->oembed = File_oembed::staticGet('file_id', $this->attachment->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function title() {
|
||||||
|
if (empty($this->attachment->title)) {
|
||||||
|
if (empty($this->oembed->title)) {
|
||||||
|
$title = $this->attachment->url;
|
||||||
|
} else {
|
||||||
|
$title = $this->oembed->title;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$title = $this->attachment->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
function linkTitle() {
|
||||||
|
return 'Our page for ' . $this->title();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recipe function for displaying a single notice.
|
||||||
|
*
|
||||||
|
* This uses all the other methods to correctly display a notice. Override
|
||||||
|
* it or one of the others to fine-tune the output.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function show()
|
||||||
|
{
|
||||||
|
$this->showStart();
|
||||||
|
$this->showNoticeAttachment();
|
||||||
|
$this->showEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
function linkAttr() {
|
||||||
|
return array('class' => 'attachment', 'href' => common_local_url('attachment', array('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');
|
||||||
|
}
|
||||||
|
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start a single notice.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function showStart()
|
||||||
|
{
|
||||||
|
// XXX: RDFa
|
||||||
|
// TODO: add notice_type class e.g., notice_video, notice_image
|
||||||
|
$this->out->elementStart('li');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* finish the notice
|
||||||
|
*
|
||||||
|
* Close the last elements in the notice list item
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function showEnd()
|
||||||
|
{
|
||||||
|
$this->out->elementEnd('li');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Attachment extends AttachmentListItem
|
||||||
|
{
|
||||||
|
function show() {
|
||||||
|
$this->showNoticeAttachment();
|
||||||
|
}
|
||||||
|
|
||||||
|
function linkAttr() {
|
||||||
|
return array('class' => 'external', 'href' => $this->attachment->url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function linkTitle() {
|
||||||
|
return 'Direct link to ' . $this->title();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showRepresentation() {
|
||||||
|
if (empty($this->oembed->type)) {
|
||||||
|
if (empty($this->attachment->mimetype)) {
|
||||||
|
$this->out->element('pre', null, 'oh well... not sure how to handle the following: ' . print_r($this->attachment, true));
|
||||||
|
} else {
|
||||||
|
switch ($this->attachment->mimetype) {
|
||||||
|
case 'image/gif':
|
||||||
|
case 'image/png':
|
||||||
|
case 'image/jpg':
|
||||||
|
case 'image/jpeg':
|
||||||
|
$this->out->element('img', array('src' => $this->attachment->url, 'alt' => 'alt'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch ($this->oembed->type) {
|
||||||
|
case 'rich':
|
||||||
|
case 'video':
|
||||||
|
case 'link':
|
||||||
|
if (!empty($this->oembed->html)) {
|
||||||
|
$this->out->raw($this->oembed->html);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'photo':
|
||||||
|
$this->out->element('img', array('src' => $this->oembed->url, 'width' => $this->oembed->width, 'height' => $this->oembed->height, 'alt' => 'alt'));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$this->out->element('pre', null, 'oh well... not sure how to handle the following oembed: ' . print_r($this->oembed, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -179,22 +179,86 @@ class NoticeListItem extends Widget
|
|||||||
{
|
{
|
||||||
$this->showStart();
|
$this->showStart();
|
||||||
$this->showNotice();
|
$this->showNotice();
|
||||||
$this->showNoticeInfo();
|
$this->showNoticeAttachments();
|
||||||
$this->showNoticeOptions();
|
$this->showNoticeOptions();
|
||||||
|
$this->showNoticeInfo();
|
||||||
$this->showEnd();
|
$this->showEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showNotice()
|
function showNotice()
|
||||||
{
|
{
|
||||||
$this->out->elementStart('div', 'entry-title');
|
if (0)
|
||||||
|
$this->out->elementStart('entry-title');
|
||||||
|
else
|
||||||
|
|
||||||
|
if ('shownotice' === $this->out->args['action']) {
|
||||||
|
$width = '85%';
|
||||||
|
} else {
|
||||||
|
$width = '90%';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$this->out->elementStart('div', array('class' => 'entry-title', 'style' => "float: left; width: $width;"));
|
||||||
$this->showAuthor();
|
$this->showAuthor();
|
||||||
$this->showContent();
|
$this->showContent();
|
||||||
$this->out->elementEnd('div');
|
$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';
|
||||||
|
}
|
||||||
|
|
||||||
|
$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);
|
||||||
|
|
||||||
|
|
||||||
|
$this->out->elementEnd('p');
|
||||||
|
}
|
||||||
|
|
||||||
function showNoticeInfo()
|
function showNoticeInfo()
|
||||||
{
|
{
|
||||||
|
if(0)
|
||||||
$this->out->elementStart('div', 'entry-content');
|
$this->out->elementStart('div', 'entry-content');
|
||||||
|
else
|
||||||
|
|
||||||
|
if ('shownotice' === $this->out->args['action']) {
|
||||||
|
$width = '85%';
|
||||||
|
} else {
|
||||||
|
$width = '90%';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->out->elementStart('div', array('class' => 'entry-content', 'style' => "float: left; width: $width;"));
|
||||||
$this->showNoticeLink();
|
$this->showNoticeLink();
|
||||||
$this->showNoticeSource();
|
$this->showNoticeSource();
|
||||||
$this->showContext();
|
$this->showContext();
|
||||||
@ -205,7 +269,10 @@ class NoticeListItem extends Widget
|
|||||||
{
|
{
|
||||||
$user = common_current_user();
|
$user = common_current_user();
|
||||||
if ($user) {
|
if ($user) {
|
||||||
|
if(0)
|
||||||
$this->out->elementStart('div', 'notice-options');
|
$this->out->elementStart('div', 'notice-options');
|
||||||
|
else
|
||||||
|
$this->out->elementStart('div', array('class' => 'notice-options', 'style' => 'float: right; width: 16%;'));
|
||||||
$this->showFaveForm();
|
$this->showFaveForm();
|
||||||
$this->showReplyLink();
|
$this->showReplyLink();
|
||||||
$this->showDeleteLink();
|
$this->showDeleteLink();
|
||||||
|
@ -151,12 +151,26 @@ class Router
|
|||||||
$m->connect('search/notice/rss?q=:q', array('action' => 'noticesearchrss'),
|
$m->connect('search/notice/rss?q=:q', array('action' => 'noticesearchrss'),
|
||||||
array('q' => '.+'));
|
array('q' => '.+'));
|
||||||
|
|
||||||
|
$m->connect('attachment/:attachment/ajax',
|
||||||
|
array('action' => 'attachment_ajax'),
|
||||||
|
array('notice' => '[0-9]+'));
|
||||||
|
|
||||||
|
$m->connect('attachment/:attachment',
|
||||||
|
array('action' => 'attachment'),
|
||||||
|
array('notice' => '[0-9]+'));
|
||||||
|
|
||||||
// notice
|
// notice
|
||||||
|
|
||||||
$m->connect('notice/new', array('action' => 'newnotice'));
|
$m->connect('notice/new', array('action' => 'newnotice'));
|
||||||
$m->connect('notice/new?replyto=:replyto',
|
$m->connect('notice/new?replyto=:replyto',
|
||||||
array('action' => 'newnotice'),
|
array('action' => 'newnotice'),
|
||||||
array('replyto' => '[A-Za-z0-9_-]+'));
|
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',
|
$m->connect('notice/:notice',
|
||||||
array('action' => 'shownotice'),
|
array('action' => 'shownotice'),
|
||||||
array('notice' => '[0-9]+'));
|
array('notice' => '[0-9]+'));
|
||||||
|
116
lib/util.php
@ -395,7 +395,7 @@ function common_render_text($text)
|
|||||||
return $r;
|
return $r;
|
||||||
}
|
}
|
||||||
|
|
||||||
function common_replace_urls_callback($text, $callback) {
|
function common_replace_urls_callback($text, $callback, $notice_id = null) {
|
||||||
// Start off with a regex
|
// Start off with a regex
|
||||||
$regex = '#'.
|
$regex = '#'.
|
||||||
'(?:'.
|
'(?:'.
|
||||||
@ -466,7 +466,11 @@ function common_replace_urls_callback($text, $callback) {
|
|||||||
$url = (mb_strpos($orig_url, htmlspecialchars($url)) === FALSE) ? $url:htmlspecialchars($url);
|
$url = (mb_strpos($orig_url, htmlspecialchars($url)) === FALSE) ? $url:htmlspecialchars($url);
|
||||||
|
|
||||||
// Call user specified func
|
// Call user specified func
|
||||||
$modified_url = call_user_func($callback, $url);
|
if (empty($notice_id)) {
|
||||||
|
$modified_url = call_user_func($callback, $url);
|
||||||
|
} else {
|
||||||
|
$modified_url = call_user_func($callback, array($url, $notice_id));
|
||||||
|
}
|
||||||
|
|
||||||
// Replace it!
|
// Replace it!
|
||||||
$start = mb_strpos($text, $url, $offset);
|
$start = mb_strpos($text, $url, $offset);
|
||||||
@ -481,107 +485,29 @@ function common_linkify($url) {
|
|||||||
// It comes in special'd, so we unspecial it before passing to the stringifying
|
// It comes in special'd, so we unspecial it before passing to the stringifying
|
||||||
// functions
|
// functions
|
||||||
$url = htmlspecialchars_decode($url);
|
$url = htmlspecialchars_decode($url);
|
||||||
$display = $url;
|
$display = File_redirection::_canonUrl($url);
|
||||||
$url = (!preg_match('#^([a-z]+://|(mailto|aim|tel):)#i', $url)) ? 'http://'.$url : $url;
|
$longurl_data = File_redirection::where($url);
|
||||||
|
if (is_array($longurl_data)) {
|
||||||
$attrs = array('href' => $url, 'rel' => 'external');
|
$longurl = $longurl_data['url'];
|
||||||
|
} elseif (is_string($longurl_data)) {
|
||||||
if ($longurl = common_longurl($url)) {
|
$longurl = $longurl_data;
|
||||||
$attrs['title'] = $longurl;
|
} else {
|
||||||
|
die('impossible to linkify');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$attrs = array('href' => $longurl, 'rel' => 'external');
|
||||||
|
if(0){
|
||||||
|
if ($longurl !== $url) {
|
||||||
|
$attrs['title'] = $longurl;
|
||||||
|
}
|
||||||
|
}
|
||||||
return XMLStringer::estring('a', $attrs, $display);
|
return XMLStringer::estring('a', $attrs, $display);
|
||||||
}
|
}
|
||||||
|
|
||||||
function common_longurl($short_url)
|
|
||||||
{
|
|
||||||
$long_url = common_shorten_link($short_url, true);
|
|
||||||
if ($long_url === $short_url) return false;
|
|
||||||
return $long_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
function common_longurl2($uri)
|
|
||||||
{
|
|
||||||
$uri_e = urlencode($uri);
|
|
||||||
$longurl = unserialize(file_get_contents("http://api.longurl.org/v1/expand?format=php&url=$uri_e"));
|
|
||||||
if (empty($longurl['long_url']) || $uri === $longurl['long_url']) return false;
|
|
||||||
return stripslashes($longurl['long_url']);
|
|
||||||
}
|
|
||||||
|
|
||||||
function common_shorten_links($text)
|
function common_shorten_links($text)
|
||||||
{
|
{
|
||||||
if (mb_strlen($text) <= 140) return $text;
|
if (mb_strlen($text) <= 140) return $text;
|
||||||
static $cache = array();
|
return common_replace_urls_callback($text, array('File_redirection', 'makeShort'));
|
||||||
if (isset($cache[$text])) return $cache[$text];
|
|
||||||
// \s = not a horizontal whitespace character (since PHP 5.2.4)
|
|
||||||
return $cache[$text] = common_replace_urls_callback($text, 'common_shorten_link');;
|
|
||||||
}
|
|
||||||
|
|
||||||
function common_shorten_link($url, $reverse = false)
|
|
||||||
{
|
|
||||||
|
|
||||||
static $url_cache = array();
|
|
||||||
if ($reverse) return isset($url_cache[$url]) ? $url_cache[$url] : $url;
|
|
||||||
|
|
||||||
$user = common_current_user();
|
|
||||||
if (!isset($user)) {
|
|
||||||
// common current user does not find a user when called from the XMPP daemon
|
|
||||||
// therefore we'll set one here fix, so that XMPP given URLs may be shortened
|
|
||||||
$user->urlshorteningservice = 'ur1.ca';
|
|
||||||
}
|
|
||||||
$curlh = curl_init();
|
|
||||||
curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait
|
|
||||||
curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica');
|
|
||||||
curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true);
|
|
||||||
|
|
||||||
switch($user->urlshorteningservice) {
|
|
||||||
case 'ur1.ca':
|
|
||||||
$short_url_service = new LilUrl;
|
|
||||||
$short_url = $short_url_service->shorten($url);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '2tu.us':
|
|
||||||
$short_url_service = new TightUrl;
|
|
||||||
$short_url = $short_url_service->shorten($url);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ptiturl.com':
|
|
||||||
$short_url_service = new PtitUrl;
|
|
||||||
$short_url = $short_url_service->shorten($url);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'bit.ly':
|
|
||||||
curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($url));
|
|
||||||
$short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'is.gd':
|
|
||||||
curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($url));
|
|
||||||
$short_url = curl_exec($curlh);
|
|
||||||
break;
|
|
||||||
case 'snipr.com':
|
|
||||||
curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($url));
|
|
||||||
$short_url = curl_exec($curlh);
|
|
||||||
break;
|
|
||||||
case 'metamark.net':
|
|
||||||
curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($url));
|
|
||||||
$short_url = curl_exec($curlh);
|
|
||||||
break;
|
|
||||||
case 'tinyurl.com':
|
|
||||||
curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($url));
|
|
||||||
$short_url = curl_exec($curlh);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$short_url = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_close($curlh);
|
|
||||||
|
|
||||||
if ($short_url) {
|
|
||||||
$url_cache[(string)$short_url] = $url;
|
|
||||||
return (string)$short_url;
|
|
||||||
}
|
|
||||||
return $url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function common_xml_safe_str($str)
|
function common_xml_safe_str($str)
|
||||||
|
BIN
theme/base/images/icons/clip-big.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
theme/base/images/icons/clip.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 2.2 KiB |
@ -12,7 +12,7 @@ img { display:block; border:0; }
|
|||||||
a abbr { cursor: pointer; border-bottom:0; }
|
a abbr { cursor: pointer; border-bottom:0; }
|
||||||
table { border-collapse:collapse; }
|
table { border-collapse:collapse; }
|
||||||
ol { list-style-position:inside; }
|
ol { list-style-position:inside; }
|
||||||
html { font-size: 100%; background-color:#fff; height:100%; }
|
html { font-size: 100%; background-color:#fff; }
|
||||||
body {
|
body {
|
||||||
background-color:#fff;
|
background-color:#fff;
|
||||||
color:#000;
|
color:#000;
|
||||||
@ -126,7 +126,7 @@ margin-left:0;
|
|||||||
|
|
||||||
.form_settings label {
|
.form_settings label {
|
||||||
margin-top:2px;
|
margin-top:2px;
|
||||||
width:145px;
|
width:143px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form_actions label {
|
.form_actions label {
|
||||||
|
Before Width: | Height: | Size: 1006 B After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 4.9 KiB |
@ -1,4 +1,4 @@
|
|||||||
/** theme: earthy base
|
/** theme: h4ck3r base
|
||||||
*
|
*
|
||||||
* @package Laconica
|
* @package Laconica
|
||||||
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
||||||
@ -12,7 +12,7 @@ img { display:block; border:0; }
|
|||||||
a abbr { cursor: pointer; border-bottom:0; }
|
a abbr { cursor: pointer; border-bottom:0; }
|
||||||
table { border-collapse:collapse; }
|
table { border-collapse:collapse; }
|
||||||
ol { list-style-position:inside; }
|
ol { list-style-position:inside; }
|
||||||
html { background-color:#fff; height:100%; }
|
html { font-size: 100%; background-color:#fff; height:100%; }
|
||||||
body {
|
body {
|
||||||
background-color:#fff;
|
background-color:#fff;
|
||||||
color:#000;
|
color:#000;
|
||||||
@ -28,7 +28,6 @@ overflow:hidden;
|
|||||||
h1 {
|
h1 {
|
||||||
font-size:1.4em;
|
font-size:1.4em;
|
||||||
margin-bottom:18px;
|
margin-bottom:18px;
|
||||||
text-align:right;
|
|
||||||
}
|
}
|
||||||
#showstream h1 { display:none; }
|
#showstream h1 { display:none; }
|
||||||
h2 { font-size:1.3em; }
|
h2 { font-size:1.3em; }
|
||||||
@ -52,9 +51,6 @@ font-size:1em;
|
|||||||
input, textarea, select {
|
input, textarea, select {
|
||||||
border-width:2px;
|
border-width:2px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-radius:4px;
|
|
||||||
-moz-border-radius:4px;
|
|
||||||
-webkit-border-radius:4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input.submit {
|
input.submit {
|
||||||
@ -87,10 +83,7 @@ border:0;
|
|||||||
|
|
||||||
.error,
|
.error,
|
||||||
.success {
|
.success {
|
||||||
padding:4px 7px;
|
padding:4px 1.55%;
|
||||||
border-radius:4px;
|
|
||||||
-moz-border-radius:4px;
|
|
||||||
-webkit-border-radius:4px;
|
|
||||||
margin-bottom:18px;
|
margin-bottom:18px;
|
||||||
}
|
}
|
||||||
form label.submit {
|
form label.submit {
|
||||||
@ -192,9 +185,6 @@ margin-left:0;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.form_settings .form_note {
|
.form_settings .form_note {
|
||||||
border-radius:4px;
|
|
||||||
-moz-border-radius:4px;
|
|
||||||
-webkit-border-radius:4px;
|
|
||||||
padding:0 7px;
|
padding:0 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,11 +239,11 @@ display:none;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#site_notice {
|
#site_notice {
|
||||||
position:absolute;
|
float:left;
|
||||||
top:65px;
|
clear:right;
|
||||||
right:18px;
|
margin-top:7px;
|
||||||
width:250px;
|
margin-right:18px;
|
||||||
width:24%;
|
width:31%;
|
||||||
}
|
}
|
||||||
#page_notice {
|
#page_notice {
|
||||||
clear:both;
|
clear:both;
|
||||||
@ -262,17 +252,17 @@ margin-bottom:18px;
|
|||||||
|
|
||||||
|
|
||||||
#anon_notice {
|
#anon_notice {
|
||||||
float:left;
|
float:right;
|
||||||
width:43.2%;
|
clear:right;
|
||||||
|
width:41.2%;
|
||||||
padding:1.1%;
|
padding:1.1%;
|
||||||
border-radius:7px;
|
|
||||||
-moz-border-radius:7px;
|
|
||||||
-webkit-border-radius:7px;
|
|
||||||
border-width:2px;
|
border-width:2px;
|
||||||
border-style:solid;
|
border-style:dashed;
|
||||||
line-height:1.5;
|
line-height:1.5;
|
||||||
font-size:1.1em;
|
font-size:1.1em;
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
|
-moz-transform:skewX(-30deg) scale(0.85);
|
||||||
|
-webkit-transform:skewX(-30deg) scale(0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -283,6 +273,7 @@ padding:18px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#site_nav_local_views {
|
#site_nav_local_views {
|
||||||
|
width:100%;
|
||||||
float:right;
|
float:right;
|
||||||
}
|
}
|
||||||
#site_nav_local_views dt {
|
#site_nav_local_views dt {
|
||||||
@ -297,12 +288,8 @@ list-style-type:none;
|
|||||||
float:left;
|
float:left;
|
||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
padding:4px 11px;
|
padding:4px 11px;
|
||||||
-moz-border-radius-topleft:4px;
|
|
||||||
-moz-border-radius-topright:4px;
|
|
||||||
-webkit-border-top-left-radius:4px;
|
|
||||||
-webkit-border-top-right-radius:4px;
|
|
||||||
border-width:1px;
|
border-width:1px;
|
||||||
border-style:solid;
|
border-style:dashed;
|
||||||
border-bottom:0;
|
border-bottom:0;
|
||||||
text-shadow: 2px 2px 2px #ddd;
|
text-shadow: 2px 2px 2px #ddd;
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
@ -310,8 +297,6 @@ font-weight:bold;
|
|||||||
#site_nav_local_views .nav {
|
#site_nav_local_views .nav {
|
||||||
float:left;
|
float:left;
|
||||||
width:100%;
|
width:100%;
|
||||||
border-bottom-width:1px;
|
|
||||||
border-bottom-style:solid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#site_nav_global_primary dt,
|
#site_nav_global_primary dt,
|
||||||
@ -387,15 +372,15 @@ margin-bottom:1em;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
width:63.009%;
|
width:60.009%;
|
||||||
min-height:259px;
|
min-height:259px;
|
||||||
padding-top:1.795%;
|
padding:1.795%;
|
||||||
padding-bottom:1.795%;
|
|
||||||
float:right;
|
float:right;
|
||||||
clear:both;
|
border-style:dashed;
|
||||||
border-radius:7px;
|
border-width:1px;
|
||||||
border-style:solid;
|
}
|
||||||
border-width:0;
|
#shownotice #content {
|
||||||
|
min-height:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content_inner {
|
#content_inner {
|
||||||
@ -409,33 +394,27 @@ width:27.917%;
|
|||||||
min-height:259px;
|
min-height:259px;
|
||||||
float:right;
|
float:right;
|
||||||
margin-right:4.385%;
|
margin-right:4.385%;
|
||||||
margin-top:73px;
|
|
||||||
padding:1.795%;
|
padding:1.795%;
|
||||||
border-radius:7px;
|
|
||||||
-moz-border-radius:7px;
|
|
||||||
-webkit-border-radius:7px;
|
|
||||||
border-width:1px;
|
border-width:1px;
|
||||||
border-style:solid;
|
border-style:dashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#form_notice {
|
#form_notice {
|
||||||
width:45.664%;
|
width:43.664%;
|
||||||
float:left;
|
float:right;
|
||||||
position:relative;
|
position:relative;
|
||||||
line-height:1;
|
line-height:1;
|
||||||
}
|
}
|
||||||
#form_notice fieldset {
|
#form_notice fieldset {
|
||||||
border:0;
|
border:0;
|
||||||
padding:0;
|
padding:0;
|
||||||
|
position:relative;
|
||||||
}
|
}
|
||||||
#form_notice legend {
|
#form_notice legend {
|
||||||
display:none;
|
display:none;
|
||||||
}
|
}
|
||||||
#form_notice textarea {
|
#form_notice textarea {
|
||||||
float:left;
|
float:left;
|
||||||
border-radius:7px;
|
|
||||||
-moz-border-radius:7px;
|
|
||||||
-webkit-border-radius:7px;
|
|
||||||
width:80.789%;
|
width:80.789%;
|
||||||
height:67px;
|
height:67px;
|
||||||
line-height:1.5;
|
line-height:1.5;
|
||||||
@ -481,7 +460,13 @@ margin-bottom:7px;
|
|||||||
margin-left:18px;
|
margin-left:18px;
|
||||||
float:left;
|
float:left;
|
||||||
}
|
}
|
||||||
|
#form_notice .error {
|
||||||
|
float:left;
|
||||||
|
clear:both;
|
||||||
|
width:96.9%;
|
||||||
|
margin-bottom:0;
|
||||||
|
line-height:1.618;
|
||||||
|
}
|
||||||
|
|
||||||
/* entity_profile */
|
/* entity_profile */
|
||||||
.entity_profile {
|
.entity_profile {
|
||||||
@ -715,32 +700,18 @@ margin-right:11px;
|
|||||||
.notice,
|
.notice,
|
||||||
.profile {
|
.profile {
|
||||||
position:relative;
|
position:relative;
|
||||||
|
padding-top:11px;
|
||||||
|
padding-bottom:11px;
|
||||||
clear:both;
|
clear:both;
|
||||||
float:left;
|
float:left;
|
||||||
width:100%;
|
width:100%;
|
||||||
border-width:1px;
|
border-top-width:1px;
|
||||||
border-style:solid;
|
border-top-style:dashed;
|
||||||
border-radius:7px;
|
|
||||||
-moz-border-radius:7px;
|
|
||||||
-webkit-border-radius:7px;
|
|
||||||
}
|
}
|
||||||
#content .notice,
|
|
||||||
#content .profile {
|
|
||||||
padding:1.795%;
|
|
||||||
margin-bottom:44px;
|
|
||||||
}
|
|
||||||
#content .notice {
|
|
||||||
width:96.25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.notices li {
|
.notices li {
|
||||||
list-style-type:none;
|
list-style-type:none;
|
||||||
}
|
}
|
||||||
.notices li.hover {
|
|
||||||
border-radius:4px;
|
|
||||||
-moz-border-radius:4px;
|
|
||||||
-webkit-border-radius:4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NOTICES */
|
/* NOTICES */
|
||||||
#notices_primary {
|
#notices_primary {
|
||||||
@ -770,16 +741,14 @@ overflow:hidden;
|
|||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice .author .photo {
|
|
||||||
margin-bottom:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vcard .photo {
|
.vcard .photo {
|
||||||
display:inline;
|
display:inline;
|
||||||
margin-right:11px;
|
margin-right:11px;
|
||||||
margin-bottom:11px;
|
|
||||||
float:left;
|
float:left;
|
||||||
}
|
}
|
||||||
|
#shownotice .vcard .photo {
|
||||||
|
margin-bottom:4px;
|
||||||
|
}
|
||||||
.vcard .url {
|
.vcard .url {
|
||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
}
|
}
|
||||||
@ -788,7 +757,7 @@ text-decoration:underline;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.notice .entry-title {
|
.notice .entry-title {
|
||||||
float:left;
|
display:inline;
|
||||||
width:100%;
|
width:100%;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
}
|
}
|
||||||
@ -812,14 +781,9 @@ border-radius:4px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.notice div.entry-content {
|
.notice div.entry-content {
|
||||||
clear:left;
|
|
||||||
float:left;
|
float:left;
|
||||||
font-size:0.95em;
|
font-size:0.95em;
|
||||||
margin-left:59px;
|
width:65%;
|
||||||
width:70%;
|
|
||||||
}
|
|
||||||
#showstream .notice div.entry-content {
|
|
||||||
margin-left:0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice .notice-options a,
|
.notice .notice-options a,
|
||||||
@ -846,23 +810,6 @@ text-transform:lowercase;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.notice-data {
|
|
||||||
position:absolute;
|
|
||||||
top:18px;
|
|
||||||
right:0;
|
|
||||||
min-height:50px;
|
|
||||||
margin-bottom:4px;
|
|
||||||
}
|
|
||||||
.notice .entry-content .notice-data dt {
|
|
||||||
display:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.notice-data a {
|
|
||||||
display:block;
|
|
||||||
outline:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.notice-options {
|
.notice-options {
|
||||||
padding-left:2%;
|
padding-left:2%;
|
||||||
float:left;
|
float:left;
|
||||||
@ -1040,6 +987,8 @@ padding-right:30px;
|
|||||||
.hentry .entry-content p {
|
.hentry .entry-content p {
|
||||||
margin-bottom:18px;
|
margin-bottom:18px;
|
||||||
}
|
}
|
||||||
|
.system_notice ul,
|
||||||
|
.instructions ul,
|
||||||
.hentry entry-content ol,
|
.hentry entry-content ol,
|
||||||
.hentry .entry-content ul {
|
.hentry .entry-content ul {
|
||||||
list-style-position:inside;
|
list-style-position:inside;
|
@ -1,4 +1,4 @@
|
|||||||
/** theme: earthy
|
/** theme: h4ck3r
|
||||||
*
|
*
|
||||||
* @package Laconica
|
* @package Laconica
|
||||||
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
||||||
@ -12,26 +12,27 @@
|
|||||||
html,
|
html,
|
||||||
body,
|
body,
|
||||||
a:active {
|
a:active {
|
||||||
background-color:#665500;
|
background-color:#000;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: Verdana, sans-serif;
|
background-image:url(../images/illustrations/illu_h4x0r1ng.gif);
|
||||||
|
font-family: monospace;
|
||||||
font-size:1em;
|
font-size:1em;
|
||||||
|
color:#647819;
|
||||||
}
|
}
|
||||||
address {
|
address {
|
||||||
margin-right:7.18%;
|
margin-right:7.18%;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
input, textarea, select, option {
|
input, textarea, select, option {
|
||||||
font-family: Verdana, sans-serif;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
input, textarea, select,
|
input, textarea, select,
|
||||||
.entity_remote_subscribe {
|
.entity_remote_subscribe {
|
||||||
border-color:#aaa;
|
border-color:#aaa;
|
||||||
|
background-color:#000;
|
||||||
|
color:#ccc;
|
||||||
}
|
}
|
||||||
#filter_tags ul li {
|
#filter_tags ul li {
|
||||||
border-color:#ddd;
|
border-color:#ddd;
|
||||||
@ -45,7 +46,7 @@ input.submit,
|
|||||||
#form_notice.warning #notice_text-count,
|
#form_notice.warning #notice_text-count,
|
||||||
.form_settings .form_note,
|
.form_settings .form_note,
|
||||||
.entity_remote_subscribe {
|
.entity_remote_subscribe {
|
||||||
background-color:#9BB43E;
|
background-color:rgba(0, 255, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
input:focus, textarea:focus, select:focus,
|
input:focus, textarea:focus, select:focus,
|
||||||
@ -54,7 +55,7 @@ border-color:#9BB43E;
|
|||||||
}
|
}
|
||||||
input.submit,
|
input.submit,
|
||||||
.entity_remote_subscribe {
|
.entity_remote_subscribe {
|
||||||
color:#dddd33;
|
color:#fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
a,
|
a,
|
||||||
@ -65,57 +66,45 @@ div.notice-options input,
|
|||||||
.form_user_nudge input.submit,
|
.form_user_nudge input.submit,
|
||||||
.entity_nudge p,
|
.entity_nudge p,
|
||||||
.form_settings input.form_action-secondary {
|
.form_settings input.form_action-secondary {
|
||||||
color:#ee4400;
|
color:#0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice,
|
.notice,
|
||||||
.profile {
|
.profile {
|
||||||
border-color:#DDAA00;
|
border-top-color:#333;
|
||||||
}
|
}
|
||||||
.section .profile {
|
.section .profile {
|
||||||
border-top-color:#aaaa66;
|
border-top-color:#87B4C8;
|
||||||
}
|
|
||||||
|
|
||||||
#content .notice p.entry-content a:visited {
|
|
||||||
background-color:#fcfcfc;
|
|
||||||
}
|
|
||||||
#content .notice p.entry-content .vcard a {
|
|
||||||
background-color:#fcfffc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#aside_primary {
|
#aside_primary {
|
||||||
background-color:#DDAA00;
|
background-color:rgba(0,128,0,0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#notice_text-count {
|
#notice_text-count {
|
||||||
color:#333;
|
color:#0f0;
|
||||||
}
|
}
|
||||||
#form_notice.warning #notice_text-count {
|
#form_notice.warning #notice_text-count {
|
||||||
color:#000;
|
color:#000;
|
||||||
}
|
}
|
||||||
#form_notice.processing #notice_action-submit {
|
#form_notice.processing #notice_action-submit {
|
||||||
background:#dddd33 url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
|
background:#ccc url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
|
||||||
cursor:wait;
|
cursor:wait;
|
||||||
text-indent:-9999px;
|
text-indent:-9999px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content,
|
#content,
|
||||||
#site_nav_local_views .nav,
|
|
||||||
#site_nav_local_views a,
|
#site_nav_local_views a,
|
||||||
#aside_primary {
|
#aside_primary {
|
||||||
border-color:#dddd33;
|
border-color:#50964D;
|
||||||
}
|
}
|
||||||
#content .notice,
|
#content,
|
||||||
#content .profile,
|
|
||||||
#site_nav_local_views .current a {
|
#site_nav_local_views .current a {
|
||||||
background-color:#dddd33;
|
background-color:rgba(0, 0, 0, 0.698);
|
||||||
}
|
|
||||||
#site_nav_local_views .current a {
|
|
||||||
color:#EE4400;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#site_nav_local_views a {
|
#site_nav_local_views a {
|
||||||
background-color:rgba(255, 255, 255, 0.2);
|
background-color:rgba(0, 200, 0, 0.3);
|
||||||
color:#fff;
|
|
||||||
}
|
}
|
||||||
#site_nav_local_views a:hover {
|
#site_nav_local_views a:hover {
|
||||||
background-color:rgba(255, 255, 255, 0.4);
|
background-color:rgba(255, 255, 255, 0.4);
|
||||||
@ -129,13 +118,11 @@ background-color:#EFF3DC;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#anon_notice {
|
#anon_notice {
|
||||||
background-color:#aaaa66;
|
color:#ccc;
|
||||||
color:#dddd33;
|
border-color:#50964D;
|
||||||
border-color:#dddd33;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#showstream #anon_notice {
|
#showstream #anon_notice {
|
||||||
background-color:#9BB43E;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#export_data li a {
|
#export_data li a {
|
||||||
@ -167,12 +154,12 @@ background-color:transparent;
|
|||||||
.form_user_subscribe input.submit,
|
.form_user_subscribe input.submit,
|
||||||
.form_user_unsubscribe input.submit {
|
.form_user_unsubscribe input.submit {
|
||||||
background-color:#9BB43E;
|
background-color:#9BB43E;
|
||||||
color:#dddd33;
|
color:#ccc;
|
||||||
}
|
}
|
||||||
.form_user_unsubscribe input.submit,
|
.form_user_unsubscribe input.submit,
|
||||||
.form_group_leave input.submit,
|
.form_group_leave input.submit,
|
||||||
.form_user_authorization input.reject {
|
.form_user_authorization input.reject {
|
||||||
background-color:#aaaa66;
|
background-color:#87B4C8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entity_edit a {
|
.entity_edit a {
|
||||||
@ -221,15 +208,13 @@ opacity:0.4;
|
|||||||
opacity:1;
|
opacity:1;
|
||||||
}
|
}
|
||||||
div.entry-content {
|
div.entry-content {
|
||||||
color:#333;
|
color:#ccc;
|
||||||
}
|
}
|
||||||
div.notice-options a,
|
div.notice-options a,
|
||||||
div.notice-options input {
|
div.notice-options input {
|
||||||
font-family:sans-serif;
|
font-family:sans-serif;
|
||||||
}
|
}
|
||||||
.notices li.hover {
|
|
||||||
/*background-color:#fcfcfc;*/
|
|
||||||
}
|
|
||||||
/*END: NOTICES */
|
/*END: NOTICES */
|
||||||
|
|
||||||
#new_group a {
|
#new_group a {
|
||||||
@ -239,7 +224,7 @@ background:transparent url(../../base/images/icons/twotone/green/news.gif) no-re
|
|||||||
.pagination .nav_prev a,
|
.pagination .nav_prev a,
|
||||||
.pagination .nav_next a {
|
.pagination .nav_next a {
|
||||||
background-repeat:no-repeat;
|
background-repeat:no-repeat;
|
||||||
border-color:#DDAA00;
|
border-color:#000;
|
||||||
}
|
}
|
||||||
.pagination .nav_prev a {
|
.pagination .nav_prev a {
|
||||||
background-image:url(../../base/images/icons/twotone/green/arrow-left.gif);
|
background-image:url(../../base/images/icons/twotone/green/arrow-left.gif);
|
Before Width: | Height: | Size: 646 B After Width: | Height: | Size: 646 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
theme/h4ck3r/images/illustrations/illu_h4x0r1ng.gif
Normal file
After Width: | Height: | Size: 423 KiB |
BIN
theme/h4ck3r/logo.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
@ -12,7 +12,7 @@ img { display:block; border:0; }
|
|||||||
a abbr { cursor: pointer; border-bottom:0; }
|
a abbr { cursor: pointer; border-bottom:0; }
|
||||||
table { border-collapse:collapse; }
|
table { border-collapse:collapse; }
|
||||||
ol { list-style-position:inside; }
|
ol { list-style-position:inside; }
|
||||||
html { font-size: 87.5%; background-color:#fff; height:100%; }
|
html { font-size: 87.5%; background-color:#fff; }
|
||||||
body {
|
body {
|
||||||
background-color:#fff;
|
background-color:#fff;
|
||||||
color:#000;
|
color:#000;
|
||||||
@ -386,12 +386,12 @@ margin-bottom:1em;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
width:100%;
|
width:67.9%;
|
||||||
min-height:259px;
|
min-height:259px;
|
||||||
padding-top:1.795%;
|
padding-top:1.795%;
|
||||||
padding-bottom:1.795%;
|
padding-bottom:1.795%;
|
||||||
|
|
||||||
float:left;
|
float:left;
|
||||||
|
clear:left;
|
||||||
border-radius:7px;
|
border-radius:7px;
|
||||||
-moz-border-radius:7px;
|
-moz-border-radius:7px;
|
||||||
-moz-border-radius-topleft:0;
|
-moz-border-radius-topleft:0;
|
||||||
@ -409,11 +409,11 @@ float:left;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#aside_primary {
|
#aside_primary {
|
||||||
width:96.3%;
|
width:27.917%;
|
||||||
min-height:259px;
|
min-height:259px;
|
||||||
float:left;
|
float:left;
|
||||||
clear:both;
|
|
||||||
padding:1.795%;
|
padding:1.795%;
|
||||||
|
margin-left:0.385%;
|
||||||
border-radius:7px;
|
border-radius:7px;
|
||||||
-moz-border-radius:7px;
|
-moz-border-radius:7px;
|
||||||
-webkit-border-radius:7px;
|
-webkit-border-radius:7px;
|
||||||
@ -730,7 +730,7 @@ list-style-type:none;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#content .notice {
|
#content .notice {
|
||||||
width:25%;
|
width:37%;
|
||||||
margin-left:17px;
|
margin-left:17px;
|
||||||
margin-bottom:47px;
|
margin-bottom:47px;
|
||||||
clear:none;
|
clear:none;
|
||||||
@ -743,6 +743,10 @@ min-height:235px;
|
|||||||
margin-bottom:18px;
|
margin-bottom:18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#shownotice #content .notice {
|
||||||
|
width:96%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* NOTICES */
|
/* NOTICES */
|
||||||
#notices_primary {
|
#notices_primary {
|
||||||
|
@ -15,7 +15,6 @@ html {
|
|||||||
html,
|
html,
|
||||||
body,
|
body,
|
||||||
a:active {
|
a:active {
|
||||||
/*background-color:#F0F2F5;*/
|
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
||||||
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 2.2 KiB |
@ -23,14 +23,16 @@ Only alter this file if you want to change the layout of the site. Please note t
|
|||||||
./default/css/display.css contains only the background images and colour rules:
|
./default/css/display.css contains only the background images and colour rules:
|
||||||
This file is a good basis for creating your own theme.
|
This file is a good basis for creating your own theme.
|
||||||
|
|
||||||
|
Let's create a theme:
|
||||||
|
|
||||||
1. Copy over the default theme to start off (replace 'mytheme'):
|
1. To start off, copy over the default theme:
|
||||||
cp -r ./default ./mytheme
|
cp -r default mytheme
|
||||||
|
|
||||||
2. Edit your mytheme stylesheet:
|
2. Edit your mytheme stylesheet:
|
||||||
nano ./mytheme/css/display.css
|
nano mytheme/css/display.css
|
||||||
|
|
||||||
3. Search and replace a colour or a path to the background image of your choice.
|
a) Search and replace your colours and background images, or
|
||||||
|
b) Create your own layout either importing a separate stylesheet (e.g., change to @import url(base.css);) or simply place it before the rest of the rules.
|
||||||
|
|
||||||
4. Set /config.php to load 'mytheme':
|
4. Set /config.php to load 'mytheme':
|
||||||
$config['site']['theme'] = 'mytheme';
|
$config['site']['theme'] = 'mytheme';
|
||||||
|