X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=index.php;h=9dd6483eee9750f81e653cdc4c6edad4be18b487;hb=96bc4efe9ea9ed513d1ec06e0823847d5eebe82f;hp=e78733bf3e432c000efee23d09f9ade06eb187e6;hpb=3433e5e8a84e3952502b79296f945e6dde2a7d75;p=github%2Fshaarli%2FShaarli.git diff --git a/index.php b/index.php index e78733bf..9dd6483e 100644 --- a/index.php +++ b/index.php @@ -1,5 +1,5 @@ +function nl2br_escaped($html) +{ + return str_replace('>','>',str_replace('<','<',nl2br($html))); +} + /* Returns the small hash of a string eg. smallHash('20111006_131924') --> yZH23w Small hashes: @@ -135,11 +141,12 @@ function smallHash($text) return $t; } +// In a string, converts urls to clickable links. // Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722 function text2clickable($url) { $redir = empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector']; - return preg_replace('!((?:https?|ftp)://\S+[[:alnum:]]/?)!si','$1',$url); + return preg_replace('!(((?:https?|ftp|file)://|apt:)\S+[[:alnum:]]/?)!si','$1',$url); } // This function inserts   where relevant so that multiple spaces are properly displayed in HTML @@ -330,13 +337,15 @@ if (isset($_POST['login'])) // You can append $_SERVER['SCRIPT_NAME'] to get the current script URL. function serverUrl() { - $serverport = ($_SERVER["SERVER_PORT"]=='80' || (!empty($_SERVER['HTTPS']) && $_SERVER["SERVER_PORT"]=='443') ? '' : ':'.$_SERVER["SERVER_PORT"]); - return 'http'.(!empty($_SERVER['HTTPS'])?'s':'').'://'.$_SERVER["SERVER_NAME"].$serverport; + $https = (!empty($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS'])=='on')) || $_SERVER["SERVER_PORT"]=='443'; // HTTPS detection. + $serverport = ($_SERVER["SERVER_PORT"]=='80' || ($https && $_SERVER["SERVER_PORT"]=='443') ? '' : ':'.$_SERVER["SERVER_PORT"]); + return 'http'.($https?'s':'').'://'.$_SERVER["SERVER_NAME"].$serverport; } +// Returns the absolute URL of current script. function indexUrl() { - return serverUrl() . ($_SERVER["SCRIPT_NAME"] == '/index.php' ? '' : $_SERVER["SCRIPT_NAME"]); + return serverUrl() . ($_SERVER["SCRIPT_NAME"] == '/index.php' ? '/' : $_SERVER["SCRIPT_NAME"]); } // Convert post_max_size/upload_max_filesize (eg.'16M') parameters to bytes. @@ -515,11 +524,12 @@ class pageBuilder $this->tpl->assign('linkcount',count($LINKSDB)); $this->tpl->assign('feedurl',htmlspecialchars(indexUrl())); $searchcrits=''; // Search criteria - if (!empty($_GET['searchtags'])) $searchcrits.='&searchtags='.$_GET['searchtags']; - elseif (!empty($_GET['searchterm'])) $searchcrits.='&searchterm='.$_GET['searchterm']; + if (!empty($_GET['searchtags'])) $searchcrits.='&searchtags='.urlencode($_GET['searchtags']); + elseif (!empty($_GET['searchterm'])) $searchcrits.='&searchterm='.urlencode($_GET['searchterm']); $this->tpl->assign('searchcrits',$searchcrits); $this->tpl->assign('source',indexUrl()); $this->tpl->assign('version',shaarli_version); + $this->tpl->assign('scripturl',indexUrl()); $this->tpl->assign('pagetitle','Shaarli'); if (!empty($GLOBALS['title'])) $this->tpl->assign('pagetitle',$GLOBALS['title']); if (!empty($GLOBALS['pagetitle'])) $this->tpl->assign('pagetitle',$GLOBALS['pagetitle']); @@ -551,6 +561,14 @@ class pageBuilder echo $mylinks['20110826_161819']['title']; foreach($mylinks as $link) echo $link['title'].' at url '.$link['url'].' ; description:'.$link['description']; + + Available keys: + title : Title of the link + url : URL of the link. Can be absolute or relative. Relative URLs are permalinks (eg.'?m-ukcw') + description : description of the entry + private : Is this link private ? 0=no, other value=yes + linkdate : date of the creation of this entry, in the form YYYYMMDD_HHMMSS (eg.'20110914_192317') + tags : tags attached to this entry (separated by spaces) We implement 3 interfaces: - ArrayAccess so that this object behaves like an associative array. @@ -688,6 +706,19 @@ class linkdb implements Iterator, Countable, ArrayAccess return $filtered; } + // Filter by day. Day must be in the form 'YYYYMMDD' (eg. '20120125') + // Sort order is: older articles first. + // eg. print_r($mydb->filterDay('20120125')); + public function filterDay($day) + { + $filtered=array(); + foreach($this->links as $l) + { + if (startsWith($l['linkdate'],$day)) $filtered[$l['linkdate']] = $l; + } + ksort($filtered); + return $filtered; + } // Filter by smallHash. // Only 1 article is returned. public function filterSmallHash($smallHash) @@ -791,7 +822,7 @@ function showATOM() if (startsWith($absurl,'?')) $absurl=$pageaddr.$absurl; // make permalink URL absolute $entries.=''.htmlspecialchars($link['title']).''.$guid.''; if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $entries.=''.htmlspecialchars($iso8601date).''; - $entries.=''.nl2br(keepMultipleSpaces(text2clickable(htmlspecialchars($link['description']))))."\n"; + $entries.=''.htmlspecialchars(nl2br(keepMultipleSpaces(text2clickable(htmlspecialchars($link['description'])))))."\n"; if ($link['tags']!='') // Adding tags to each ATOM entry (as mentioned in ATOM specification) { foreach(explode(' ',$link['tags']) as $tag) @@ -803,14 +834,14 @@ function showATOM() $feed=''; $feed.=''.htmlspecialchars($GLOBALS['title']).''; if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $feed.=''.htmlspecialchars($latestDate).''; - $feed.=''; + $feed.=''; if (!empty($GLOBALS['config']['PUBSUBHUB_URL'])) { $feed.=''; $feed.=''; $feed.=''; } - $feed.=''.htmlspecialchars($pageaddr).''; + $feed.=''.htmlspecialchars($pageaddr).''.htmlspecialchars($pageaddr).''; $feed.=''.htmlspecialchars($pageaddr).''."\n\n"; // Yes, I know I should use a real IRI (RFC3987), but the site URL will do. $feed.=$entries; $feed.=''; @@ -928,7 +959,57 @@ function renderPage() 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))); + + $linksToDisplay=$LINKSDB->filterDay($day); + // We pre-format some fields for proper output. + foreach($linksToDisplay as $key=>$link) + { + $linksToDisplay[$key]['taglist']=explode(' ',$link['tags']); + $linksToDisplay[$key]['formatedDescription']=nl2br(keepMultipleSpaces(text2clickable(htmlspecialchars($link['description'])))); + $linksToDisplay[$key]['thumbnail'] = thumbnail($link['url']); + } + + /* We need to spread the articles on 3 columns. + I did not want to use a javascript lib like http://masonry.desandro.com/ + so I manually spread entries with a simple method: I roughly evaluate the + height of a div according to title and description length. + */ + $columns=array(array(),array(),array()); // Entries to display, for each column. + $fill=array(0,0,0); // Rough estimate of columns fill. + foreach($linksToDisplay as $key=>$link) + { + // Roughly estimate length of entry (by counting characters) + // 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. + array_push($columns[$index],$link); // Put entry in this column. + $fill[$index]+=$length; + } + $PAGE = new pageBuilder; + $PAGE->assign('linksToDisplay',$linksToDisplay); + $PAGE->assign('col1',$columns[0]); + $PAGE->assign('col2',$columns[1]); + $PAGE->assign('col3',$columns[2]); + $PAGE->assign('day',utf8_encode(strftime('%A %d, %B %Y',linkdate2timestamp($day.'_000000')))); + $PAGE->assign('previousday',$previousday); + $PAGE->assign('nextday',$nextday); + $PAGE->renderPage('daily'); + exit; + } // -------- Handle other actions allowed for non-logged in users: if (!isLoggedIn()) @@ -1418,6 +1499,7 @@ function buildLinkList($PAGE) // 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) { if (!$GLOBALS['config']['ENABLE_THUMBNAILS']) return ''; @@ -1431,32 +1513,38 @@ 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 ''; + if (!empty($params['v'])) return 'YouTube thumbnail'; } if ($domain=='youtu.be') // Youtube short links { $path = parse_url($url,PHP_URL_PATH); - return ''; + return '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 ($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 ''; - if (startsWith($path,'/gallery/')) return ''; - if (substr_count($path,'/')==1) return ''; + 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 ($domain=='i.imgur.com') { $pi = pathinfo(parse_url($url,PHP_URL_PATH)); - if (!empty($pi['filename'])) return ''; + if (!empty($pi['filename'])) return '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 ''; + return 'DailyMotion thumbnail'; } } if (endsWith($domain,'.imageshack.us')) @@ -1465,7 +1553,7 @@ 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 ''; + return 'imageshack.us thumbnail'; } } @@ -1478,6 +1566,7 @@ function thumbnail($url,$href=false) if ($domain=='flickr.com' || endsWith($domain,'.flickr.com') || $domain=='vimeo.com' || $domain=='ted.com' || endsWith($domain,'.ted.com') + || $domain=='xkcd.com' || endsWith($domain,'.xkcd.com') ) { if ($domain=='vimeo.com') @@ -1485,13 +1574,18 @@ function thumbnail($url,$href=false) $path = parse_url($url,PHP_URL_PATH); if (!preg_match('!/\d+.+?!',$path)) return ''; // 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 ($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. } $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 'thumbnail'; } // For all other, we try to make a thumbnail of links ending with .jpg/jpeg/png/gif @@ -1790,6 +1884,35 @@ function genThumbnail() } } } + + elseif ($domain=='xkcd.com' || endsWith($domain,'.xkcd.com')) + { + // There is no thumbnail available for xkcd comics, so download the whole image and resize it. + // http://xkcd.com/327/ + // <BLABLA> + list($httpstatus,$headers,$data) = getHTTP($url,5); + if (strpos($httpstatus,'200 OK')!==false) + { + // Extract the link to the thumbnail + preg_match('!