<?php
-// Shaarli 0.0.34 beta - Shaare your links...
+// Shaarli 0.0.38 beta - Shaare your links...
// The personal, minimalist, super-fast, no-database delicious clone. By sebsauvage.net
// http://sebsauvage.net/wiki/doku.php?id=php:shaarli
// Licence: http://www.opensource.org/licenses/zlib-license.php
ini_set('memory_limit', '128M'); // Try to set max upload file size and read (May not work on some hosts).
ini_set('post_max_size', '16M');
ini_set('upload_max_filesize', '16M');
+define('shaarli_version','0.0.38 beta');
define('PHPPREFIX','<?php /* '); // Prefix to encapsulate data in php code.
define('PHPSUFFIX',' */ ?>'); // Suffix to encapsulate data in php code.
checkphpversion();
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
-define('shaarli_version','0.0.34 beta');
if (!is_dir($GLOBALS['config']['DATADIR'])) { mkdir($GLOBALS['config']['DATADIR'],0705); chmod($GLOBALS['config']['DATADIR'],0705); }
+if (!is_dir('tmp')) { mkdir('tmp',0705); chmod('tmp',0705); } // For RainTPL temporary files.
if (!is_file($GLOBALS['config']['DATADIR'].'/.htaccess')) { file_put_contents($GLOBALS['config']['DATADIR'].'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files.
if ($GLOBALS['config']['ENABLE_LOCALCACHE'])
{
// even in the absence of <pre> (This is used in description to keep text formatting)
function keepMultipleSpaces($text)
{
- return str_replace(' ',' ',$text);
-
+ return str_replace(' ',' ',$text);
+
}
// ------------------------------------------------------------------------------------------
// Sniff browser language to display dates in the right format automatically.
$this->tpl->assign('version',shaarli_version);
$this->tpl->assign('scripturl',indexUrl());
$this->tpl->assign('pagetitle','Shaarli');
+ $this->tpl->assign('privateonly',!empty($_SESSION['privateonly'])); // Show only private links ?
if (!empty($GLOBALS['title'])) $this->tpl->assign('pagetitle',$GLOBALS['title']);
if (!empty($GLOBALS['pagetitle'])) $this->tpl->assign('pagetitle',$GLOBALS['pagetitle']);
$this->tpl->assign('shaarlititle',empty($GLOBALS['title']) ? 'Shaarli': $GLOBALS['title'] );
arsort($tags); // Sort tags by usage (most used tag first)
return $tags;
}
+
+ // Returns the list of days containing articles (oldest first)
+ // Output: An array containing days (in format YYYYMMDD).
+ public function days()
+ {
+ $linkdays=array();
+ foreach(array_keys($this->links) as $day)
+ {
+ $linkdays[substr($day,0,8)]=0;
+ }
+ $linkdays=array_keys($linkdays);
+ sort($linkdays);
+ return $linkdays;
+ }
}
// ------------------------------------------------------------------------------------------
exit;
}
+// ------------------------------------------------------------------------------------------
+// Daily RSS feed: 1 RSS entry per day giving all the links on that day.
+// Gives the last 7 days (which have links).
+// This RSS feed cannot be filtered.
+function showDailyRSS()
+{
+ global $LINKSDB;
+
+ /* Some Shaarlies may have very few links, so we need to look
+ back in time (rsort()) until we have enough days ($nb_of_days).
+ */
+ $linkdates=array(); foreach($LINKSDB as $linkdate=>$value) { $linkdates[]=$linkdate; }
+ rsort($linkdates);
+ $nb_of_days=7; // We take 7 days.
+ $today=Date('Ymd');
+ $days=array();
+ foreach($linkdates as $linkdate)
+ {
+ $day=substr($linkdate,0,8); // Extract day (without time)
+ if (strcmp($day,$today)<0)
+ {
+ if (empty($days[$day])) $days[$day]=array();
+ $days[$day][]=$linkdate;
+ }
+ if (count($days)>$nb_of_days) break; // Have we collected enough days ?
+ }
+
+ // Build the RSS feed.
+ header('Content-Type: application/rss+xml; charset=utf-8');
+ $pageaddr=htmlspecialchars(indexUrl());
+ echo '<?xml version="1.0" encoding="UTF-8"?><rss version="2.0">';
+ echo '<channel><title>Daily - '.htmlspecialchars($GLOBALS['title']).'</title><link>'.$pageaddr.'</link>';
+ echo '<description>Daily shared links</description><language>en-en</language><copyright>'.$pageaddr.'</copyright>'."\n";
+
+ foreach($days as $day=>$linkdates) // For each day.
+ {
+ $daydate = utf8_encode(strftime('%A %d, %B %Y',linkdate2timestamp($day.'_000000'))); // Full text date
+ $rfc822date = linkdate2rfc822($day.'_000000');
+ $absurl=htmlspecialchars(indexUrl().'?do=daily&day='.$day); // Absolute URL of the corresponding "Daily" page.
+ echo '<item><title>'.htmlspecialchars($GLOBALS['title'].' - '.$daydate).'</title><guid>'.$absurl.'</guid><link>'.$absurl.'</link>';
+ echo '<pubDate>'.htmlspecialchars($rfc822date)."</pubDate>";
+
+ // Build the HTML body of this RSS entry.
+ $html='';
+ $href='';
+ $links=array();
+ // We pre-format some fields for proper output.
+ foreach($linkdates as $linkdate)
+ {
+ $l = $LINKSDB[$linkdate];
+ $l['formatedDescription']=nl2br(keepMultipleSpaces(text2clickable(htmlspecialchars($l['description']))));
+ $l['thumbnail'] = thumbnail($l['url']);
+ $l['localdate']=linkdate2locale($l['linkdate']);
+ if (startsWith($l['url'],'?')) $l['url']=indexUrl().$l['url']; // make permalink URL absolute
+ $links[$linkdate]=$l;
+ }
+ // Then build the HTML for this day:
+ $tpl = new RainTPL;
+ $tpl->assign('links',$links);
+ $html = $tpl->draw('dailyrss',$return_string=true);
+ echo "\n";
+ echo '<description><![CDATA['.$html.']]></description>'."\n</item>\n\n";
+
+ }
+ echo '</channel></rss>';
+ exit;
+}
+
+
// ------------------------------------------------------------------------------------------
// Render HTML page (according to URL parameters and user rights)
function renderPage()
if ($GLOBALS['config']['OPEN_SHAARLI']) { header('Location: ?'); exit; } // No need to login for open Shaarli
$token=''; if (ban_canLogin()) $token=getToken(); // Do not waste token generation if not useful.
$PAGE = new pageBuilder;
- $PAGE->assign('token',$token);
+ $PAGE->assign('token',$token);
$PAGE->assign('returnurl',(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER']:''));
$PAGE->renderPage('loginform');
exit;
foreach($links as $link)
{
$permalink='?'.htmlspecialchars(smallhash($link['linkdate']),ENT_QUOTES);
- $thumb=thumbnail($link['url'],$permalink);
+ $thumb=lazyThumbnail($link['url'],$permalink);
if ($thumb!='') // Only output links which have a thumbnail.
{
- $link['thumbnail']=$thumb; // Thumbnail HTML code.
- $link['permalink']=$permalink;
- $linksToDisplay[]=$link; // Add to array.
+ $link['thumbnail']=$thumb; // Thumbnail HTML code.
+ $link['permalink']=$permalink;
+ $linksToDisplay[]=$link; // Add to array.
}
}
$PAGE = new pageBuilder;
- $PAGE->assign('linksToDisplay',$linksToDisplay);
- $PAGE->renderPage('picwall');
+ $PAGE->assign('linksToDisplay',$linksToDisplay);
+ $PAGE->renderPage('picwall');
exit;
}
$tagList=array();
foreach($tags as $key=>$value)
{
- $tagList[$key] = array('count'=>$value,'size'=>max(40*$value/$maxcount,8));
+ $tagList[$key] = array('count'=>$value,'size'=>max(40*$value/$maxcount,8));
}
$PAGE = new pageBuilder;
- $PAGE->assign('tags',$tagList);
- $PAGE->renderPage('tagcloud');
- exit;
+ $PAGE->assign('tags',$tagList);
+ $PAGE->renderPage('tagcloud');
+ exit;
}
// -------- User clicks on a tag in a link: The tag is added to the list of searched tags (searchtags=...)
// Get previous URL (http_referer) and add the tag to the searchtags parameters in query.
if (empty($_SERVER['HTTP_REFERER'])) { header('Location: ?searchtags='.urlencode($_GET['addtag'])); exit; } // In case browser does not send HTTP_REFERER
parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params);
- $params['searchtags'] = (empty($params['searchtags']) ? trim($_GET['addtag']) : trim($params['searchtags']).' '.urlencode(trim($_GET['addtag'])));
+ $params['searchtags'] = (empty($params['searchtags']) ? trim($_GET['addtag']) : trim($params['searchtags']).' '.trim($_GET['addtag']));
unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different)
header('Location: ?'.http_build_query($params));
exit;
exit;
}
+ // -------- User wants to see only private links (toggle)
+ if (isset($_GET['privateonly']))
+ {
+ if (empty($_SESSION['privateonly']))
+ {
+ $_SESSION['privateonly']=1; // See only private links
+ }
+ else
+ {
+ unset($_SESSION['privateonly']); // See all links
+ }
+ header('Location: '.(empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER']));
+ exit;
+ }
+
// --------- Daily (all links form a specific day) ----------------------
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=daily'))
{
$day=Date('Ymd',strtotime('-1 day')); // Yesterday, in format YYYYMMDD.
if (isset($_GET['day'])) $day=$_GET['day'];
-
- $previousday = Date('Ymd',strtotime('-1 day',strtotime($day)));
- $nextday = Date('Ymd',strtotime('+1 day',strtotime($day)));
+ $days = $LINKSDB->days();
+ $i = array_search($day,$days);
+ if ($i==false) { $i=count($days)-1; $day=$days[$i]; }
+ $previousday='';
+ $nextday='';
+ if ($i!==false)
+ {
+ if ($i>1) $previousday=$days[$i-1];
+ if ($i<count($days)-1) $nextday=$days[$i+1];
+ }
+
$linksToDisplay=$LINKSDB->filterDay($day);
// We pre-format some fields for proper output.
foreach($linksToDisplay as $key=>$link)
foreach($linksToDisplay as $key=>$link)
{
// Roughly estimate length of entry (by counting characters)
- $length=strlen($link['title'])+strlen($link['description']);
- if ($link['thumbnail']) $length +=100; // 1 thumbnails roughly take as much space as 100 words;
-
+ // Title: 30 chars = 1 line. 1 line is 30 pixels height.
+ // Description: 836 characters gives roughly 342 pixel height.
+ // This is not perfect, but it's usually ok.
+ $length=strlen($link['title'])+(342*strlen($link['description']))/836;
+ if ($link['thumbnail']) $length +=100; // 1 thumbnails roughly takes 100 pixels height.
// Then put in column which is the less filled:
$smallest=min($fill); // find smallest value in array.
$index=array_search($smallest,$fill); // find index of this smallest value.
$fill[$index]+=$length;
}
$PAGE = new pageBuilder;
- $PAGE->assign('linksToDisplay',$linksToDisplay);
+ $PAGE->assign('linksToDisplay',$linksToDisplay);
$PAGE->assign('col1',$columns[0]);
$PAGE->assign('col2',$columns[1]);
$PAGE->assign('col3',$columns[2]);
header('Location: ?do=login&post='.urlencode($_GET['post']).(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').(!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'')); // Redirect to login page, then back to post link.
exit;
}
- $PAGE = new pageBuilder;
- buildLinkList($PAGE); // Compute list of links to display
- $PAGE->renderPage('linklist');
- exit; // Never remove this one ! All operations below are reserved for logged in user.
+ $PAGE = new pageBuilder;
+ buildLinkList($PAGE); // Compute list of links to display
+ $PAGE->renderPage('linklist');
+ exit; // Never remove this one ! All operations below are reserved for logged in user.
}
// -------- All other functions are reserved for the registered user:
// -------- Display the Tools menu if requested (import/export/bookmarklet...)
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=tools'))
{
- $PAGE = new pageBuilder;
- $PAGE->assign('pageabsaddr',indexUrl());
- $PAGE->renderPage('tools');
+ $PAGE = new pageBuilder;
+ $PAGE->assign('pageabsaddr',indexUrl());
+ $PAGE->renderPage('tools');
exit;
}
}
else // show the change password form.
{
- $PAGE = new pageBuilder;
- $PAGE->assign('token',getToken());
- $PAGE->renderPage('changepassword');
- exit;
+ $PAGE = new pageBuilder;
+ $PAGE->assign('token',getToken());
+ $PAGE->renderPage('changepassword');
+ exit;
}
}
}
else // Show the configuration form.
{
- $PAGE = new pageBuilder;
+ $PAGE = new pageBuilder;
$PAGE->assign('token',getToken());
$PAGE->assign('title',htmlspecialchars( empty($GLOBALS['title']) ? '' : $GLOBALS['title'] , ENT_QUOTES));
$PAGE->assign('redirector',htmlspecialchars( empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'] , ENT_QUOTES));
list($timezone_form,$timezone_js) = templateTZform($GLOBALS['timezone']);
$PAGE->assign('timezone_form',$timezone_form); // FIXME: put entire tz form generation in template ?
$PAGE->assign('timezone_js',$timezone_js);
- $PAGE->renderPage('configure');
- exit;
+ $PAGE->renderPage('configure');
+ exit;
}
}
{
if (empty($_POST['fromtag']))
{
- $PAGE = new pageBuilder;
- $PAGE->assign('token',getToken());
- $PAGE->renderPage('changetag');
- exit;
+ $PAGE = new pageBuilder;
+ $PAGE->assign('token',getToken());
+ $PAGE->renderPage('changetag');
+ exit;
}
if (!tokenOk($_POST['token'])) die('Wrong token.');
// -------- User wants to add a link without using the bookmarklet: show form.
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=addlink'))
{
- $PAGE = new pageBuilder;
- $PAGE->renderPage('addlink');
+ $PAGE = new pageBuilder;
+ $PAGE->renderPage('addlink');
exit;
}
{
$link = $LINKSDB[$_GET['edit_link']]; // Read database
if (!$link) { header('Location: ?'); exit; } // Link not found in database.
- $PAGE = new pageBuilder;
- $PAGE->assign('link',$link);
- $PAGE->assign('link_is_new',false);
- $PAGE->assign('token',getToken()); // XSRF protection.
- $PAGE->assign('http_referer',(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''));
- $PAGE->renderPage('editlink');
+ $PAGE = new pageBuilder;
+ $PAGE->assign('link',$link);
+ $PAGE->assign('link_is_new',false);
+ $PAGE->assign('token',getToken()); // XSRF protection.
+ $PAGE->assign('http_referer',(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''));
+ $PAGE->renderPage('editlink');
exit;
}
$link = array('linkdate'=>$linkdate,'title'=>$title,'url'=>$url,'description'=>$description,'tags'=>$tags,'private'=>0);
}
- $PAGE = new pageBuilder;
- $PAGE->assign('link',$link);
- $PAGE->assign('link_is_new',$link_is_new);
- $PAGE->assign('token',getToken()); // XSRF protection.
- $PAGE->assign('http_referer',(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''));
- $PAGE->renderPage('editlink');
+ $PAGE = new pageBuilder;
+ $PAGE->assign('link',$link);
+ $PAGE->assign('link_is_new',$link_is_new);
+ $PAGE->assign('token',getToken()); // XSRF protection.
+ $PAGE->assign('http_referer',(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''));
+ $PAGE->renderPage('editlink');
exit;
}
{
if (empty($_GET['what']))
{
- $PAGE = new pageBuilder;
- $PAGE->renderPage('export');
- exit;
+ $PAGE = new pageBuilder;
+ $PAGE->renderPage('export');
+ exit;
}
$exportWhat=$_GET['what'];
if (!array_intersect(array('all','public','private'),array($exportWhat))) die('What are you trying to export ???');
// -------- Show upload/import dialog:
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=import'))
{
- $PAGE = new pageBuilder;
+ $PAGE = new pageBuilder;
$PAGE->assign('token',getToken());
$PAGE->assign('maxfilesize',getMaxFileSize());
- $PAGE->renderPage('import');
+ $PAGE->renderPage('import');
exit;
}
$search_crits=explode(' ',trim($_GET['searchtags']));
$search_type='tags';
}
- elseif (isset($_SERVER["QUERY_STRING"]) && preg_match('/[a-zA-Z0-9-_@]{6}(&.+?)?/',$_SERVER["QUERY_STRING"])) // Detect smallHashes in URL
+ elseif (isset($_SERVER['QUERY_STRING']) && preg_match('/[a-zA-Z0-9-_@]{6}(&.+?)?/',$_SERVER['QUERY_STRING'])) // Detect smallHashes in URL
{
$linksToDisplay = $LINKSDB->filterSmallHash(substr(trim($_SERVER["QUERY_STRING"], '/'),0,6));
$search_type='permalink';
}
else
$linksToDisplay = $LINKSDB; // otherwise, display without filtering.
-
+
+ // Option: Show only private links
+ if (!empty($_SESSION['privateonly']))
+ {
+ $tmp = array();
+ foreach($linksToDisplay as $linkdate=>$link)
+ {
+ if ($link['private']!=0) $tmp[$linkdate]=$link;
+ }
+ $linksToDisplay=$tmp;
+ }
// ---- Handle paging.
/* Can someone explain to me why you get the following error when using array_keys() on an object which implements the interface ArrayAccess ???
return;
}
-// Returns the HTML code to display a thumbnail for a link
+// Compute the thumbnail for a link.
+//
// with a link to the original URL.
// Understands various services (youtube.com...)
// Input: $url = url for which the thumbnail must be found.
// $href = if provided, this URL will be followed instead of $url
-// Returns '' if no thumbnail available.
-function thumbnail($url,$href=false)
+// Returns an associative array with thumbnail attributes (src,href,width,height,style,alt)
+// Some of them may be missing.
+// Return an empty array if no thumbnail available.
+function computeThumbnail($url,$href=false)
{
- if (!$GLOBALS['config']['ENABLE_THUMBNAILS']) return '';
-
+ if (!$GLOBALS['config']['ENABLE_THUMBNAILS']) return array();
if ($href==false) $href=$url;
// For most hosts, the URL of the thumbnail can be easily deduced from the URL of the link.
if ($domain=='youtube.com' || $domain=='www.youtube.com')
{
parse_str(parse_url($url,PHP_URL_QUERY), $params); // Extract video ID and get thumbnail
- if (!empty($params['v'])) return '<a href="'.htmlspecialchars($href).'"><img src="http://img.youtube.com/vi/'.htmlspecialchars($params['v']).'/default.jpg" width="120" height="90" alt="YouTube thumbnail"></a>';
+ if (!empty($params['v'])) return array('src'=>'http://img.youtube.com/vi/'.$params['v'].'/default.jpg',
+ 'href'=>$href,'width'=>'120','height'=>'90','alt'=>'YouTube thumbnail');
}
if ($domain=='youtu.be') // Youtube short links
{
$path = parse_url($url,PHP_URL_PATH);
- return '<a href="'.htmlspecialchars($href).'"><img src="http://img.youtube.com/vi'.htmlspecialchars($path).'/default.jpg" width="120" height="90" alt="YouTube thumbnail"></a>';
+ return array('src'=>'http://img.youtube.com/vi'.$path.'/default.jpg',
+ 'href'=>$href,'width'=>'120','height'=>'90','alt'=>'YouTube thumbnail');
}
if ($domain=='pix.toile-libre.org') // pix.toile-libre.org image hosting
{
parse_str(parse_url($url,PHP_URL_QUERY), $params); // Extract image filename.
- if (!empty($params) && !empty($params['img'])) return '<a href="'.htmlspecialchars($href).'"><img src="http://pix.toile-libre.org/upload/thumb/'.urlencode($params['img']).'" style:"max-width:120px; max-height:150px" alt="pix.toile-libre.org thumbnail"></a>';
+ if (!empty($params) && !empty($params['img'])) return array('src'=>'http://pix.toile-libre.org/upload/thumb/'.urlencode($params['img']),
+ 'href'=>$href,'style'=>'max-width:120px; max-height:150px','alt'=>'pix.toile-libre.org thumbnail');
}
if ($domain=='imgur.com')
{
$path = parse_url($url,PHP_URL_PATH);
- if (startsWith($path,'/a/')) return ''; // Thumbnails for albums are not available.
- if (startsWith($path,'/r/')) return '<a href="'.htmlspecialchars($href).'"><img src="http://i.imgur.com/'.htmlspecialchars(basename($path)).'s.jpg" width="90" height="90" alt="imgur.com thumbnail"></a>';
- if (startsWith($path,'/gallery/')) return '<a href="'.htmlspecialchars($href).'"><img src="http://i.imgur.com'.htmlspecialchars(substr($path,8)).'s.jpg" width="90" height="90" alt="imgur.com thumbnail"></a>';
- if (substr_count($path,'/')==1) return '<a href="'.htmlspecialchars($href).'"><img src="http://i.imgur.com/'.htmlspecialchars(substr($path,1)).'s.jpg" width="90" height="90" alt="imgur.com thumbnail"></a>';
+ if (startsWith($path,'/a/')) return array(); // Thumbnails for albums are not available.
+ if (startsWith($path,'/r/')) return array('src'=>'http://i.imgur.com/'.basename($path).'s.jpg',
+ 'href'=>$href,'width'=>'90','height'=>'90','alt'=>'imgur.com thumbnail');
+ if (startsWith($path,'/gallery/')) return array('src'=>'http://i.imgur.com'.substr($path,8).'s.jpg',
+ 'href'=>$href,'width'=>'90','height'=>'90','alt'=>'imgur.com thumbnail');
+
+ if (substr_count($path,'/')==1) return array('src'=>'http://i.imgur.com/'.substr($path,1).'s.jpg',
+ 'href'=>$href,'width'=>'90','height'=>'90','alt'=>'imgur.com thumbnail');
}
if ($domain=='i.imgur.com')
{
$pi = pathinfo(parse_url($url,PHP_URL_PATH));
- if (!empty($pi['filename'])) return '<a href="'.htmlspecialchars($href).'"><img src="http://i.imgur.com/'.htmlspecialchars($pi['filename']).'s.jpg" width="90" height="90" alt="imgur.com thumbnail"></a>';
+ if (!empty($pi['filename'])) return array('src'=>'http://i.imgur.com/'.$pi['filename'].'s.jpg',
+ 'href'=>$href,'width'=>'90','height'=>'90','alt'=>'imgur.com thumbnail');
}
if ($domain=='dailymotion.com' || $domain=='www.dailymotion.com')
{
if (strpos($url,'dailymotion.com/video/')!==false)
{
$thumburl=str_replace('dailymotion.com/video/','dailymotion.com/thumbnail/video/',$url);
- return '<a href="'.htmlspecialchars($href).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;" alt="DailyMotion thumbnail"></a>';
+ return array('src'=>$thumburl,
+ 'href'=>$href,'width'=>'120','style'=>'height:auto;','alt'=>'DailyMotion thumbnail');
}
}
if (endsWith($domain,'.imageshack.us'))
if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif')
{
$thumburl = substr($url,0,strlen($url)-strlen($ext)).'th.'.$ext;
- return '<a href="'.htmlspecialchars($href).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;" alt="imageshack.us thumbnail"></a>';
+ return array('src'=>$thumburl,
+ 'href'=>$href,'width'=>'120','style'=>'height:auto;','alt'=>'imageshack.us thumbnail');
}
}
// So we deport the thumbnail generation in order not to slow down page generation
// (and we also cache the thumbnail)
- if (!$GLOBALS['config']['ENABLE_LOCALCACHE']) return ''; // If local cache is disabled, no thumbnails for services which require the use a local cache.
+ if (!$GLOBALS['config']['ENABLE_LOCALCACHE']) return array(); // If local cache is disabled, no thumbnails for services which require the use a local cache.
if ($domain=='flickr.com' || endsWith($domain,'.flickr.com')
|| $domain=='vimeo.com'
if ($domain=='vimeo.com')
{ // Make sure this vimeo url points to a video (/xxx... where xxx is numeric)
$path = parse_url($url,PHP_URL_PATH);
- if (!preg_match('!/\d+.+?!',$path)) return ''; // This is not a single video URL.
+ if (!preg_match('!/\d+.+?!',$path)) return array(); // This is not a single video URL.
}
if ($domain=='xkcd.com' || endsWith($domain,'.xkcd.com'))
{ // Make sure this url points to a single comic (/xxx... where xxx is numeric)
$path = parse_url($url,PHP_URL_PATH);
- if (!preg_match('!/\d+.+?!',$path)) return '';
+ if (!preg_match('!/\d+.+?!',$path)) return array();
}
if ($domain=='ted.com' || endsWith($domain,'.ted.com'))
{ // Make sure this TED url points to a video (/talks/...)
$path = parse_url($url,PHP_URL_PATH);
- if ("/talks/" !== substr($path,0,7)) return ''; // This is not a single video URL.
+ if ("/talks/" !== substr($path,0,7)) return array(); // This is not a single video URL.
}
$sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation)
- return '<a href="'.htmlspecialchars($href).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;" alt="thumbnail"></a>';
+ return array('src'=>indexUrl().'?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url),
+ 'href'=>$href,'width'=>'120','style'=>'height:auto;','alt'=>'thumbnail');
}
// For all other, we try to make a thumbnail of links ending with .jpg/jpeg/png/gif
if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif')
{
$sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation)
- return '<a href="'.htmlspecialchars($href).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;"></a>';
+ return array('src'=>indexUrl().'?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url),
+ 'href'=>$href,'width'=>'120','style'=>'height:auto;','alt'=>'thumbnail');
}
- return ''; // No thumbnail.
+ return array(); // No thumbnail.
}
+
+// Returns the HTML code to display a thumbnail for a link
+// with a link to the original URL.
+// Understands various services (youtube.com...)
+// Input: $url = url for which the thumbnail must be found.
+// $href = if provided, this URL will be followed instead of $url
+// Returns '' if no thumbnail available.
+function thumbnail($url,$href=false)
+{
+ $t = computeThumbnail($url,$href);
+ if (count($t)==0) return ''; // Empty array = no thumbnail for this URL.
+
+ $html='<a href="'.htmlspecialchars($t['href']).'"><img src="'.htmlspecialchars($t['src']).'"';
+ if (!empty($t['width'])) $html.=' width="'.htmlspecialchars($t['width']).'"';
+ if (!empty($t['height'])) $html.=' height="'.htmlspecialchars($t['height']).'"';
+ if (!empty($t['style'])) $html.=' style="'.htmlspecialchars($t['style']).'"';
+ if (!empty($t['alt'])) $html.=' alt="'.htmlspecialchars($t['alt']).'"';
+ $html.='></a>';
+ return $html;
+}
+
+
+// Returns the HTML code to display a thumbnail for a link
+// for the picture wall (using lazy image loading)
+// Understands various services (youtube.com...)
+// Input: $url = url for which the thumbnail must be found.
+// $href = if provided, this URL will be followed instead of $url
+// Returns '' if no thumbnail available.
+function lazyThumbnail($url,$href=false)
+{
+ $t = computeThumbnail($url,$href);
+ if (count($t)==0) return ''; // Empty array = no thumbnail for this URL.
+
+ $html='<a href="'.htmlspecialchars($t['href']).'">';
+
+ // Lazy image (only loaded by javascript when in the viewport).
+ $html.='<img class="lazyimage" src="#" data-original="'.htmlspecialchars($t['src']).'"';
+ if (!empty($t['width'])) $html.=' width="'.htmlspecialchars($t['width']).'"';
+ if (!empty($t['height'])) $html.=' height="'.htmlspecialchars($t['height']).'"';
+ if (!empty($t['style'])) $html.=' style="'.htmlspecialchars($t['style']).'"';
+ if (!empty($t['alt'])) $html.=' alt="'.htmlspecialchars($t['alt']).'"';
+ $html.='>';
+
+ // No-javascript fallback:
+ $html.='<noscript><img src="'.htmlspecialchars($t['src']).'"';
+ if (!empty($t['width'])) $html.=' width="'.htmlspecialchars($t['width']).'"';
+ if (!empty($t['height'])) $html.=' height="'.htmlspecialchars($t['height']).'"';
+ if (!empty($t['style'])) $html.=' style="'.htmlspecialchars($t['style']).'"';
+ if (!empty($t['alt'])) $html.=' alt="'.htmlspecialchars($t['alt']).'"';
+ $html.='></noscript></a>';
+
+ return $html;
+}
+
+
// -----------------------------------------------------------------------------------------------
// Installation
// This function should NEVER be called if the file data/config.php exists.
// The thumbnail for TED talks is located in the <link rel="image_src" [...]> tag on that page
// http://www.ted.com/talks/mikko_hypponen_fighting_viruses_defending_the_net.html
// <link rel="image_src" href="http://images.ted.com/images/ted/28bced335898ba54d4441809c5b1112ffaf36781_389x292.jpg" />
- list($httpstatus,$headers,$data) = getHTTP($url,5);
+ list($httpstatus,$headers,$data) = getHTTP($url,5);
if (strpos($httpstatus,'200 OK')!==false)
{
// Extract the link to the thumbnail
- preg_match('!link rel="image_src" href="(http://images.ted.com/images/ted/.+_\d+x\d+\.jpg)[^s]!',$data,$matches);
+ preg_match('!link rel="image_src" href="(http://images.ted.com/images/ted/.+_\d+x\d+\.jpg)"!',$data,$matches);
if (!empty($matches[1]))
{ // Let's download the image.
$imageurl=$matches[1];
$LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in).
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'ws=')) { processWS(); exit; } // Webservices (for jQuery/jQueryUI)
if (!isset($_SESSION['LINKS_PER_PAGE'])) $_SESSION['LINKS_PER_PAGE']=$GLOBALS['config']['LINKS_PER_PAGE'];
+if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=dailyrss')) { showDailyRSS(); exit; }
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=rss')) { showRSS(); exit; }
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=atom')) { showATOM(); exit; }
renderPage();