diff options
author | Seb Sauvage <sebsauvage@sebsauvage.net> | 2011-10-06 16:56:16 +0200 |
---|---|---|
committer | Emilien Klein <emilien@klein.st> | 2011-10-06 16:56:16 +0200 |
commit | 99c9c9541b012eebdb84ee33a765bb18a62fb0d7 (patch) | |
tree | 75566579cb42c2febacfd52dd1e69ab8f2842b21 /index.php | |
parent | dcd653d10e168e655ce080da6886ef9fc2c1d3e1 (diff) | |
download | Shaarli-99c9c9541b012eebdb84ee33a765bb18a62fb0d7.tar.gz Shaarli-99c9c9541b012eebdb84ee33a765bb18a62fb0d7.tar.zst Shaarli-99c9c9541b012eebdb84ee33a765bb18a62fb0d7.zip |
Version 0.0.24 beta:
- Corrected: Now thumnails also work for imgur gallery links (/gallery/…) (Thanks to Accent Grave for the correction)
- Corrected: Removed useless debugging information in log.
- Corrected: The filter in RSS/ATOM feed now works again properly (it was broken in 0.0.17 beta)
- New: As per request, you can now post an entry without a link. (You can use Shaarli as a kind of “personal twitter”).
- New: Each Shaarli entry now has a short link (just click on the date of a link). Now you can send a link that points to a single entry in your Shaarli.
- New: In descriptions, URLs are now clickable.
- New: Thumbnails will be generated for all link pointing to .jpg/png/gif (as long as the images are less than 4 Mb and take less than 30 seconds to download).
Diffstat (limited to 'index.php')
-rw-r--r-- | index.php | 129 |
1 files changed, 114 insertions, 15 deletions
@@ -1,5 +1,5 @@ | |||
1 | <?php | 1 | <?php |
2 | // Shaarli 0.0.23 beta - Shaare your links... | 2 | // Shaarli 0.0.24 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 |
@@ -49,7 +49,7 @@ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |||
49 | header("Cache-Control: no-store, no-cache, must-revalidate"); | 49 | header("Cache-Control: no-store, no-cache, must-revalidate"); |
50 | header("Cache-Control: post-check=0, pre-check=0", false); | 50 | header("Cache-Control: post-check=0, pre-check=0", false); |
51 | header("Pragma: no-cache"); | 51 | header("Pragma: no-cache"); |
52 | define('shaarli_version','0.0.23 beta'); | 52 | define('shaarli_version','0.0.24 beta'); |
53 | if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); } | 53 | if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); } |
54 | if (!is_dir(CACHEDIR)) { mkdir(CACHEDIR,0705); chmod(CACHEDIR,0705); } | 54 | if (!is_dir(CACHEDIR)) { mkdir(CACHEDIR,0705); chmod(CACHEDIR,0705); } |
55 | if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. | 55 | if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. |
@@ -105,6 +105,29 @@ function logm($message) | |||
105 | file_put_contents(DATADIR.'/log.txt',$t,FILE_APPEND); | 105 | file_put_contents(DATADIR.'/log.txt',$t,FILE_APPEND); |
106 | } | 106 | } |
107 | 107 | ||
108 | /* Returns the small hash of a string | ||
109 | eg. smallHash('20111006_131924') --> yZH23w | ||
110 | Small hashes: | ||
111 | - are unique (well, as unique as crc32, at last) | ||
112 | - are always 6 characters long. | ||
113 | - only use the following characters: a-z A-Z 0-9 - _ @ | ||
114 | - are NOT cryptographically secure (they CAN be forged) | ||
115 | In Shaarli, they are used as a tinyurl-like link to individual entries. | ||
116 | */ | ||
117 | function smallHash($text) | ||
118 | { | ||
119 | $t = rtrim(base64_encode(hash('crc32',$text,true)),'='); | ||
120 | $t = str_replace('+','-',$t); // Get rid of characters which need encoding in URLs. | ||
121 | $t = str_replace('/','_',$t); | ||
122 | $t = str_replace('=','@',$t); | ||
123 | return $t; | ||
124 | } | ||
125 | |||
126 | // Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722 | ||
127 | function text2clickable($url) | ||
128 | { | ||
129 | return preg_replace('!((?:https?|ftp)://\S+[[:alnum:]]/?)!si','<a href="$1" rel="nofollow">$1</a> ',$url); | ||
130 | } | ||
108 | // ------------------------------------------------------------------------------------------ | 131 | // ------------------------------------------------------------------------------------------ |
109 | // Sniff browser language to display dates in the right format automatically. | 132 | // Sniff browser language to display dates in the right format automatically. |
110 | // (Note that is may not work on your server if the corresponding local is not installed.) | 133 | // (Note that is may not work on your server if the corresponding local is not installed.) |
@@ -381,7 +404,7 @@ function getHTTP($url,$timeout=30) | |||
381 | { | 404 | { |
382 | $options = array('http'=>array('method'=>'GET','timeout' => $timeout)); // Force network timeout | 405 | $options = array('http'=>array('method'=>'GET','timeout' => $timeout)); // Force network timeout |
383 | $context = stream_context_create($options); | 406 | $context = stream_context_create($options); |
384 | $data=file_get_contents($url,false,$context,-1, 2000000); // We download at most 2 Mb from source. | 407 | $data=file_get_contents($url,false,$context,-1, 4000000); // We download at most 4 Mb from source. |
385 | if (!$data) { $lasterror=error_get_last(); return array($lasterror['message'],array(),''); } | 408 | if (!$data) { $lasterror=error_get_last(); return array($lasterror['message'],array(),''); } |
386 | $httpStatus=$http_response_header[0]; // eg. "HTTP/1.1 200 OK" | 409 | $httpStatus=$http_response_header[0]; // eg. "HTTP/1.1 200 OK" |
387 | $responseHeaders=http_parse_headers($http_response_header); | 410 | $responseHeaders=http_parse_headers($http_response_header); |
@@ -567,6 +590,22 @@ class linkdb implements Iterator, Countable, ArrayAccess | |||
567 | krsort($filtered); | 590 | krsort($filtered); |
568 | return $filtered; | 591 | return $filtered; |
569 | } | 592 | } |
593 | |||
594 | // Filter by smallHash. | ||
595 | // Only 1 article is returned. | ||
596 | public function filterSmallHash($smallHash) | ||
597 | { | ||
598 | $filtered=array(); | ||
599 | foreach($this->links as $l) | ||
600 | { | ||
601 | if ($smallHash==smallHash($l['linkdate'])) // Yes, this is ugly and slow | ||
602 | { | ||
603 | $filtered[$l['linkdate']] = $l; | ||
604 | return $filtered; | ||
605 | } | ||
606 | } | ||
607 | return $filtered; | ||
608 | } | ||
570 | 609 | ||
571 | // Returns the list of all tags | 610 | // Returns the list of all tags |
572 | // Output: associative array key=tags, value=0 | 611 | // Output: associative array key=tags, value=0 |
@@ -1011,7 +1050,7 @@ HTML; | |||
1011 | $linkdate = strval(date('Ymd_His')); | 1050 | $linkdate = strval(date('Ymd_His')); |
1012 | $title = (empty($_GET['title']) ? '' : $_GET['title'] ); // Get title if it was provided in URL (by the bookmarklet). | 1051 | $title = (empty($_GET['title']) ? '' : $_GET['title'] ); // Get title if it was provided in URL (by the bookmarklet). |
1013 | $description=''; $tags=''; $private=0; | 1052 | $description=''; $tags=''; $private=0; |
1014 | if (parse_url($url,PHP_URL_SCHEME)=='') $url = 'http://'.$url; | 1053 | if (($url!='') && parse_url($url,PHP_URL_SCHEME)=='') $url = 'http://'.$url; |
1015 | // If this is an HTTP link, we try go get the page to extact the title (otherwise we will to straight to the edit form.) | 1054 | // If this is an HTTP link, we try go get the page to extact the title (otherwise we will to straight to the edit form.) |
1016 | if (empty($title) && parse_url($url,PHP_URL_SCHEME)=='http') | 1055 | if (empty($title) && parse_url($url,PHP_URL_SCHEME)=='http') |
1017 | { | 1056 | { |
@@ -1019,6 +1058,7 @@ HTML; | |||
1019 | // FIXME: Decode charset according to specified in either 1) HTTP response headers or 2) <head> in html | 1058 | // FIXME: Decode charset according to specified in either 1) HTTP response headers or 2) <head> in html |
1020 | if (strpos($status,'200 OK')) $title=html_entity_decode(html_extract_title($data),ENT_QUOTES,'UTF-8'); | 1059 | if (strpos($status,'200 OK')) $title=html_entity_decode(html_extract_title($data),ENT_QUOTES,'UTF-8'); |
1021 | } | 1060 | } |
1061 | if ($url=='') $url='?'.smallHash($linkdate); // In case of empty URL, this is just a text (with a link that point to itself) | ||
1022 | $link = array('linkdate'=>$linkdate,'title'=>$title,'url'=>$url,'description'=>$description,'tags'=>$tags,'private'=>0); | 1062 | $link = array('linkdate'=>$linkdate,'title'=>$title,'url'=>$url,'description'=>$description,'tags'=>$tags,'private'=>0); |
1023 | } | 1063 | } |
1024 | list($editform,$onload)=templateEditForm($link,$link_is_new); | 1064 | list($editform,$onload)=templateEditForm($link,$link_is_new); |
@@ -1236,7 +1276,7 @@ HTML; | |||
1236 | function templateLinkList() | 1276 | function templateLinkList() |
1237 | { | 1277 | { |
1238 | global $LINKSDB; | 1278 | global $LINKSDB; |
1239 | 1279 | ||
1240 | // Search according to entered search terms: | 1280 | // Search according to entered search terms: |
1241 | $linksToDisplay=array(); | 1281 | $linksToDisplay=array(); |
1242 | $searched=''; | 1282 | $searched=''; |
@@ -1251,6 +1291,10 @@ function templateLinkList() | |||
1251 | $tagshtml=''; foreach(explode(' ',trim($_GET['searchtags'])) as $tag) $tagshtml.='<span class="linktag" title="Remove tag"><a href="?removetag='.htmlspecialchars($tag).'">'.htmlspecialchars($tag).' <span style="border-left:1px solid #aaa; padding-left:5px; color:#6767A7;">x</span></a></span> '; | 1291 | $tagshtml=''; foreach(explode(' ',trim($_GET['searchtags'])) as $tag) $tagshtml.='<span class="linktag" title="Remove tag"><a href="?removetag='.htmlspecialchars($tag).'">'.htmlspecialchars($tag).' <span style="border-left:1px solid #aaa; padding-left:5px; color:#6767A7;">x</span></a></span> '; |
1252 | $searched=' <b>'.count($linksToDisplay).' results for tags '.$tagshtml.':</b>'; | 1292 | $searched=' <b>'.count($linksToDisplay).' results for tags '.$tagshtml.':</b>'; |
1253 | } | 1293 | } |
1294 | elseif (preg_match('/[a-zA-Z0-9-_@]{6}/',$_SERVER["QUERY_STRING"])) // Detect smallHashes in URL | ||
1295 | { | ||
1296 | $linksToDisplay = $LINKSDB->filterSmallHash($_SERVER["QUERY_STRING"]); | ||
1297 | } | ||
1254 | else | 1298 | else |
1255 | $linksToDisplay = $LINKSDB; // otherwise, display without filtering. | 1299 | $linksToDisplay = $LINKSDB; // otherwise, display without filtering. |
1256 | 1300 | ||
@@ -1273,7 +1317,7 @@ function templateLinkList() | |||
1273 | while ($i<$end && $i<count($keys)) | 1317 | while ($i<$end && $i<count($keys)) |
1274 | { | 1318 | { |
1275 | $link = $linksToDisplay[$keys[$i]]; | 1319 | $link = $linksToDisplay[$keys[$i]]; |
1276 | $description=$link['description']; | 1320 | $description=text2clickable(htmlspecialchars($link['description'])); |
1277 | $title=$link['title']; | 1321 | $title=$link['title']; |
1278 | $classprivate = ($link['private']==0 ? '' : 'class="private"'); | 1322 | $classprivate = ($link['private']==0 ? '' : 'class="private"'); |
1279 | 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>'; | 1323 | 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>'; |
@@ -1281,9 +1325,10 @@ function templateLinkList() | |||
1281 | if ($link['tags']!='') foreach(explode(' ',$link['tags']) as $tag) { $tags.='<span class="linktag" title="Add tag"><a href="?addtag='.htmlspecialchars($tag).'">'.htmlspecialchars($tag).'</a></span> '; } | 1325 | if ($link['tags']!='') foreach(explode(' ',$link['tags']) as $tag) { $tags.='<span class="linktag" title="Add tag"><a href="?addtag='.htmlspecialchars($tag).'">'.htmlspecialchars($tag).'</a></span> '; } |
1282 | $linklist.='<li '.$classprivate.'>'.thumbnail($link['url']); | 1326 | $linklist.='<li '.$classprivate.'>'.thumbnail($link['url']); |
1283 | $linklist.='<div class="linkcontainer"><span class="linktitle"><a href="'.htmlspecialchars($link['url']).'">'.htmlspecialchars($title).'</a></span>'.$actions.'<br>'; | 1327 | $linklist.='<div class="linkcontainer"><span class="linktitle"><a href="'.htmlspecialchars($link['url']).'">'.htmlspecialchars($title).'</a></span>'.$actions.'<br>'; |
1284 | if ($description!='') $linklist.='<div class="linkdescription">'.nl2br(htmlspecialchars($description)).'</div><br>'; | 1328 | if ($description!='') $linklist.='<div class="linkdescription">'.nl2br($description).'</div><br>'; |
1285 | if (!HIDE_TIMESTAMPS || isLoggedIn()) $linklist.='<span class="linkdate">'.htmlspecialchars(linkdate2locale($link['linkdate'])).' - </span>'; | 1329 | if (!HIDE_TIMESTAMPS || isLoggedIn()) $linklist.='<span class="linkdate" title="Short link here"><a href="?'.smallHash($link['linkdate']).'">'.htmlspecialchars(linkdate2locale($link['linkdate'])).' </a> - </span>'; |
1286 | $linklist.='<span class="linkurl">'.htmlspecialchars($link['url']).'</span><br>'.$tags."</div></li>\n"; | 1330 | else $linklist.='<span class="linkdate" title="Short link here"><a href="?'.smallHash($link['linkdate']).'">link</a> - </span>'; |
1331 | $linklist.='<span class="linkurl" title="Short link">'.htmlspecialchars($link['url']).'</span><br>'.$tags."</div></li>\n"; | ||
1287 | $i++; | 1332 | $i++; |
1288 | } | 1333 | } |
1289 | 1334 | ||
@@ -1323,6 +1368,7 @@ function thumbnail($url) | |||
1323 | { | 1368 | { |
1324 | $path = parse_url($url,PHP_URL_PATH); | 1369 | $path = parse_url($url,PHP_URL_PATH); |
1325 | if (substr_count($path,'/')==1) return '<div class="thumbnail"><a href="'.htmlspecialchars($url).'"><img src="http://i.imgur.com/'.htmlspecialchars(substr($path,1)).'s.jpg" width="90" height="90"></a></div>'; | 1370 | if (substr_count($path,'/')==1) return '<div class="thumbnail"><a href="'.htmlspecialchars($url).'"><img src="http://i.imgur.com/'.htmlspecialchars(substr($path,1)).'s.jpg" width="90" height="90"></a></div>'; |
1371 | if (strpos($path,'/gallery/')==0) return '<div class="thumbnail"><a href="'.htmlspecialchars($url).'"><img src="http://i.imgur.com'.htmlspecialchars(substr($path,8)).'s.jpg" width="90" height="90"></a></div>'; | ||
1326 | } | 1372 | } |
1327 | if ($domain=='i.imgur.com') | 1373 | if ($domain=='i.imgur.com') |
1328 | { | 1374 | { |
@@ -1356,6 +1402,15 @@ function thumbnail($url) | |||
1356 | return '<div class="thumbnail"><a href="'.htmlspecialchars($url).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;"></a></div>'; | 1402 | return '<div class="thumbnail"><a href="'.htmlspecialchars($url).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;"></a></div>'; |
1357 | } | 1403 | } |
1358 | 1404 | ||
1405 | // For all other, we try to make a thumbnail of links ending with .jpg/jpeg/png/gif | ||
1406 | // Technically speaking, we should download ALL links and check their Content-Type to see if they are images. | ||
1407 | // But using the extension will do. | ||
1408 | $ext=strtolower(pathinfo($url,PATHINFO_EXTENSION)); | ||
1409 | if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif') | ||
1410 | { | ||
1411 | $sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation) | ||
1412 | return '<div class="thumbnail"><a href="'.htmlspecialchars($url).'"><img src="?do=genthumbnail&hmac='.htmlspecialchars($sign).'&url='.urlencode($url).'" width="120" style="height:auto;"></a></div>'; | ||
1413 | } | ||
1359 | return ''; // No thumbnail. | 1414 | return ''; // No thumbnail. |
1360 | 1415 | ||
1361 | } | 1416 | } |
@@ -1406,8 +1461,10 @@ $(document).ready(function() | |||
1406 | JS; | 1461 | JS; |
1407 | } | 1462 | } |
1408 | $feedurl=htmlspecialchars(serverUrl().$_SERVER['SCRIPT_NAME']); | 1463 | $feedurl=htmlspecialchars(serverUrl().$_SERVER['SCRIPT_NAME']); |
1409 | if (!empty($_GET['searchtags'])) $feedurl.='&searchtags='.$_GET['searchtags']; | 1464 | $feedsearch=''; |
1410 | elseif (!empty($_GET['searchterm'])) $feedurl.='&searchterm='.$_GET['searchterm']; | 1465 | if (!empty($_GET['searchtags'])) $feedsearch.='&searchtags='.$_GET['searchtags']; |
1466 | elseif (!empty($_GET['searchterm'])) $feedsearch.='&searchterm='.$_GET['searchterm']; | ||
1467 | $version=shaarli_version; | ||
1411 | 1468 | ||
1412 | $title = htmlspecialchars( $GLOBALS['title'] ); | 1469 | $title = htmlspecialchars( $GLOBALS['title'] ); |
1413 | echo <<<HTML | 1470 | echo <<<HTML |
@@ -1415,12 +1472,12 @@ JS; | |||
1415 | <head> | 1472 | <head> |
1416 | <title>{$title}</title> | 1473 | <title>{$title}</title> |
1417 | <link rel="alternate" type="application/rss+xml" href="{$feedurl}" /> | 1474 | <link rel="alternate" type="application/rss+xml" href="{$feedurl}" /> |
1418 | <link type="text/css" rel="stylesheet" href="shaarli.css" /> | 1475 | <link type="text/css" rel="stylesheet" href="shaarli.css?version={$version}" /> |
1419 | {$jsincludes} | 1476 | {$jsincludes} |
1420 | </head> | 1477 | </head> |
1421 | <body {$data['onload']}>{$newversion} | 1478 | <body {$data['onload']}>{$newversion} |
1422 | <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> | 1479 | <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> |
1423 | <b><i>{$title}</i></b> - <a href="?">Home</a> {$menu} <a href="{$feedurl}?do=rss" style="padding-left:30px;">RSS Feed</a> <a href="{$feedurl}?do=atom" style="padding-left:10px;">ATOM Feed</a> | 1480 | <b><i>{$title}</i></b> - <a href="?">Home</a> {$menu} <a href="{$feedurl}?do=rss{$feedsearch}" style="padding-left:30px;">RSS Feed</a> <a href="{$feedurl}?do=atom{$feedsearch}" style="padding-left:10px;">ATOM Feed</a> |
1424 | <a href="?do=tagcloud">Tag cloud</a> | 1481 | <a href="?do=tagcloud">Tag cloud</a> |
1425 | {$data['pageheader']} | 1482 | {$data['pageheader']} |
1426 | </div> | 1483 | </div> |
@@ -1645,7 +1702,6 @@ function genThumbnail() | |||
1645 | 1702 | ||
1646 | // Is this a link to an image, or to a flickr page ? | 1703 | // Is this a link to an image, or to a flickr page ? |
1647 | $imageurl=''; | 1704 | $imageurl=''; |
1648 | logm('url: '.$url); | ||
1649 | if (endswith(parse_url($url,PHP_URL_PATH),'.jpg')) | 1705 | if (endswith(parse_url($url,PHP_URL_PATH),'.jpg')) |
1650 | { // This is a direct link to an image. eg. http://farm1.static.flickr.com/5/5921913_ac83ed27bd_o.jpg | 1706 | { // This is a direct link to an image. eg. http://farm1.static.flickr.com/5/5921913_ac83ed27bd_o.jpg |
1651 | preg_match('!(http://farm\d+.static.flickr.com/\d+/\d+_\w+_)\w.jpg!',$url,$matches); | 1707 | preg_match('!(http://farm\d+.static.flickr.com/\d+/\d+_\w+_)\w.jpg!',$url,$matches); |
@@ -1671,7 +1727,6 @@ function genThumbnail() | |||
1671 | return; | 1727 | return; |
1672 | } | 1728 | } |
1673 | } | 1729 | } |
1674 | else logm('unkown flickr url: '.$url); | ||
1675 | } | 1730 | } |
1676 | 1731 | ||
1677 | if ($domain=='vimeo.com' ) | 1732 | if ($domain=='vimeo.com' ) |
@@ -1695,6 +1750,20 @@ function genThumbnail() | |||
1695 | } | 1750 | } |
1696 | } | 1751 | } |
1697 | } | 1752 | } |
1753 | |||
1754 | // For all other domains, we try to download the image and make a thumbnail. | ||
1755 | list($httpstatus,$headers,$data) = getHTTP($url,30); // We allow 30 seconds max to download (and downloads are limited to 4 Mb) | ||
1756 | if (strpos($httpstatus,'200 OK')) | ||
1757 | { | ||
1758 | $filepath=CACHEDIR.'/'.$thumbname; | ||
1759 | file_put_contents($filepath,$data); // Save image to cache. | ||
1760 | if (resizeImage($filepath)) | ||
1761 | { | ||
1762 | header('Content-Type: image/jpeg'); | ||
1763 | echo file_get_contents($filepath); | ||
1764 | return; | ||
1765 | } | ||
1766 | } | ||
1698 | 1767 | ||
1699 | // Otherwise, return an empty image (8x8 transparent gif) | 1768 | // Otherwise, return an empty image (8x8 transparent gif) |
1700 | $blankgif = base64_decode('R0lGODlhCAAIAIAAAP///////yH5BAEKAAEALAAAAAAIAAgAAAIHjI+py+1dAAA7'); | 1769 | $blankgif = base64_decode('R0lGODlhCAAIAIAAAP///////yH5BAEKAAEALAAAAAAIAAgAAAIHjI+py+1dAAA7'); |
@@ -1703,6 +1772,36 @@ function genThumbnail() | |||
1703 | echo $blankgif; | 1772 | echo $blankgif; |
1704 | } | 1773 | } |
1705 | 1774 | ||
1775 | // Make a thumbnail of the image (to width: 120 pixels) | ||
1776 | // Returns true if success, false otherwise. | ||
1777 | function resizeImage($filepath) | ||
1778 | { | ||
1779 | if (!function_exists('imagecreatefromjpeg')) return false; // GD not present: no thumbnail possible. | ||
1780 | |||
1781 | // Trick: some stupid people rename GIF as JPEG... or else. | ||
1782 | // So we really try to open each image type whatever the extension is. | ||
1783 | $header=file_get_contents($filepath,false,NULL,0,256); // Read first 256 bytes and try to sniff file type. | ||
1784 | $im=false; | ||
1785 | if (strpos($header,'GIF8')==0) $im = imagecreatefromgif($filepath); // Well this is crude, but it should be enough. | ||
1786 | if (strpos($header,'PNG')==1) $im = imagecreatefrompng($filepath); | ||
1787 | if (strpos($header,'JFIF')) $im = imagecreatefromjpeg($filepath); | ||
1788 | if (!$im) return false; // Unable to open image (corrupted or not an image) | ||
1789 | $w = imagesx($im); | ||
1790 | $h = imagesy($im); | ||
1791 | $nw = 120; // Desired width | ||
1792 | $nh = floor(($h*$nw)/$w); // Compute new width/height while keeping ratio | ||
1793 | // Resize image: | ||
1794 | $im2 = imagecreatetruecolor($nw,$nh); | ||
1795 | imagecopyresampled($im2, $im, 0, 0, 0, 0, $nw, $nh, $w, $h); | ||
1796 | imageinterlace($im2,true); // For progressive JPEG. | ||
1797 | $tempname=$filepath.'_TEMP.jpg'; | ||
1798 | imagejpeg($im2, $tempname, 90); | ||
1799 | imagedestroy($im); | ||
1800 | imagedestroy($im2); | ||
1801 | rename($tempname,$filepath); // Overwrite original picture with thumbnail. | ||
1802 | return true; | ||
1803 | } | ||
1804 | |||
1706 | // Invalidate caches when the database is changed or the user logs out. | 1805 | // Invalidate caches when the database is changed or the user logs out. |
1707 | // (eg. tags cache). | 1806 | // (eg. tags cache). |
1708 | function invalidateCaches() | 1807 | function invalidateCaches() |