From 008d8b95ef7d7b5e8e79b633ecc6d0097e0b0e28 Mon Sep 17 00:00:00 2001 From: Seb Sauvage Date: Thu, 13 Oct 2011 13:10:10 +0200 Subject: =?UTF-8?q?Version=200.0.25=20beta:=20-=20Changed:=20Now=20thumbna?= =?UTF-8?q?ils=20generated=20by=20Shaarli=20are=20croped=20to=20a=20height?= =?UTF-8?q?=20of=20120=20pixels.=20-=20Changed:=20YouTube=20thumbnails=20n?= =?UTF-8?q?ow=20use=20default.jpg=20instead=20of=202.jpg=20(This=20is=20us?= =?UTF-8?q?ually=20more=20pertinent).=20-=20Changed:=20As=20per=20request,?= =?UTF-8?q?=20configuration=20options=20(such=20as=20HIDE=5FTIMESTAMPS,=20?= =?UTF-8?q?ENABLE=5FTHUMBNAILS,=20etc.)=20can=20now=20be=20put=20in=20a=20?= =?UTF-8?q?an=20external=20file=20so=20that=20you=20do=20not=20have=20to?= =?UTF-8?q?=20tweak=20them=20again=20when=20you=20upgrade=20Shaarli.=20Jus?= =?UTF-8?q?t=20add=20the=20file=20data/options.php.=20-=20Corrected:=20Sha?= =?UTF-8?q?arli=20now=20supports=20newlines=20in=20titles=20(thanks=20to?= =?UTF-8?q?=20dixy).=20-=20Changed:=20If=20a=20single=20link=20is=20displa?= =?UTF-8?q?yed,=20the=20page=20title=20contains=20the=20title=20of=20the?= =?UTF-8?q?=20link.=20-=20Changed:=20Shaarli=20page=20title=20is=20clickab?= =?UTF-8?q?le=20(and=20has=20the=20same=20link=20as=20=E2=80=9CHome?= =?UTF-8?q?=E2=80=9D).=20-=20Added:=20Better=20CSS=20for=20printing=20(tha?= =?UTF-8?q?nks=20to=20jerrywham=20suggestion)=20-=20Changed:=20A=20few=20C?= =?UTF-8?q?SS=20tweaks=20(thanks=20to=20maethor=20for=20suggestion)=20-=20?= =?UTF-8?q?Added:=20You=20can=20now=20use=20a=20redirector=20or=20anonymiz?= =?UTF-8?q?ing=20proxy=20for=20links=20(such=20as=20http://anonym.to/=3F?= =?UTF-8?q?=20to=20mask=20you=20HTTP=5FREFERER).=20Just=20go=20to=20Tools?= =?UTF-8?q?=20>=20Configure=20>=20Redirector.=20(thanks=20to=20Accent=20Gr?= =?UTF-8?q?ave=20for=20the=20suggestion)=20-=20Added:=20The=20option=20ENA?= =?UTF-8?q?BLE=5FLOCALCACHE=20can=20be=20set=20to=20false=20for=20those=20?= =?UTF-8?q?who=20have=20a=20limited=20quota=20on=20their=20host.=20This=20?= =?UTF-8?q?will=20disable=20the=20local=20thumbnail=20cache.=20Services=20?= =?UTF-8?q?which=20require=20the=20use=20of=20the=20cache=20will=20have=20?= =?UTF-8?q?no=20thumbnails=20(vimeo,=20flickr,=20direct=20link=20to=20imag?= =?UTF-8?q?e).=20Other=20services=20will=20still=20have=20a=20thumbnail=20?= =?UTF-8?q?(youtube,imgur.com,dailymotion,imageshack.us).=20-=20Corrected:?= =?UTF-8?q?=20The=20link=20to=20the=20RSS=20feed=20in=20page=20header=20wa?= =?UTF-8?q?s=20not=20correct.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.php | 190 +++++++++++++++++++++++++++++++++++------------------------- shaarli.css | 37 ++++++++---- 2 files changed, 139 insertions(+), 88 deletions(-) diff --git a/index.php b/index.php index 6e7e638c..ce6a51c4 100644 --- a/index.php +++ b/index.php @@ -1,29 +1,30 @@ $1 ',$url); + $redir = empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector']; + return preg_replace('!((?:https?|ftp)://\S+[[:alnum:]]/?)!si','$1 ',$url); } // ------------------------------------------------------------------------------------------ // Sniff browser language to display dates in the right format automatically. @@ -180,7 +188,7 @@ function check_auth($login,$password) // Returns true if the user is logged in. function isLoggedIn() { - if (OPEN_SHAARLI) return true; + if ($GLOBALS['config']['OPEN_SHAARLI']) return true; // If session does not exist on server side, or IP address has changed, or session has expired, logout. if (empty($_SESSION['uid']) || $_SESSION['ip']!=allIPs() || time()>=$_SESSION['expires_on']) @@ -201,21 +209,21 @@ function logout() { if (isset($_SESSION)) { unset($_SESSION['uid']); unset($_SES // ------------------------------------------------------------------------------------------ // Brute force protection system // Several consecutive failed logins will ban the IP address for 30 minutes. -if (!is_file(IPBANS_FILENAME)) file_put_contents(IPBANS_FILENAME, "array(),'BANS'=>array()),true).";\n?>"); -include IPBANS_FILENAME; +if (!is_file($GLOBALS['config']['IPBANS_FILENAME'])) file_put_contents($GLOBALS['config']['IPBANS_FILENAME'], "array(),'BANS'=>array()),true).";\n?>"); +include $GLOBALS['config']['IPBANS_FILENAME']; // Signal a failed login. Will ban the IP if too many failures: function ban_loginFailed() { $ip=$_SERVER["REMOTE_ADDR"]; $gb=$GLOBALS['IPBANS']; if (!isset($gb['FAILURES'][$ip])) $gb['FAILURES'][$ip]=0; $gb['FAILURES'][$ip]++; - if ($gb['FAILURES'][$ip]>(BAN_AFTER-1)) + if ($gb['FAILURES'][$ip]>($GLOBALS['config']['BAN_AFTER']-1)) { - $gb['BANS'][$ip]=time()+BAN_DURATION; + $gb['BANS'][$ip]=time()+$GLOBALS['config']['BAN_DURATION']; logm('IP address banned from login'); } $GLOBALS['IPBANS'] = $gb; - file_put_contents(IPBANS_FILENAME, ""); + file_put_contents($GLOBALS['config']['IPBANS_FILENAME'], ""); } // Signals a successful login. Resets failed login counter. @@ -224,7 +232,7 @@ function ban_loginOk() $ip=$_SERVER["REMOTE_ADDR"]; $gb=$GLOBALS['IPBANS']; unset($gb['FAILURES'][$ip]); unset($gb['BANS'][$ip]); $GLOBALS['IPBANS'] = $gb; - file_put_contents(IPBANS_FILENAME, ""); + file_put_contents($GLOBALS['config']['IPBANS_FILENAME'], ""); } // Checks if the user CAN login. If 'true', the user can try to login. @@ -238,7 +246,7 @@ function ban_canLogin() { // Ban expired, user can try to login again. logm('Ban lifted.'); unset($gb['FAILURES'][$ip]); unset($gb['BANS'][$ip]); - file_put_contents(IPBANS_FILENAME, ""); + file_put_contents($GLOBALS['config']['IPBANS_FILENAME'], ""); return true; // Ban has expired, user can login. } return false; // User is banned. @@ -420,7 +428,7 @@ function getHTTP($url,$timeout=30) // (Returns an empty string if not found.) function html_extract_title($html) { - return preg_match('!(.*?)!i', $html, $matches) ? $matches[1] : ''; + return preg_match('!(.*)!is', $html, $matches) ? trim(str_replace("\n",' ', $matches[1])) : '' ; } // ------------------------------------------------------------------------------------------ @@ -511,14 +519,14 @@ class linkdb implements Iterator, Countable, ArrayAccess // ---- Misc methods private function checkdb() // Check if db directory and file exists. { - if (!file_exists(DATASTORE)) // Create a dummy database for example. + if (!file_exists($GLOBALS['config']['DATASTORE'])) // Create a dummy database for example. { $this->links = array(); $link = array('title'=>'Shaarli - sebsauvage.net','url'=>'http://sebsauvage.net/wiki/doku.php?id=php:shaarli','description'=>'Welcome to Shaarli ! This is a bookmark. To edit or delete me, you must first login.','private'=>0,'linkdate'=>'20110914_190000','tags'=>'opensource software'); $this->links[$link['linkdate']] = $link; $link = array('title'=>'My secret stuff... - Pastebin.com','url'=>'http://pastebin.com/smCEEeSn','description'=>'SShhhh!! I\'m a private link only YOU can see. You can delete me too.','private'=>1,'linkdate'=>'20110914_074522','tags'=>'secretstuff'); $this->links[$link['linkdate']] = $link; - file_put_contents(DATASTORE, PHPPREFIX.base64_encode(gzdeflate(serialize($this->links))).PHPSUFFIX); // Write database to disk + file_put_contents($GLOBALS['config']['DATASTORE'], PHPPREFIX.base64_encode(gzdeflate(serialize($this->links))).PHPSUFFIX); // Write database to disk } } @@ -526,7 +534,7 @@ class linkdb implements Iterator, Countable, ArrayAccess private function readdb() { // Read data - $this->links=(file_exists(DATASTORE) ? unserialize(gzinflate(base64_decode(substr(file_get_contents(DATASTORE),strlen(PHPPREFIX),-strlen(PHPSUFFIX))))) : array() ); + $this->links=(file_exists($GLOBALS['config']['DATASTORE']) ? unserialize(gzinflate(base64_decode(substr(file_get_contents($GLOBALS['config']['DATASTORE']),strlen(PHPPREFIX),-strlen(PHPSUFFIX))))) : array() ); // Note that gzinflate is faster than gzuncompress. See: http://www.php.net/manual/en/function.gzdeflate.php#96439 // If user is not logged in, filter private links. @@ -546,7 +554,7 @@ class linkdb implements Iterator, Countable, ArrayAccess public function savedb() { if (!$this->loggedin) die('You are not authorized to change the database.'); - file_put_contents(DATASTORE, PHPPREFIX.base64_encode(gzdeflate(serialize($this->links))).PHPSUFFIX); + file_put_contents($GLOBALS['config']['DATASTORE'], PHPPREFIX.base64_encode(gzdeflate(serialize($this->links))).PHPSUFFIX); } // Returns the link for a given URL (if it exists). false it does not exist. @@ -644,7 +652,7 @@ function showRSS() $link = $linksToDisplay[$keys[$i]]; $rfc822date = linkdate2rfc822($link['linkdate']); echo ''.htmlspecialchars($link['title']).''.htmlspecialchars($link['url']).''.htmlspecialchars($link['url']).''; - if (!HIDE_TIMESTAMPS || isLoggedIn()) echo ''.htmlspecialchars($rfc822date).''; + if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) echo ''.htmlspecialchars($rfc822date).''; echo ''."\n"; $i++; } @@ -676,13 +684,13 @@ function showATOM() $iso8601date = linkdate2iso8601($link['linkdate']); $latestDate = max($latestDate,$iso8601date); $entries.=''.htmlspecialchars($link['title']).''.htmlspecialchars($link['url']).''; - if (!HIDE_TIMESTAMPS || isLoggedIn()) $entries.=''.htmlspecialchars($iso8601date).''; + if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $entries.=''.htmlspecialchars($iso8601date).''; $entries.=''.nl2br(htmlspecialchars($link['description'])).''."\n"; $i++; } $feed=''; $feed.=''.htmlspecialchars($GLOBALS['title']).''; - if (!HIDE_TIMESTAMPS || isLoggedIn()) $feed.=''.htmlspecialchars($latestDate).''; + if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $feed.=''.htmlspecialchars($latestDate).''; $feed.=''; $feed.=''.htmlspecialchars($pageaddr).''; $feed.=''.htmlspecialchars($pageaddr).''."\n\n"; // Yes, I know I should use a real IRI (RFC3987), but the site URL will do. @@ -705,7 +713,7 @@ function renderPage() // -------- Display login form. if (startswith($_SERVER["QUERY_STRING"],'do=login')) { - if (OPEN_SHAARLI) { header('Location: ?'); exit; } // No need to login for open Shaarli + if ($GLOBALS['config']['OPEN_SHAARLI']) { header('Location: ?'); exit; } // No need to login for open Shaarli if (!ban_canLogin()) { $loginform='
You have been banned from login after too many failed attempts. Try later.
'; @@ -820,7 +828,7 @@ HTML; { $pageabsaddr=serverUrl().$_SERVER["SCRIPT_NAME"]; // Why doesn't php have a built-in function for that ? // The javascript code for the bookmarklet: - $changepwd = (OPEN_SHAARLI ? '' : 'Change password - Change your password.

' ); + $changepwd = ($GLOBALS['config']['OPEN_SHAARLI'] ? '' : 'Change password - Change your password.

' ); $toolbar= <<
{$changepwd} @@ -839,7 +847,7 @@ HTML; // -------- User wants to change his/her password. if (startswith($_SERVER["QUERY_STRING"],'do=changepasswd')) { - if (OPEN_SHAARLI) die('You are not supposed to change a password on an Open Shaarli.'); + if ($GLOBALS['config']['OPEN_SHAARLI']) die('You are not supposed to change a password on an Open Shaarli.'); if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) { if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away ! @@ -882,6 +890,7 @@ HTML; $tz = $_POST['continent'].'/'.$_POST['city']; $GLOBALS['timezone'] = $tz; $GLOBALS['title']=$_POST['title']; + $GLOBALS['redirector']=$_POST['redirector']; writeConfig(); echo ''; exit; @@ -890,6 +899,7 @@ HTML; { $token = getToken(); $title = htmlspecialchars( empty($GLOBALS['title']) ? '' : $GLOBALS['title'] , ENT_QUOTES); + $redirector = htmlspecialchars( empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'] , ENT_QUOTES); list($timezone_form,$timezone_js) = templateTZform($GLOBALS['timezone']); $timezone_html=''; if ($timezone_form!='') $timezone_html='Timezone:'.$timezone_form.''; $changepwdform= << Page title: {$timezone_html} +Redirector
(e.g. http://anonym.to/? will mask the HTTP_REFERER) @@ -1283,13 +1294,13 @@ function templateLinkList() if (!empty($_GET['searchterm'])) // Fulltext search { $linksToDisplay = $LINKSDB->filterFulltext(trim($_GET['searchterm'])); - $searched=' '.count($linksToDisplay).' results for '.htmlspecialchars(trim($_GET['searchterm'])).':'; + $searched=count($linksToDisplay).' results for '.htmlspecialchars(trim($_GET['searchterm'])).':'; } elseif (!empty($_GET['searchtags'])) // Search by tag { $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); $tagshtml=''; foreach(explode(' ',trim($_GET['searchtags'])) as $tag) $tagshtml.=''.htmlspecialchars($tag).' x '; - $searched=' '.count($linksToDisplay).' results for tags '.$tagshtml.':'; + $searched=''.count($linksToDisplay).' results for tags '.$tagshtml.':'; } elseif (preg_match('/[a-zA-Z0-9-_@]{6}/',$_SERVER["QUERY_STRING"])) // Detect smallHashes in URL { @@ -1297,7 +1308,7 @@ function templateLinkList() } else $linksToDisplay = $LINKSDB; // otherwise, display without filtering. - + if ($searched!='') $searched='
'.$searched.'
'; $linklist=''; $actions=''; @@ -1307,13 +1318,19 @@ function templateLinkList() If my class implements ArrayAccess, why won't array_keys() accept it ? ( $keys=array_keys($linksToDisplay); ) */ $keys=array(); foreach($linksToDisplay as $key=>$value) { $keys[]=$key; } // Stupid and ugly. Thanks php. + + // If there is only a single link, we change on-the-fly the title of the page. + if (count($linksToDisplay)==1) $GLOBALS['pagetitle'] = $linksToDisplay[$keys[0]]['title'].' - '.$GLOBALS['title']; + $pagecount = ceil(count($keys)/$_SESSION['LINKS_PER_PAGE']); $pagecount = ($pagecount==0 ? 1 : $pagecount); $page=( empty($_GET['page']) ? 1 : intval($_GET['page'])); $page = ( $page<1 ? 1 : $page ); $page = ( $page>$pagecount ? $pagecount : $page ); $i = ($page-1)*$_SESSION['LINKS_PER_PAGE']; // Start index. - $end = $i+$_SESSION['LINKS_PER_PAGE']; + $end = $i+$_SESSION['LINKS_PER_PAGE']; + $redir = empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector']; // optional redirector URL + while ($i<$end && $i'; $tags=''; - if ($link['tags']!='') foreach(explode(' ',$link['tags']) as $tag) { $tags.=''.htmlspecialchars($tag).' '; } + if ($link['tags']!='') + { + foreach(explode(' ',$link['tags']) as $tag) { $tags.=''.htmlspecialchars($tag).' '; } + $tags='
'.$tags.'
'; + } $linklist.='
  • '.thumbnail($link['url']); - $linklist.='
  • \n"; $i++; @@ -1353,16 +1374,16 @@ HTML; // Understands various services (youtube.com...) function thumbnail($url) { - if (!ENABLE_THUMBNAILS) return ''; + if (!$GLOBALS['config']['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 ) + // (eg. http://www.youtube.com/watch?v=spVypYk4kto ---> http://img.youtube.com/vi/spVypYk4kto/default.jpg ) // ^^^^^^^^^^^ ^^^^^^^^^^^ $domain = parse_url($url,PHP_URL_HOST); if ($domain=='youtube.com' || $domain=='www.youtube.com') { parse_str(parse_url($url,PHP_URL_QUERY), $params); // Extract video ID and get thumbnail - if (!empty($params['v'])) return '
    '; + if (!empty($params['v'])) return '
    '; } if ($domain=='imgur.com') { @@ -1393,9 +1414,13 @@ function thumbnail($url) } } + // 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 (!$GLOBALS['config']['ENABLE_LOCALCACHE']) return ''; // If local cache is disabled, no thumbnails for services which require the use a local cache. + if ($domain=='flickr.com' || endsWith($domain,'.flickr.com') || $domain=='vimeo.com') { $sign = hash_hmac('sha256', $url, $GLOBALS['salt']); // We use the salt to sign data (it's random, secret, and specific to each installation) @@ -1432,7 +1457,7 @@ function templatePage($data) if ($newversion!='') $newversion='
    Shaarli '.htmlspecialchars($newversion).' is available.
    '; $linkcount = count($LINKSDB); $open=''; - if (OPEN_SHAARLI) + if ($GLOBALS['config']['OPEN_SHAARLI']) { $menu=' Tools  Add link'; $open='Open '; @@ -1445,10 +1470,10 @@ function templatePage($data) if (!array_key_exists($k,$data)) $data[$k]=''; } $jsincludes=''; $jsincludes_bottom = ''; - if (OPEN_SHAARLI || isLoggedIn()) + if ($GLOBALS['config']['OPEN_SHAARLI'] || isLoggedIn()) { - $jsincludes=''; $source = serverUrl().$_SERVER['SCRIPT_NAME']; + $jsincludes=''; $jsincludes_bottom = << $(document).ready(function() @@ -1464,20 +1489,23 @@ JS; $feedsearch=''; if (!empty($_GET['searchtags'])) $feedsearch.='&searchtags='.$_GET['searchtags']; elseif (!empty($_GET['searchterm'])) $feedsearch.='&searchterm='.$_GET['searchterm']; + $filtered_feed= ($feedsearch=='' ? '' : 'Filtered '); $version=shaarli_version; $title = htmlspecialchars( $GLOBALS['title'] ); + $pagetitle = htmlspecialchars( empty($GLOBALS['pagetitle']) ? $title : $GLOBALS['pagetitle'] ); echo << -{$title} - +{$pagetitle} + + {$jsincludes} {$newversion} @@ -1617,7 +1645,7 @@ function processWS() if (empty($_SESSION['tags'])) $_SESSION['tags'] = $LINKSDB->allTags(); foreach($_SESSION['tags'] as $key=>$value) { - if (startsWith($key,$last,$case=false) && !in_array($key,$tags)) $suggested[$addtags.$key.' ']=0;//FIXME + if (startsWith($key,$last,$case=false) && !in_array($key,$tags)) $suggested[$addtags.$key.' ']=0; } echo json_encode(array_keys($suggested)); exit; @@ -1643,10 +1671,13 @@ function processWS() // (otherwise, the function simply returns.) function writeConfig() { - if (is_file(CONFIG_FILE) && !isLoggedIn()) die('You are not authorized to alter config.'); // Only logged in user can alter config. + if (is_file($GLOBALS['config']['CONFIG_FILE']) && !isLoggedIn()) die('You are not authorized to alter config.'); // Only logged in user can alter config. + if (empty($GLOBALS['redirector'])) $GLOBALS['redirector']=''; $config=''; - if (!file_put_contents(CONFIG_FILE,$config) || strcmp(file_get_contents(CONFIG_FILE),$config)!=0) + $config .='$GLOBALS[\'timezone\']='.var_export($GLOBALS['timezone'],true).'; date_default_timezone_set('.var_export($GLOBALS['timezone'],true).'); $GLOBALS[\'title\']='.var_export($GLOBALS['title'],true).';'; + $config .= '$GLOBALS[\'redirector\']='.var_export($GLOBALS['redirector'],true).'; '; + $config .= ' ?>'; + if (!file_put_contents($GLOBALS['config']['CONFIG_FILE'],$config) || strcmp(file_get_contents($GLOBALS['config']['CONFIG_FILE']),$config)!=0) { echo ''; exit; @@ -1670,18 +1701,18 @@ function genThumbnail() // 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)) + if (is_file($GLOBALS['config']['CACHEDIR'].'/'.$thumbname)) { // We have the thumbnail, just serve it: header('Content-Type: image/jpeg'); - echo file_get_contents(CACHEDIR.'/'.$thumbname); + echo file_get_contents($GLOBALS['config']['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)) + if (is_file($GLOBALS['config']['CACHEDIR'].'/'.$blankname)) { header('Content-Type: image/gif'); - echo file_get_contents(CACHEDIR.'/'.$blankname); + echo file_get_contents($GLOBALS['config']['CACHEDIR'].'/'.$blankname); return; } @@ -1721,7 +1752,7 @@ function genThumbnail() 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. + file_put_contents($GLOBALS['config']['CACHEDIR'].'/'.$thumbname,$data); // Save image to cache. header('Content-Type: image/jpeg'); echo $data; return; @@ -1743,7 +1774,7 @@ function genThumbnail() list($httpstatus,$headers,$data) = getHTTP($imageurl,10); if (strpos($httpstatus,'200 OK')) { - file_put_contents(CACHEDIR.'/'.$thumbname,$data); // Save image to cache. + file_put_contents($GLOBALS['config']['CACHEDIR'].'/'.$thumbname,$data); // Save image to cache. header('Content-Type: image/jpeg'); echo $data; return; @@ -1755,7 +1786,7 @@ function genThumbnail() list($httpstatus,$headers,$data) = getHTTP($url,30); // We allow 30 seconds max to download (and downloads are limited to 4 Mb) if (strpos($httpstatus,'200 OK')) { - $filepath=CACHEDIR.'/'.$thumbname; + $filepath=$GLOBALS['config']['CACHEDIR'].'/'.$thumbname; file_put_contents($filepath,$data); // Save image to cache. if (resizeImage($filepath)) { @@ -1765,9 +1796,10 @@ function genThumbnail() } } + // 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. + file_put_contents($GLOBALS['config']['CACHEDIR'].'/'.$blankname,$blankgif); // Also put something in cache so that this URL is not requested twice. header('Content-Type: image/gif'); echo $blankgif; } @@ -1788,11 +1820,13 @@ function resizeImage($filepath) if (!$im) return false; // Unable to open image (corrupted or not an image) $w = imagesx($im); $h = imagesy($im); + $ystart = 0; $yheight=$h; + if ($h>$w) { $ystart= ($h/2)-($w/2); $yheight=$w/2; } $nw = 120; // Desired width - $nh = floor(($h*$nw)/$w); // Compute new width/height while keeping ratio + $nh = min(floor(($h*$nw)/$w),120); // Compute new width/height, but maximum 120 pixels height. // Resize image: $im2 = imagecreatetruecolor($nw,$nh); - imagecopyresampled($im2, $im, 0, 0, 0, 0, $nw, $nh, $w, $h); + imagecopyresampled($im2, $im, 0, 0, 0, $ystart, $nw, $nh, $w, $yheight); imageinterlace($im2,true); // For progressive JPEG. $tempname=$filepath.'_TEMP.jpg'; imagejpeg($im2, $tempname, 90); @@ -1810,9 +1844,9 @@ function invalidateCaches() } 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). +$LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['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; +if (!isset($_SESSION['LINKS_PER_PAGE'])) $_SESSION['LINKS_PER_PAGE']=$GLOBALS['config']['LINKS_PER_PAGE']; if (startswith($_SERVER["QUERY_STRING"],'do=rss')) { showRSS(); exit; } if (startswith($_SERVER["QUERY_STRING"],'do=atom')) { showATOM(); exit; } renderPage(); diff --git a/shaarli.css b/shaarli.css index a3b9434b..320c7a43 100644 --- a/shaarli.css +++ b/shaarli.css @@ -33,10 +33,13 @@ filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#6A6A6A', EndC padding: 0 10 5 10; margin: auto; } +#shaarli_title { font-weight:bold; font-style:italic; } +#shaarli_title a { color: #fff !important; } #pageheader a:link { color:#bbb; text-decoration:none;} #pageheader a:visited { color:#bbb; text-decoration:none;} #pageheader a:hover { color:#FFFFC9; text-decoration:none;} #pageheader a:active { color:#bbb; text-decoration:none;} +#searchcriteria { padding: 4 0 5 5; font-weight:bold;} .paging { background-color:#777; color:#ccc; text-align:center; padding:0 0 3 0; clear:both;} .paging a:link { color:#ccc; text-decoration:none;} .paging a:visited { color:#ccc; } @@ -47,17 +50,20 @@ margin: auto; #linklist li { padding:4 10 8 20; border-top: 1px solid #bbb; clear:both; } #linklist li.private { background-color: #ccc; border-left:8px solid #888; } .linktitle { font-size:14pt; font-weight:bold; } -.linktitle a { text-decoration: none; color:#0000EE; } -.linktitle a:hover { text-decoration: underline; } -.linktitle a:visited { color:#0000BB; } +.linktitle a { text-decoration: none; color:#3465A4; } +.linktitle a:hover { color:#F57900; } .linkdate { font-size:8pt; color:#888; } .linkdate a { text-decoration: none; color:#888; } -.linkdate a:hover { text-decoration: underline; } +.linkdate a:hover { color: #F57900 } .linkurl { font-size:8pt; color:#4BAA74; } .linkdescription { color:#000; margin-top:0px; margin-bottom:0px; font-weight:normal; } +.linkdescription a { text-decoration: none; color:#3465A4; } +.linkdescription a:hover { color:#F57900; } +.linktaglist { } .linktag { font-size:9pt; color:#777; background-color:#ddd; padding:0 6 0 6; -moz-box-shadow: inset 2px 2px 3px #ffffff; -webkit-box-shadow: inset 2px 2px 3px #ffffff; box-shadow: inset 2px 2px 3px ffffff; -border-bottom:1px solid #aaa; border-right:1px solid #aaa; } -.linktag a { color:#777; text-decoration:none; } +border-bottom:1px solid #aaa; border-right:1px solid #aaa; border-radius: 0.3em; } +.linktag:hover { border-color: #555573; color:#000; } +.linktag a { color:#777; text-decoration:none; } .linkshort { font-size:8pt; color:#888; } .linkshort a { text-decoration: none; color:#393964; } .linkshort a:hover { text-decoration: underline; } @@ -68,16 +74,27 @@ border-bottom:1px solid #aaa; border-right:1px solid #aaa; } #cloudtag a { color:black; text-decoration:none; } #installform td { font-size: 10pt; padding:10 5 10 5; } #configform td { color:#ccc; font-size: 10pt; padding:10 5 10 5; } -.thumbnail { float:right; margin-left: 10px; } - -/* If you want thumbnails on the right: +.thumbnail { float:right; margin-left: 10px; } +/* If you want thumbnails on the left: .thumbnail { float:left; margin-right: 10px; } .linkcontainer { position: static; margin-left:130px; } */ - /* Minimal customisation for jQuery widgets */ .ui-autocomplete { background-color:#fff; padding-left:5px;} .ui-state-hover { background-color: #604dff; color:#fff; } +@media print { +html {border:none;background:#fff!important;color:#000!important;} +body {font-size:12pt;width:auto!important;margin:auto!important;} +p {orphans:3; /*pas de ligne seule en bas */widows:3;/*pas de ligne seule en haut*/} +a {color:#000!important;text-decoration:none!important;} +#pageheader, .paging, #linklist li form, #footer {display:none;} +#linklist li { padding:2 0 10 0; border-top: 2px solid #000; clear:both; } +#linklist li.private { background-color: none; border-left:0; } +.linkdate { line-height:2; } +.linkurl { color:#000; } +.linkdescription { font-size:10pt;} +.linktag { border: 1px solid black; font-style:italic; font-size:8pt;} + } \ No newline at end of file -- cgit v1.2.3