aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSeb Sauvage <sebsauvage@sebsauvage.net>2011-09-17 00:24:10 +0200
committerEmilien Klein <emilien@klein.st>2011-09-17 00:24:10 +0200
commit4887ceda72ed74fb13879e0502cbc848f06ac890 (patch)
tree2720b668cfec0431f8763381cecc15332ed6760a
parent6d6ea97528474ff1b09c0ace18d322ffab5575ee (diff)
downloadShaarli-4887ceda72ed74fb13879e0502cbc848f06ac890.tar.gz
Shaarli-4887ceda72ed74fb13879e0502cbc848f06ac890.tar.zst
Shaarli-4887ceda72ed74fb13879e0502cbc848f06ac890.zip
Version 0.0.9 beta
-rw-r--r--index.php92
1 files changed, 59 insertions, 33 deletions
diff --git a/index.php b/index.php
index 0b836ae9..d46bd84f 100644
--- a/index.php
+++ b/index.php
@@ -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.
15define('IPBANS_FILENAME',DATADIR.'/ipbans.php'); // File storage for failures and bans. 15define('IPBANS_FILENAME',DATADIR.'/ipbans.php'); // File storage for failures and bans.
16define('BAN_AFTER',4); // Ban IP after this many failures. 16define('BAN_AFTER',4); // Ban IP after this many failures.
17define('BAN_DURATION',1800); // Ban duration for IP address after login failures (in seconds) (1800 sec. = 30 minutes) 17define('BAN_DURATION',1800); // Ban duration for IP address after login failures (in seconds) (1800 sec. = 30 minutes)
18checkphpversion();
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. 22error_reporting(E_ALL^E_WARNING); // See all error except warnings.
22error_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.
24ob_start(); 25ob_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");
27header("Cache-Control: no-store, no-cache, must-revalidate"); 28header("Cache-Control: no-store, no-cache, must-revalidate");
28header("Cache-Control: post-check=0, pre-check=0", false); 29header("Cache-Control: post-check=0, pre-check=0", false);
29header("Pragma: no-cache"); 30header("Pragma: no-cache");
30define('shaarli_version','0.0.8 beta'); 31define('shaarli_version','0.0.9 beta');
31if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); } 32if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); }
32if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. 33if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files.
33if (!is_file(CONFIG_FILE)) install(); 34if (!is_file(CONFIG_FILE)) install();
@@ -42,6 +43,19 @@ autoLocale(); // Sniff browser language and set date format accordingly.
42header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling. 43header('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
47function 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
47function logm($message) 61function 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*/
297function getHTTP($url,$timeout=30) 311function 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.
1066function install() 1089function 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">
1086body { font-family: "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif; font-size:10pt; background-color: #ffffff; } 1112body { 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;">
1091Login: <input type="text" name="setlogin"><br><br>Password: <input type="password" name="setpassword"><br><br> 1117Login: <input type="text" name="setlogin"><br><br>Password: <input type="password" name="setpassword"><br><br>
1092Timezone: <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>
1094HTML; 1120HTML;
1095 exit; 1121 exit;