diff options
Diffstat (limited to 'index.php')
-rw-r--r-- | index.php | 254 |
1 files changed, 127 insertions, 127 deletions
@@ -1,9 +1,9 @@ | |||
1 | <?php | 1 | <?php |
2 | // Shaarli 0.0.42 beta - Shaare your links... | 2 | // Shaarli 0.0.42 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 |
6 | // Requires: php 5.1.x (but autocomplete fields will only work if you have php 5.2.x) | 6 | // Requires: PHP 5.1.x (but autocomplete fields will only work if you have PHP 5.2.x) |
7 | // ----------------------------------------------------------------------------------------------- | 7 | // ----------------------------------------------------------------------------------------------- |
8 | // NEVER TRUST IN PHP.INI | 8 | // NEVER TRUST IN PHP.INI |
9 | // Some hosts do not define a default timezone in php.ini, | 9 | // Some hosts do not define a default timezone in php.ini, |
@@ -24,7 +24,7 @@ $GLOBALS['config']['HIDE_TIMESTAMPS'] = false; // If true, the moment when links | |||
24 | $GLOBALS['config']['ENABLE_THUMBNAILS'] = true; // Enable thumbnails in links. | 24 | $GLOBALS['config']['ENABLE_THUMBNAILS'] = true; // Enable thumbnails in links. |
25 | $GLOBALS['config']['CACHEDIR'] = 'cache'; // Cache directory for thumbnails for SLOW services (like flickr) | 25 | $GLOBALS['config']['CACHEDIR'] = 'cache'; // Cache directory for thumbnails for SLOW services (like flickr) |
26 | $GLOBALS['config']['PAGECACHE'] = 'pagecache'; // Page cache directory. | 26 | $GLOBALS['config']['PAGECACHE'] = 'pagecache'; // Page cache directory. |
27 | $GLOBALS['config']['ENABLE_LOCALCACHE'] = true; // Enable Shaarli to store thumbnail in a local cache. Disable to reduce webspace usage. | 27 | $GLOBALS['config']['ENABLE_LOCALCACHE'] = true; // Enable Shaarli to store thumbnail in a local cache. Disable to reduce web space usage. |
28 | $GLOBALS['config']['PUBSUBHUB_URL'] = ''; // PubSubHubbub support. Put an empty string to disable, or put your hub url here to enable. | 28 | $GLOBALS['config']['PUBSUBHUB_URL'] = ''; // PubSubHubbub support. Put an empty string to disable, or put your hub url here to enable. |
29 | $GLOBALS['config']['RAINTPL_TMP'] = 'tmp' ; // Raintpl cache directory | 29 | $GLOBALS['config']['RAINTPL_TMP'] = 'tmp' ; // Raintpl cache directory |
30 | $GLOBALS['config']['RAINTPL_TPL'] = 'tpl/' ; // Raintpl template directory (keep the trailling slash!) | 30 | $GLOBALS['config']['RAINTPL_TPL'] = 'tpl/' ; // Raintpl template directory (keep the trailling slash!) |
@@ -32,13 +32,13 @@ $GLOBALS['config']['UPDATECHECK_FILENAME'] = $GLOBALS['config']['DATADIR'].'/las | |||
32 | $GLOBALS['config']['UPDATECHECK_INTERVAL'] = 86400 ; // Updates check frequency for Shaarli. 86400 seconds=24 hours | 32 | $GLOBALS['config']['UPDATECHECK_INTERVAL'] = 86400 ; // Updates check frequency for Shaarli. 86400 seconds=24 hours |
33 | // Note: You must have publisher.php in the same directory as Shaarli index.php | 33 | // Note: You must have publisher.php in the same directory as Shaarli index.php |
34 | // ----------------------------------------------------------------------------------------------- | 34 | // ----------------------------------------------------------------------------------------------- |
35 | // You should not touch below (or at your own risks !) | 35 | // You should not touch below (or at your own risks!) |
36 | // Optionnal config file. | 36 | // Optional config file. |
37 | if (is_file($GLOBALS['config']['DATADIR'].'/options.php')) require($GLOBALS['config']['DATADIR'].'/options.php'); | 37 | if (is_file($GLOBALS['config']['DATADIR'].'/options.php')) require($GLOBALS['config']['DATADIR'].'/options.php'); |
38 | 38 | ||
39 | define('shaarli_version','0.0.42 beta'); | 39 | define('shaarli_version','0.0.42 beta'); |
40 | define('PHPPREFIX','<?php /* '); // Prefix to encapsulate data in php code. | 40 | define('PHPPREFIX','<?php /* '); // Prefix to encapsulate data in PHP code. |
41 | define('PHPSUFFIX',' */ ?>'); // Suffix to encapsulate data in php code. | 41 | define('PHPSUFFIX',' */ ?>'); // Suffix to encapsulate data in PHP code. |
42 | // http://server.com/x/shaarli --> /shaarli/ | 42 | // http://server.com/x/shaarli --> /shaarli/ |
43 | define('WEB_PATH', substr($_SERVER["REQUEST_URI"], 0, 1+strrpos($_SERVER["REQUEST_URI"], '/', 0))); | 43 | define('WEB_PATH', substr($_SERVER["REQUEST_URI"], 0, 1+strrpos($_SERVER["REQUEST_URI"], '/', 0))); |
44 | 44 | ||
@@ -50,8 +50,8 @@ session_set_cookie_params($cookie['lifetime'],$cookiedir,$_SERVER['HTTP_HOST']); | |||
50 | // Set session parameters on server side. | 50 | // Set session parameters on server side. |
51 | define('INACTIVITY_TIMEOUT',3600); // (in seconds). If the user does not access any page within this time, his/her session is considered expired. | 51 | define('INACTIVITY_TIMEOUT',3600); // (in seconds). If the user does not access any page within this time, his/her session is considered expired. |
52 | ini_set('session.use_cookies', 1); // Use cookies to store session. | 52 | ini_set('session.use_cookies', 1); // Use cookies to store session. |
53 | ini_set('session.use_only_cookies', 1); // Force cookies for session (phpsessionID forbidden in URL) | 53 | ini_set('session.use_only_cookies', 1); // Force cookies for session (phpsessionID forbidden in URL). |
54 | ini_set('session.use_trans_sid', false); // Prevent php to use sessionID in URL if cookies are disabled. | 54 | ini_set('session.use_trans_sid', false); // Prevent PHP form using sessionID in URL if cookies are disabled. |
55 | session_name('shaarli'); | 55 | session_name('shaarli'); |
56 | if (session_id() == '') session_start(); // Start session if needed (Some server auto-start sessions). | 56 | if (session_id() == '') session_start(); // Start session if needed (Some server auto-start sessions). |
57 | 57 | ||
@@ -86,7 +86,7 @@ header("Cache-Control: no-store, no-cache, must-revalidate"); | |||
86 | header("Cache-Control: post-check=0, pre-check=0", false); | 86 | header("Cache-Control: post-check=0, pre-check=0", false); |
87 | header("Pragma: no-cache"); | 87 | header("Pragma: no-cache"); |
88 | 88 | ||
89 | // Directories creations (Note that your web host may require differents rights than 705.) | 89 | // Directories creations (Note that your web host may require different rights than 705.) |
90 | if (!is_writable(realpath(dirname(__FILE__)))) die('<pre>ERROR: Shaarli does not have the right to write in its own directory ('.realpath(dirname(__FILE__)).').</pre>'); | 90 | if (!is_writable(realpath(dirname(__FILE__)))) die('<pre>ERROR: Shaarli does not have the right to write in its own directory ('.realpath(dirname(__FILE__)).').</pre>'); |
91 | 91 | ||
92 | // Handling of old config file which do not have the new parameters. | 92 | // Handling of old config file which do not have the new parameters. |
@@ -110,13 +110,13 @@ define('STAY_SIGNED_IN_TOKEN', sha1($GLOBALS['hash'].$_SERVER["REMOTE_ADDR"].$GL | |||
110 | autoLocale(); // Sniff browser language and set date format accordingly. | 110 | autoLocale(); // Sniff browser language and set date format accordingly. |
111 | header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling. | 111 | header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling. |
112 | 112 | ||
113 | // Check php version | 113 | // Check PHP version |
114 | function checkphpversion() | 114 | function checkphpversion() |
115 | { | 115 | { |
116 | if (version_compare(PHP_VERSION, '5.1.0') < 0) | 116 | if (version_compare(PHP_VERSION, '5.1.0') < 0) |
117 | { | 117 | { |
118 | header('Content-Type: text/plain; charset=utf-8'); | 118 | header('Content-Type: text/plain; charset=utf-8'); |
119 | echo 'Your server supports php '.PHP_VERSION.'. Shaarli requires at least php 5.1.0, and thus cannot run. Sorry.'; | 119 | echo 'Your server supports PHP '.PHP_VERSION.'. Shaarli requires at least php 5.1.0, and thus cannot run. Sorry.'; |
120 | exit; | 120 | exit; |
121 | } | 121 | } |
122 | } | 122 | } |
@@ -135,7 +135,7 @@ function checkUpdate() | |||
135 | $version=shaarli_version; | 135 | $version=shaarli_version; |
136 | list($httpstatus,$headers,$data) = getHTTP('http://sebsauvage.net/files/shaarli_version.txt',2); | 136 | list($httpstatus,$headers,$data) = getHTTP('http://sebsauvage.net/files/shaarli_version.txt',2); |
137 | if (strpos($httpstatus,'200 OK')!==false) $version=$data; | 137 | if (strpos($httpstatus,'200 OK')!==false) $version=$data; |
138 | // If failed, nevermind. We don't want to bother the user with that. | 138 | // If failed, never mind. We don't want to bother the user with that. |
139 | file_put_contents($GLOBALS['config']['UPDATECHECK_FILENAME'],$version); // touch file date | 139 | file_put_contents($GLOBALS['config']['UPDATECHECK_FILENAME'],$version); // touch file date |
140 | } | 140 | } |
141 | // Compare versions: | 141 | // Compare versions: |
@@ -151,11 +151,11 @@ function checkUpdate() | |||
151 | class pageCache | 151 | class pageCache |
152 | { | 152 | { |
153 | private $url; // Full URL of the page to cache (typically the value returned by pageUrl()) | 153 | private $url; // Full URL of the page to cache (typically the value returned by pageUrl()) |
154 | private $shouldBeCached; // boolean: Should this url be cached ? | 154 | private $shouldBeCached; // boolean: Should this url be cached? |
155 | private $filename; // Name of the cache file for this url | 155 | private $filename; // Name of the cache file for this url. |
156 | 156 | ||
157 | /* | 157 | /* |
158 | $url = url (typically the value returned by pageUrl()) | 158 | $url = URL (typically the value returned by pageUrl()) |
159 | $shouldBeCached = boolean. If false, the cache will be disabled. | 159 | $shouldBeCached = boolean. If false, the cache will be disabled. |
160 | */ | 160 | */ |
161 | public function __construct($url,$shouldBeCached) | 161 | public function __construct($url,$shouldBeCached) |
@@ -217,7 +217,7 @@ function nl2br_escaped($html) | |||
217 | } | 217 | } |
218 | 218 | ||
219 | /* Returns the small hash of a string, using RFC 4648 base64url format | 219 | /* Returns the small hash of a string, using RFC 4648 base64url format |
220 | eg. smallHash('20111006_131924') --> yZH23w | 220 | e.g. smallHash('20111006_131924') --> yZH23w |
221 | Small hashes: | 221 | Small hashes: |
222 | - are unique (well, as unique as crc32, at last) | 222 | - are unique (well, as unique as crc32, at last) |
223 | - are always 6 characters long. | 223 | - are always 6 characters long. |
@@ -231,7 +231,7 @@ function smallHash($text) | |||
231 | return strtr($t, '+/', '-_'); | 231 | return strtr($t, '+/', '-_'); |
232 | } | 232 | } |
233 | 233 | ||
234 | // In a string, converts urls to clickable links. | 234 | // In a string, converts URLs to clickable links. |
235 | // Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722 | 235 | // Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722 |
236 | function text2clickable($url) | 236 | function text2clickable($url) |
237 | { | 237 | { |
@@ -252,8 +252,8 @@ function keepMultipleSpaces($text) | |||
252 | function autoLocale() | 252 | function autoLocale() |
253 | { | 253 | { |
254 | $loc='en_US'; // Default if browser does not send HTTP_ACCEPT_LANGUAGE | 254 | $loc='en_US'; // Default if browser does not send HTTP_ACCEPT_LANGUAGE |
255 | if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) // eg. "fr,fr-fr;q=0.8,en;q=0.5,en-us;q=0.3" | 255 | if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) // e.g. "fr,fr-fr;q=0.8,en;q=0.5,en-us;q=0.3" |
256 | { // (It's a bit crude, but it works very well. Prefered language is always presented first.) | 256 | { // (It's a bit crude, but it works very well. Preferred language is always presented first.) |
257 | if (preg_match('/([a-z]{2}(-[a-z]{2})?)/i',$_SERVER['HTTP_ACCEPT_LANGUAGE'],$matches)) $loc=$matches[1]; | 257 | if (preg_match('/([a-z]{2}(-[a-z]{2})?)/i',$_SERVER['HTTP_ACCEPT_LANGUAGE'],$matches)) $loc=$matches[1]; |
258 | } | 258 | } |
259 | setlocale(LC_TIME,$loc); // LC_TIME = Set local for date/time format only. | 259 | setlocale(LC_TIME,$loc); // LC_TIME = Set local for date/time format only. |
@@ -290,7 +290,7 @@ function allIPs() | |||
290 | } | 290 | } |
291 | 291 | ||
292 | function fillSessionInfo() { | 292 | function fillSessionInfo() { |
293 | $_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand()); // generate unique random number (different than phpsessionid) | 293 | $_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand()); // Generate unique random number (different than phpsessionid) |
294 | $_SESSION['ip']=allIPs(); // We store IP address(es) of the client to make sure session is not hijacked. | 294 | $_SESSION['ip']=allIPs(); // We store IP address(es) of the client to make sure session is not hijacked. |
295 | $_SESSION['username']=$GLOBALS['login']; | 295 | $_SESSION['username']=$GLOBALS['login']; |
296 | $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT; // Set session expiration. | 296 | $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT; // Set session expiration. |
@@ -394,7 +394,7 @@ if (isset($_POST['login'])) | |||
394 | { | 394 | { |
395 | if (!ban_canLogin()) die('I said: NO. You are banned for the moment. Go away.'); | 395 | if (!ban_canLogin()) die('I said: NO. You are banned for the moment. Go away.'); |
396 | if (isset($_POST['password']) && tokenOk($_POST['token']) && (check_auth($_POST['login'], $_POST['password']))) | 396 | if (isset($_POST['password']) && tokenOk($_POST['token']) && (check_auth($_POST['login'], $_POST['password']))) |
397 | { // Login/password is ok. | 397 | { // Login/password is OK. |
398 | ban_loginOk(); | 398 | ban_loginOk(); |
399 | // If user wants to keep the session cookie even after the browser closes: | 399 | // If user wants to keep the session cookie even after the browser closes: |
400 | if (!empty($_POST['longlastingsession'])) | 400 | if (!empty($_POST['longlastingsession'])) |
@@ -405,7 +405,7 @@ if (isset($_POST['login'])) | |||
405 | 405 | ||
406 | $cookiedir = ''; if(dirname($_SERVER['SCRIPT_NAME'])!='/') $cookiedir=dirname($_SERVER["SCRIPT_NAME"]).'/'; | 406 | $cookiedir = ''; if(dirname($_SERVER['SCRIPT_NAME'])!='/') $cookiedir=dirname($_SERVER["SCRIPT_NAME"]).'/'; |
407 | session_set_cookie_params($_SESSION['longlastingsession'],$cookiedir,$_SERVER['HTTP_HOST']); // Set session cookie expiration on client side | 407 | session_set_cookie_params($_SESSION['longlastingsession'],$cookiedir,$_SERVER['HTTP_HOST']); // Set session cookie expiration on client side |
408 | // Note: Never forget the trailing slash on the cookie path ! | 408 | // Note: Never forget the trailing slash on the cookie path! |
409 | session_regenerate_id(true); // Send cookie with new expiration date to browser. | 409 | session_regenerate_id(true); // Send cookie with new expiration date to browser. |
410 | } | 410 | } |
411 | else // Standard session expiration (=when browser closes) | 411 | else // Standard session expiration (=when browser closes) |
@@ -437,7 +437,7 @@ if (isset($_POST['login'])) | |||
437 | // Misc utility functions: | 437 | // Misc utility functions: |
438 | 438 | ||
439 | // Returns the server URL (including port and http/https), without path. | 439 | // Returns the server URL (including port and http/https), without path. |
440 | // eg. "http://myserver.com:8080" | 440 | // e.g. "http://myserver.com:8080" |
441 | // You can append $_SERVER['SCRIPT_NAME'] to get the current script URL. | 441 | // You can append $_SERVER['SCRIPT_NAME'] to get the current script URL. |
442 | function serverUrl() | 442 | function serverUrl() |
443 | { | 443 | { |
@@ -447,24 +447,24 @@ function serverUrl() | |||
447 | } | 447 | } |
448 | 448 | ||
449 | // Returns the absolute URL of current script, without the query. | 449 | // Returns the absolute URL of current script, without the query. |
450 | // (eg. http://sebsauvage.net/links/) | 450 | // (e.g. http://sebsauvage.net/links/) |
451 | function indexUrl() | 451 | function indexUrl() |
452 | { | 452 | { |
453 | $scriptname = $_SERVER["SCRIPT_NAME"]; | 453 | $scriptname = $_SERVER["SCRIPT_NAME"]; |
454 | // If the script is named 'index.php', we remove it (for better looking URLs, | 454 | // If the script is named 'index.php', we remove it (for better looking URLs, |
455 | // eg. http://mysite.com/shaarli/?abcde instead of http://mysite.com/shaarli/index.php?abcde) | 455 | // e.g. http://mysite.com/shaarli/?abcde instead of http://mysite.com/shaarli/index.php?abcde) |
456 | if (endswith($scriptname,'index.php')) $scriptname = substr($scriptname,0,strlen($scriptname)-9); | 456 | if (endswith($scriptname,'index.php')) $scriptname = substr($scriptname,0,strlen($scriptname)-9); |
457 | return serverUrl() . $scriptname; | 457 | return serverUrl() . $scriptname; |
458 | } | 458 | } |
459 | 459 | ||
460 | // Returns the absolute URL of current script, WITH the query. | 460 | // Returns the absolute URL of current script, WITH the query. |
461 | // (eg. http://sebsauvage.net/links/?toto=titi&spamspamspam=humbug) | 461 | // (e.g. http://sebsauvage.net/links/?toto=titi&spamspamspam=humbug) |
462 | function pageUrl() | 462 | function pageUrl() |
463 | { | 463 | { |
464 | return indexUrl().(!empty($_SERVER["QUERY_STRING"]) ? '?'.$_SERVER["QUERY_STRING"] : ''); | 464 | return indexUrl().(!empty($_SERVER["QUERY_STRING"]) ? '?'.$_SERVER["QUERY_STRING"] : ''); |
465 | } | 465 | } |
466 | 466 | ||
467 | // Convert post_max_size/upload_max_filesize (eg.'16M') parameters to bytes. | 467 | // Convert post_max_size/upload_max_filesize (e.g. '16M') parameters to bytes. |
468 | function return_bytes($val) | 468 | function return_bytes($val) |
469 | { | 469 | { |
470 | $val = trim($val); $last=strtolower($val[strlen($val)-1]); | 470 | $val = trim($val); $last=strtolower($val[strlen($val)-1]); |
@@ -485,7 +485,7 @@ function getMaxFileSize() | |||
485 | $size2 = return_bytes(ini_get('upload_max_filesize')); | 485 | $size2 = return_bytes(ini_get('upload_max_filesize')); |
486 | // Return the smaller of two: | 486 | // Return the smaller of two: |
487 | $maxsize = min($size1,$size2); | 487 | $maxsize = min($size1,$size2); |
488 | // FIXME: Then convert back to readable notations ? (eg. 2M instead of 2000000) | 488 | // FIXME: Then convert back to readable notations ? (e.g. 2M instead of 2000000) |
489 | return $maxsize; | 489 | return $maxsize; |
490 | } | 490 | } |
491 | 491 | ||
@@ -533,7 +533,7 @@ function linkdate2iso8601($linkdate) | |||
533 | function linkdate2locale($linkdate) | 533 | function linkdate2locale($linkdate) |
534 | { | 534 | { |
535 | return utf8_encode(strftime('%c',linkdate2timestamp($linkdate))); // %c is for automatic date format according to locale. | 535 | return utf8_encode(strftime('%c',linkdate2timestamp($linkdate))); // %c is for automatic date format according to locale. |
536 | // Note that if you use a local which is not installed on your webserver, | 536 | // Note that if you use a locale which is not installed on your webserver, |
537 | // the date will not be displayed in the chosen locale, but probably in US notation. | 537 | // the date will not be displayed in the chosen locale, but probably in US notation. |
538 | } | 538 | } |
539 | 539 | ||
@@ -555,10 +555,10 @@ function http_parse_headers_shaarli( $headers ) | |||
555 | } | 555 | } |
556 | 556 | ||
557 | /* GET an URL. | 557 | /* GET an URL. |
558 | Input: $url : url to get (http://...) | 558 | Input: $url : URL to get (http://...) |
559 | $timeout : Network timeout (will wait this many seconds for an anwser before giving up). | 559 | $timeout : Network timeout (will wait this many seconds for an anwser before giving up). |
560 | Output: An array. [0] = HTTP status message (eg. "HTTP/1.1 200 OK") or error message | 560 | Output: An array. [0] = HTTP status message (e.g. "HTTP/1.1 200 OK") or error message |
561 | [1] = associative array containing HTTP response headers (eg. echo getHTTP($url)[1]['Content-Type']) | 561 | [1] = associative array containing HTTP response headers (e.g. echo getHTTP($url)[1]['Content-Type']) |
562 | [2] = data | 562 | [2] = data |
563 | Example: list($httpstatus,$headers,$data) = getHTTP('http://sebauvage.net/'); | 563 | Example: list($httpstatus,$headers,$data) = getHTTP('http://sebauvage.net/'); |
564 | if (strpos($httpstatus,'200 OK')!==false) | 564 | if (strpos($httpstatus,'200 OK')!==false) |
@@ -574,11 +574,11 @@ function getHTTP($url,$timeout=30) | |||
574 | $context = stream_context_create($options); | 574 | $context = stream_context_create($options); |
575 | $data=file_get_contents($url,false,$context,-1, 4000000); // We download at most 4 Mb from source. | 575 | $data=file_get_contents($url,false,$context,-1, 4000000); // We download at most 4 Mb from source. |
576 | if (!$data) { return array('HTTP Error',array(),''); } | 576 | if (!$data) { return array('HTTP Error',array(),''); } |
577 | $httpStatus=$http_response_header[0]; // eg. "HTTP/1.1 200 OK" | 577 | $httpStatus=$http_response_header[0]; // e.g. "HTTP/1.1 200 OK" |
578 | $responseHeaders=http_parse_headers_shaarli($http_response_header); | 578 | $responseHeaders=http_parse_headers_shaarli($http_response_header); |
579 | return array($httpStatus,$responseHeaders,$data); | 579 | return array($httpStatus,$responseHeaders,$data); |
580 | } | 580 | } |
581 | catch (Exception $e) // getHTTP *can* fail silentely (we don't care if the title cannot be fetched) | 581 | catch (Exception $e) // getHTTP *can* fail silently (we don't care if the title cannot be fetched) |
582 | { | 582 | { |
583 | return array($e->getMessage(),'',''); | 583 | return array($e->getMessage(),'',''); |
584 | } | 584 | } |
@@ -604,14 +604,14 @@ function getToken() | |||
604 | return $rnd; | 604 | return $rnd; |
605 | } | 605 | } |
606 | 606 | ||
607 | // Tells if a token is ok. Using this function will destroy the token. | 607 | // Tells if a token is OK. Using this function will destroy the token. |
608 | // true=token is ok. | 608 | // true=token is OK. |
609 | function tokenOk($token) | 609 | function tokenOk($token) |
610 | { | 610 | { |
611 | if (isset($_SESSION['tokens'][$token])) | 611 | if (isset($_SESSION['tokens'][$token])) |
612 | { | 612 | { |
613 | unset($_SESSION['tokens'][$token]); // Token is used: destroy it. | 613 | unset($_SESSION['tokens'][$token]); // Token is used: destroy it. |
614 | return true; // Token is ok. | 614 | return true; // Token is OK. |
615 | } | 615 | } |
616 | return false; // Wrong token, or already used. | 616 | return false; // Wrong token, or already used. |
617 | } | 617 | } |
@@ -646,7 +646,7 @@ class pageBuilder | |||
646 | $this->tpl->assign('version',shaarli_version); | 646 | $this->tpl->assign('version',shaarli_version); |
647 | $this->tpl->assign('scripturl',indexUrl()); | 647 | $this->tpl->assign('scripturl',indexUrl()); |
648 | $this->tpl->assign('pagetitle','Shaarli'); | 648 | $this->tpl->assign('pagetitle','Shaarli'); |
649 | $this->tpl->assign('privateonly',!empty($_SESSION['privateonly'])); // Show only private links ? | 649 | $this->tpl->assign('privateonly',!empty($_SESSION['privateonly'])); // Show only private links? |
650 | if (!empty($GLOBALS['title'])) $this->tpl->assign('pagetitle',$GLOBALS['title']); | 650 | if (!empty($GLOBALS['title'])) $this->tpl->assign('pagetitle',$GLOBALS['title']); |
651 | if (!empty($GLOBALS['titleLink'])) $this->tpl->assign('titleLink',$GLOBALS['titleLink']); | 651 | if (!empty($GLOBALS['titleLink'])) $this->tpl->assign('titleLink',$GLOBALS['titleLink']); |
652 | if (!empty($GLOBALS['pagetitle'])) $this->tpl->assign('pagetitle',$GLOBALS['pagetitle']); | 652 | if (!empty($GLOBALS['pagetitle'])) $this->tpl->assign('pagetitle',$GLOBALS['pagetitle']); |
@@ -662,7 +662,7 @@ class pageBuilder | |||
662 | } | 662 | } |
663 | 663 | ||
664 | // Render a specific page (using a template). | 664 | // Render a specific page (using a template). |
665 | // eg. pb.renderPage('picwall') | 665 | // e.g. pb.renderPage('picwall') |
666 | public function renderPage($page) | 666 | public function renderPage($page) |
667 | { | 667 | { |
668 | if ($this->tpl===false) $this->initialize(); // Lazy initialization | 668 | if ($this->tpl===false) $this->initialize(); // Lazy initialization |
@@ -681,10 +681,10 @@ class pageBuilder | |||
681 | 681 | ||
682 | Available keys: | 682 | Available keys: |
683 | title : Title of the link | 683 | title : Title of the link |
684 | url : URL of the link. Can be absolute or relative. Relative URLs are permalinks (eg.'?m-ukcw') | 684 | url : URL of the link. Can be absolute or relative. Relative URLs are permalinks (e.g.'?m-ukcw') |
685 | description : description of the entry | 685 | description : description of the entry |
686 | private : Is this link private ? 0=no, other value=yes | 686 | private : Is this link private? 0=no, other value=yes |
687 | linkdate : date of the creation of this entry, in the form YYYYMMDD_HHMMSS (eg.'20110914_192317') | 687 | linkdate : date of the creation of this entry, in the form YYYYMMDD_HHMMSS (e.g.'20110914_192317') |
688 | tags : tags attached to this entry (separated by spaces) | 688 | tags : tags attached to this entry (separated by spaces) |
689 | 689 | ||
690 | We implement 3 interfaces: | 690 | We implement 3 interfaces: |
@@ -694,15 +694,15 @@ class pageBuilder | |||
694 | */ | 694 | */ |
695 | class linkdb implements Iterator, Countable, ArrayAccess | 695 | class linkdb implements Iterator, Countable, ArrayAccess |
696 | { | 696 | { |
697 | private $links; // List of links (associative array. Key=linkdate (eg. "20110823_124546"), value= associative array (keys:title,description...) | 697 | private $links; // List of links (associative array. Key=linkdate (e.g. "20110823_124546"), value= associative array (keys:title,description...) |
698 | private $urls; // List of all recorded URLs (key=url, value=linkdate) for fast reserve search (url-->linkdate) | 698 | private $urls; // List of all recorded URLs (key=url, value=linkdate) for fast reserve search (url-->linkdate) |
699 | private $keys; // List of linkdate keys (for the Iterator interface implementation) | 699 | private $keys; // List of linkdate keys (for the Iterator interface implementation) |
700 | private $position; // Position in the $this->keys array. (for the Iterator interface implementation.) | 700 | private $position; // Position in the $this->keys array. (for the Iterator interface implementation.) |
701 | private $loggedin; // Is the used logged in ? (used to filter private links) | 701 | private $loggedin; // Is the user logged in? (used to filter private links) |
702 | 702 | ||
703 | // Constructor: | 703 | // Constructor: |
704 | function __construct($isLoggedIn) | 704 | function __construct($isLoggedIn) |
705 | // Input : $isLoggedIn : is the used logged in ? | 705 | // Input : $isLoggedIn : is the user logged in? |
706 | { | 706 | { |
707 | $this->loggedin = $isLoggedIn; | 707 | $this->loggedin = $isLoggedIn; |
708 | $this->checkdb(); // Make sure data file exists. | 708 | $this->checkdb(); // Make sure data file exists. |
@@ -716,7 +716,7 @@ class linkdb implements Iterator, Countable, ArrayAccess | |||
716 | public function offsetSet($offset, $value) | 716 | public function offsetSet($offset, $value) |
717 | { | 717 | { |
718 | if (!$this->loggedin) die('You are not authorized to add a link.'); | 718 | if (!$this->loggedin) die('You are not authorized to add a link.'); |
719 | if (empty($value['linkdate']) || empty($value['url'])) die('Internal Error: A link should always have a linkdate and url.'); | 719 | if (empty($value['linkdate']) || empty($value['url'])) die('Internal Error: A link should always have a linkdate and URL.'); |
720 | if (empty($offset)) die('You must specify a key.'); | 720 | if (empty($offset)) die('You must specify a key.'); |
721 | $this->links[$offset] = $value; | 721 | $this->links[$offset] = $value; |
722 | $this->urls[$value['url']]=$offset; | 722 | $this->urls[$value['url']]=$offset; |
@@ -779,19 +779,19 @@ class linkdb implements Iterator, Countable, ArrayAccess | |||
779 | invalidateCaches(); | 779 | invalidateCaches(); |
780 | } | 780 | } |
781 | 781 | ||
782 | // Returns the link for a given URL (if it exists). false it does not exist. | 782 | // Returns the link for a given URL (if it exists). False if it does not exist. |
783 | public function getLinkFromUrl($url) | 783 | public function getLinkFromUrl($url) |
784 | { | 784 | { |
785 | if (isset($this->urls[$url])) return $this->links[$this->urls[$url]]; | 785 | if (isset($this->urls[$url])) return $this->links[$this->urls[$url]]; |
786 | return false; | 786 | return false; |
787 | } | 787 | } |
788 | 788 | ||
789 | // Case insentitive search among links (in url, title and description). Returns filtered list of links. | 789 | // Case insensitive search among links (in the URLs, title and description). Returns filtered list of links. |
790 | // eg. print_r($mydb->filterFulltext('hollandais')); | 790 | // e.g. print_r($mydb->filterFulltext('hollandais')); |
791 | public function filterFulltext($searchterms) | 791 | public function filterFulltext($searchterms) |
792 | { | 792 | { |
793 | // FIXME: explode(' ',$searchterms) and perform a AND search. | 793 | // FIXME: explode(' ',$searchterms) and perform a AND search. |
794 | // FIXME: accept double-quotes to search for a string "as is" ? | 794 | // FIXME: accept double-quotes to search for a string "as is"? |
795 | $filtered=array(); | 795 | $filtered=array(); |
796 | $s = strtolower($searchterms); | 796 | $s = strtolower($searchterms); |
797 | foreach($this->links as $l) | 797 | foreach($this->links as $l) |
@@ -808,7 +808,7 @@ class linkdb implements Iterator, Countable, ArrayAccess | |||
808 | 808 | ||
809 | // Filter by tag. | 809 | // Filter by tag. |
810 | // You can specify one or more tags (tags can be separated by space or comma). | 810 | // You can specify one or more tags (tags can be separated by space or comma). |
811 | // eg. print_r($mydb->filterTags('linux programming')); | 811 | // e.g. print_r($mydb->filterTags('linux programming')); |
812 | public function filterTags($tags,$casesensitive=false) | 812 | public function filterTags($tags,$casesensitive=false) |
813 | { | 813 | { |
814 | $t = str_replace(',',' ',($casesensitive?$tags:strtolower($tags))); | 814 | $t = str_replace(',',' ',($casesensitive?$tags:strtolower($tags))); |
@@ -824,9 +824,9 @@ class linkdb implements Iterator, Countable, ArrayAccess | |||
824 | return $filtered; | 824 | return $filtered; |
825 | } | 825 | } |
826 | 826 | ||
827 | // Filter by day. Day must be in the form 'YYYYMMDD' (eg. '20120125') | 827 | // Filter by day. Day must be in the form 'YYYYMMDD' (e.g. '20120125') |
828 | // Sort order is: older articles first. | 828 | // Sort order is: older articles first. |
829 | // eg. print_r($mydb->filterDay('20120125')); | 829 | // e.g. print_r($mydb->filterDay('20120125')); |
830 | public function filterDay($day) | 830 | public function filterDay($day) |
831 | { | 831 | { |
832 | $filtered=array(); | 832 | $filtered=array(); |
@@ -881,13 +881,13 @@ class linkdb implements Iterator, Countable, ArrayAccess | |||
881 | } | 881 | } |
882 | 882 | ||
883 | // ------------------------------------------------------------------------------------------ | 883 | // ------------------------------------------------------------------------------------------ |
884 | // Ouput the last N links in RSS 2.0 format. | 884 | // Output the last N links in RSS 2.0 format. |
885 | function showRSS() | 885 | function showRSS() |
886 | { | 886 | { |
887 | header('Content-Type: application/rss+xml; charset=utf-8'); | 887 | header('Content-Type: application/rss+xml; charset=utf-8'); |
888 | 888 | ||
889 | // $usepermalink : If true, use permalink instead of final link. | 889 | // $usepermalink : If true, use permalink instead of final link. |
890 | // User just has to add 'permalink' in URL parameters. eg. http://mysite.com/shaarli/?do=rss&permalinks | 890 | // User just has to add 'permalink' in URL parameters. e.g. http://mysite.com/shaarli/?do=rss&permalinks |
891 | $usepermalinks = isset($_GET['permalinks']); | 891 | $usepermalinks = isset($_GET['permalinks']); |
892 | 892 | ||
893 | // Cache system | 893 | // Cache system |
@@ -896,9 +896,9 @@ function showRSS() | |||
896 | $cached = $cache->cachedVersion(); if (!empty($cached)) { echo $cached; exit; } | 896 | $cached = $cache->cachedVersion(); if (!empty($cached)) { echo $cached; exit; } |
897 | 897 | ||
898 | // If cached was not found (or not usable), then read the database and build the response: | 898 | // If cached was not found (or not usable), then read the database and build the response: |
899 | $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in). | 899 | $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if user it not logged in). |
900 | 900 | ||
901 | // Optionnaly filter the results: | 901 | // Optionally filter the results: |
902 | $linksToDisplay=array(); | 902 | $linksToDisplay=array(); |
903 | if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']); | 903 | if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']); |
904 | elseif (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); | 904 | elseif (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); |
@@ -955,13 +955,13 @@ function showRSS() | |||
955 | } | 955 | } |
956 | 956 | ||
957 | // ------------------------------------------------------------------------------------------ | 957 | // ------------------------------------------------------------------------------------------ |
958 | // Ouput the last N links in ATOM format. | 958 | // Output the last N links in ATOM format. |
959 | function showATOM() | 959 | function showATOM() |
960 | { | 960 | { |
961 | header('Content-Type: application/atom+xml; charset=utf-8'); | 961 | header('Content-Type: application/atom+xml; charset=utf-8'); |
962 | 962 | ||
963 | // $usepermalink : If true, use permalink instead of final link. | 963 | // $usepermalink : If true, use permalink instead of final link. |
964 | // User just has to add 'permalink' in URL parameters. eg. http://mysite.com/shaarli/?do=atom&permalinks | 964 | // User just has to add 'permalink' in URL parameters. e.g. http://mysite.com/shaarli/?do=atom&permalinks |
965 | $usepermalinks = isset($_GET['permalinks']); | 965 | $usepermalinks = isset($_GET['permalinks']); |
966 | 966 | ||
967 | // Cache system | 967 | // Cache system |
@@ -973,7 +973,7 @@ function showATOM() | |||
973 | $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in). | 973 | $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in). |
974 | 974 | ||
975 | 975 | ||
976 | // Optionnaly filter the results: | 976 | // Optionally filter the results: |
977 | $linksToDisplay=array(); | 977 | $linksToDisplay=array(); |
978 | if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']); | 978 | if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']); |
979 | elseif (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); | 979 | elseif (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); |
@@ -1069,7 +1069,7 @@ function showDailyRSS() | |||
1069 | if (empty($days[$day])) $days[$day]=array(); | 1069 | if (empty($days[$day])) $days[$day]=array(); |
1070 | $days[$day][]=$linkdate; | 1070 | $days[$day][]=$linkdate; |
1071 | } | 1071 | } |
1072 | if (count($days)>$nb_of_days) break; // Have we collected enough days ? | 1072 | if (count($days)>$nb_of_days) break; // Have we collected enough days? |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | // Build the RSS feed. | 1075 | // Build the RSS feed. |
@@ -1148,7 +1148,7 @@ function showDaily() | |||
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | /* We need to spread the articles on 3 columns. | 1150 | /* We need to spread the articles on 3 columns. |
1151 | I did not want to use a javascript lib like http://masonry.desandro.com/ | 1151 | I did not want to use a JavaScript lib like http://masonry.desandro.com/ |
1152 | so I manually spread entries with a simple method: I roughly evaluate the | 1152 | so I manually spread entries with a simple method: I roughly evaluate the |
1153 | height of a div according to title and description length. | 1153 | height of a div according to title and description length. |
1154 | */ | 1154 | */ |
@@ -1159,7 +1159,7 @@ function showDaily() | |||
1159 | // Roughly estimate length of entry (by counting characters) | 1159 | // Roughly estimate length of entry (by counting characters) |
1160 | // Title: 30 chars = 1 line. 1 line is 30 pixels height. | 1160 | // Title: 30 chars = 1 line. 1 line is 30 pixels height. |
1161 | // Description: 836 characters gives roughly 342 pixel height. | 1161 | // Description: 836 characters gives roughly 342 pixel height. |
1162 | // This is not perfect, but it's usually ok. | 1162 | // This is not perfect, but it's usually OK. |
1163 | $length=strlen($link['title'])+(342*strlen($link['description']))/836; | 1163 | $length=strlen($link['title'])+(342*strlen($link['description']))/836; |
1164 | if ($link['thumbnail']) $length +=100; // 1 thumbnails roughly takes 100 pixels height. | 1164 | if ($link['thumbnail']) $length +=100; // 1 thumbnails roughly takes 100 pixels height. |
1165 | // Then put in column which is the less filled: | 1165 | // Then put in column which is the less filled: |
@@ -1212,7 +1212,7 @@ function renderPage() | |||
1212 | // -------- Picture wall | 1212 | // -------- Picture wall |
1213 | if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=picwall')) | 1213 | if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=picwall')) |
1214 | { | 1214 | { |
1215 | // Optionnaly filter the results: | 1215 | // Optionally filter the results: |
1216 | $links=array(); | 1216 | $links=array(); |
1217 | if (!empty($_GET['searchterm'])) $links = $LINKSDB->filterFulltext($_GET['searchterm']); | 1217 | if (!empty($_GET['searchterm'])) $links = $LINKSDB->filterFulltext($_GET['searchterm']); |
1218 | elseif (!empty($_GET['searchtags'])) $links = $LINKSDB->filterTags(trim($_GET['searchtags'])); | 1218 | elseif (!empty($_GET['searchtags'])) $links = $LINKSDB->filterTags(trim($_GET['searchtags'])); |
@@ -1292,7 +1292,7 @@ function renderPage() | |||
1292 | if (isset($_GET['linksperpage'])) | 1292 | if (isset($_GET['linksperpage'])) |
1293 | { | 1293 | { |
1294 | if (is_numeric($_GET['linksperpage'])) { $_SESSION['LINKS_PER_PAGE']=abs(intval($_GET['linksperpage'])); } | 1294 | if (is_numeric($_GET['linksperpage'])) { $_SESSION['LINKS_PER_PAGE']=abs(intval($_GET['linksperpage'])); } |
1295 | // Make sure the referer is from Shaarli itself. | 1295 | // Make sure the referrer is Shaarli itself. |
1296 | $referer = '?'; | 1296 | $referer = '?'; |
1297 | if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['HTTP_HOST'])==0) | 1297 | if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['HTTP_HOST'])==0) |
1298 | $referer = $_SERVER['HTTP_REFERER']; | 1298 | $referer = $_SERVER['HTTP_REFERER']; |
@@ -1311,7 +1311,7 @@ function renderPage() | |||
1311 | { | 1311 | { |
1312 | unset($_SESSION['privateonly']); // See all links | 1312 | unset($_SESSION['privateonly']); // See all links |
1313 | } | 1313 | } |
1314 | // Make sure the referer is from Shaarli itself. | 1314 | // Make sure the referrer is Shaarli itself. |
1315 | $referer = '?'; | 1315 | $referer = '?'; |
1316 | if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['HTTP_HOST'])==0) | 1316 | if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['HTTP_HOST'])==0) |
1317 | $referer = $_SERVER['HTTP_REFERER']; | 1317 | $referer = $_SERVER['HTTP_REFERER']; |
@@ -1322,7 +1322,7 @@ function renderPage() | |||
1322 | // -------- Handle other actions allowed for non-logged in users: | 1322 | // -------- Handle other actions allowed for non-logged in users: |
1323 | if (!isLoggedIn()) | 1323 | if (!isLoggedIn()) |
1324 | { | 1324 | { |
1325 | // User tries to post new link but is not loggedin: | 1325 | // User tries to post new link but is not logged in: |
1326 | // Show login screen, then redirect to ?post=... | 1326 | // Show login screen, then redirect to ?post=... |
1327 | if (isset($_GET['post'])) | 1327 | if (isset($_GET['post'])) |
1328 | { | 1328 | { |
@@ -1332,7 +1332,7 @@ function renderPage() | |||
1332 | $PAGE = new pageBuilder; | 1332 | $PAGE = new pageBuilder; |
1333 | buildLinkList($PAGE,$LINKSDB); // Compute list of links to display | 1333 | buildLinkList($PAGE,$LINKSDB); // Compute list of links to display |
1334 | $PAGE->renderPage('linklist'); | 1334 | $PAGE->renderPage('linklist'); |
1335 | exit; // Never remove this one ! All operations below are reserved for logged in user. | 1335 | exit; // Never remove this one! All operations below are reserved for logged in user. |
1336 | } | 1336 | } |
1337 | 1337 | ||
1338 | // -------- All other functions are reserved for the registered user: | 1338 | // -------- All other functions are reserved for the registered user: |
@@ -1353,7 +1353,7 @@ function renderPage() | |||
1353 | if ($GLOBALS['config']['OPEN_SHAARLI']) die('You are not supposed to change a password on an Open Shaarli.'); | 1353 | if ($GLOBALS['config']['OPEN_SHAARLI']) die('You are not supposed to change a password on an Open Shaarli.'); |
1354 | if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) | 1354 | if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) |
1355 | { | 1355 | { |
1356 | if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away ! | 1356 | if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away! |
1357 | 1357 | ||
1358 | // Make sure old password is correct. | 1358 | // Make sure old password is correct. |
1359 | $oldhash = sha1($_POST['oldpassword'].$GLOBALS['login'].$GLOBALS['salt']); | 1359 | $oldhash = sha1($_POST['oldpassword'].$GLOBALS['login'].$GLOBALS['salt']); |
@@ -1380,7 +1380,7 @@ function renderPage() | |||
1380 | { | 1380 | { |
1381 | if (!empty($_POST['title']) ) | 1381 | if (!empty($_POST['title']) ) |
1382 | { | 1382 | { |
1383 | if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away ! | 1383 | if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away! |
1384 | $tz = 'UTC'; | 1384 | $tz = 'UTC'; |
1385 | if (!empty($_POST['continent']) && !empty($_POST['city'])) | 1385 | if (!empty($_POST['continent']) && !empty($_POST['city'])) |
1386 | if (isTZvalid($_POST['continent'],$_POST['city'])) | 1386 | if (isTZvalid($_POST['continent'],$_POST['city'])) |
@@ -1404,7 +1404,7 @@ function renderPage() | |||
1404 | $PAGE->assign('title',htmlspecialchars( empty($GLOBALS['title']) ? '' : $GLOBALS['title'] , ENT_QUOTES)); | 1404 | $PAGE->assign('title',htmlspecialchars( empty($GLOBALS['title']) ? '' : $GLOBALS['title'] , ENT_QUOTES)); |
1405 | $PAGE->assign('redirector',htmlspecialchars( empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'] , ENT_QUOTES)); | 1405 | $PAGE->assign('redirector',htmlspecialchars( empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'] , ENT_QUOTES)); |
1406 | list($timezone_form,$timezone_js) = templateTZform($GLOBALS['timezone']); | 1406 | list($timezone_form,$timezone_js) = templateTZform($GLOBALS['timezone']); |
1407 | $PAGE->assign('timezone_form',$timezone_form); // FIXME: put entire tz form generation in template ? | 1407 | $PAGE->assign('timezone_form',$timezone_form); // FIXME: Put entire tz form generation in template? |
1408 | $PAGE->assign('timezone_js',$timezone_js); | 1408 | $PAGE->assign('timezone_js',$timezone_js); |
1409 | $PAGE->renderPage('configure'); | 1409 | $PAGE->renderPage('configure'); |
1410 | exit; | 1410 | exit; |
@@ -1428,7 +1428,7 @@ function renderPage() | |||
1428 | if (!empty($_POST['deletetag']) && !empty($_POST['fromtag'])) | 1428 | if (!empty($_POST['deletetag']) && !empty($_POST['fromtag'])) |
1429 | { | 1429 | { |
1430 | $needle=trim($_POST['fromtag']); | 1430 | $needle=trim($_POST['fromtag']); |
1431 | $linksToAlter = $LINKSDB->filterTags($needle,true); // true for case-sensitive tag search. | 1431 | $linksToAlter = $LINKSDB->filterTags($needle,true); // True for case-sensitive tag search. |
1432 | foreach($linksToAlter as $key=>$value) | 1432 | foreach($linksToAlter as $key=>$value) |
1433 | { | 1433 | { |
1434 | $tags = explode(' ',trim($value['tags'])); | 1434 | $tags = explode(' ',trim($value['tags'])); |
@@ -1436,7 +1436,7 @@ function renderPage() | |||
1436 | $value['tags']=trim(implode(' ',$tags)); | 1436 | $value['tags']=trim(implode(' ',$tags)); |
1437 | $LINKSDB[$key]=$value; | 1437 | $LINKSDB[$key]=$value; |
1438 | } | 1438 | } |
1439 | $LINKSDB->savedb(); // save to disk | 1439 | $LINKSDB->savedb(); // Save to disk. |
1440 | echo '<script language="JavaScript">alert("Tag was removed from '.count($linksToAlter).' links.");document.location=\'?\';</script>'; | 1440 | echo '<script language="JavaScript">alert("Tag was removed from '.count($linksToAlter).' links.");document.location=\'?\';</script>'; |
1441 | exit; | 1441 | exit; |
1442 | } | 1442 | } |
@@ -1449,17 +1449,17 @@ function renderPage() | |||
1449 | foreach($linksToAlter as $key=>$value) | 1449 | foreach($linksToAlter as $key=>$value) |
1450 | { | 1450 | { |
1451 | $tags = explode(' ',trim($value['tags'])); | 1451 | $tags = explode(' ',trim($value['tags'])); |
1452 | $tags[array_search($needle,$tags)] = trim($_POST['totag']); // Remplace tags value. | 1452 | $tags[array_search($needle,$tags)] = trim($_POST['totag']); // Replace tags value. |
1453 | $value['tags']=trim(implode(' ',$tags)); | 1453 | $value['tags']=trim(implode(' ',$tags)); |
1454 | $LINKSDB[$key]=$value; | 1454 | $LINKSDB[$key]=$value; |
1455 | } | 1455 | } |
1456 | $LINKSDB->savedb(); // save to disk | 1456 | $LINKSDB->savedb(); // Save to disk. |
1457 | echo '<script language="JavaScript">alert("Tag was renamed in '.count($linksToAlter).' links.");document.location=\'?searchtags='.urlencode($_POST['totag']).'\';</script>'; | 1457 | echo '<script language="JavaScript">alert("Tag was renamed in '.count($linksToAlter).' links.");document.location=\'?searchtags='.urlencode($_POST['totag']).'\';</script>'; |
1458 | exit; | 1458 | exit; |
1459 | } | 1459 | } |
1460 | } | 1460 | } |
1461 | 1461 | ||
1462 | // -------- User wants to add a link without using the bookmarklet: show form. | 1462 | // -------- User wants to add a link without using the bookmarklet: Show form. |
1463 | if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=addlink')) | 1463 | if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=addlink')) |
1464 | { | 1464 | { |
1465 | $PAGE = new pageBuilder; | 1465 | $PAGE = new pageBuilder; |
@@ -1471,7 +1471,7 @@ function renderPage() | |||
1471 | // -------- User clicked the "Save" button when editing a link: Save link to database. | 1471 | // -------- User clicked the "Save" button when editing a link: Save link to database. |
1472 | if (isset($_POST['save_edit'])) | 1472 | if (isset($_POST['save_edit'])) |
1473 | { | 1473 | { |
1474 | if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away ! | 1474 | if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away! |
1475 | $tags = trim(preg_replace('/\s\s+/',' ', $_POST['lf_tags'])); // Remove multiple spaces. | 1475 | $tags = trim(preg_replace('/\s\s+/',' ', $_POST['lf_tags'])); // Remove multiple spaces. |
1476 | $linkdate=$_POST['lf_linkdate']; | 1476 | $linkdate=$_POST['lf_linkdate']; |
1477 | $url = trim($_POST['lf_url']); | 1477 | $url = trim($_POST['lf_url']); |
@@ -1481,7 +1481,7 @@ function renderPage() | |||
1481 | 'linkdate'=>$linkdate,'tags'=>str_replace(',',' ',$tags)); | 1481 | 'linkdate'=>$linkdate,'tags'=>str_replace(',',' ',$tags)); |
1482 | if ($link['title']=='') $link['title']=$link['url']; // If title is empty, use the URL as title. | 1482 | if ($link['title']=='') $link['title']=$link['url']; // If title is empty, use the URL as title. |
1483 | $LINKSDB[$linkdate] = $link; | 1483 | $LINKSDB[$linkdate] = $link; |
1484 | $LINKSDB->savedb(); // save to disk | 1484 | $LINKSDB->savedb(); // Save to disk. |
1485 | pubsubhub(); | 1485 | pubsubhub(); |
1486 | 1486 | ||
1487 | // If we are called from the bookmarklet, we must close the popup: | 1487 | // If we are called from the bookmarklet, we must close the popup: |
@@ -1495,7 +1495,7 @@ function renderPage() | |||
1495 | // -------- User clicked the "Cancel" button when editing a link. | 1495 | // -------- User clicked the "Cancel" button when editing a link. |
1496 | if (isset($_POST['cancel_edit'])) | 1496 | if (isset($_POST['cancel_edit'])) |
1497 | { | 1497 | { |
1498 | // If we are called from the bookmarklet, we must close the popup; | 1498 | // If we are called from the bookmarklet, we must close the popup: |
1499 | if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script language="JavaScript">self.close();</script>'; exit; } | 1499 | if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script language="JavaScript">self.close();</script>'; exit; } |
1500 | $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); | 1500 | $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); |
1501 | $returnurl .= '#'.smallHash($_POST['lf_linkdate']); // Scroll to the link which has been edited. | 1501 | $returnurl .= '#'.smallHash($_POST['lf_linkdate']); // Scroll to the link which has been edited. |
@@ -1503,12 +1503,12 @@ function renderPage() | |||
1503 | exit; | 1503 | exit; |
1504 | } | 1504 | } |
1505 | 1505 | ||
1506 | // -------- User clicked the "Delete" button when editing a link : Delete link from database. | 1506 | // -------- User clicked the "Delete" button when editing a link: Delete link from database. |
1507 | if (isset($_POST['delete_link'])) | 1507 | if (isset($_POST['delete_link'])) |
1508 | { | 1508 | { |
1509 | if (!tokenOk($_POST['token'])) die('Wrong token.'); | 1509 | if (!tokenOk($_POST['token'])) die('Wrong token.'); |
1510 | // We do not need to ask for confirmation: | 1510 | // We do not need to ask for confirmation: |
1511 | // - confirmation is handled by javascript | 1511 | // - confirmation is handled by JavaScript |
1512 | // - we are protected from XSRF by the token. | 1512 | // - we are protected from XSRF by the token. |
1513 | $linkdate=$_POST['lf_linkdate']; | 1513 | $linkdate=$_POST['lf_linkdate']; |
1514 | unset($LINKSDB[$linkdate]); | 1514 | unset($LINKSDB[$linkdate]); |
@@ -1558,7 +1558,7 @@ function renderPage() | |||
1558 | $tags = (empty($_GET['tags']) ? '' : $_GET['tags'] ); // Get tags if it was provided in URL | 1558 | $tags = (empty($_GET['tags']) ? '' : $_GET['tags'] ); // Get tags if it was provided in URL |
1559 | $private = (!empty($_GET['private']) && $_GET['private'] === "1" ? 1 : 0); // Get private if it was provided in URL | 1559 | $private = (!empty($_GET['private']) && $_GET['private'] === "1" ? 1 : 0); // Get private if it was provided in URL |
1560 | if (($url!='') && parse_url($url,PHP_URL_SCHEME)=='') $url = 'http://'.$url; | 1560 | if (($url!='') && parse_url($url,PHP_URL_SCHEME)=='') $url = 'http://'.$url; |
1561 | // 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.) | 1561 | // If this is an HTTP link, we try go get the page to extract the title (otherwise we will to straight to the edit form.) |
1562 | if (empty($title) && parse_url($url,PHP_URL_SCHEME)=='http') | 1562 | if (empty($title) && parse_url($url,PHP_URL_SCHEME)=='http') |
1563 | { | 1563 | { |
1564 | list($status,$headers,$data) = getHTTP($url,4); // Short timeout to keep the application responsive. | 1564 | list($status,$headers,$data) = getHTTP($url,4); // Short timeout to keep the application responsive. |
@@ -1612,7 +1612,7 @@ function renderPage() | |||
1612 | exit; | 1612 | exit; |
1613 | } | 1613 | } |
1614 | $exportWhat=$_GET['what']; | 1614 | $exportWhat=$_GET['what']; |
1615 | if (!array_intersect(array('all','public','private'),array($exportWhat))) die('What are you trying to export ???'); | 1615 | if (!array_intersect(array('all','public','private'),array($exportWhat))) die('What are you trying to export???'); |
1616 | 1616 | ||
1617 | header('Content-Type: text/html; charset=utf-8'); | 1617 | header('Content-Type: text/html; charset=utf-8'); |
1618 | header('Content-disposition: attachment; filename=bookmarks_'.$exportWhat.'_'.strval(date('Ymd_His')).'.html'); | 1618 | header('Content-disposition: attachment; filename=bookmarks_'.$exportWhat.'_'.strval(date('Ymd_His')).'.html'); |
@@ -1685,8 +1685,8 @@ function importFile() | |||
1685 | $filename=$_FILES['filetoupload']['name']; | 1685 | $filename=$_FILES['filetoupload']['name']; |
1686 | $filesize=$_FILES['filetoupload']['size']; | 1686 | $filesize=$_FILES['filetoupload']['size']; |
1687 | $data=file_get_contents($_FILES['filetoupload']['tmp_name']); | 1687 | $data=file_get_contents($_FILES['filetoupload']['tmp_name']); |
1688 | $private = (empty($_POST['private']) ? 0 : 1); // Should the links be imported as private ? | 1688 | $private = (empty($_POST['private']) ? 0 : 1); // Should the links be imported as private? |
1689 | $overwrite = !empty($_POST['overwrite']) ; // Should the imported links overwrite existing ones ? | 1689 | $overwrite = !empty($_POST['overwrite']) ; // Should the imported links overwrite existing ones? |
1690 | $import_count=0; | 1690 | $import_count=0; |
1691 | 1691 | ||
1692 | // Sniff file type: | 1692 | // Sniff file type: |
@@ -1697,7 +1697,7 @@ function importFile() | |||
1697 | if ($type=='netscape') | 1697 | if ($type=='netscape') |
1698 | { | 1698 | { |
1699 | // This is a standard Netscape-style bookmark file. | 1699 | // This is a standard Netscape-style bookmark file. |
1700 | // This format is supported by all browsers (except IE, of course), also delicious, diigo and others. | 1700 | // This format is supported by all browsers (except IE, of course), also Delicious, Diigo and others. |
1701 | foreach(explode('<DT>',$data) as $html) // explode is very fast | 1701 | foreach(explode('<DT>',$data) as $html) // explode is very fast |
1702 | { | 1702 | { |
1703 | $link = array('linkdate'=>'','title'=>'','url'=>'','description'=>'','tags'=>'','private'=>0); | 1703 | $link = array('linkdate'=>'','title'=>'','url'=>'','description'=>'','tags'=>'','private'=>0); |
@@ -1731,14 +1731,14 @@ function importFile() | |||
1731 | 1731 | ||
1732 | // Make sure date/time is not already used by another link. | 1732 | // Make sure date/time is not already used by another link. |
1733 | // (Some bookmark files have several different links with the same ADD_DATE) | 1733 | // (Some bookmark files have several different links with the same ADD_DATE) |
1734 | // We increment date by 1 second until we find a date which is not used in db. | 1734 | // We increment date by 1 second until we find a date which is not used in DB. |
1735 | // (so that links that have the same date/time are more or less kept grouped by date, but do not conflict.) | 1735 | // (so that links that have the same date/time are more or less kept grouped by date, but do not conflict.) |
1736 | while (!empty($LINKSDB[date('Ymd_His',$raw_add_date)])) { $raw_add_date++; }// Yes, I know it's ugly. | 1736 | while (!empty($LINKSDB[date('Ymd_His',$raw_add_date)])) { $raw_add_date++; }// Yes, I know it's ugly. |
1737 | $link['linkdate']=date('Ymd_His',$raw_add_date); | 1737 | $link['linkdate']=date('Ymd_His',$raw_add_date); |
1738 | $LINKSDB[$link['linkdate']] = $link; | 1738 | $LINKSDB[$link['linkdate']] = $link; |
1739 | $import_count++; | 1739 | $import_count++; |
1740 | } | 1740 | } |
1741 | else // link already present in database. | 1741 | else // Link already present in database. |
1742 | { | 1742 | { |
1743 | if ($overwrite) | 1743 | if ($overwrite) |
1744 | { // If overwrite is required, we import link data, except date/time. | 1744 | { // If overwrite is required, we import link data, except date/time. |
@@ -1789,13 +1789,13 @@ function buildLinkList($PAGE,$LINKSDB) | |||
1789 | { | 1789 | { |
1790 | header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); | 1790 | header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); |
1791 | echo '<h1>404 Not found.</h1>Oh crap. The link you are trying to reach does not exist or has been deleted.'; | 1791 | echo '<h1>404 Not found.</h1>Oh crap. The link you are trying to reach does not exist or has been deleted.'; |
1792 | echo '<br>You would mind <a href="?">clicking here</a> ?'; | 1792 | echo '<br>You would mind <a href="?">clicking here</a>?'; |
1793 | exit; | 1793 | exit; |
1794 | } | 1794 | } |
1795 | $search_type='permalink'; | 1795 | $search_type='permalink'; |
1796 | } | 1796 | } |
1797 | else | 1797 | else |
1798 | $linksToDisplay = $LINKSDB; // otherwise, display without filtering. | 1798 | $linksToDisplay = $LINKSDB; // Otherwise, display without filtering. |
1799 | 1799 | ||
1800 | // Option: Show only private links | 1800 | // Option: Show only private links |
1801 | if (!empty($_SESSION['privateonly'])) | 1801 | if (!empty($_SESSION['privateonly'])) |
@@ -1809,11 +1809,11 @@ function buildLinkList($PAGE,$LINKSDB) | |||
1809 | } | 1809 | } |
1810 | 1810 | ||
1811 | // ---- Handle paging. | 1811 | // ---- Handle paging. |
1812 | /* Can someone explain to me why you get the following error when using array_keys() on an object which implements the interface ArrayAccess ??? | 1812 | /* Can someone explain to me why you get the following error when using array_keys() on an object which implements the interface ArrayAccess??? |
1813 | "Warning: array_keys() expects parameter 1 to be array, object given in ... " | 1813 | "Warning: array_keys() expects parameter 1 to be array, object given in ... " |
1814 | If my class implements ArrayAccess, why won't array_keys() accept it ? ( $keys=array_keys($linksToDisplay); ) | 1814 | If my class implements ArrayAccess, why won't array_keys() accept it ? ( $keys=array_keys($linksToDisplay); ) |
1815 | */ | 1815 | */ |
1816 | $keys=array(); foreach($linksToDisplay as $key=>$value) { $keys[]=$key; } // Stupid and ugly. Thanks php. | 1816 | $keys=array(); foreach($linksToDisplay as $key=>$value) { $keys[]=$key; } // Stupid and ugly. Thanks PHP. |
1817 | 1817 | ||
1818 | // If there is only a single link, we change on-the-fly the title of the page. | 1818 | // If there is only a single link, we change on-the-fly the title of the page. |
1819 | if (count($linksToDisplay)==1) $GLOBALS['pagetitle'] = $linksToDisplay[$keys[0]]['title'].' - '.$GLOBALS['title']; | 1819 | if (count($linksToDisplay)==1) $GLOBALS['pagetitle'] = $linksToDisplay[$keys[0]]['title'].' - '.$GLOBALS['title']; |
@@ -1860,7 +1860,7 @@ function buildLinkList($PAGE,$LINKSDB) | |||
1860 | $PAGE->assign('result_count',count($linksToDisplay)); | 1860 | $PAGE->assign('result_count',count($linksToDisplay)); |
1861 | $PAGE->assign('search_type',$search_type); | 1861 | $PAGE->assign('search_type',$search_type); |
1862 | $PAGE->assign('search_crits',$search_crits); | 1862 | $PAGE->assign('search_crits',$search_crits); |
1863 | $PAGE->assign('redirector',empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector']); // optional redirector URL | 1863 | $PAGE->assign('redirector',empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector']); // Optional redirector URL. |
1864 | $PAGE->assign('token',$token); | 1864 | $PAGE->assign('token',$token); |
1865 | $PAGE->assign('links',$linkDisp); | 1865 | $PAGE->assign('links',$linkDisp); |
1866 | return; | 1866 | return; |
@@ -1868,9 +1868,9 @@ function buildLinkList($PAGE,$LINKSDB) | |||
1868 | 1868 | ||
1869 | // Compute the thumbnail for a link. | 1869 | // Compute the thumbnail for a link. |
1870 | // | 1870 | // |
1871 | // with a link to the original URL. | 1871 | // With a link to the original URL. |
1872 | // Understands various services (youtube.com...) | 1872 | // Understands various services (youtube.com...) |
1873 | // Input: $url = url for which the thumbnail must be found. | 1873 | // Input: $url = URL for which the thumbnail must be found. |
1874 | // $href = if provided, this URL will be followed instead of $url | 1874 | // $href = if provided, this URL will be followed instead of $url |
1875 | // Returns an associative array with thumbnail attributes (src,href,width,height,style,alt) | 1875 | // Returns an associative array with thumbnail attributes (src,href,width,height,style,alt) |
1876 | // Some of them may be missing. | 1876 | // Some of them may be missing. |
@@ -1881,7 +1881,7 @@ function computeThumbnail($url,$href=false) | |||
1881 | if ($href==false) $href=$url; | 1881 | if ($href==false) $href=$url; |
1882 | 1882 | ||
1883 | // For most hosts, the URL of the thumbnail can be easily deduced from the URL of the link. | 1883 | // For most hosts, the URL of the thumbnail can be easily deduced from the URL of the link. |
1884 | // (eg. http://www.youtube.com/watch?v=spVypYk4kto ---> http://img.youtube.com/vi/spVypYk4kto/default.jpg ) | 1884 | // (e.g. http://www.youtube.com/watch?v=spVypYk4kto ---> http://img.youtube.com/vi/spVypYk4kto/default.jpg ) |
1885 | // ^^^^^^^^^^^ ^^^^^^^^^^^ | 1885 | // ^^^^^^^^^^^ ^^^^^^^^^^^ |
1886 | $domain = parse_url($url,PHP_URL_HOST); | 1886 | $domain = parse_url($url,PHP_URL_HOST); |
1887 | if ($domain=='youtube.com' || $domain=='www.youtube.com') | 1887 | if ($domain=='youtube.com' || $domain=='www.youtube.com') |
@@ -1954,17 +1954,17 @@ function computeThumbnail($url,$href=false) | |||
1954 | ) | 1954 | ) |
1955 | { | 1955 | { |
1956 | if ($domain=='vimeo.com') | 1956 | if ($domain=='vimeo.com') |
1957 | { // Make sure this vimeo url points to a video (/xxx... where xxx is numeric) | 1957 | { // Make sure this vimeo URL points to a video (/xxx... where xxx is numeric) |
1958 | $path = parse_url($url,PHP_URL_PATH); | 1958 | $path = parse_url($url,PHP_URL_PATH); |
1959 | if (!preg_match('!/\d+.+?!',$path)) return array(); // This is not a single video URL. | 1959 | if (!preg_match('!/\d+.+?!',$path)) return array(); // This is not a single video URL. |
1960 | } | 1960 | } |
1961 | if ($domain=='xkcd.com' || endsWith($domain,'.xkcd.com')) | 1961 | if ($domain=='xkcd.com' || endsWith($domain,'.xkcd.com')) |
1962 | { // Make sure this url points to a single comic (/xxx... where xxx is numeric) | 1962 | { // Make sure this URL points to a single comic (/xxx... where xxx is numeric) |
1963 | $path = parse_url($url,PHP_URL_PATH); | 1963 | $path = parse_url($url,PHP_URL_PATH); |
1964 | if (!preg_match('!/\d+.+?!',$path)) return array(); | 1964 | if (!preg_match('!/\d+.+?!',$path)) return array(); |
1965 | } | 1965 | } |
1966 | if ($domain=='ted.com' || endsWith($domain,'.ted.com')) | 1966 | if ($domain=='ted.com' || endsWith($domain,'.ted.com')) |
1967 | { // Make sure this TED url points to a video (/talks/...) | 1967 | { // Make sure this TED URL points to a video (/talks/...) |
1968 | $path = parse_url($url,PHP_URL_PATH); | 1968 | $path = parse_url($url,PHP_URL_PATH); |
1969 | if ("/talks/" !== substr($path,0,7)) return array(); // This is not a single video URL. | 1969 | if ("/talks/" !== substr($path,0,7)) return array(); // This is not a single video URL. |
1970 | } | 1970 | } |
@@ -1991,7 +1991,7 @@ function computeThumbnail($url,$href=false) | |||
1991 | // Returns the HTML code to display a thumbnail for a link | 1991 | // Returns the HTML code to display a thumbnail for a link |
1992 | // with a link to the original URL. | 1992 | // with a link to the original URL. |
1993 | // Understands various services (youtube.com...) | 1993 | // Understands various services (youtube.com...) |
1994 | // Input: $url = url for which the thumbnail must be found. | 1994 | // Input: $url = URL for which the thumbnail must be found. |
1995 | // $href = if provided, this URL will be followed instead of $url | 1995 | // $href = if provided, this URL will be followed instead of $url |
1996 | // Returns '' if no thumbnail available. | 1996 | // Returns '' if no thumbnail available. |
1997 | function thumbnail($url,$href=false) | 1997 | function thumbnail($url,$href=false) |
@@ -2012,7 +2012,7 @@ function thumbnail($url,$href=false) | |||
2012 | // Returns the HTML code to display a thumbnail for a link | 2012 | // Returns the HTML code to display a thumbnail for a link |
2013 | // for the picture wall (using lazy image loading) | 2013 | // for the picture wall (using lazy image loading) |
2014 | // Understands various services (youtube.com...) | 2014 | // Understands various services (youtube.com...) |
2015 | // Input: $url = url for which the thumbnail must be found. | 2015 | // Input: $url = URL for which the thumbnail must be found. |
2016 | // $href = if provided, this URL will be followed instead of $url | 2016 | // $href = if provided, this URL will be followed instead of $url |
2017 | // Returns '' if no thumbnail available. | 2017 | // Returns '' if no thumbnail available. |
2018 | function lazyThumbnail($url,$href=false) | 2018 | function lazyThumbnail($url,$href=false) |
@@ -2022,7 +2022,7 @@ function lazyThumbnail($url,$href=false) | |||
2022 | 2022 | ||
2023 | $html='<a href="'.htmlspecialchars($t['href']).'">'; | 2023 | $html='<a href="'.htmlspecialchars($t['href']).'">'; |
2024 | 2024 | ||
2025 | // Lazy image (only loaded by javascript when in the viewport). | 2025 | // Lazy image (only loaded by JavaScript when in the viewport). |
2026 | if (!empty($GLOBALS['disablejquery'])) // (except if jQuery is disabled) | 2026 | if (!empty($GLOBALS['disablejquery'])) // (except if jQuery is disabled) |
2027 | $html.='<img class="lazyimage" src="'.htmlspecialchars($t['src']).'"'; | 2027 | $html.='<img class="lazyimage" src="'.htmlspecialchars($t['src']).'"'; |
2028 | else | 2028 | else |
@@ -2034,7 +2034,7 @@ function lazyThumbnail($url,$href=false) | |||
2034 | if (!empty($t['alt'])) $html.=' alt="'.htmlspecialchars($t['alt']).'"'; | 2034 | if (!empty($t['alt'])) $html.=' alt="'.htmlspecialchars($t['alt']).'"'; |
2035 | $html.='>'; | 2035 | $html.='>'; |
2036 | 2036 | ||
2037 | // No-javascript fallback. | 2037 | // No-JavaScript fallback. |
2038 | $html.='<noscript><img src="'.htmlspecialchars($t['src']).'"'; | 2038 | $html.='<noscript><img src="'.htmlspecialchars($t['src']).'"'; |
2039 | if (!empty($t['width'])) $html.=' width="'.htmlspecialchars($t['width']).'"'; | 2039 | if (!empty($t['width'])) $html.=' width="'.htmlspecialchars($t['width']).'"'; |
2040 | if (!empty($t['height'])) $html.=' height="'.htmlspecialchars($t['height']).'"'; | 2040 | if (!empty($t['height'])) $html.=' height="'.htmlspecialchars($t['height']).'"'; |
@@ -2071,7 +2071,7 @@ function install() | |||
2071 | header('Location: '.indexUrl().'?test_session'); // Redirect to check stored data. | 2071 | header('Location: '.indexUrl().'?test_session'); // Redirect to check stored data. |
2072 | } | 2072 | } |
2073 | if (isset($_GET['test_session'])) | 2073 | if (isset($_GET['test_session'])) |
2074 | { // Step 3: Sessions are ok. Remove test parameter from URL. | 2074 | { // Step 3: Sessions are OK. Remove test parameter from URL. |
2075 | header('Location: '.indexUrl()); | 2075 | header('Location: '.indexUrl()); |
2076 | } | 2076 | } |
2077 | 2077 | ||
@@ -2089,7 +2089,7 @@ function install() | |||
2089 | $GLOBALS['hash'] = sha1($_POST['setpassword'].$GLOBALS['login'].$GLOBALS['salt']); | 2089 | $GLOBALS['hash'] = sha1($_POST['setpassword'].$GLOBALS['login'].$GLOBALS['salt']); |
2090 | $GLOBALS['title'] = (empty($_POST['title']) ? 'Shared links on '.htmlspecialchars(indexUrl()) : $_POST['title'] ); | 2090 | $GLOBALS['title'] = (empty($_POST['title']) ? 'Shared links on '.htmlspecialchars(indexUrl()) : $_POST['title'] ); |
2091 | writeConfig(); | 2091 | writeConfig(); |
2092 | echo '<script language="JavaScript">alert("Shaarli is now configured. Please enter your login/password and start shaaring your links !");document.location=\'?do=login\';</script>'; | 2092 | echo '<script language="JavaScript">alert("Shaarli is now configured. Please enter your login/password and start shaaring your links!");document.location=\'?do=login\';</script>'; |
2093 | exit; | 2093 | exit; |
2094 | } | 2094 | } |
2095 | 2095 | ||
@@ -2104,14 +2104,14 @@ function install() | |||
2104 | exit; | 2104 | exit; |
2105 | } | 2105 | } |
2106 | 2106 | ||
2107 | // Generates the timezone selection form and javascript. | 2107 | // Generates the timezone selection form and JavaScript. |
2108 | // Input: (optional) current timezone (can be 'UTC/UTC'). It will be pre-selected. | 2108 | // Input: (optional) current timezone (can be 'UTC/UTC'). It will be pre-selected. |
2109 | // Output: array(html,js) | 2109 | // Output: array(html,js) |
2110 | // Example: list($htmlform,$js) = templateTZform('Europe/Paris'); // Europe/Paris pre-selected. | 2110 | // Example: list($htmlform,$js) = templateTZform('Europe/Paris'); // Europe/Paris pre-selected. |
2111 | // Returns array('','') if server does not support timezones list. (eg. php 5.1 on free.fr) | 2111 | // Returns array('','') if server does not support timezones list. (e.g. PHP 5.1 on free.fr) |
2112 | function templateTZform($ptz=false) | 2112 | function templateTZform($ptz=false) |
2113 | { | 2113 | { |
2114 | if (function_exists('timezone_identifiers_list')) // because of old php version (5.1) which can be found on free.fr | 2114 | if (function_exists('timezone_identifiers_list')) // because of old PHP version (5.1) which can be found on free.fr |
2115 | { | 2115 | { |
2116 | // Try to split the provided timezone. | 2116 | // Try to split the provided timezone. |
2117 | if ($ptz==false) { $l=timezone_identifiers_list(); $ptz=$l[0]; } | 2117 | if ($ptz==false) { $l=timezone_identifiers_list(); $ptz=$l[0]; } |
@@ -2120,7 +2120,7 @@ function templateTZform($ptz=false) | |||
2120 | // Display config form: | 2120 | // Display config form: |
2121 | $timezone_form = ''; | 2121 | $timezone_form = ''; |
2122 | $timezone_js = ''; | 2122 | $timezone_js = ''; |
2123 | // The list is in the forme "Europe/Paris", "America/Argentina/Buenos_Aires"... | 2123 | // The list is in the form "Europe/Paris", "America/Argentina/Buenos_Aires"... |
2124 | // We split the list in continents/cities. | 2124 | // We split the list in continents/cities. |
2125 | $continents = array(); | 2125 | $continents = array(); |
2126 | $cities = array(); | 2126 | $cities = array(); |
@@ -2158,9 +2158,9 @@ function templateTZform($ptz=false) | |||
2158 | function isTZvalid($continent,$city) | 2158 | function isTZvalid($continent,$city) |
2159 | { | 2159 | { |
2160 | $tz = $continent.'/'.$city; | 2160 | $tz = $continent.'/'.$city; |
2161 | if (function_exists('timezone_identifiers_list')) // because of old php version (5.1) which can be found on free.fr | 2161 | if (function_exists('timezone_identifiers_list')) // because of old PHP version (5.1) which can be found on free.fr |
2162 | { | 2162 | { |
2163 | if (in_array($tz, timezone_identifiers_list())) // it's a valid timezone ? | 2163 | if (in_array($tz, timezone_identifiers_list())) // it's a valid timezone? |
2164 | return true; | 2164 | return true; |
2165 | } | 2165 | } |
2166 | return false; | 2166 | return false; |
@@ -2203,7 +2203,7 @@ if (!function_exists('json_encode')) { | |||
2203 | } | 2203 | } |
2204 | 2204 | ||
2205 | // Webservices (for use with jQuery/jQueryUI) | 2205 | // Webservices (for use with jQuery/jQueryUI) |
2206 | // eg. index.php?ws=tags&term=minecr | 2206 | // e.g. index.php?ws=tags&term=minecr |
2207 | function processWS() | 2207 | function processWS() |
2208 | { | 2208 | { |
2209 | if (empty($_GET['ws']) || empty($_GET['term'])) return; | 2209 | if (empty($_GET['ws']) || empty($_GET['term'])) return; |
@@ -2211,7 +2211,7 @@ function processWS() | |||
2211 | $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in). | 2211 | $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in). |
2212 | header('Content-Type: application/json; charset=utf-8'); | 2212 | header('Content-Type: application/json; charset=utf-8'); |
2213 | 2213 | ||
2214 | // Search in tags (case insentitive, cumulative search) | 2214 | // Search in tags (case insensitive, cumulative search) |
2215 | if ($_GET['ws']=='tags') | 2215 | if ($_GET['ws']=='tags') |
2216 | { | 2216 | { |
2217 | $tags=explode(' ',str_replace(',',' ',$term)); $last = array_pop($tags); // Get the last term ("a b c d" ==> "a b c", "d") | 2217 | $tags=explode(' ',str_replace(',',' ',$term)); $last = array_pop($tags); // Get the last term ("a b c d" ==> "a b c", "d") |
@@ -2227,7 +2227,7 @@ function processWS() | |||
2227 | exit; | 2227 | exit; |
2228 | } | 2228 | } |
2229 | 2229 | ||
2230 | // Search a single tag (case sentitive, single tag search) | 2230 | // Search a single tag (case sensitive, single tag search) |
2231 | if ($_GET['ws']=='singletag') | 2231 | if ($_GET['ws']=='singletag') |
2232 | { | 2232 | { |
2233 | /* To speed up things, we store list of tags in session */ | 2233 | /* To speed up things, we store list of tags in session */ |
@@ -2243,7 +2243,7 @@ function processWS() | |||
2243 | 2243 | ||
2244 | // Re-write configuration file according to globals. | 2244 | // Re-write configuration file according to globals. |
2245 | // Requires some $GLOBALS to be set (login,hash,salt,title). | 2245 | // Requires some $GLOBALS to be set (login,hash,salt,title). |
2246 | // If the config file cannot be saved, an error message is dislayed and the user is redirected to "Tools" menu. | 2246 | // If the config file cannot be saved, an error message is displayed and the user is redirected to "Tools" menu. |
2247 | // (otherwise, the function simply returns.) | 2247 | // (otherwise, the function simply returns.) |
2248 | function writeConfig() | 2248 | function writeConfig() |
2249 | { | 2249 | { |
@@ -2263,12 +2263,12 @@ function writeConfig() | |||
2263 | } | 2263 | } |
2264 | } | 2264 | } |
2265 | 2265 | ||
2266 | /* Because some f*cking services like Flickr require an extra HTTP request to get the thumbnail URL, | 2266 | /* Because some f*cking services like flickr require an extra HTTP request to get the thumbnail URL, |
2267 | I have deported the thumbnail URL code generation here, otherwise this would slow down page generation. | 2267 | I have deported the thumbnail URL code generation here, otherwise this would slow down page generation. |
2268 | The following function takes the URL a link (eg. a flickr page) and return the proper thumbnail. | 2268 | The following function takes the URL a link (e.g. a flickr page) and return the proper thumbnail. |
2269 | This function is called by passing the url: | 2269 | This function is called by passing the URL: |
2270 | http://mywebsite.com/shaarli/?do=genthumbnail&hmac=[HMAC]&url=[URL] | 2270 | http://mywebsite.com/shaarli/?do=genthumbnail&hmac=[HMAC]&url=[URL] |
2271 | [URL] is the URL of the link (eg. a flickr page) | 2271 | [URL] is the URL of the link (e.g. a flickr page) |
2272 | [HMAC] is the signature for the [URL] (so that these URL cannot be forged). | 2272 | [HMAC] is the signature for the [URL] (so that these URL cannot be forged). |
2273 | The function below will fetch the image from the webservice and store it in the cache. | 2273 | The function below will fetch the image from the webservice and store it in the cache. |
2274 | */ | 2274 | */ |
@@ -2276,7 +2276,7 @@ function genThumbnail() | |||
2276 | { | 2276 | { |
2277 | // Make sure the parameters in the URL were generated by us. | 2277 | // Make sure the parameters in the URL were generated by us. |
2278 | $sign = hash_hmac('sha256', $_GET['url'], $GLOBALS['salt']); | 2278 | $sign = hash_hmac('sha256', $_GET['url'], $GLOBALS['salt']); |
2279 | if ($sign!=$_GET['hmac']) die('Naughty boy !'); | 2279 | if ($sign!=$_GET['hmac']) die('Naughty boy!'); |
2280 | 2280 | ||
2281 | // Let's see if we don't already have the image for this URL in the cache. | 2281 | // Let's see if we don't already have the image for this URL in the cache. |
2282 | $thumbname=hash('sha1',$_GET['url']).'.jpg'; | 2282 | $thumbname=hash('sha1',$_GET['url']).'.jpg'; |
@@ -2301,22 +2301,22 @@ function genThumbnail() | |||
2301 | 2301 | ||
2302 | if ($domain=='flickr.com' || endsWith($domain,'.flickr.com')) | 2302 | if ($domain=='flickr.com' || endsWith($domain,'.flickr.com')) |
2303 | { | 2303 | { |
2304 | // Crude replacement to handle new Flickr domain policy (They prefer www. now) | 2304 | // Crude replacement to handle new flickr domain policy (They prefer www. now) |
2305 | $url = str_replace('http://flickr.com/','http://www.flickr.com/',$url); | 2305 | $url = str_replace('http://flickr.com/','http://www.flickr.com/',$url); |
2306 | 2306 | ||
2307 | // Is this a link to an image, or to a flickr page ? | 2307 | // Is this a link to an image, or to a flickr page ? |
2308 | $imageurl=''; | 2308 | $imageurl=''; |
2309 | if (endswith(parse_url($url,PHP_URL_PATH),'.jpg')) | 2309 | if (endswith(parse_url($url,PHP_URL_PATH),'.jpg')) |
2310 | { // This is a direct link to an image. eg. http://farm1.staticflickr.com/5/5921913_ac83ed27bd_o.jpg | 2310 | { // This is a direct link to an image. e.g. http://farm1.staticflickr.com/5/5921913_ac83ed27bd_o.jpg |
2311 | preg_match('!(http://farm\d+\.staticflickr\.com/\d+/\d+_\w+_)\w.jpg!',$url,$matches); | 2311 | preg_match('!(http://farm\d+\.staticflickr\.com/\d+/\d+_\w+_)\w.jpg!',$url,$matches); |
2312 | if (!empty($matches[1])) $imageurl=$matches[1].'m.jpg'; | 2312 | if (!empty($matches[1])) $imageurl=$matches[1].'m.jpg'; |
2313 | } | 2313 | } |
2314 | else // this is a flickr page (html) | 2314 | else // This is a flickr page (html) |
2315 | { | 2315 | { |
2316 | list($httpstatus,$headers,$data) = getHTTP($url,20); // Get the flickr html page. | 2316 | list($httpstatus,$headers,$data) = getHTTP($url,20); // Get the flickr html page. |
2317 | if (strpos($httpstatus,'200 OK')!==false) | 2317 | if (strpos($httpstatus,'200 OK')!==false) |
2318 | { | 2318 | { |
2319 | // Flickr now nicely provides the URL of the thumbnail in each flickr page. | 2319 | // flickr now nicely provides the URL of the thumbnail in each flickr page. |
2320 | preg_match('!<link rel=\"image_src\" href=\"(.+?)\"!',$data,$matches); | 2320 | preg_match('!<link rel=\"image_src\" href=\"(.+?)\"!',$data,$matches); |
2321 | if (!empty($matches[1])) $imageurl=$matches[1]; | 2321 | if (!empty($matches[1])) $imageurl=$matches[1]; |
2322 | 2322 | ||
@@ -2347,7 +2347,7 @@ function genThumbnail() | |||
2347 | elseif ($domain=='vimeo.com' ) | 2347 | elseif ($domain=='vimeo.com' ) |
2348 | { | 2348 | { |
2349 | // This is more complex: we have to perform a HTTP request, then parse the result. | 2349 | // This is more complex: we have to perform a HTTP request, then parse the result. |
2350 | // Maybe we should deport this to javascript ? Example: http://stackoverflow.com/questions/1361149/get-img-thumbnails-from-vimeo/4285098#4285098 | 2350 | // Maybe we should deport this to JavaScript ? Example: http://stackoverflow.com/questions/1361149/get-img-thumbnails-from-vimeo/4285098#4285098 |
2351 | $vid = substr(parse_url($url,PHP_URL_PATH),1); | 2351 | $vid = substr(parse_url($url,PHP_URL_PATH),1); |
2352 | list($httpstatus,$headers,$data) = getHTTP('http://vimeo.com/api/v2/video/'.htmlspecialchars($vid).'.php',5); | 2352 | list($httpstatus,$headers,$data) = getHTTP('http://vimeo.com/api/v2/video/'.htmlspecialchars($vid).'.php',5); |
2353 | if (strpos($httpstatus,'200 OK')!==false) | 2353 | if (strpos($httpstatus,'200 OK')!==false) |
@@ -2483,7 +2483,7 @@ function resizeImage($filepath) | |||
2483 | } | 2483 | } |
2484 | 2484 | ||
2485 | // Invalidate caches when the database is changed or the user logs out. | 2485 | // Invalidate caches when the database is changed or the user logs out. |
2486 | // (eg. tags cache). | 2486 | // (e.g. tags cache). |
2487 | function invalidateCaches() | 2487 | function invalidateCaches() |
2488 | { | 2488 | { |
2489 | unset($_SESSION['tags']); // Purge cache attached to session. | 2489 | unset($_SESSION['tags']); // Purge cache attached to session. |