From: Seb Sauvage Date: Wed, 1 Feb 2012 22:07:32 +0000 (+0100) Subject: Version 0.0.37 beta X-Git-Url: https://git.immae.eu/?p=github%2Fshaarli%2FShaarli.git;a=commitdiff_plain;h=a22e60cc0abb0547af8d792dec15f59bf77b5630 Version 0.0.37 beta - Added: Basic CSS for mobiles, which makes Shaarli much more usable on mobile devices. - Added: Picture wall no more instantly kills your browser. Now it uses lazy image loading [0]: The picture are loaded only as you scroll the page. This will reduce browser memory usage (especially on mobile devices) and will reduce server load. If you have javascript disabled, the page will still work as before (all images loaded at once). - Added: RSS feed for the “Daily” page. 1 RSS entry per day, with all links of that day. RSS feed provides the last 7 days (only non-empty days are returned). - Added: In link list, added an icon to see only private links. Click to toggle (only private / all). [0] http://www.appelsiini.net/projects/lazyload --- diff --git a/images/feed-icon-14x14.png b/images/feed-icon-14x14.png new file mode 100644 index 00000000..b3c949d2 Binary files /dev/null and b/images/feed-icon-14x14.png differ diff --git a/images/private_16x16.png b/images/private_16x16.png new file mode 100644 index 00000000..d58c4823 Binary files /dev/null and b/images/private_16x16.png differ diff --git a/inc/jquery.lazyload.min.js b/inc/jquery.lazyload.min.js new file mode 100644 index 00000000..2364d8d9 --- /dev/null +++ b/inc/jquery.lazyload.min.js @@ -0,0 +1,15 @@ +/* + * Lazy Load - jQuery plugin for lazy loading images + * + * Copyright (c) 2007-2012 Mika Tuupola + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + * Project home: + * http://www.appelsiini.net/projects/lazyload + * + * Version: 1.7.0 + * + */ +(function(a,b){$window=a(b),a.fn.lazyload=function(c){var d={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!0,appear:null,load:null};c&&(undefined!==c.failurelimit&&(c.failure_limit=c.failurelimit,delete c.failurelimit),undefined!==c.effectspeed&&(c.effect_speed=c.effectspeed,delete c.effectspeed),a.extend(d,c));var e=this;return 0==d.event.indexOf("scroll")&&a(d.container).bind(d.event,function(b){var c=0;e.each(function(){$this=a(this);if(d.skip_invisible&&!$this.is(":visible"))return;if(!a.abovethetop(this,d)&&!a.leftofbegin(this,d))if(!a.belowthefold(this,d)&&!a.rightoffold(this,d))$this.trigger("appear");else if(++c>d.failure_limit)return!1})}),this.each(function(){var b=this,c=a(b);b.loaded=!1,c.one("appear",function(){if(!this.loaded){if(d.appear){var f=e.length;d.appear.call(b,f,d)}a("").bind("load",function(){c.hide().attr("src",c.data(d.data_attribute))[d.effect](d.effect_speed),b.loaded=!0;var f=a.grep(e,function(a){return!a.loaded});e=a(f);if(d.load){var g=e.length;d.load.call(b,g,d)}}).attr("src",c.data(d.data_attribute))}}),0!=d.event.indexOf("scroll")&&c.bind(d.event,function(a){b.loaded||c.trigger("appear")})}),$window.bind("resize",function(b){a(d.container).trigger(d.event)}),a(d.container).trigger(d.event),this},a.belowthefold=function(c,d){if(d.container===undefined||d.container===b)var e=$window.height()+$window.scrollTop();else var e=a(d.container).offset().top+a(d.container).height();return e<=a(c).offset().top-d.threshold},a.rightoffold=function(c,d){if(d.container===undefined||d.container===b)var e=$window.width()+$window.scrollLeft();else var e=a(d.container).offset().left+a(d.container).width();return e<=a(c).offset().left-d.threshold},a.abovethetop=function(c,d){if(d.container===undefined||d.container===b)var e=$window.scrollTop();else var e=a(d.container).offset().top;return e>=a(c).offset().top+d.threshold+a(c).height()},a.leftofbegin=function(c,d){if(d.container===undefined||d.container===b)var e=$window.scrollLeft();else var e=a(d.container).offset().left;return e>=a(c).offset().left+d.threshold+a(c).width()},a.inviewport=function(b,c){return!a.rightofscreen(b,c)&&!a.leftofscreen(b,c)&&!a.belowthefold(b,c)&&!a.abovethetop(b,c)},a.extend(a.expr[":"],{"below-the-fold":function(c){return a.belowthefold(c,{threshold:0,container:b})},"above-the-top":function(c){return!a.belowthefold(c,{threshold:0,container:b})},"right-of-screen":function(c){return a.rightoffold(c,{threshold:0,container:b})},"left-of-screen":function(c){return!a.rightoffold(c,{threshold:0,container:b})},"in-viewport":function(c){return!a.inviewport(c,{threshold:0,container:b})},"above-the-fold":function(c){return!a.belowthefold(c,{threshold:0,container:b})},"right-of-fold":function(c){return a.rightoffold(c,{threshold:0,container:b})},"left-of-fold":function(c){return!a.rightoffold(c,{threshold:0,container:b})}})})(jQuery,window) diff --git a/inc/shaarli.css b/inc/shaarli.css index a949666e..5b4b88b6 100644 --- a/inc/shaarli.css +++ b/inc/shaarli.css @@ -184,6 +184,12 @@ cursor:pointer; .paging a:visited { color:#ccc; } .paging a:hover { color:#FFFFC9; } .paging a:active { color:#fff; } +#paging_privatelinks { float:left; } +#paging_linksperpage { float:right; padding-right:5px; } +#paging_current { display:inline; color:#fff; padding:0 20 0 20; } +#paging_older { margin-right:15px; } +#paging_newer { margin-left:15px; } + #headerform { color:#ffffff; padding:5px 5px 5px 5px; clear: both;} #toolsdiv { color:#ffffff; padding:5px 5px 5px 5px; clear:left; } #uploaddiv { color:#ffffff; padding:5px 5px 5px 5px; clear:left; } @@ -325,6 +331,11 @@ div.daily position:relative; border-bottom: 2px solid black; } + +#daily_col1 { float:left;position:relative; width:33%; padding-left:1%; } +#daily_col2 { float:left;position:relative; width:33%; } +#daily_col3 { float:left;position:relative; width:33%;} + div.dailyAbout { float:left; @@ -383,6 +394,11 @@ div.dailyEntryDescription clear:both; } +/* For lazy images loading in picture wall. + using http://www.appelsiini.net/projects/lazyload + */ +.lazyimage { display:none; } + @media print { html {border:none;background:#fff!important;color:#000!important;} body {font-size:12pt;width:auto!important;margin:auto!important;} @@ -397,3 +413,36 @@ a {color:#000!important;text-decoration:none!important;} .linktag { border: 1px solid black; font-style:italic; font-size:8pt;} } + + +@media handheld, only screen and (max-width: 480px), only screen and (max-device-width: 854px) +{ +/* A few fixes for mobile devices (far from perfect). */ +.nomobile { display:none; } +#logo { display:none; } +#pageheader a +{ + padding:5px; + border-radius: 5px 5px 5px 5px; + margin:3px; +} +.searchform,.tagfilter { display:block !important; margin:0px !important; padding:0px !important; width:100% !important; } +.searchform input,.tagfilter input { margin:0px !important; padding:0px !important; display:inline !important; } +.tagfilter input.bigbutton,.searchform input.bigbutton,.addform input.bigbutton{ width:30%; font-size:smaller;} +#searchform_value { width:70% !important; } +#tagfilter_value { width:70% !important; } +div.qrcode { position:relative; float:left; top:-10px; left:0px; } +#paging_privatelinks { float;none; } +#paging_linksperpage { float:none; margin-bottom:10px; font-size:smaller;} +#paging_older,#paging_newer,#paging_linksperpage a { border: 1px solid black; padding:3px 5px 3px 5px; background-color:#666; color:#fff; border-radius: 5px 5px 5px 5px;} +.thumbnail { float:none; height:auto; margin: 0px; text-align:center;} +#cloudtag { padding:0px; } +div.dailyAbout { float:none; position:relative; width:100%; clear:both; padding:0px; top:0px; left:0px; } +#daily_col1,#daily_col2,#daily_col3 { float:none; width:100%; padding:0px;} +div.dailyTitle { font-size: 18pt; margin-top:5px; padding:0px;} +div.dailyDate { font-size: 11pt;padding:0px; display:block; } +div.dailyEntryTitle { font-size:16pt; font-weight:bold;} +div.dailyEntryDescription { font-size:10pt; } + +} + diff --git a/index.php b/index.php index 9dd6483e..936d6129 100644 --- a/index.php +++ b/index.php @@ -1,5 +1,5 @@ (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. @@ -849,6 +849,75 @@ function showATOM() 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 ''; + echo 'Daily - '.htmlspecialchars($GLOBALS['title']).''.$pageaddr.''; + echo 'Daily shared linksen-en'.$pageaddr.''."\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 ''.htmlspecialchars($GLOBALS['title'].' - '.$daydate).''.$absurl.''.$absurl.''; + echo ''.htmlspecialchars($rfc822date).""; + + // 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 ''."\n\n\n"; + + } + echo ''; + exit; +} + + // ------------------------------------------------------------------------------------------ // Render HTML page (according to URL parameters and user rights) function renderPage() @@ -861,7 +930,7 @@ 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; @@ -890,17 +959,17 @@ function renderPage() 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; } @@ -915,12 +984,12 @@ function renderPage() $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=...) @@ -960,6 +1029,21 @@ function renderPage() 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')) { @@ -1000,7 +1084,7 @@ function renderPage() $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]); @@ -1021,10 +1105,10 @@ function renderPage() 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: @@ -1032,9 +1116,9 @@ function renderPage() // -------- 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; } @@ -1058,10 +1142,10 @@ function renderPage() } 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; } } @@ -1084,15 +1168,15 @@ function renderPage() } 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; } } @@ -1101,10 +1185,10 @@ function renderPage() { 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.'); @@ -1148,8 +1232,8 @@ function renderPage() // -------- 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; } @@ -1207,12 +1291,12 @@ function renderPage() { $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; } @@ -1246,12 +1330,12 @@ function renderPage() $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; } @@ -1260,9 +1344,9 @@ function renderPage() { 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 ???'); @@ -1313,10 +1397,10 @@ HTML; // -------- 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; } @@ -1430,14 +1514,24 @@ function buildLinkList($PAGE) $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 ??? @@ -1494,16 +1588,18 @@ function buildLinkList($PAGE) 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. @@ -1513,38 +1609,47 @@ function thumbnail($url,$href=false) 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 'YouTube thumbnail'; + 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 'YouTube thumbnail'; + 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 'pix.toile-libre.org thumbnail'; + 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 'imgur.com thumbnail'; - if (startsWith($path,'/gallery/')) return 'imgur.com thumbnail'; - if (substr_count($path,'/')==1) return 'imgur.com thumbnail'; + 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 'imgur.com thumbnail'; + 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 'DailyMotion thumbnail'; + return array('src'=>$thumburl, + 'href'=>$href,'width'=>'120','style'=>'height:auto;','alt'=>'DailyMotion thumbnail'); } } if (endsWith($domain,'.imageshack.us')) @@ -1553,7 +1658,8 @@ function thumbnail($url,$href=false) if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif') { $thumburl = substr($url,0,strlen($url)-strlen($ext)).'th.'.$ext; - return 'imageshack.us thumbnail'; + return array('src'=>$thumburl, + 'href'=>$href,'width'=>'120','style'=>'height:auto;','alt'=>'imageshack.us thumbnail'); } } @@ -1561,7 +1667,7 @@ function thumbnail($url,$href=false) // 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' @@ -1572,20 +1678,21 @@ function thumbnail($url,$href=false) 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 'thumbnail'; + 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 @@ -1595,12 +1702,68 @@ function thumbnail($url,$href=false) 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 ''; + 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=''; + + // Lazy image (only loaded by javascript when in the viewport). + $html.=' tag on that page // http://www.ted.com/talks/mikko_hypponen_fighting_viruses_defending_the_net.html // - 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]; @@ -1982,6 +2145,7 @@ if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=g $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(); diff --git a/tpl/daily.html b/tpl/daily.html index 9ee74739..bdaf2032 100644 --- a/tpl/daily.html +++ b/tpl/daily.html @@ -7,14 +7,15 @@
All links of one day
in a single page.
<Previous day - - Next day> + Next day>

+ Daily RSS Feed
-
The Shaarli Daily
-
——————————— {$day} ———————————
+
The Shaarli Daily
+
——————————— {$day} ———————————
{if="$linksToDisplay"} -
+
{loop="col1"}
permalink
@@ -26,7 +27,7 @@ {/loop}
-
+
{loop="col2"}
permalink
@@ -38,7 +39,7 @@ {/loop}
-
+
{loop="col3"}
permalink
diff --git a/tpl/dailyrss.html b/tpl/dailyrss.html new file mode 100644 index 00000000..436e1cd2 --- /dev/null +++ b/tpl/dailyrss.html @@ -0,0 +1,8 @@ +{loop="links"} +

{$value.title|htmlspecialchars}

+ {if="!$GLOBALS['config']['HIDE_TIMESTAMPS']"}{$value.localdate|htmlspecialchars} - {/if}{if="$value.tags"}{$value.tags|htmlspecialchars}{/if}
+ {$value.url|htmlspecialchars}

+ {if="$value.thumbnail"}{$value.thumbnail}{/if}
+ {if="$value.description"}{$value.formatedDescription}{/if} +


+{/loop} \ No newline at end of file diff --git a/tpl/includes.html b/tpl/includes.html index 7cfb07f2..5319f452 100644 --- a/tpl/includes.html +++ b/tpl/includes.html @@ -1,5 +1,7 @@ {$pagetitle} + + diff --git a/tpl/linklist.html b/tpl/linklist.html index dc5b5398..1067d6fc 100644 --- a/tpl/linklist.html +++ b/tpl/linklist.html @@ -5,8 +5,8 @@ @@ -60,16 +60,14 @@ {include="page.footer"} \ No newline at end of file diff --git a/tpl/linklist.paging.html b/tpl/linklist.paging.html index 27e7440d..b1f9871f 100644 --- a/tpl/linklist.paging.html +++ b/tpl/linklist.paging.html @@ -1,9 +1,14 @@ -
-
- Links per page: 20 50 100 -
-
- {if="$previous_page_url"} ◄Older {/if} - page {$page_current} / {$page_max} - {if="$next_page_url"} Newer► {/if} -
\ No newline at end of file +
+{if="isLoggedIn()"} + +{/if} +
+ Links per page: 20 50 100 +
+
+ {if="$previous_page_url"} ◄Older {/if} +
page {$page_current} / {$page_max}
+ {if="$next_page_url"} Newer► {/if} +
\ No newline at end of file diff --git a/tpl/page.header.html b/tpl/page.header.html index 0c304367..3ad2f205 100644 --- a/tpl/page.header.html +++ b/tpl/page.header.html @@ -1,12 +1,12 @@ -
Shaare your links...
{$linkcount} links
+
Shaare your links...
{$linkcount} links
{$shaarlititle} {if="!empty($_GET['source']) && $_GET['source']=='bookmarklet'"} {ignore} When called as a popup from bookmarklet, do not display menu. {/ignore} {else} - Home + Home {if="isLoggedIn()"} LogoutToolsAdd link {elseif="$GLOBALS['config']['OPEN_SHAARLI']"} @@ -14,8 +14,8 @@ {else} Login {/if} - RSS Feed - ATOM Feed + RSS Feed + ATOM Feed Tag cloud Picture wall Daily diff --git a/tpl/picwall.html b/tpl/picwall.html index da6df762..2083a629 100644 --- a/tpl/picwall.html +++ b/tpl/picwall.html @@ -1,6 +1,8 @@ -{include="includes"} +{include="includes"} + +
@@ -14,4 +16,9 @@
{include="page.footer"} + \ No newline at end of file