From a22e60cc0abb0547af8d792dec15f59bf77b5630 Mon Sep 17 00:00:00 2001 From: Seb Sauvage Date: Wed, 1 Feb 2012 23:07:32 +0100 Subject: [PATCH 1/1] =?utf8?q?Version=200.0.37=20beta=20-=20Added:=20Basic?= =?utf8?q?=20CSS=20for=20mobiles,=20which=20makes=20Shaarli=20much=20more?= =?utf8?q?=20usable=20on=20mobile=20devices.=20-=20Added:=20Picture=20wall?= =?utf8?q?=20no=20more=20instantly=20kills=20your=20browser.=20Now=20it=20?= =?utf8?q?uses=20lazy=20image=20loading=20[0]:=20The=20picture=20are=20loa?= =?utf8?q?ded=20only=20as=20you=20scroll=20the=20page.=20This=20will=20red?= =?utf8?q?uce=20browser=20memory=20usage=20(especially=20on=20mobile=20dev?= =?utf8?q?ices)=20and=20will=20reduce=20server=20load.=20If=20you=20have?= =?utf8?q?=20javascript=20disabled,=20the=20page=20will=20still=20work=20a?= =?utf8?q?s=20before=20(all=20images=20loaded=20at=20once).=20-=20Added:?= =?utf8?q?=20RSS=20feed=20for=20the=20=E2=80=9CDaily=E2=80=9D=20page.=201?= =?utf8?q?=20RSS=20entry=20per=20day,=20with=20all=20links=20of=20that=20d?= =?utf8?q?ay.=20RSS=20feed=20provides=20the=20last=207=20days=20(only=20no?= =?utf8?q?n-empty=20days=20are=20returned).=20-=20Added:=20In=20link=20lis?= =?utf8?q?t,=20added=20an=20icon=20to=20see=20only=20private=20links.=20Cl?= =?utf8?q?ick=20to=20toggle=20(only=20private=20/=20all).?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit [0] http://www.appelsiini.net/projects/lazyload --- images/feed-icon-14x14.png | Bin 0 -> 689 bytes images/private_16x16.png | Bin 0 -> 439 bytes inc/jquery.lazyload.min.js | 15 ++ inc/shaarli.css | 49 ++++++ index.php | 322 ++++++++++++++++++++++++++++--------- tpl/daily.html | 13 +- tpl/dailyrss.html | 8 + tpl/includes.html | 2 + tpl/linklist.html | 20 ++- tpl/linklist.paging.html | 23 +-- tpl/page.header.html | 8 +- tpl/picwall.html | 9 +- 12 files changed, 359 insertions(+), 110 deletions(-) create mode 100644 images/feed-icon-14x14.png create mode 100644 images/private_16x16.png create mode 100644 inc/jquery.lazyload.min.js create mode 100644 tpl/dailyrss.html diff --git a/images/feed-icon-14x14.png b/images/feed-icon-14x14.png new file mode 100644 index 0000000000000000000000000000000000000000..b3c949d2244f2c0c81d65e74719af2a1b56d06a3 GIT binary patch literal 689 zcmV;i0#5yjP)(tky!*UETcH-TCU7SrqEjJM#?B`_A)!p7(kFf9-P@=@15kkTkGK zgFusyy#KECqZzRdBLb=P?$(kUP;>kYTDeG&{|a+iOiRbI6nbQ)j#7bOf>iF=C+|_py<&Fo1F5cC*iEM?zZGC{ejNg4LWYp=S$L6Qaby6y zp$+F`250{%tU{Lg$5*ROH}y!1UKJS4*xqd7P(Y3JQF?lrnf?yerr%&6yGXLG1ur*B z{$&R1@Oj)yl@%rY5rh?j(j10Yz_DBs`AKFU_QnB;)(aqQmGi&ieOS|21^NP9UMpa< zU&p!f6RZ6Owp^X!EXA=0SbN&h?CrQK%Q3(=YBqqHD^9ZUM0Hxt-6-KT;>lf@j?Z+v zHm(}`>85I&E<7e}oz?6UwjAogowzGO8kSN7+2`b^$Az9L{K5*ko87EV45LT-`_##3 z>d3AGh@>=mbg34|6}+-gT9N+6Dr@44VEl44O&{&|w=qpbzC#iWMKa?5)>tI+KLQK@ Xq0QFqn(9Yl00000NkvXXu0mjfZ8tV2Vo@k1g5VYsK}fAhV>C23 zHaRx5ID|tE&VoZjh?5pbL^m_&ABeCm3>u;!sKM*K*Wo;0_@dui4;;=ppL5>N^PJ~7 zjb^i{hc(c}I3D9R2JsoI*gz_Jz$xIX*uqrhYz*^Q#B%BtKI~Zq-bWMd*gwTwor8o9 zF5_0LKjL~seiT{*_y3i_d7KT0Z}BtqO|-(vXq|&@Kwt1Jvb~1y$fXA>ScOg~IO87hO;cHO?U&JXPvLdUt9F=hC zU^?DBfkU}PU0lO1Mk|p|S;7-siT#;?%XEKN*0ok(JyL%k(I3i1-NjwGfaUkDb+9e> hycODj-2eZ=a11WdRbp(XJP-f?002ovPDHLkV1oCI!OQ>v literal 0 HcmV?d00001 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 @@ -
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 -- 2.41.0