aboutsummaryrefslogtreecommitdiffhomepage
path: root/index.php
diff options
context:
space:
mode:
Diffstat (limited to 'index.php')
-rw-r--r--index.php128
1 files changed, 106 insertions, 22 deletions
diff --git a/index.php b/index.php
index ba3d9c34..46a8c902 100644
--- a/index.php
+++ b/index.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2// Shaarli 0.0.33 beta - Shaare your links... 2// Shaarli 0.0.34 beta - Shaare your links...
3// The personal, minimalist, super-fast, no-database delicious clone. By sebsauvage.net 3// The personal, minimalist, super-fast, no-database delicious clone. By sebsauvage.net
4// http://sebsauvage.net/wiki/doku.php?id=php:shaarli 4// http://sebsauvage.net/wiki/doku.php?id=php:shaarli
5// Licence: http://www.opensource.org/licenses/zlib-license.php 5// Licence: http://www.opensource.org/licenses/zlib-license.php
@@ -58,7 +58,7 @@ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
58header("Cache-Control: no-store, no-cache, must-revalidate"); 58header("Cache-Control: no-store, no-cache, must-revalidate");
59header("Cache-Control: post-check=0, pre-check=0", false); 59header("Cache-Control: post-check=0, pre-check=0", false);
60header("Pragma: no-cache"); 60header("Pragma: no-cache");
61define('shaarli_version','0.0.33 beta'); 61define('shaarli_version','0.0.34 beta');
62if (!is_dir($GLOBALS['config']['DATADIR'])) { mkdir($GLOBALS['config']['DATADIR'],0705); chmod($GLOBALS['config']['DATADIR'],0705); } 62if (!is_dir($GLOBALS['config']['DATADIR'])) { mkdir($GLOBALS['config']['DATADIR'],0705); chmod($GLOBALS['config']['DATADIR'],0705); }
63if (!is_file($GLOBALS['config']['DATADIR'].'/.htaccess')) { file_put_contents($GLOBALS['config']['DATADIR'].'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. 63if (!is_file($GLOBALS['config']['DATADIR'].'/.htaccess')) { file_put_contents($GLOBALS['config']['DATADIR'].'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files.
64if ($GLOBALS['config']['ENABLE_LOCALCACHE']) 64if ($GLOBALS['config']['ENABLE_LOCALCACHE'])
@@ -141,11 +141,12 @@ function smallHash($text)
141 return $t; 141 return $t;
142} 142}
143 143
144// In a string, converts urls to clickable links.
144// Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722 145// Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722
145function text2clickable($url) 146function text2clickable($url)
146{ 147{
147 $redir = empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector']; 148 $redir = empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'];
148 return preg_replace('!((?:https?|ftp)://\S+[[:alnum:]]/?)!si','<a href="'.$redir.'$1" rel="nofollow">$1</a>',$url); 149 return preg_replace('!(((?:https?|ftp|file)://|apt:)\S+[[:alnum:]]/?)!si','<a href="'.$redir.'$1" rel="nofollow">$1</a>',$url);
149} 150}
150 151
151// This function inserts &nbsp; where relevant so that multiple spaces are properly displayed in HTML 152// This function inserts &nbsp; where relevant so that multiple spaces are properly displayed in HTML
@@ -336,13 +337,15 @@ if (isset($_POST['login']))
336// You can append $_SERVER['SCRIPT_NAME'] to get the current script URL. 337// You can append $_SERVER['SCRIPT_NAME'] to get the current script URL.
337function serverUrl() 338function serverUrl()
338{ 339{
339 $serverport = ($_SERVER["SERVER_PORT"]=='80' || (!empty($_SERVER['HTTPS']) && $_SERVER["SERVER_PORT"]=='443') ? '' : ':'.$_SERVER["SERVER_PORT"]); 340 $https = (!empty($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS'])=='on')) || $_SERVER["SERVER_PORT"]=='443'; // HTTPS detection.
340 return 'http'.(!empty($_SERVER['HTTPS'])?'s':'').'://'.$_SERVER["SERVER_NAME"].$serverport; 341 $serverport = ($_SERVER["SERVER_PORT"]=='80' || ($https && $_SERVER["SERVER_PORT"]=='443') ? '' : ':'.$_SERVER["SERVER_PORT"]);
342 return 'http'.($https?'s':'').'://'.$_SERVER["SERVER_NAME"].$serverport;
341} 343}
342 344
345// Returns the absolute URL of current script.
343function indexUrl() 346function indexUrl()
344{ 347{
345 return serverUrl() . ($_SERVER["SCRIPT_NAME"] == '/index.php' ? '' : $_SERVER["SCRIPT_NAME"]); 348 return serverUrl() . ($_SERVER["SCRIPT_NAME"] == '/index.php' ? '/' : $_SERVER["SCRIPT_NAME"]);
346} 349}
347 350
348// Convert post_max_size/upload_max_filesize (eg.'16M') parameters to bytes. 351// Convert post_max_size/upload_max_filesize (eg.'16M') parameters to bytes.
@@ -526,6 +529,7 @@ class pageBuilder
526 $this->tpl->assign('searchcrits',$searchcrits); 529 $this->tpl->assign('searchcrits',$searchcrits);
527 $this->tpl->assign('source',indexUrl()); 530 $this->tpl->assign('source',indexUrl());
528 $this->tpl->assign('version',shaarli_version); 531 $this->tpl->assign('version',shaarli_version);
532 $this->tpl->assign('scripturl',indexUrl());
529 $this->tpl->assign('pagetitle','Shaarli'); 533 $this->tpl->assign('pagetitle','Shaarli');
530 if (!empty($GLOBALS['title'])) $this->tpl->assign('pagetitle',$GLOBALS['title']); 534 if (!empty($GLOBALS['title'])) $this->tpl->assign('pagetitle',$GLOBALS['title']);
531 if (!empty($GLOBALS['pagetitle'])) $this->tpl->assign('pagetitle',$GLOBALS['pagetitle']); 535 if (!empty($GLOBALS['pagetitle'])) $this->tpl->assign('pagetitle',$GLOBALS['pagetitle']);
@@ -557,6 +561,14 @@ class pageBuilder
557 echo $mylinks['20110826_161819']['title']; 561 echo $mylinks['20110826_161819']['title'];
558 foreach($mylinks as $link) 562 foreach($mylinks as $link)
559 echo $link['title'].' at url '.$link['url'].' ; description:'.$link['description']; 563 echo $link['title'].' at url '.$link['url'].' ; description:'.$link['description'];
564
565 Available keys:
566 title : Title of the link
567 url : URL of the link. Can be absolute or relative. Relative URLs are permalinks (eg.'?m-ukcw')
568 description : description of the entry
569 private : Is this link private ? 0=no, other value=yes
570 linkdate : date of the creation of this entry, in the form YYYYMMDD_HHMMSS (eg.'20110914_192317')
571 tags : tags attached to this entry (separated by spaces)
560 572
561 We implement 3 interfaces: 573 We implement 3 interfaces:
562 - ArrayAccess so that this object behaves like an associative array. 574 - ArrayAccess so that this object behaves like an associative array.
@@ -694,6 +706,19 @@ class linkdb implements Iterator, Countable, ArrayAccess
694 return $filtered; 706 return $filtered;
695 } 707 }
696 708
709 // Filter by day. Day must be in the form 'YYYYMMDD' (eg. '20120125')
710 // Sort order is: older articles first.
711 // eg. print_r($mydb->filterDay('20120125'));
712 public function filterDay($day)
713 {
714 $filtered=array();
715 foreach($this->links as $l)
716 {
717 if (startsWith($l['linkdate'],$day)) $filtered[$l['linkdate']] = $l;
718 }
719 ksort($filtered);
720 return $filtered;
721 }
697 // Filter by smallHash. 722 // Filter by smallHash.
698 // Only 1 article is returned. 723 // Only 1 article is returned.
699 public function filterSmallHash($smallHash) 724 public function filterSmallHash($smallHash)
@@ -934,7 +959,55 @@ function renderPage()
934 header('Location: '.(empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER'])); 959 header('Location: '.(empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER']));
935 exit; 960 exit;
936 } 961 }
937 962
963 // --------- Daily (all links form a specific day) ----------------------
964 if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=daily'))
965 {
966 $day=Date('Ymd',strtotime('-1 day')); // Yesterday, in format YYYYMMDD.
967 if (isset($_GET['day'])) $day=$_GET['day'];
968
969 $previousday = Date('Ymd',strtotime('-1 day',strtotime($day)));
970 $nextday = Date('Ymd',strtotime('+1 day',strtotime($day)));
971
972 $linksToDisplay=$LINKSDB->filterDay($day);
973 // We pre-format some fields for proper output.
974 foreach($linksToDisplay as $key=>$link)
975 {
976 $linksToDisplay[$key]['taglist']=explode(' ',$link['tags']);
977 $linksToDisplay[$key]['formatedDescription']=nl2br(keepMultipleSpaces(text2clickable(htmlspecialchars($link['description']))));
978 $linksToDisplay[$key]['thumbnail'] = thumbnail($link['url']);
979 }
980
981 /* We need to spread the articles on 3 columns.
982 I did not want to use a javascript lib like http://masonry.desandro.com/
983 so I manually spread entries with a simple method: I roughly evaluate the
984 height of a div according to title and description length.
985 */
986 $columns=array(array(),array(),array()); // Entries to display, for each column.
987 $fill=array(0,0,0); // Rough estimate of columns fill.
988 foreach($linksToDisplay as $key=>$link)
989 {
990 // Roughly estimate length of entry (by counting characters)
991 $length=strlen($link['title'])+strlen($link['description']);
992 if ($link['thumbnail']) $length +=100; // 1 thumbnails roughly take as much space as 100 words;
993
994 // Then put in column which is the less filled:
995 $smallest=min($fill); // find smallest value in array.
996 $index=array_search($smallest,$fill); // find index of this smallest value.
997 array_push($columns[$index],$link); // Put entry in this column.
998 $fill[$index]+=$length;
999 }
1000 $PAGE = new pageBuilder;
1001 $PAGE->assign('linksToDisplay',$linksToDisplay);
1002 $PAGE->assign('col1',$columns[0]);
1003 $PAGE->assign('col2',$columns[1]);
1004 $PAGE->assign('col3',$columns[2]);
1005 $PAGE->assign('day',utf8_encode(strftime('%A %d, %B %Y',linkdate2timestamp($day.'_000000'))));
1006 $PAGE->assign('previousday',$previousday);
1007 $PAGE->assign('nextday',$nextday);
1008 $PAGE->renderPage('daily');
1009 exit;
1010 }
938 1011
939 // -------- Handle other actions allowed for non-logged in users: 1012 // -------- Handle other actions allowed for non-logged in users:
940 if (!isLoggedIn()) 1013 if (!isLoggedIn())
@@ -1424,6 +1497,7 @@ function buildLinkList($PAGE)
1424// Understands various services (youtube.com...) 1497// Understands various services (youtube.com...)
1425// Input: $url = url for which the thumbnail must be found. 1498// Input: $url = url for which the thumbnail must be found.
1426// $href = if provided, this URL will be followed instead of $url 1499// $href = if provided, this URL will be followed instead of $url
1500// Returns '' if no thumbnail available.
1427function thumbnail($url,$href=false) 1501function thumbnail($url,$href=false)
1428{ 1502{
1429 if (!$GLOBALS['config']['ENABLE_THUMBNAILS']) return ''; 1503 if (!$GLOBALS['config']['ENABLE_THUMBNAILS']) return '';
@@ -1437,32 +1511,38 @@ function thumbnail($url,$href=false)
1437 if ($domain=='youtube.com' || $domain=='www.youtube.com') 1511 if ($domain=='youtube.com' || $domain=='www.youtube.com')
1438 { 1512 {
1439 parse_str(parse_url($url,PHP_URL_QUERY), $params); // Extract video ID and get thumbnail 1513 parse_str(parse_url($url,PHP_URL_QUERY), $params); // Extract video ID and get thumbnail
1440 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"></a>'; 1514 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>';
1441 } 1515 }
1442 if ($domain=='youtu.be') // Youtube short links 1516 if ($domain=='youtu.be') // Youtube short links
1443 { 1517 {
1444 $path = parse_url($url,PHP_URL_PATH); 1518 $path = parse_url($url,PHP_URL_PATH);
1445 return '<a href="'.htmlspecialchars($href).'"><img src="http://img.youtube.com/vi'.htmlspecialchars($path).'/default.jpg" width="120" height="90"></a>'; 1519 return '<a href="'.htmlspecialchars($href).'"><img src="http://img.youtube.com/vi'.htmlspecialchars($path).'/default.jpg" width="120" height="90" alt="YouTube thumbnail"></a>';
1446 } 1520 }
1521 if ($domain=='pix.toile-libre.org') // pix.toile-libre.org image hosting
1522 {
1523 parse_str(parse_url($url,PHP_URL_QUERY), $params); // Extract image filename.
1524 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>';
1525 }
1526
1447 if ($domain=='imgur.com') 1527 if ($domain=='imgur.com')
1448 { 1528 {
1449 $path = parse_url($url,PHP_URL_PATH); 1529 $path = parse_url($url,PHP_URL_PATH);
1450 if (startsWith($path,'/a/')) return ''; // Thumbnails for albums are not available. 1530 if (startsWith($path,'/a/')) return ''; // Thumbnails for albums are not available.
1451 if (startsWith($path,'/r/')) return '<a href="'.htmlspecialchars($href).'"><img src="http://i.imgur.com/'.htmlspecialchars(basename($path)).'s.jpg" width="90" height="90"></a>'; 1531 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>';
1452 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"></a>'; 1532 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>';
1453 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"></a>'; 1533 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>';
1454 } 1534 }
1455 if ($domain=='i.imgur.com') 1535 if ($domain=='i.imgur.com')
1456 { 1536 {
1457 $pi = pathinfo(parse_url($url,PHP_URL_PATH)); 1537 $pi = pathinfo(parse_url($url,PHP_URL_PATH));
1458 if (!empty($pi['filename'])) return '<a href="'.htmlspecialchars($href).'"><img src="http://i.imgur.com/'.htmlspecialchars($pi['filename']).'s.jpg" width="90" height="90"></a>'; 1538 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>';
1459 } 1539 }
1460 if ($domain=='dailymotion.com' || $domain=='www.dailymotion.com') 1540 if ($domain=='dailymotion.com' || $domain=='www.dailymotion.com')
1461 { 1541 {
1462 if (strpos($url,'dailymotion.com/video/')!==false) 1542 if (strpos($url,'dailymotion.com/video/')!==false)
1463 { 1543 {
1464 $thumburl=str_replace('dailymotion.com/video/','dailymotion.com/thumbnail/video/',$url); 1544 $thumburl=str_replace('dailymotion.com/video/','dailymotion.com/thumbnail/video/',$url);
1465 return '<a href="'.htmlspecialchars($href).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;"></a>'; 1545 return '<a href="'.htmlspecialchars($href).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;" alt="DailyMotion thumbnail"></a>';
1466 } 1546 }
1467 } 1547 }
1468 if (endsWith($domain,'.imageshack.us')) 1548 if (endsWith($domain,'.imageshack.us'))
@@ -1471,7 +1551,7 @@ function thumbnail($url,$href=false)
1471 if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif') 1551 if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif')
1472 { 1552 {
1473 $thumburl = substr($url,0,strlen($url)-strlen($ext)).'th.'.$ext; 1553 $thumburl = substr($url,0,strlen($url)-strlen($ext)).'th.'.$ext;
1474 return '<a href="'.htmlspecialchars($href).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;"></a>'; 1554 return '<a href="'.htmlspecialchars($href).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;" alt="imageshack.us thumbnail"></a>';
1475 } 1555 }
1476 } 1556 }
1477 1557
@@ -1487,11 +1567,15 @@ function thumbnail($url,$href=false)
1487 || $domain=='xkcd.com' || endsWith($domain,'.xkcd.com') 1567 || $domain=='xkcd.com' || endsWith($domain,'.xkcd.com')
1488 ) 1568 )
1489 { 1569 {
1490 if ($domain=='vimeo.com' || $domain=='xkcd.com' || endsWith($domain,'.xkcd.com')) 1570 if ($domain=='vimeo.com')
1491 { // Make sure the url is of the form /xxx... where xxx is numeric 1571 { // Make sure this vimeo url points to a video (/xxx... where xxx is numeric)
1492 // For Vimeo's videos and xkcd's comics 1572 $path = parse_url($url,PHP_URL_PATH);
1573 if (!preg_match('!/\d+.+?!',$path)) return ''; // This is not a single video URL.
1574 }
1575 if ($domain=='xkcd.com' || endsWith($domain,'.xkcd.com'))
1576 { // Make sure this url points to a single comic (/xxx... where xxx is numeric)
1493 $path = parse_url($url,PHP_URL_PATH); 1577 $path = parse_url($url,PHP_URL_PATH);
1494 if (!preg_match('!/\d+.+?!',$path)) return ''; // This is not a single video/comic URL. 1578 if (!preg_match('!/\d+.+?!',$path)) return '';
1495 } 1579 }
1496 if ($domain=='ted.com' || endsWith($domain,'.ted.com')) 1580 if ($domain=='ted.com' || endsWith($domain,'.ted.com'))
1497 { // Make sure this TED url points to a video (/talks/...) 1581 { // Make sure this TED url points to a video (/talks/...)
@@ -1499,7 +1583,7 @@ function thumbnail($url,$href=false)
1499 if ("/talks/" !== substr($path,0,7)) return ''; // This is not a single video URL. 1583 if ("/talks/" !== substr($path,0,7)) return ''; // This is not a single video URL.
1500 } 1584 }
1501 $sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation) 1585 $sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation)
1502 return '<a href="'.htmlspecialchars($href).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;"></a>'; 1586 return '<a href="'.htmlspecialchars($href).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;" alt="thumbnail"></a>';
1503 } 1587 }
1504 1588
1505 // For all other, we try to make a thumbnail of links ending with .jpg/jpeg/png/gif 1589 // For all other, we try to make a thumbnail of links ending with .jpg/jpeg/png/gif
@@ -1798,7 +1882,7 @@ function genThumbnail()
1798 } 1882 }
1799 } 1883 }
1800 } 1884 }
1801 1885
1802 elseif ($domain=='xkcd.com' || endsWith($domain,'.xkcd.com')) 1886 elseif ($domain=='xkcd.com' || endsWith($domain,'.xkcd.com'))
1803 { 1887 {
1804 // There is no thumbnail available for xkcd comics, so download the whole image and resize it. 1888 // There is no thumbnail available for xkcd comics, so download the whole image and resize it.
@@ -1826,7 +1910,7 @@ function genThumbnail()
1826 } 1910 }
1827 } 1911 }
1828 } 1912 }
1829 } 1913 }
1830 1914
1831 else 1915 else
1832 { 1916 {