diff options
author | Seb Sauvage <sebsauvage@sebsauvage.net> | 2011-09-17 00:24:10 +0200 |
---|---|---|
committer | Emilien Klein <emilien@klein.st> | 2011-09-17 00:24:10 +0200 |
commit | 4887ceda72ed74fb13879e0502cbc848f06ac890 (patch) | |
tree | 2720b668cfec0431f8763381cecc15332ed6760a | |
parent | 6d6ea97528474ff1b09c0ace18d322ffab5575ee (diff) | |
download | Shaarli-4887ceda72ed74fb13879e0502cbc848f06ac890.tar.gz Shaarli-4887ceda72ed74fb13879e0502cbc848f06ac890.tar.zst Shaarli-4887ceda72ed74fb13879e0502cbc848f06ac890.zip |
Version 0.0.9 beta
-rw-r--r-- | index.php | 92 |
1 files changed, 59 insertions, 33 deletions
@@ -1,10 +1,10 @@ | |||
1 | <?php | 1 | <?php |
2 | // Shaarli 0.0.8 beta - Shaare your links... | 2 | // Shaarli 0.0.9 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 | 6 | ||
7 | // Requires: php 5.2.x | 7 | // Requires: php 5.1.x |
8 | 8 | ||
9 | // ----------------------------------------------------------------------------------------------- | 9 | // ----------------------------------------------------------------------------------------------- |
10 | // User config: | 10 | // User config: |
@@ -15,11 +15,12 @@ define('LINKS_PER_PAGE',20); // Default links per page. | |||
15 | define('IPBANS_FILENAME',DATADIR.'/ipbans.php'); // File storage for failures and bans. | 15 | define('IPBANS_FILENAME',DATADIR.'/ipbans.php'); // File storage for failures and bans. |
16 | define('BAN_AFTER',4); // Ban IP after this many failures. | 16 | define('BAN_AFTER',4); // Ban IP after this many failures. |
17 | define('BAN_DURATION',1800); // Ban duration for IP address after login failures (in seconds) (1800 sec. = 30 minutes) | 17 | define('BAN_DURATION',1800); // Ban duration for IP address after login failures (in seconds) (1800 sec. = 30 minutes) |
18 | checkphpversion(); | ||
18 | 19 | ||
19 | // ----------------------------------------------------------------------------------------------- | 20 | // ----------------------------------------------------------------------------------------------- |
20 | // Program config (touch at your own risks !) | 21 | // Program config (touch at your own risks !) |
21 | //error_reporting(E_ALL^E_WARNING); // See all error except warnings. | 22 | error_reporting(E_ALL^E_WARNING); // See all error except warnings. |
22 | error_reporting(-1); // See all errors (for debugging only) | 23 | //error_reporting(-1); // See all errors (for debugging only) |
23 | $STARTTIME = microtime(true); // Measure page execution time. | 24 | $STARTTIME = microtime(true); // Measure page execution time. |
24 | ob_start(); | 25 | ob_start(); |
25 | // Prevent caching: (yes, it's ugly) | 26 | // Prevent caching: (yes, it's ugly) |
@@ -27,7 +28,7 @@ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |||
27 | header("Cache-Control: no-store, no-cache, must-revalidate"); | 28 | header("Cache-Control: no-store, no-cache, must-revalidate"); |
28 | header("Cache-Control: post-check=0, pre-check=0", false); | 29 | header("Cache-Control: post-check=0, pre-check=0", false); |
29 | header("Pragma: no-cache"); | 30 | header("Pragma: no-cache"); |
30 | define('shaarli_version','0.0.8 beta'); | 31 | define('shaarli_version','0.0.9 beta'); |
31 | if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); } | 32 | if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); } |
32 | if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. | 33 | if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. |
33 | if (!is_file(CONFIG_FILE)) install(); | 34 | if (!is_file(CONFIG_FILE)) install(); |
@@ -42,6 +43,19 @@ autoLocale(); // Sniff browser language and set date format accordingly. | |||
42 | header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling. | 43 | header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling. |
43 | $LINKSDB=false; | 44 | $LINKSDB=false; |
44 | 45 | ||
46 | // Check php version | ||
47 | function checkphpversion() | ||
48 | { | ||
49 | $ver=phpversion(); | ||
50 | if (preg_match('!(\d+)\.(\d+)\.(\d+)!',$ver,$matches)) // (because phpversion() sometimes returns strings like "5.2.4-2ubuntu5.2") | ||
51 | { | ||
52 | list($match,$major,$minor,$release) = $matches; | ||
53 | if ($major>=5 && $minor>=1) return; // 5.1.x or higher is ok. | ||
54 | die('Your server supports php '.$ver.'. Shaarli requires at last php 5.1, and thus cannot run. Sorry.'); | ||
55 | } | ||
56 | // if cannot check php version... well, at your own risks. | ||
57 | } | ||
58 | |||
45 | // ----------------------------------------------------------------------------------------------- | 59 | // ----------------------------------------------------------------------------------------------- |
46 | // Log to text file | 60 | // Log to text file |
47 | function logm($message) | 61 | function logm($message) |
@@ -285,7 +299,7 @@ function http_parse_headers( $headers ) | |||
285 | /* GET an URL. | 299 | /* GET an URL. |
286 | Input: $url : url to get (http://...) | 300 | Input: $url : url to get (http://...) |
287 | $timeout : Network timeout (will wait this many seconds for an anwser before giving up). | 301 | $timeout : Network timeout (will wait this many seconds for an anwser before giving up). |
288 | Output: An array. [0] = HTTP status message (eg. "HTTP/1.1 200 OK") | 302 | Output: An array. [0] = HTTP status message (eg. "HTTP/1.1 200 OK") or error message |
289 | [1] = associative array containing HTTP response headers (eg. echo getHTTP($url)[1]['Content-Type']) | 303 | [1] = associative array containing HTTP response headers (eg. echo getHTTP($url)[1]['Content-Type']) |
290 | [2] = data | 304 | [2] = data |
291 | Example: list($httpstatus,$headers,$data) = getHTTP('http://sebauvage.net/'); | 305 | Example: list($httpstatus,$headers,$data) = getHTTP('http://sebauvage.net/'); |
@@ -296,14 +310,20 @@ function http_parse_headers( $headers ) | |||
296 | */ | 310 | */ |
297 | function getHTTP($url,$timeout=30) | 311 | function getHTTP($url,$timeout=30) |
298 | { | 312 | { |
299 | //FIXME: trap error correctly (unresolved host, unsupported protocol, etc.) | 313 | try |
300 | $options = array('http'=>array('method'=>'GET','timeout' => $timeout)); // Force network timeout | 314 | { |
301 | $context = stream_context_create($options); | 315 | $options = array('http'=>array('method'=>'GET','timeout' => $timeout)); // Force network timeout |
302 | $data=file_get_contents($url,false,$context,-1, 2000000); // We download at most 2 Mb from source. | 316 | $context = stream_context_create($options); |
303 | if (!$data) { $lasterror=error_get_last(); return array($lasterror['message'],array(),''); } | 317 | $data=file_get_contents($url,false,$context,-1, 2000000); // We download at most 2 Mb from source. |
304 | $httpStatus=$http_response_header[0]; // eg. "HTTP/1.1 200 OK" | 318 | if (!$data) { $lasterror=error_get_last(); return array($lasterror['message'],array(),''); } |
305 | $responseHeaders=http_parse_headers($http_response_header); | 319 | $httpStatus=$http_response_header[0]; // eg. "HTTP/1.1 200 OK" |
306 | return array($httpStatus,$responseHeaders,$data); | 320 | $responseHeaders=http_parse_headers($http_response_header); |
321 | return array($httpStatus,$responseHeaders,$data); | ||
322 | } | ||
323 | catch (Exception $e) // getHTTP *can* fail silentely (we don't care if the title cannot be fetched) | ||
324 | { | ||
325 | return array($e->getMessage(),'',''); | ||
326 | } | ||
307 | } | 327 | } |
308 | 328 | ||
309 | // Extract title from an HTML document. | 329 | // Extract title from an HTML document. |
@@ -546,8 +566,9 @@ function renderPage() | |||
546 | if (isset($_GET['addtag'])) | 566 | if (isset($_GET['addtag'])) |
547 | { | 567 | { |
548 | // Get previous URL (http_referer) and add the tag to the searchtags parameters in query. | 568 | // Get previous URL (http_referer) and add the tag to the searchtags parameters in query. |
569 | if (empty($_SERVER['HTTP_REFERER'])) { header('Location: ?searchtags='.urlencode($_GET['addtag'])); exit; } // In case browser does not send HTTP_REFERER | ||
549 | parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params); | 570 | parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params); |
550 | $params['searchtags'] = (empty($params['searchtags']) ? trim($_GET['addtag']) : trim($params['searchtags'].' '.$_GET['addtag'])); | 571 | $params['searchtags'] = (empty($params['searchtags']) ? trim($_GET['addtag']) : trim($params['searchtags'].' '.urlencode($_GET['addtag']))); |
551 | unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different) | 572 | unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different) |
552 | header('Location: ?'.http_build_query($params)); | 573 | header('Location: ?'.http_build_query($params)); |
553 | exit; | 574 | exit; |
@@ -557,6 +578,7 @@ function renderPage() | |||
557 | if (isset($_GET['removetag'])) | 578 | if (isset($_GET['removetag'])) |
558 | { | 579 | { |
559 | // Get previous URL (http_referer) and remove the tag from the searchtags parameters in query. | 580 | // Get previous URL (http_referer) and remove the tag from the searchtags parameters in query. |
581 | if (empty($_SERVER['HTTP_REFERER'])) { header('Location: ?'); exit; } // In case browser does not send HTTP_REFERER | ||
560 | parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params); | 582 | parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params); |
561 | if (isset($params['searchtags'])) | 583 | if (isset($params['searchtags'])) |
562 | { | 584 | { |
@@ -573,7 +595,7 @@ function renderPage() | |||
573 | if (isset($_GET['linksperpage'])) | 595 | if (isset($_GET['linksperpage'])) |
574 | { | 596 | { |
575 | if (is_numeric($_GET['linksperpage'])) { $_SESSION['LINKS_PER_PAGE']=abs(intval($_GET['linksperpage'])); } | 597 | if (is_numeric($_GET['linksperpage'])) { $_SESSION['LINKS_PER_PAGE']=abs(intval($_GET['linksperpage'])); } |
576 | header('Location: '.$_SERVER['HTTP_REFERER']); | 598 | header('Location: '.(empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER'])); |
577 | exit; | 599 | exit; |
578 | } | 600 | } |
579 | 601 | ||
@@ -644,7 +666,8 @@ HTML; | |||
644 | 666 | ||
645 | // If we are called from the bookmarklet, we must close the popup: | 667 | // If we are called from the bookmarklet, we must close the popup: |
646 | if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script language="JavaScript">self.close();</script>'; exit; } | 668 | if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script language="JavaScript">self.close();</script>'; exit; } |
647 | header('Location: '.$_POST['returnurl']); // After saving the link, redirect to the page the user was on. | 669 | $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); |
670 | header('Location: '.$returnurl); // After saving the link, redirect to the page the user was on. | ||
648 | exit; | 671 | exit; |
649 | } | 672 | } |
650 | 673 | ||
@@ -942,7 +965,7 @@ function templateLinkList() | |||
942 | $tags=''; | 965 | $tags=''; |
943 | if ($link['tags']!='') foreach(explode(' ',$link['tags']) as $tag) { $tags.='<span class="linktag" title="Add tag"><a href="?addtag='.htmlspecialchars($tag).'">'.htmlspecialchars($tag).'</a></span> '; } | 966 | if ($link['tags']!='') foreach(explode(' ',$link['tags']) as $tag) { $tags.='<span class="linktag" title="Add tag"><a href="?addtag='.htmlspecialchars($tag).'">'.htmlspecialchars($tag).'</a></span> '; } |
944 | $linklist.='<li '.$classprivate.'><span class="linktitle"><a href="'.htmlspecialchars($link['url']).'">'.htmlspecialchars($title).'</a></span>'.$actions.'<br>'; | 967 | $linklist.='<li '.$classprivate.'><span class="linktitle"><a href="'.htmlspecialchars($link['url']).'">'.htmlspecialchars($title).'</a></span>'.$actions.'<br>'; |
945 | if ($description!='') $linklist.='<div class="linkdescription">'.str_replace("\n",'<br>',htmlspecialchars($description)).'</div><br>'; | 968 | if ($description!='') $linklist.='<div class="linkdescription">'.nl2br(htmlspecialchars($description)).'</div><br>'; |
946 | $linklist.='<span class="linkdate">'.htmlspecialchars(linkdate2locale($link['linkdate'])).' - </span><span class="linkurl">'.htmlspecialchars($link['url']).'</span><br>'.$tags."</li>\n"; | 969 | $linklist.='<span class="linkdate">'.htmlspecialchars(linkdate2locale($link['linkdate'])).' - </span><span class="linkurl">'.htmlspecialchars($link['url']).'</span><br>'.$tags."</li>\n"; |
947 | $i++; | 970 | $i++; |
948 | } | 971 | } |
@@ -1065,22 +1088,25 @@ HTML; | |||
1065 | // This function should NEVER be called if the file data/config.php exists. | 1088 | // This function should NEVER be called if the file data/config.php exists. |
1066 | function install() | 1089 | function install() |
1067 | { | 1090 | { |
1068 | // FIXME: check version of php ? | 1091 | if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) |
1069 | if (isset($_POST['setlogin']) && isset($_POST['setpassword']) && isset($_POST['settimezone'])) | ||
1070 | { | 1092 | { |
1071 | if ($_POST['setlogin']!='' && $_POST['setpassword']!='' && in_array($_POST['settimezone'],timezone_identifiers_list())) | 1093 | $tz=(empty($_POST['settimezone']) ? 'UTC':$_POST['settimezone']); |
1072 | { // Everything is ok, let's create config file. | 1094 | // Everything is ok, let's create config file. |
1073 | $salt=sha1(uniqid('',true).'_'.mt_rand()); // Salt renders rainbow-tables attacks useless. | 1095 | $salt=sha1(uniqid('',true).'_'.mt_rand()); // Salt renders rainbow-tables attacks useless. |
1074 | $hash = sha1($_POST['setpassword'].$_POST['setlogin'].$salt); | 1096 | $hash = sha1($_POST['setpassword'].$_POST['setlogin'].$salt); |
1075 | $config='<?php $GLOBALS[\'login\']='.var_export($_POST['setlogin'],true).'; $GLOBALS[\'hash\']='.var_export($hash,true).'; $GLOBALS[\'salt\']='.var_export($salt,true).'; date_default_timezone_set('.var_export($_POST['settimezone'],true).'); ?>'; | 1097 | $config='<?php $GLOBALS[\'login\']='.var_export($_POST['setlogin'],true).'; $GLOBALS[\'hash\']='.var_export($hash,true).'; $GLOBALS[\'salt\']='.var_export($salt,true).'; date_default_timezone_set('.var_export($tz,true).'); ?>'; |
1076 | file_put_contents(CONFIG_FILE,$config); | 1098 | file_put_contents(CONFIG_FILE,$config); |
1077 | echo '<script language="JavaScript">alert("Shaarli is now configured. Please enter your login/password and start shaaring your links !");document.location=\'?do=login\';</script>'; | 1099 | echo '<script language="JavaScript">alert("Shaarli is now configured. Please enter your login/password and start shaaring your links !");document.location=\'?do=login\';</script>'; |
1078 | exit; | 1100 | exit; |
1079 | } | 1101 | } |
1080 | } | ||
1081 | // Display config form: | 1102 | // Display config form: |
1082 | $timezones=''; | 1103 | $timezoneselect=''; |
1083 | foreach(timezone_identifiers_list() as $tz) $timezones.='<option value="'.htmlspecialchars($tz).'">'.htmlspecialchars($tz)."</option>\n"; | 1104 | if (function_exists('timezone_identifiers_list')) // because of old php version (5.1) which can be found on free.fr |
1105 | { | ||
1106 | $timezones=''; | ||
1107 | foreach(timezone_identifiers_list() as $tz) $timezones.='<option value="'.htmlspecialchars($tz).'">'.htmlspecialchars($tz)."</option>\n"; | ||
1108 | $timezoneselect='Timezone: <select name="settimezone"><option value="" selected>(please select:)</option>'.$timezones.'</select><br><br>'; | ||
1109 | } | ||
1084 | echo <<<HTML | 1110 | echo <<<HTML |
1085 | <html><title>Shaarli - Configuration</title><style type="text/css"> | 1111 | <html><title>Shaarli - Configuration</title><style type="text/css"> |
1086 | body { font-family: "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif; font-size:10pt; background-color: #ffffff; } | 1112 | body { font-family: "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif; font-size:10pt; background-color: #ffffff; } |
@@ -1089,7 +1115,7 @@ input { border: 1px solid #aaa; background-color:#F0F0FF; padding: 2 5 2 5; -moz | |||
1089 | </style></head><body onload="document.configform.setlogin.focus();"><h1>Shaarli - Shaare your links...</h1>It looks like it's the first time you run Shaarli. Please chose a login/password and a timezone:<br> | 1115 | </style></head><body onload="document.configform.setlogin.focus();"><h1>Shaarli - Shaare your links...</h1>It looks like it's the first time you run Shaarli. Please chose a login/password and a timezone:<br> |
1090 | <form method="POST" action="" name="configform" style="border:1px solid black; padding:10 10 10 10;"> | 1116 | <form method="POST" action="" name="configform" style="border:1px solid black; padding:10 10 10 10;"> |
1091 | Login: <input type="text" name="setlogin"><br><br>Password: <input type="password" name="setpassword"><br><br> | 1117 | Login: <input type="text" name="setlogin"><br><br>Password: <input type="password" name="setpassword"><br><br> |
1092 | Timezone: <select name="settimezone"><option value="0" selected>(please select:)</option>{$timezones}</select><br><br> | 1118 | {$timezoneselect} |
1093 | <input type="submit" name="Save" value="Save config" class="bigbutton"></form></body></html> | 1119 | <input type="submit" name="Save" value="Save config" class="bigbutton"></form></body></html> |
1094 | HTML; | 1120 | HTML; |
1095 | exit; | 1121 | exit; |