From 28770b26b1a33ed079f9d777bfc6346e7a291c19 Mon Sep 17 00:00:00 2001 From: Seb Sauvage Date: Wed, 28 Sep 2011 14:44:02 +0200 Subject: [PATCH] Version 0.0.22 beta: - Corrected: Title was not properly passed if you had to login when using the bookmarklet (patch by shenshei). - New: Support for thumbnails for flickr.com. - Changed: Some hosts (flickr, vimeo) are slow as hell for the thumbnails, or require an extra HTTP request. For these hosts the thumbnail generation has been deported outside the generation of the page to keep Shaarli snappy. For those slow services the thumbnails are also cached. - New: As per request, you can now stay signed in (Your session will be kept open even if you close the browser). This is just a checkbox in login screen. --- index.php | 168 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 147 insertions(+), 21 deletions(-) diff --git a/index.php b/index.php index 57a64004..6732083c 100644 --- a/index.php +++ b/index.php @@ -1,5 +1,5 @@ ' : ''); - $loginform='
Login:    Password : '.$returnurl_html.'
'; + $loginform='
Login:    Password :
'; + $loginform.=' Stay signed in (Do not check on public computers)'.$returnurl_html.'
'; $onload = 'onload="document.loginform.login.focus();"'; $data = array('pageheader'=>$loginform,'body'=>'','onload'=>$onload); templatePage($data); exit; } - // -------- User wants to logout. if (startswith($_SERVER["QUERY_STRING"],'do=logout')) { @@ -740,7 +758,7 @@ function renderPage() // Show login screen, then redirect to ?post=... if (isset($_GET['post'])) { - header('Location: ?do=login&post='.urlencode($_GET['post']).(isset($_GET['source'])?'&source='.urlencode($_GET['source']):'')); // Redirect to login page, then back to post link. + 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. exit; } @@ -1291,6 +1309,10 @@ HTML; function thumbnail($url) { if (!ENABLE_THUMBNAILS) return ''; + + // For most hosts, the URL of the thumbnail can be easily deduced from the URL of the link. + // (eg. http://www.youtube.com/watch?v=spVypYk4kto ---> http://img.youtube.com/vi/spVypYk4kto/2.jpg ) + // ^^^^^^^^^^^ ^^^^^^^^^^^ $domain = parse_url($url,PHP_URL_HOST); if ($domain=='youtube.com' || $domain=='www.youtube.com') { @@ -1315,20 +1337,16 @@ function thumbnail($url) return '
'; } } - if ($domain=='vimeo.com') + + // Some other hosts are SLOW AS HELL and usually require an extra HTTP request to get the thumbnail URL. + // So we deport the thumbnail generation in order not to slow down page generation + // (and we also cache the thumbnail) + if ($domain=='flickr.com' || endsWith($domain,'.flickr.com') || $domain=='vimeo.com') { - // This is more complex: we have to perform a HTTP request, then parse the result. - // This slows down page generation :-( - // Maybe we should deport this to javascript ? Example: http://stackoverflow.com/questions/1361149/get-img-thumbnails-from-vimeo/4285098#4285098 - $vid = substr(parse_url($url,PHP_URL_PATH),1); - // We allow 2 seconds for Vimeo servers to respond. - list($httpstatus,$headers,$data) = getHTTP('http://vimeo.com/api/v2/video/'.htmlspecialchars($vid).'.php',2); - if (strpos($httpstatus,'200 OK')) - { - $t = unserialize($data); - if (!empty($t[0]['thumbnail_medium'])) return '
'; - } + $sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation) + return '
'; } + return ''; // No thumbnail. } @@ -1569,6 +1587,113 @@ function writeConfig() } } +/* Because some f*cking services like Flickr require an extra HTTP request to get the thumbnail URL, + I have deported the thumbnail URL code generation here, otherwise this would slow down page generation. + The following function takes the URL a link (eg. a flickr page) and return the proper thumbnail. + This function is called by passing the url: + http://mywebsite.com/shaarli/?do=genthumbnail&hmac=[HMAC]&url=[URL] + [URL] is the URL of the link (eg. a flickr page) + [HMAC] is the signature for the [URL] (so that these URL cannot be forged). + The function below will fetch the image from the webservice and store it in the cache. +*/ +function genThumbnail() +{ + // Make sure the parameters in the URL were generated by us. + $sign = hash_hmac('sha256', $_GET['url'], $GLOBALS['salt']); + if ($sign!=$_GET['hmac']) die('Naughty boy !'); + + // Let's see if we don't already have the image for this URL in the cache. + $thumbname=hash('sha1',$_GET['url']).'.jpg'; + if (is_file(CACHEDIR.'/'.$thumbname)) + { // We have the thumbnail, just serve it: + header('Content-Type: image/jpeg'); + echo file_get_contents(CACHEDIR.'/'.$thumbname); + return; + } + // We may also serve a blank image (if service did not respond) + $blankname=hash('sha1',$_GET['url']).'.gif'; + if (is_file(CACHEDIR.'/'.$blankname)) + { + header('Content-Type: image/gif'); + echo file_get_contents(CACHEDIR.'/'.$blankname); + return; + } + + // Otherwise, generate the thumbnail. + $url = $_GET['url']; + $domain = parse_url($url,PHP_URL_HOST); + + if ($domain=='flickr.com' || endsWith($domain,'.flickr.com')) + { + // WTF ? I need a flickr API key to get a fucking thumbnail ? No way. + // I'll extract the thumbnail URL myself. First, we have to get the flickr HTML page. + // All images in Flickr are in the form: + // http://farm[farm].static.flickr.com/[server]/[id]_[secret]_[size].jpg + // Example: http://farm7.static.flickr.com/6205/6088513739_fc158467fe_z.jpg + // We want the 240x120 format, which is _m.jpg. + // We search for the first image in the page which does not have the _s size, + // when use the _m to get the thumbnail. + + // Is this a link to an image, or to a flickr page ? + $imageurl=''; + logm('url: '.$url); + if (endswith(parse_url($url,PHP_URL_PATH),'.jpg')) + { // This is a direct link to an image. eg. http://farm1.static.flickr.com/5/5921913_ac83ed27bd_o.jpg + preg_match('!(http://farm\d+.static.flickr.com/\d+/\d+_\w+_)\w.jpg!',$url,$matches); + if (!empty($matches[1])) $imageurl=$matches[1].'m.jpg'; + } + else // this is a flickr page (html) + { + list($httpstatus,$headers,$data) = getHTTP($url,20); // Get the flickr html page. + if (strpos($httpstatus,'200 OK')) + { + preg_match('!(http://farm\d+.static.flickr.com/\d+/\d+_\w+_)[^s].jpg!',$data,$matches); + if (!empty($matches[1])) $imageurl=$matches[1].'m.jpg'; + } + } + if ($imageurl!='') + { // Let's download the image. + list($httpstatus,$headers,$data) = getHTTP($imageurl,10); // Image is 240x120, so 10 seconds to download should be enough. + if (strpos($httpstatus,'200 OK')) + { + file_put_contents(CACHEDIR.'/'.$thumbname,$data); // Save image to cache. + header('Content-Type: image/jpeg'); + echo $data; + return; + } + } + else logm('unkown flickr url: '.$url); + } + + if ($domain=='vimeo.com' ) + { + // This is more complex: we have to perform a HTTP request, then parse the result. + // Maybe we should deport this to javascript ? Example: http://stackoverflow.com/questions/1361149/get-img-thumbnails-from-vimeo/4285098#4285098 + $vid = substr(parse_url($url,PHP_URL_PATH),1); + list($httpstatus,$headers,$data) = getHTTP('http://vimeo.com/api/v2/video/'.htmlspecialchars($vid).'.php',5); + if (strpos($httpstatus,'200 OK')) + { + $t = unserialize($data); + $imageurl = $t[0]['thumbnail_medium']; + // Then we download the image and serve it to our client. + list($httpstatus,$headers,$data) = getHTTP($imageurl,10); + if (strpos($httpstatus,'200 OK')) + { + file_put_contents(CACHEDIR.'/'.$thumbname,$data); // Save image to cache. + header('Content-Type: image/jpeg'); + echo $data; + return; + } + } + } + + // Otherwise, return an empty image (8x8 transparent gif) + $blankgif = base64_decode('R0lGODlhCAAIAIAAAP///////yH5BAEKAAEALAAAAAAIAAgAAAIHjI+py+1dAAA7'); + file_put_contents(CACHEDIR.'/'.$blankname,$blankgif); // Also put something in cache so that this URL is not requested twice. + header('Content-Type: image/gif'); + echo $blankgif; +} + // Invalidate caches when the database is changed or the user logs out. // (eg. tags cache). function invalidateCaches() @@ -1576,6 +1701,7 @@ function invalidateCaches() unset($_SESSION['tags']); } +if (startswith($_SERVER["QUERY_STRING"],'do=genthumbnail')) { genThumbnail(); exit; } // Thumbnail generation/cache does not need the link database. $LINKSDB=new linkdb(isLoggedIn() || OPEN_SHAARLI); // Read links from database (and filter private links if used it not logged in). if (startswith($_SERVER["QUERY_STRING"],'ws=')) { processWS(); exit; } // Webservices (for jQuery/jQueryUI) if (!isset($_SESSION['LINKS_PER_PAGE'])) $_SESSION['LINKS_PER_PAGE']=LINKS_PER_PAGE; -- 2.41.0