diff options
Diffstat (limited to 'index.php')
-rw-r--r-- | index.php | 197 |
1 files changed, 132 insertions, 65 deletions
@@ -1,5 +1,5 @@ | |||
1 | <?php | 1 | <?php |
2 | // Shaarli 0.0.27 beta - Shaare your links... | 2 | // Shaarli 0.0.28 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 |
@@ -20,7 +20,8 @@ $GLOBALS['config']['HIDE_TIMESTAMPS'] = false; // If true, the moment when links | |||
20 | $GLOBALS['config']['ENABLE_THUMBNAILS'] = true; // Enable thumbnails in links. | 20 | $GLOBALS['config']['ENABLE_THUMBNAILS'] = true; // Enable thumbnails in links. |
21 | $GLOBALS['config']['CACHEDIR'] = 'cache'; // Cache directory for thumbnails for SLOW services (like flickr) | 21 | $GLOBALS['config']['CACHEDIR'] = 'cache'; // Cache directory for thumbnails for SLOW services (like flickr) |
22 | $GLOBALS['config']['ENABLE_LOCALCACHE'] = true; // Enable Shaarli to store thumbnail in a local cache. Disable to reduce webspace usage. | 22 | $GLOBALS['config']['ENABLE_LOCALCACHE'] = true; // Enable Shaarli to store thumbnail in a local cache. Disable to reduce webspace usage. |
23 | 23 | $GLOBALS['config']['PUBSUBHUB_URL'] = ''; // PubSubHub support. Put an empty string to disable, or put your hub url here to enable. | |
24 | // Note: You must have publisher.php in the same directory as Shaarli index.php | ||
24 | // ----------------------------------------------------------------------------------------------- | 25 | // ----------------------------------------------------------------------------------------------- |
25 | // Program config (touch at your own risks !) | 26 | // Program config (touch at your own risks !) |
26 | $GLOBALS['config']['UPDATECHECK_FILENAME'] = $GLOBALS['config']['DATADIR'].'/lastupdatecheck.txt'; // For updates check of Shaarli. | 27 | $GLOBALS['config']['UPDATECHECK_FILENAME'] = $GLOBALS['config']['DATADIR'].'/lastupdatecheck.txt'; // For updates check of Shaarli. |
@@ -53,7 +54,7 @@ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |||
53 | header("Cache-Control: no-store, no-cache, must-revalidate"); | 54 | header("Cache-Control: no-store, no-cache, must-revalidate"); |
54 | header("Cache-Control: post-check=0, pre-check=0", false); | 55 | header("Cache-Control: post-check=0, pre-check=0", false); |
55 | header("Pragma: no-cache"); | 56 | header("Pragma: no-cache"); |
56 | define('shaarli_version','0.0.27 beta'); | 57 | define('shaarli_version','0.0.28 beta'); |
57 | if (!is_dir($GLOBALS['config']['DATADIR'])) { mkdir($GLOBALS['config']['DATADIR'],0705); chmod($GLOBALS['config']['DATADIR'],0705); } | 58 | if (!is_dir($GLOBALS['config']['DATADIR'])) { mkdir($GLOBALS['config']['DATADIR'],0705); chmod($GLOBALS['config']['DATADIR'],0705); } |
58 | if (!is_file($GLOBALS['config']['DATADIR'].'/.htaccess')) { file_put_contents($GLOBALS['config']['DATADIR'].'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. | 59 | if (!is_file($GLOBALS['config']['DATADIR'].'/.htaccess')) { file_put_contents($GLOBALS['config']['DATADIR'].'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. |
59 | if ($GLOBALS['config']['ENABLE_LOCALCACHE']) | 60 | if ($GLOBALS['config']['ENABLE_LOCALCACHE']) |
@@ -94,7 +95,7 @@ function checkUpdate() | |||
94 | { | 95 | { |
95 | $version=shaarli_version; | 96 | $version=shaarli_version; |
96 | list($httpstatus,$headers,$data) = getHTTP('http://sebsauvage.net/files/shaarli_version.txt',2); | 97 | list($httpstatus,$headers,$data) = getHTTP('http://sebsauvage.net/files/shaarli_version.txt',2); |
97 | if (strpos($httpstatus,'200 OK')) $version=$data; | 98 | if (strpos($httpstatus,'200 OK')!==false) $version=$data; |
98 | // If failed, nevermind. We don't want to bother the user with that. | 99 | // If failed, nevermind. We don't want to bother the user with that. |
99 | file_put_contents($GLOBALS['config']['UPDATECHECK_FILENAME'],$version); // touch file date | 100 | file_put_contents($GLOBALS['config']['UPDATECHECK_FILENAME'],$version); // touch file date |
100 | } | 101 | } |
@@ -150,6 +151,23 @@ function autoLocale() | |||
150 | } | 151 | } |
151 | 152 | ||
152 | // ------------------------------------------------------------------------------------------ | 153 | // ------------------------------------------------------------------------------------------ |
154 | // PubSubHub protocol support (if enabled) [UNTESTED] | ||
155 | // (Source: http://aldarone.fr/les-flux-rss-shaarli-et-pubsubhubbub/ ) | ||
156 | if (!empty($GLOBALS['config']['PUBSUBHUB_URL'])) include './publisher.php'; | ||
157 | function pubsubhub() | ||
158 | { | ||
159 | if (!empty($GLOBALS['config']['PUBSUBHUB_URL'])) | ||
160 | { | ||
161 | $p = new Publisher($GLOBALS['config']['PUBSUBHUB_URL']); | ||
162 | $topic_url = array ( | ||
163 | serverUrl().$_SERVER['SCRIPT_NAME'].'?do=atom', | ||
164 | serverUrl().$_SERVER['SCRIPT_NAME'].'?do=rss' | ||
165 | ); | ||
166 | $p->publish_update($topic_url); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | // ------------------------------------------------------------------------------------------ | ||
153 | // Session management | 171 | // Session management |
154 | define('INACTIVITY_TIMEOUT',3600); // (in seconds). If the user does not access any page within this time, his/her session is considered expired. | 172 | define('INACTIVITY_TIMEOUT',3600); // (in seconds). If the user does not access any page within this time, his/her session is considered expired. |
155 | ini_set('session.use_cookies', 1); // Use cookies to store session. | 173 | ini_set('session.use_cookies', 1); // Use cookies to store session. |
@@ -378,13 +396,13 @@ function linkdate2locale($linkdate) | |||
378 | } | 396 | } |
379 | 397 | ||
380 | // Parse HTTP response headers and return an associative array. | 398 | // Parse HTTP response headers and return an associative array. |
381 | function http_parse_headers( $headers ) | 399 | function http_parse_headers_shaarli( $headers ) |
382 | { | 400 | { |
383 | $res=array(); | 401 | $res=array(); |
384 | foreach($headers as $header) | 402 | foreach($headers as $header) |
385 | { | 403 | { |
386 | $i = strpos($header,': '); | 404 | $i = strpos($header,': '); |
387 | if ($i) | 405 | if ($i!==false) |
388 | { | 406 | { |
389 | $key=substr($header,0,$i); | 407 | $key=substr($header,0,$i); |
390 | $value=substr($header,$i+2,strlen($header)-$i-2); | 408 | $value=substr($header,$i+2,strlen($header)-$i-2); |
@@ -401,7 +419,7 @@ function http_parse_headers( $headers ) | |||
401 | [1] = associative array containing HTTP response headers (eg. echo getHTTP($url)[1]['Content-Type']) | 419 | [1] = associative array containing HTTP response headers (eg. echo getHTTP($url)[1]['Content-Type']) |
402 | [2] = data | 420 | [2] = data |
403 | Example: list($httpstatus,$headers,$data) = getHTTP('http://sebauvage.net/'); | 421 | Example: list($httpstatus,$headers,$data) = getHTTP('http://sebauvage.net/'); |
404 | if (strpos($httpstatus,'200 OK')) | 422 | if (strpos($httpstatus,'200 OK')!==false) |
405 | echo 'Data type: '.htmlspecialchars($headers['Content-Type']); | 423 | echo 'Data type: '.htmlspecialchars($headers['Content-Type']); |
406 | else | 424 | else |
407 | echo 'There was an error: '.htmlspecialchars($httpstatus) | 425 | echo 'There was an error: '.htmlspecialchars($httpstatus) |
@@ -415,7 +433,7 @@ function getHTTP($url,$timeout=30) | |||
415 | $data=file_get_contents($url,false,$context,-1, 4000000); // We download at most 4 Mb from source. | 433 | $data=file_get_contents($url,false,$context,-1, 4000000); // We download at most 4 Mb from source. |
416 | if (!$data) { $lasterror=error_get_last(); return array($lasterror['message'],array(),''); } | 434 | if (!$data) { $lasterror=error_get_last(); return array($lasterror['message'],array(),''); } |
417 | $httpStatus=$http_response_header[0]; // eg. "HTTP/1.1 200 OK" | 435 | $httpStatus=$http_response_header[0]; // eg. "HTTP/1.1 200 OK" |
418 | $responseHeaders=http_parse_headers($http_response_header); | 436 | $responseHeaders=http_parse_headers_shaarli($http_response_header); |
419 | return array($httpStatus,$responseHeaders,$data); | 437 | return array($httpStatus,$responseHeaders,$data); |
420 | } | 438 | } |
421 | catch (Exception $e) // getHTTP *can* fail silentely (we don't care if the title cannot be fetched) | 439 | catch (Exception $e) // getHTTP *can* fail silentely (we don't care if the title cannot be fetched) |
@@ -428,7 +446,7 @@ function getHTTP($url,$timeout=30) | |||
428 | // (Returns an empty string if not found.) | 446 | // (Returns an empty string if not found.) |
429 | function html_extract_title($html) | 447 | function html_extract_title($html) |
430 | { | 448 | { |
431 | return preg_match('!<title>(.*)</title>!is', $html, $matches) ? trim(str_replace("\n",' ', $matches[1])) : '' ; | 449 | return preg_match('!<title>(.*?)</title>!is', $html, $matches) ? trim(str_replace("\n",' ', $matches[1])) : '' ; |
432 | } | 450 | } |
433 | 451 | ||
434 | // ------------------------------------------------------------------------------------------ | 452 | // ------------------------------------------------------------------------------------------ |
@@ -574,7 +592,10 @@ class linkdb implements Iterator, Countable, ArrayAccess | |||
574 | $s = strtolower($searchterms); | 592 | $s = strtolower($searchterms); |
575 | foreach($this->links as $l) | 593 | foreach($this->links as $l) |
576 | { | 594 | { |
577 | $found=strpos(strtolower($l['title']),$s) || strpos(strtolower($l['description']),$s) || strpos(strtolower($l['url']),$s) || strpos(strtolower($l['tags']),$s); | 595 | $found= (strpos(strtolower($l['title']),$s)!==false) |
596 | || (strpos(strtolower($l['description']),$s)!==false) | ||
597 | || (strpos(strtolower($l['url']),$s)!==false) | ||
598 | || (strpos(strtolower($l['tags']),$s)!==false); | ||
578 | if ($found) $filtered[$l['linkdate']] = $l; | 599 | if ($found) $filtered[$l['linkdate']] = $l; |
579 | } | 600 | } |
580 | krsort($filtered); | 601 | krsort($filtered); |
@@ -644,16 +665,29 @@ function showRSS() | |||
644 | $pageaddr=htmlspecialchars(serverUrl().$_SERVER["SCRIPT_NAME"]); | 665 | $pageaddr=htmlspecialchars(serverUrl().$_SERVER["SCRIPT_NAME"]); |
645 | echo '<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">'; | 666 | echo '<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">'; |
646 | echo '<channel><title>'.htmlspecialchars($GLOBALS['title']).'</title><link>'.$pageaddr.'</link>'; | 667 | echo '<channel><title>'.htmlspecialchars($GLOBALS['title']).'</title><link>'.$pageaddr.'</link>'; |
647 | echo '<description>Shared links</description><language></language><copyright>'.$pageaddr.'</copyright>'."\n\n"; | 668 | echo '<description>Shared links</description><language>en-en</language><copyright>'.$pageaddr.'</copyright>'."\n\n"; |
669 | if (!empty($GLOBALS['config']['PUBSUBHUB_URL'])) | ||
670 | { | ||
671 | echo '<!-- PubSubHubbub Discovery -->'; | ||
672 | echo '<link rel="hub" href="'.htmlspecialchars($GLOBALS['config']['PUBSUBHUB_URL']).'" xmlns="http://www.w3.org/2005/Atom" />'; | ||
673 | echo '<link rel="self" href="'.htmlspecialchars($pageaddr).'?do=rss" xmlns="http://www.w3.org/2005/Atom" />'; | ||
674 | echo '<!-- End Of PubSubHubbub Discovery -->'; | ||
675 | } | ||
648 | $i=0; | 676 | $i=0; |
649 | $keys=array(); foreach($linksToDisplay as $key=>$value) { $keys[]=$key; } // No, I can't use array_keys(). | 677 | $keys=array(); foreach($linksToDisplay as $key=>$value) { $keys[]=$key; } // No, I can't use array_keys(). |
650 | while ($i<50 && $i<count($keys)) | 678 | while ($i<50 && $i<count($keys)) |
651 | { | 679 | { |
652 | $link = $linksToDisplay[$keys[$i]]; | 680 | $link = $linksToDisplay[$keys[$i]]; |
653 | $rfc822date = linkdate2rfc822($link['linkdate']); | 681 | $rfc822date = linkdate2rfc822($link['linkdate']); |
654 | echo '<item><title>'.htmlspecialchars($link['title']).'</title><guid>'.htmlspecialchars($link['url']).'</guid><link>'.htmlspecialchars($link['url']).'</link>'; | 682 | $absurl = htmlspecialchars($link['url']); |
655 | if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) echo '<pubDate>'.htmlspecialchars($rfc822date).'</pubDate>'; | 683 | if (startsWith($absurl,'?')) $absurl=$pageaddr.$absurl; // make permalink URL absolute |
656 | echo '<description><![CDATA['.nl2br(htmlspecialchars($link['description'])).']]></description></item>'."\n"; | 684 | echo '<item><title>'.htmlspecialchars($link['title']).'</title><guid>'.$absurl.'</guid><link>'.$absurl.'</link>'; |
685 | if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) echo '<pubDate>'.htmlspecialchars($rfc822date)."</pubDate>\n"; | ||
686 | if ($link['tags']!='') // Adding tags to each RSS entry (as mentioned in RSS specification) | ||
687 | { | ||
688 | foreach(explode(' ',$link['tags']) as $tag) { echo '<category domain="'.htmlspecialchars($pageaddr).'">'.htmlspecialchars($tag).'</category>'."\n"; } | ||
689 | } | ||
690 | echo '<description><![CDATA['.nl2br(text2clickable(htmlspecialchars($link['description']))).']]></description>'."\n</item>\n"; | ||
657 | $i++; | 691 | $i++; |
658 | } | 692 | } |
659 | echo '</channel></rss>'; | 693 | echo '</channel></rss>'; |
@@ -683,15 +717,29 @@ function showATOM() | |||
683 | $link = $linksToDisplay[$keys[$i]]; | 717 | $link = $linksToDisplay[$keys[$i]]; |
684 | $iso8601date = linkdate2iso8601($link['linkdate']); | 718 | $iso8601date = linkdate2iso8601($link['linkdate']); |
685 | $latestDate = max($latestDate,$iso8601date); | 719 | $latestDate = max($latestDate,$iso8601date); |
686 | $entries.='<entry><title>'.htmlspecialchars($link['title']).'</title><link href="'.htmlspecialchars($link['url']).'"/><id>'.htmlspecialchars($link['url']).'</id>'; | 720 | $absurl = htmlspecialchars($link['url']); |
721 | if (startsWith($absurl,'?')) $absurl=$pageaddr.$absurl; // make permalink URL absolute | ||
722 | $entries.='<entry><title>'.htmlspecialchars($link['title']).'</title><link href="'.$absurl.'" /><id>'.$absurl.'</id>'; | ||
687 | if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $entries.='<updated>'.htmlspecialchars($iso8601date).'</updated>'; | 723 | if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $entries.='<updated>'.htmlspecialchars($iso8601date).'</updated>'; |
688 | $entries.='<summary>'.nl2br(htmlspecialchars($link['description'])).'</summary></entry>'."\n"; | 724 | $entries.='<summary>'.nl2br(text2clickable(htmlspecialchars($link['description'])))."</summary>\n"; |
725 | if ($link['tags']!='') // Adding tags to each ATOM entry (as mentioned in ATOM specification) | ||
726 | { | ||
727 | foreach(explode(' ',$link['tags']) as $tag) | ||
728 | { $entries.='<category scheme="'.htmlspecialchars($pageaddr,ENT_QUOTES).'" term="'.htmlspecialchars($tag,ENT_QUOTES).'" />'."\n"; } | ||
729 | } | ||
730 | $entries.="</entry>\n"; | ||
689 | $i++; | 731 | $i++; |
690 | } | 732 | } |
691 | $feed='<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom">'; | 733 | $feed='<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom">'; |
692 | $feed.='<title>'.htmlspecialchars($GLOBALS['title']).'</title>'; | 734 | $feed.='<title>'.htmlspecialchars($GLOBALS['title']).'</title>'; |
693 | if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $feed.='<updated>'.htmlspecialchars($latestDate).'</updated>'; | 735 | if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $feed.='<updated>'.htmlspecialchars($latestDate).'</updated>'; |
694 | $feed.='<link href="'.htmlspecialchars($pageaddr).'" />'; | 736 | $feed.='<link rel="self" href="'.htmlspecialchars($pageaddr).'" />'; |
737 | if (!empty($GLOBALS['config']['PUBSUBHUB_URL'])) | ||
738 | { | ||
739 | $feed.='<!-- PubSubHubbub Discovery -->'; | ||
740 | $feed.='<link rel="hub" href="'.htmlspecialchars($GLOBALS['config']['PUBSUBHUB_URL']).'" />'; | ||
741 | $feed.='<!-- End Of PubSubHubbub Discovery -->'; | ||
742 | } | ||
695 | $feed.='<author><uri>'.htmlspecialchars($pageaddr).'</uri></author>'; | 743 | $feed.='<author><uri>'.htmlspecialchars($pageaddr).'</uri></author>'; |
696 | $feed.='<id>'.htmlspecialchars($pageaddr).'</id>'."\n\n"; // Yes, I know I should use a real IRI (RFC3987), but the site URL will do. | 744 | $feed.='<id>'.htmlspecialchars($pageaddr).'</id>'."\n\n"; // Yes, I know I should use a real IRI (RFC3987), but the site URL will do. |
697 | $feed.=$entries; | 745 | $feed.=$entries; |
@@ -747,13 +795,14 @@ function renderPage() | |||
747 | elseif (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); | 795 | elseif (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); |
748 | else $linksToDisplay = $LINKSDB; | 796 | else $linksToDisplay = $LINKSDB; |
749 | $body=''; | 797 | $body=''; |
798 | |||
750 | foreach($linksToDisplay as $link) | 799 | foreach($linksToDisplay as $link) |
751 | { | 800 | { |
752 | $thumb=thumbnail($link['url']); | 801 | $href='?'.htmlspecialchars(smallhash($link['linkdate']),ENT_QUOTES); |
802 | $thumb=thumbnail($link['url'],$href); | ||
753 | if ($thumb!='') | 803 | if ($thumb!='') |
754 | { | 804 | { |
755 | $url=htmlspecialchars($link['url'],ENT_QUOTES); | 805 | $body.='<div class="picwall_pictureframe">'.$thumb.'<a href="'.$href.'"><span class="info">'.htmlspecialchars($link['title']).'</span></a></div>'; |
756 | $body.='<div class="picwall_pictureframe">'.$thumb.'<a href="'.$url.'"><span class="info">'.htmlspecialchars($link['title']).'</span></a></div>'; | ||
757 | 806 | ||
758 | } | 807 | } |
759 | } | 808 | } |
@@ -831,15 +880,15 @@ function renderPage() | |||
831 | // Show login screen, then redirect to ?post=... | 880 | // Show login screen, then redirect to ?post=... |
832 | if (isset($_GET['post'])) | 881 | if (isset($_GET['post'])) |
833 | { | 882 | { |
834 | header('Location: ?do=login&post='.urlencode($_GET['post']).(isset($_GET['title'])?'&title='.urlencode($_GET['title']):'').(isset($_GET['source'])?'&source='.urlencode($_GET['source']):'')); // Redirect to login page, then back to post link. | 883 | header('Location: ?do=login&post='.urlencode($_GET['post']).(iset($_GET['title'])?'&title='.urlencode($_GET['title']):'').(isset($_GET['source'])?'&source='.urlencode($_GET['source']):'')); // Redirect to login page, then back to post link. |
835 | exit; | 884 | exit; |
836 | } | 885 | } |
837 | 886 | ||
838 | // Show search form and display list of links. | 887 | // Show search form and display list of links. |
839 | $searchform=<<<HTML | 888 | $searchform=<<<HTML |
840 | <div id="headerform" style="width:100%; white-space:nowrap;";> | 889 | <div id="headerform" style="width:100%; white-space:nowrap;";> |
841 | <form method="GET" name="searchform" style="display:inline;"><input type="text" name="searchterm" style="width:50%" value=""> <input type="submit" value="Search" class="bigbutton"></form> | 890 | <form method="GET" class="searchform" name="searchform" style="display:inline;"><input type="text" name="searchterm" style="width:30%" value=""> <input type="submit" value="Search" class="bigbutton"></form> |
842 | <form method="GET" name="tagfilter" style="display:inline;padding-left:24px;"><input type="text" name="searchtags" id="searchtags" style="width:20%" value=""> <input type="submit" value="Filter by tag" class="bigbutton"></form> | 891 | <form method="GET" class="tagfilter" name="tagfilter" style="display:inline;margin-left:24px;"><input type="text" name="searchtags" id="searchtags" style="width:10%" value=""> <input type="submit" value="Filter by tag" class="bigbutton"></form> |
843 | </div> | 892 | </div> |
844 | HTML; | 893 | HTML; |
845 | $data = array('pageheader'=>$searchform,'body'=>templateLinkList(),'onload'=>''); | 894 | $data = array('pageheader'=>$searchform,'body'=>templateLinkList(),'onload'=>''); |
@@ -856,13 +905,13 @@ HTML; | |||
856 | // The javascript code for the bookmarklet: | 905 | // The javascript code for the bookmarklet: |
857 | $changepwd = ($GLOBALS['config']['OPEN_SHAARLI'] ? '' : '<a href="?do=changepasswd"><b>Change password</b></a> - Change your password.<br><br>' ); | 906 | $changepwd = ($GLOBALS['config']['OPEN_SHAARLI'] ? '' : '<a href="?do=changepasswd"><b>Change password</b></a> - Change your password.<br><br>' ); |
858 | $toolbar= <<<HTML | 907 | $toolbar= <<<HTML |
859 | <div id="headerform"><br> | 908 | <div id="toolsdiv"><br> |
860 | {$changepwd} | 909 | {$changepwd} |
861 | <a href="?do=configure"><b>Configure your Shaarli</b></a> - Change Title, timezone...<br><br> | 910 | <a href="?do=configure"><b>Configure your Shaarli</b></a> - Change Title, timezone...<br><br> |
862 | <a href="?do=changetag"><b>Rename/delete tags</b></a> - Rename or delete a tag in all links.<br><br> | 911 | <a href="?do=changetag"><b>Rename/delete tags</b></a> - Rename or delete a tag in all links.<br><br> |
863 | <a href="?do=import"><b>Import</b></a> - Import Netscape html bookmarks (as exported from Firefox, Chrome, Opera, delicious...)<br><br> | 912 | <a href="?do=import"><b>Import</b></a> - Import Netscape html bookmarks (as exported from Firefox, Chrome, Opera, delicious...)<br><br> |
864 | <a href="?do=export"><b>Export</b></a> - Export Netscape html bookmarks (which can be imported in Firefox, Chrome, Opera, delicious...)<br><br> | 913 | <a href="?do=export"><b>Export</b></a> - Export Netscape html bookmarks (which can be imported in Firefox, Chrome, Opera, delicious...)<br><br> |
865 | <a class="smallbutton" style="color:black;" onclick="alert('Drag this link to your bookmarks toolbar, or right-click it and choose Bookmark This Link...');return false;" href="javascript:javascript:(function(){var%20url%20=%20location.href;var%20title%20=%20document.title%20||%20url;window.open('{$pageabsaddr}?post='%20+%20encodeURIComponent(url)+'&title='%20+%20encodeURIComponent(title)+'&source=bookmarklet','_blank','menubar=no,height=400,width=608,toolbar=no,scrollbars=no,status=no');})();">Shaare link</a> - Drag this link to your bookmarks toolbar (or right-click it and choose Bookmark This Link....). Then click "Shaare link" button in any page you want to share.<br><br> | 914 | <a class="smallbutton" onclick="alert('Drag this link to your bookmarks toolbar, or right-click it and choose Bookmark This Link...');return false;" href="javascript:javascript:(function(){var%20url%20=%20location.href;var%20title%20=%20document.title%20||%20url;window.open('{$pageabsaddr}?post='%20+%20encodeURIComponent(url)+'&title='%20+%20encodeURIComponent(title)+'&source=bookmarklet','_blank','menubar=no,height=400,width=608,toolbar=no,scrollbars=no,status=no');})();">Shaare link</a> - Drag this link to your bookmarks toolbar (or right-click it and choose Bookmark This Link....). Then click "Shaare link" button in any page you want to share.<br><br> |
866 | </div> | 915 | </div> |
867 | HTML; | 916 | HTML; |
868 | $data = array('pageheader'=>$toolbar,'body'=>'','onload'=>''); | 917 | $data = array('pageheader'=>$toolbar,'body'=>'','onload'=>''); |
@@ -892,7 +941,7 @@ HTML; | |||
892 | { | 941 | { |
893 | $token = getToken(); | 942 | $token = getToken(); |
894 | $changepwdform= <<<HTML | 943 | $changepwdform= <<<HTML |
895 | <form method="POST" action="" name="changepasswordform" style="padding:10 10 10 10;"> | 944 | <form method="POST" action="" name="changepasswordform" id="changepasswordform"> |
896 | Old password: <input type="password" name="oldpassword"> | 945 | Old password: <input type="password" name="oldpassword"> |
897 | New password: <input type="password" name="setpassword"> | 946 | New password: <input type="password" name="setpassword"> |
898 | <input type="hidden" name="token" value="{$token}"> | 947 | <input type="hidden" name="token" value="{$token}"> |
@@ -951,7 +1000,7 @@ HTML; | |||
951 | { | 1000 | { |
952 | $token = getToken(); | 1001 | $token = getToken(); |
953 | $changetagform = <<<HTML | 1002 | $changetagform = <<<HTML |
954 | <form method="POST" action="" name="changetag" style="padding:10 10 10 10;"> | 1003 | <form method="POST" action="" name="changetag" id="changetag"> |
955 | <input type="hidden" name="token" value="{$token}"> | 1004 | <input type="hidden" name="token" value="{$token}"> |
956 | Tag: <input type="text" name="fromtag" id="fromtag"> | 1005 | Tag: <input type="text" name="fromtag" id="fromtag"> |
957 | <input type="text" name="totag" style="margin-left:40px;"><input type="submit" name="renametag" value="Rename tag" class="bigbutton"> | 1006 | <input type="text" name="totag" style="margin-left:40px;"><input type="submit" name="renametag" value="Rename tag" class="bigbutton"> |
@@ -976,6 +1025,7 @@ HTML; | |||
976 | $LINKSDB[$key]=$value; | 1025 | $LINKSDB[$key]=$value; |
977 | } | 1026 | } |
978 | $LINKSDB->savedb(); // save to disk | 1027 | $LINKSDB->savedb(); // save to disk |
1028 | pubsubhub(); | ||
979 | invalidateCaches(); | 1029 | invalidateCaches(); |
980 | echo '<script language="JavaScript">alert("Tag was removed from '.count($linksToAlter).' links.");document.location=\'?\';</script>'; | 1030 | echo '<script language="JavaScript">alert("Tag was removed from '.count($linksToAlter).' links.");document.location=\'?\';</script>'; |
981 | exit; | 1031 | exit; |
@@ -1004,7 +1054,7 @@ HTML; | |||
1004 | if (startswith($_SERVER["QUERY_STRING"],'do=addlink')) | 1054 | if (startswith($_SERVER["QUERY_STRING"],'do=addlink')) |
1005 | { | 1055 | { |
1006 | $onload = 'onload="document.addform.post.focus();"'; | 1056 | $onload = 'onload="document.addform.post.focus();"'; |
1007 | $addform= '<div id="headerform"><form method="GET" action="" name="addform"><input type="text" name="post" style="width:70%;"> <input type="submit" value="Add link" class="bigbutton"></div>'; | 1057 | $addform= '<div id="headerform"><form method="GET" action="" name="addform" class="addform"><input type="text" name="post" style="width:50%;"> <input type="submit" value="Add link" class="bigbutton"></div>'; |
1008 | $data = array('pageheader'=>$addform,'body'=>'','onload'=>$onload); | 1058 | $data = array('pageheader'=>$addform,'body'=>'','onload'=>$onload); |
1009 | templatePage($data); | 1059 | templatePage($data); |
1010 | exit; | 1060 | exit; |
@@ -1075,9 +1125,9 @@ HTML; | |||
1075 | $url=$_GET['post']; | 1125 | $url=$_GET['post']; |
1076 | 1126 | ||
1077 | // We remove the annoying parameters added by FeedBurner and GoogleFeedProxy (?utm_source=...) | 1127 | // We remove the annoying parameters added by FeedBurner and GoogleFeedProxy (?utm_source=...) |
1078 | $i=strpos($url,'&utm_source='); if ($i) $url=substr($url,0,$i); | 1128 | $i=strpos($url,'&utm_source='); if ($i!==false) $url=substr($url,0,$i); |
1079 | $i=strpos($url,'?utm_source='); if ($i) $url=substr($url,0,$i); | 1129 | $i=strpos($url,'?utm_source='); if ($i!==false) $url=substr($url,0,$i); |
1080 | $i=strpos($url,'#xtor=RSS-'); if ($i) $url=substr($url,0,$i); | 1130 | $i=strpos($url,'#xtor=RSS-'); if ($i!==false) $url=substr($url,0,$i); |
1081 | 1131 | ||
1082 | $link_is_new = false; | 1132 | $link_is_new = false; |
1083 | $link = $LINKSDB->getLinkFromUrl($url); // Check if URL is not already in database (in this case, we will edit the existing link) | 1133 | $link = $LINKSDB->getLinkFromUrl($url); // Check if URL is not already in database (in this case, we will edit the existing link) |
@@ -1093,7 +1143,7 @@ HTML; | |||
1093 | { | 1143 | { |
1094 | list($status,$headers,$data) = getHTTP($url,4); // Short timeout to keep the application responsive. | 1144 | list($status,$headers,$data) = getHTTP($url,4); // Short timeout to keep the application responsive. |
1095 | // FIXME: Decode charset according to specified in either 1) HTTP response headers or 2) <head> in html | 1145 | // FIXME: Decode charset according to specified in either 1) HTTP response headers or 2) <head> in html |
1096 | if (strpos($status,'200 OK')) $title=html_entity_decode(html_extract_title($data),ENT_QUOTES,'UTF-8'); | 1146 | if (strpos($status,'200 OK')!==false) $title=html_entity_decode(html_extract_title($data),ENT_QUOTES,'UTF-8'); |
1097 | } | 1147 | } |
1098 | if ($url=='') $url='?'.smallHash($linkdate); // In case of empty URL, this is just a text (with a link that point to itself) | 1148 | if ($url=='') $url='?'.smallHash($linkdate); // In case of empty URL, this is just a text (with a link that point to itself) |
1099 | $link = array('linkdate'=>$linkdate,'title'=>$title,'url'=>$url,'description'=>$description,'tags'=>$tags,'private'=>0); | 1149 | $link = array('linkdate'=>$linkdate,'title'=>$title,'url'=>$url,'description'=>$description,'tags'=>$tags,'private'=>0); |
@@ -1110,7 +1160,7 @@ HTML; | |||
1110 | if (empty($_GET['what'])) | 1160 | if (empty($_GET['what'])) |
1111 | { | 1161 | { |
1112 | $toolbar= <<<HTML | 1162 | $toolbar= <<<HTML |
1113 | <div id="headerform"><br> | 1163 | <div id="toolsdiv"> |
1114 | <a href="?do=export&what=all"><b>Export all</b></a> - Export all links<br><br> | 1164 | <a href="?do=export&what=all"><b>Export all</b></a> - Export all links<br><br> |
1115 | <a href="?do=export&what=public"><b>Export public</b></a> - Export public links only<br><br> | 1165 | <a href="?do=export&what=public"><b>Export public</b></a> - Export public links only<br><br> |
1116 | <a href="?do=export&what=private"><b>Export private</b></a> - Export private links only<br><br> | 1166 | <a href="?do=export&what=private"><b>Export private</b></a> - Export private links only<br><br> |
@@ -1172,9 +1222,9 @@ HTML; | |||
1172 | $maxfilesize=getMaxFileSize(); | 1222 | $maxfilesize=getMaxFileSize(); |
1173 | $onload = 'onload="document.uploadform.filetoupload.focus();"'; | 1223 | $onload = 'onload="document.uploadform.filetoupload.focus();"'; |
1174 | $uploadform=<<<HTML | 1224 | $uploadform=<<<HTML |
1175 | <div id="headerform"> | 1225 | <div id="uploaddiv"> |
1176 | Import Netscape html bookmarks (as exported from Firefox/Chrome/Opera/delicious/diigo...) (Max: {$maxfilesize} bytes). | 1226 | Import Netscape html bookmarks (as exported from Firefox/Chrome/Opera/delicious/diigo...) (Max: {$maxfilesize} bytes). |
1177 | <form method="POST" action="?do=upload" enctype="multipart/form-data" name="uploadform"> | 1227 | <form method="POST" action="?do=upload" enctype="multipart/form-data" name="uploadform" id="uploadform"> |
1178 | <input type="hidden" name="token" value="{$token}"> | 1228 | <input type="hidden" name="token" value="{$token}"> |
1179 | <input type="file" name="filetoupload" size="80"> | 1229 | <input type="file" name="filetoupload" size="80"> |
1180 | <input type="hidden" name="MAX_FILE_SIZE" value="{$maxfilesize}"> | 1230 | <input type="hidden" name="MAX_FILE_SIZE" value="{$maxfilesize}"> |
@@ -1192,8 +1242,8 @@ HTML; | |||
1192 | // -------- Otherwise, simply display search form and links: | 1242 | // -------- Otherwise, simply display search form and links: |
1193 | $searchform=<<<HTML | 1243 | $searchform=<<<HTML |
1194 | <div id="headerform" style="width:100%; white-space:nowrap;";> | 1244 | <div id="headerform" style="width:100%; white-space:nowrap;";> |
1195 | <form method="GET" name="searchform" style="display:inline;"><input type="text" name="searchterm" style="width:50%" value=""> <input type="submit" value="Search" class="bigbutton"></form> | 1245 | <form method="GET" class="searchform" name="searchform"><input type="text" name="searchterm" style="width:30%" value=""> <input type="submit" value="Search" class="bigbutton"></form> |
1196 | <form method="GET" name="tagfilter" style="display:inline;padding-left:24px;"><input type="text" name="searchtags" id="searchtags" style="width:20%" value=""> <input type="submit" value="Filter by tag" class="bigbutton"></form> | 1246 | <form method="GET" class="tagfilter" name="tagfilter" style="margin-left:24px;"><input type="text" name="searchtags" id="searchtags" style="width:10%" value=""> <input type="submit" value="Filter by tag" class="bigbutton"></form> |
1197 | </div> | 1247 | </div> |
1198 | HTML; | 1248 | HTML; |
1199 | $data = array('pageheader'=>$searchform,'body'=>templateLinkList(),'onload'=>''); | 1249 | $data = array('pageheader'=>$searchform,'body'=>templateLinkList(),'onload'=>''); |
@@ -1362,7 +1412,8 @@ function templateLinkList() | |||
1362 | $link = $linksToDisplay[$keys[$i]]; | 1412 | $link = $linksToDisplay[$keys[$i]]; |
1363 | $description=text2clickable(htmlspecialchars($link['description'])); | 1413 | $description=text2clickable(htmlspecialchars($link['description'])); |
1364 | $title=$link['title']; | 1414 | $title=$link['title']; |
1365 | $classprivate = ($link['private']==0 ? '' : 'class="private"'); | 1415 | $classLi = $i%2!=0 ? '' : 'class="publicLinkHightLight"'; |
1416 | $classprivate = ($link['private']==0 ? $classLi : 'class="private"'); | ||
1366 | if (isLoggedIn()) $actions=' <form method="GET" class="buttoneditform"><input type="hidden" name="edit_link" value="'.$link['linkdate'].'"><input type="submit" value="Edit" class="smallbutton"></form>'; | 1417 | if (isLoggedIn()) $actions=' <form method="GET" class="buttoneditform"><input type="hidden" name="edit_link" value="'.$link['linkdate'].'"><input type="submit" value="Edit" class="smallbutton"></form>'; |
1367 | $tags=''; | 1418 | $tags=''; |
1368 | if ($link['tags']!='') | 1419 | if ($link['tags']!='') |
@@ -1389,19 +1440,24 @@ function templateLinkList() | |||
1389 | $linksperpage = <<<HTML | 1440 | $linksperpage = <<<HTML |
1390 | <div style="float:right; padding-right:5px;"> | 1441 | <div style="float:right; padding-right:5px;"> |
1391 | Links per page: <a href="?linksperpage=20">20</a> <a href="?linksperpage=50">50</a> <a href="?linksperpage=100">100</a> | 1442 | Links per page: <a href="?linksperpage=20">20</a> <a href="?linksperpage=50">50</a> <a href="?linksperpage=100">100</a> |
1392 | <form method="GET" style="display:inline;"><input type="text" name="linksperpage" size="2" style="height:15px;"></form></div> | 1443 | <form method="GET" style="display:inline;" class="linksperpage"><input type="text" name="linksperpage" size="2" style="height:15px;"></form></div> |
1393 | HTML; | 1444 | HTML; |
1394 | $paging = '<div class="paging">'.$linksperpage.$paging.'</div>'; | 1445 | $paging = '<div class="paging">'.$linksperpage.$paging.'</div>'; |
1395 | $linklist='<div id="linklist">'.$paging.$searched.'<ul>'.$linklist.'</ul>'.$paging.'</div>'; | 1446 | $linklist='<div id="linklist">'.$paging.$searched.'<ul>'.$linklist.'</ul>'.$paging.'</div>'; |
1396 | return $linklist; | 1447 | return $linklist; |
1397 | } | 1448 | } |
1398 | 1449 | ||
1399 | // Returns the HTML code to display a thumbnail for a link. | 1450 | // Returns the HTML code to display a thumbnail for a link |
1451 | // with a link to the original URL. | ||
1400 | // Understands various services (youtube.com...) | 1452 | // Understands various services (youtube.com...) |
1401 | function thumbnail($url) | 1453 | // Input: $url = url for which the thumbnail must be found. |
1454 | // $href = if provided, this URL will be followed instead of $url | ||
1455 | function thumbnail($url,$href=false) | ||
1402 | { | 1456 | { |
1403 | if (!$GLOBALS['config']['ENABLE_THUMBNAILS']) return ''; | 1457 | if (!$GLOBALS['config']['ENABLE_THUMBNAILS']) return ''; |
1404 | 1458 | ||
1459 | if ($href==false) $href=$url; | ||
1460 | |||
1405 | // For most hosts, the URL of the thumbnail can be easily deduced from the URL of the link. | 1461 | // For most hosts, the URL of the thumbnail can be easily deduced from the URL of the link. |
1406 | // (eg. http://www.youtube.com/watch?v=spVypYk4kto ---> http://img.youtube.com/vi/spVypYk4kto/default.jpg ) | 1462 | // (eg. http://www.youtube.com/watch?v=spVypYk4kto ---> http://img.youtube.com/vi/spVypYk4kto/default.jpg ) |
1407 | // ^^^^^^^^^^^ ^^^^^^^^^^^ | 1463 | // ^^^^^^^^^^^ ^^^^^^^^^^^ |
@@ -1409,26 +1465,32 @@ function thumbnail($url) | |||
1409 | if ($domain=='youtube.com' || $domain=='www.youtube.com') | 1465 | if ($domain=='youtube.com' || $domain=='www.youtube.com') |
1410 | { | 1466 | { |
1411 | parse_str(parse_url($url,PHP_URL_QUERY), $params); // Extract video ID and get thumbnail | 1467 | parse_str(parse_url($url,PHP_URL_QUERY), $params); // Extract video ID and get thumbnail |
1412 | if (!empty($params['v'])) return '<a href="'.htmlspecialchars($url).'"><img src="http://img.youtube.com/vi/'.htmlspecialchars($params['v']).'/default.jpg" width="120" height="90"></a>'; | 1468 | 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>'; |
1413 | } | 1469 | } |
1470 | if ($domain=='youtu.be') // Youtube short links | ||
1471 | { | ||
1472 | $path = parse_url($url,PHP_URL_PATH); | ||
1473 | return '<a href="'.htmlspecialchars($href).'"><img src="http://img.youtube.com/vi'.htmlspecialchars($path).'/default.jpg" width="120" height="90"></a>'; | ||
1474 | } | ||
1414 | if ($domain=='imgur.com') | 1475 | if ($domain=='imgur.com') |
1415 | { | 1476 | { |
1416 | $path = parse_url($url,PHP_URL_PATH); | 1477 | $path = parse_url($url,PHP_URL_PATH); |
1417 | if (strpos($path,'/r/')==0) return '<a href="'.htmlspecialchars($url).'"><img src="http://i.imgur.com/'.htmlspecialchars(basename($path)).'s.jpg" width="90" height="90"></a>'; | 1478 | if (startsWith($path,'/a/')) return ''; // Thumbnails for albums are not available. |
1418 | if (strpos($path,'/gallery/')==0) return '<a href="'.htmlspecialchars($url).'"><img src="http://i.imgur.com'.htmlspecialchars(substr($path,8)).'s.jpg" width="90" height="90"></a>'; | 1479 | 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>'; |
1419 | if (substr_count($path,'/')==1) return '<a href="'.htmlspecialchars($url).'"><img src="http://i.imgur.com/'.htmlspecialchars(substr($path,1)).'s.jpg" width="90" height="90"></a>'; | 1480 | 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>'; |
1481 | 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>'; | ||
1420 | } | 1482 | } |
1421 | if ($domain=='i.imgur.com') | 1483 | if ($domain=='i.imgur.com') |
1422 | { | 1484 | { |
1423 | $pi = pathinfo(parse_url($url,PHP_URL_PATH)); | 1485 | $pi = pathinfo(parse_url($url,PHP_URL_PATH)); |
1424 | if (!empty($pi['filename'])) return '<a href="'.htmlspecialchars($url).'"><img src="http://i.imgur.com/'.htmlspecialchars($pi['filename']).'s.jpg" width="90" height="90"></a>'; | 1486 | 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>'; |
1425 | } | 1487 | } |
1426 | if ($domain=='dailymotion.com' || $domain=='www.dailymotion.com') | 1488 | if ($domain=='dailymotion.com' || $domain=='www.dailymotion.com') |
1427 | { | 1489 | { |
1428 | if (strpos($url,'dailymotion.com/video/')) | 1490 | if (strpos($url,'dailymotion.com/video/')!==false) |
1429 | { | 1491 | { |
1430 | $thumburl=str_replace('dailymotion.com/video/','dailymotion.com/thumbnail/video/',$url); | 1492 | $thumburl=str_replace('dailymotion.com/video/','dailymotion.com/thumbnail/video/',$url); |
1431 | return '<a href="'.htmlspecialchars($url).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;"></a>'; | 1493 | return '<a href="'.htmlspecialchars($href).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;"></a>'; |
1432 | } | 1494 | } |
1433 | } | 1495 | } |
1434 | if (endsWith($domain,'.imageshack.us')) | 1496 | if (endsWith($domain,'.imageshack.us')) |
@@ -1437,11 +1499,10 @@ function thumbnail($url) | |||
1437 | if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif') | 1499 | if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif') |
1438 | { | 1500 | { |
1439 | $thumburl = substr($url,0,strlen($url)-strlen($ext)).'th.'.$ext; | 1501 | $thumburl = substr($url,0,strlen($url)-strlen($ext)).'th.'.$ext; |
1440 | return '<a href="'.htmlspecialchars($url).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;"></a>'; | 1502 | return '<a href="'.htmlspecialchars($href).'"><img src="'.htmlspecialchars($thumburl).'" width="120" style="height:auto;"></a>'; |
1441 | } | 1503 | } |
1442 | } | 1504 | } |
1443 | 1505 | ||
1444 | |||
1445 | // Some other hosts are SLOW AS HELL and usually require an extra HTTP request to get the thumbnail URL. | 1506 | // Some other hosts are SLOW AS HELL and usually require an extra HTTP request to get the thumbnail URL. |
1446 | // So we deport the thumbnail generation in order not to slow down page generation | 1507 | // So we deport the thumbnail generation in order not to slow down page generation |
1447 | // (and we also cache the thumbnail) | 1508 | // (and we also cache the thumbnail) |
@@ -1450,8 +1511,13 @@ function thumbnail($url) | |||
1450 | 1511 | ||
1451 | if ($domain=='flickr.com' || endsWith($domain,'.flickr.com') || $domain=='vimeo.com') | 1512 | if ($domain=='flickr.com' || endsWith($domain,'.flickr.com') || $domain=='vimeo.com') |
1452 | { | 1513 | { |
1514 | if ($domain=='vimeo.com') | ||
1515 | { // Make sure this vimeo url points to a video (/xxx... where xxx is numeric) | ||
1516 | $path = parse_url($url,PHP_URL_PATH); | ||
1517 | if (!preg_match('!/\d+.+?!',$path)) return ''; // This is not a single video URL. | ||
1518 | } | ||
1453 | $sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation) | 1519 | $sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation) |
1454 | return '<a href="'.htmlspecialchars($url).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;"></a>'; | 1520 | return '<a href="'.htmlspecialchars($href).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;"></a>'; |
1455 | } | 1521 | } |
1456 | 1522 | ||
1457 | // For all other, we try to make a thumbnail of links ending with .jpg/jpeg/png/gif | 1523 | // For all other, we try to make a thumbnail of links ending with .jpg/jpeg/png/gif |
@@ -1461,7 +1527,7 @@ function thumbnail($url) | |||
1461 | if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif') | 1527 | if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif') |
1462 | { | 1528 | { |
1463 | $sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation) | 1529 | $sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation) |
1464 | return '<a href="'.htmlspecialchars($url).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;"></a>'; | 1530 | return '<a href="'.htmlspecialchars($href).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;"></a>'; |
1465 | } | 1531 | } |
1466 | return ''; // No thumbnail. | 1532 | return ''; // No thumbnail. |
1467 | 1533 | ||
@@ -1527,12 +1593,13 @@ JS; | |||
1527 | <title>{$pagetitle}</title> | 1593 | <title>{$pagetitle}</title> |
1528 | <link rel="alternate" type="application/rss+xml" href="{$feedurl}?do=rss{$searchcrits}" title="{$filtered_feed}RSS Feed" /> | 1594 | <link rel="alternate" type="application/rss+xml" href="{$feedurl}?do=rss{$searchcrits}" title="{$filtered_feed}RSS Feed" /> |
1529 | <link rel="alternate" type="application/atom+xml" href="{$feedurl}?do=atom{$searchcrits}" title="{$filtered_feed}ATOM Feed" /> | 1595 | <link rel="alternate" type="application/atom+xml" href="{$feedurl}?do=atom{$searchcrits}" title="{$filtered_feed}ATOM Feed" /> |
1596 | <link href="./images/favicon.ico" rel="shortcut icon" type="image/x-icon" /> | ||
1530 | <link type="text/css" rel="stylesheet" href="shaarli.css?version={$version}" /> | 1597 | <link type="text/css" rel="stylesheet" href="shaarli.css?version={$version}" /> |
1531 | {$jsincludes} | 1598 | {$jsincludes} |
1532 | </head> | 1599 | </head> |
1533 | <body {$data['onload']}>{$newversion} | 1600 | <body {$data['onload']}>{$newversion} |
1534 | <div id="pageheader"><div style="float:right; font-style:italic; color:#bbb; text-align:right; padding:0 5 0 0;">Shaare your links...<br>{$linkcount} links</div> | 1601 | <div id="pageheader"><div id="logo" title="Share your links !"></div><div style="float:right; font-style:italic; color:#bbb; text-align:right; padding:0 5 0 0;">Shaare your links...<br>{$linkcount} links</div> |
1535 | <span id="shaarli_title"><a href="?">{$title}</a></span> - <a href="?">Home</a> {$menu} <a href="{$feedurl}?do=rss{$searchcrits}" style="padding-left:30px;">RSS Feed</a> <a href="{$feedurl}?do=atom{$searchcrits}" style="padding-left:10px;">ATOM Feed</a> | 1602 | <span id="shaarli_title"><a href="?">{$title}</a></span> - <a href="?">Home</a> {$menu} <a href="{$feedurl}?do=rss{$searchcrits}">RSS Feed</a> <a href="{$feedurl}?do=atom{$searchcrits}" style="padding-left:10px;">ATOM Feed</a> |
1536 | <a href="?do=tagcloud">Tag cloud</a> <a href="?do=picwall{$searchcrits}">Picture wall</a> | 1603 | <a href="?do=tagcloud">Tag cloud</a> <a href="?do=picwall{$searchcrits}">Picture wall</a> |
1537 | {$data['pageheader']} | 1604 | {$data['pageheader']} |
1538 | </div> | 1605 | </div> |
@@ -1540,7 +1607,7 @@ JS; | |||
1540 | 1607 | ||
1541 | HTML; | 1608 | HTML; |
1542 | $exectime = round(microtime(true)-$STARTTIME,4); | 1609 | $exectime = round(microtime(true)-$STARTTIME,4); |
1543 | echo '<div id="footer"><b><a href="http://sebsauvage.net/wiki/doku.php?id=php:shaarli">Shaarli '.shaarli_version.'</a></b> - The personal, minimalist, super-fast, no-database delicious clone. By sebsauvage.net<br>Who gives a shit that this page was generated in '.$exectime.' seconds ?</div>'; | 1610 | echo '<div id="footer"><b><a href="http://sebsauvage.net/wiki/doku.php?id=php:shaarli">Shaarli '.shaarli_version.'</a></b> - The personal, minimalist, super-fast, no-database delicious clone. By sebsauvage.net. Theme by idleman.fr.<br>Who gives a shit that this page was generated in '.$exectime.' seconds ?</div>'; |
1544 | if (isLoggedIn()) echo '<script language="JavaScript">function confirmDeleteLink() { var agree=confirm("Are you sure you want to delete this link ?"); if (agree) return true ; else return false ; }</script>'; | 1611 | if (isLoggedIn()) echo '<script language="JavaScript">function confirmDeleteLink() { var agree=confirm("Are you sure you want to delete this link ?"); if (agree) return true ; else return false ; }</script>'; |
1545 | echo $jsincludes_bottom.'</body></html>'; | 1612 | echo $jsincludes_bottom.'</body></html>'; |
1546 | } | 1613 | } |
@@ -1614,7 +1681,7 @@ function templateTZform($ptz=false) | |||
1614 | { | 1681 | { |
1615 | if ($tz=='UTC') $tz='UTC/UTC'; | 1682 | if ($tz=='UTC') $tz='UTC/UTC'; |
1616 | $spos = strpos($tz,'/'); | 1683 | $spos = strpos($tz,'/'); |
1617 | if ($spos) | 1684 | if ($spos!==false) |
1618 | { | 1685 | { |
1619 | $continent=substr($tz,0,$spos); $city=substr($tz,$spos+1); | 1686 | $continent=substr($tz,0,$spos); $city=substr($tz,$spos+1); |
1620 | $continents[$continent]=1; | 1687 | $continents[$continent]=1; |
@@ -1768,7 +1835,7 @@ function genThumbnail() | |||
1768 | else // this is a flickr page (html) | 1835 | else // this is a flickr page (html) |
1769 | { | 1836 | { |
1770 | list($httpstatus,$headers,$data) = getHTTP($url,20); // Get the flickr html page. | 1837 | list($httpstatus,$headers,$data) = getHTTP($url,20); // Get the flickr html page. |
1771 | if (strpos($httpstatus,'200 OK')) | 1838 | if (strpos($httpstatus,'200 OK')!==false) |
1772 | { | 1839 | { |
1773 | preg_match('!(http://farm\d+.static.flickr.com/\d+/\d+_\w+_)[^s].jpg!',$data,$matches); | 1840 | preg_match('!(http://farm\d+.static.flickr.com/\d+/\d+_\w+_)[^s].jpg!',$data,$matches); |
1774 | if (!empty($matches[1])) $imageurl=$matches[1].'m.jpg'; | 1841 | if (!empty($matches[1])) $imageurl=$matches[1].'m.jpg'; |
@@ -1777,7 +1844,7 @@ function genThumbnail() | |||
1777 | if ($imageurl!='') | 1844 | if ($imageurl!='') |
1778 | { // Let's download the image. | 1845 | { // Let's download the image. |
1779 | list($httpstatus,$headers,$data) = getHTTP($imageurl,10); // Image is 240x120, so 10 seconds to download should be enough. | 1846 | list($httpstatus,$headers,$data) = getHTTP($imageurl,10); // Image is 240x120, so 10 seconds to download should be enough. |
1780 | if (strpos($httpstatus,'200 OK')) | 1847 | if (strpos($httpstatus,'200 OK')!==false) |
1781 | { | 1848 | { |
1782 | file_put_contents($GLOBALS['config']['CACHEDIR'].'/'.$thumbname,$data); // Save image to cache. | 1849 | file_put_contents($GLOBALS['config']['CACHEDIR'].'/'.$thumbname,$data); // Save image to cache. |
1783 | header('Content-Type: image/jpeg'); | 1850 | header('Content-Type: image/jpeg'); |
@@ -1793,13 +1860,13 @@ function genThumbnail() | |||
1793 | // Maybe we should deport this to javascript ? Example: http://stackoverflow.com/questions/1361149/get-img-thumbnails-from-vimeo/4285098#4285098 | 1860 | // Maybe we should deport this to javascript ? Example: http://stackoverflow.com/questions/1361149/get-img-thumbnails-from-vimeo/4285098#4285098 |
1794 | $vid = substr(parse_url($url,PHP_URL_PATH),1); | 1861 | $vid = substr(parse_url($url,PHP_URL_PATH),1); |
1795 | list($httpstatus,$headers,$data) = getHTTP('http://vimeo.com/api/v2/video/'.htmlspecialchars($vid).'.php',5); | 1862 | list($httpstatus,$headers,$data) = getHTTP('http://vimeo.com/api/v2/video/'.htmlspecialchars($vid).'.php',5); |
1796 | if (strpos($httpstatus,'200 OK')) | 1863 | if (strpos($httpstatus,'200 OK')!==false) |
1797 | { | 1864 | { |
1798 | $t = unserialize($data); | 1865 | $t = unserialize($data); |
1799 | $imageurl = $t[0]['thumbnail_medium']; | 1866 | $imageurl = $t[0]['thumbnail_medium']; |
1800 | // Then we download the image and serve it to our client. | 1867 | // Then we download the image and serve it to our client. |
1801 | list($httpstatus,$headers,$data) = getHTTP($imageurl,10); | 1868 | list($httpstatus,$headers,$data) = getHTTP($imageurl,10); |
1802 | if (strpos($httpstatus,'200 OK')) | 1869 | if (strpos($httpstatus,'200 OK')!==false) |
1803 | { | 1870 | { |
1804 | file_put_contents($GLOBALS['config']['CACHEDIR'].'/'.$thumbname,$data); // Save image to cache. | 1871 | file_put_contents($GLOBALS['config']['CACHEDIR'].'/'.$thumbname,$data); // Save image to cache. |
1805 | header('Content-Type: image/jpeg'); | 1872 | header('Content-Type: image/jpeg'); |
@@ -1811,7 +1878,7 @@ function genThumbnail() | |||
1811 | 1878 | ||
1812 | // For all other domains, we try to download the image and make a thumbnail. | 1879 | // For all other domains, we try to download the image and make a thumbnail. |
1813 | list($httpstatus,$headers,$data) = getHTTP($url,30); // We allow 30 seconds max to download (and downloads are limited to 4 Mb) | 1880 | list($httpstatus,$headers,$data) = getHTTP($url,30); // We allow 30 seconds max to download (and downloads are limited to 4 Mb) |
1814 | if (strpos($httpstatus,'200 OK')) | 1881 | if (strpos($httpstatus,'200 OK')!==false) |
1815 | { | 1882 | { |
1816 | $filepath=$GLOBALS['config']['CACHEDIR'].'/'.$thumbname; | 1883 | $filepath=$GLOBALS['config']['CACHEDIR'].'/'.$thumbname; |
1817 | file_put_contents($filepath,$data); // Save image to cache. | 1884 | file_put_contents($filepath,$data); // Save image to cache. |
@@ -1841,9 +1908,9 @@ function resizeImage($filepath) | |||
1841 | // So we really try to open each image type whatever the extension is. | 1908 | // So we really try to open each image type whatever the extension is. |
1842 | $header=file_get_contents($filepath,false,NULL,0,256); // Read first 256 bytes and try to sniff file type. | 1909 | $header=file_get_contents($filepath,false,NULL,0,256); // Read first 256 bytes and try to sniff file type. |
1843 | $im=false; | 1910 | $im=false; |
1844 | if (strpos($header,'GIF8')==0) $im = imagecreatefromgif($filepath); // Well this is crude, but it should be enough. | 1911 | $i=strpos($header,'GIF8'); if (($i!==false) && ($i==0)) $im = imagecreatefromgif($filepath); // Well this is crude, but it should be enough. |
1845 | if (strpos($header,'PNG')==1) $im = imagecreatefrompng($filepath); | 1912 | $i=strpos($header,'PNG'); if (($i!==false) && ($i==1)) $im = imagecreatefrompng($filepath); |
1846 | if (strpos($header,'JFIF')) $im = imagecreatefromjpeg($filepath); | 1913 | $i=strpos($header,'JFIF'); if ($i!==false) $im = imagecreatefromjpeg($filepath); |
1847 | if (!$im) return false; // Unable to open image (corrupted or not an image) | 1914 | if (!$im) return false; // Unable to open image (corrupted or not an image) |
1848 | $w = imagesx($im); | 1915 | $w = imagesx($im); |
1849 | $h = imagesy($im); | 1916 | $h = imagesy($im); |