aboutsummaryrefslogtreecommitdiffhomepage
path: root/index.php
diff options
context:
space:
mode:
Diffstat (limited to 'index.php')
-rw-r--r--index.php96
1 files changed, 85 insertions, 11 deletions
diff --git a/index.php b/index.php
index d1f31609..1423cafb 100644
--- a/index.php
+++ b/index.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2// Shaarli 0.0.11 beta - Shaare your links... 2// Shaarli 0.0.12 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
@@ -15,6 +15,7 @@ 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)
18define('OPEN_SHAARLI',false); // If true, anyone can add/edit/delete links without having to login
18if (get_magic_quotes_gpc()) 19if (get_magic_quotes_gpc())
19{ 20{
20 header('Content-Type: text/plain; charset=utf-8'); 21 header('Content-Type: text/plain; charset=utf-8');
@@ -34,7 +35,7 @@ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
34header("Cache-Control: no-store, no-cache, must-revalidate"); 35header("Cache-Control: no-store, no-cache, must-revalidate");
35header("Cache-Control: post-check=0, pre-check=0", false); 36header("Cache-Control: post-check=0, pre-check=0", false);
36header("Pragma: no-cache"); 37header("Pragma: no-cache");
37define('shaarli_version','0.0.11 beta'); 38define('shaarli_version','0.0.12 beta');
38if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); } 39if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); }
39if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. 40if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files.
40if (!is_file(CONFIG_FILE)) install(); 41if (!is_file(CONFIG_FILE)) install();
@@ -124,6 +125,8 @@ function check_auth($login,$password)
124// Returns true if the user is logged in. 125// Returns true if the user is logged in.
125function isLoggedIn() 126function isLoggedIn()
126{ 127{
128 if (OPEN_SHAARLI) return true;
129
127 // If session does not exist on server side, or IP address has changed, or session has expired, logout. 130 // If session does not exist on server side, or IP address has changed, or session has expired, logout.
128 if (empty($_SESSION['uid']) || $_SESSION['ip']!=allIPs() || time()>=$_SESSION['expires_on']) 131 if (empty($_SESSION['uid']) || $_SESSION['ip']!=allIPs() || time()>=$_SESSION['expires_on'])
129 { 132 {
@@ -504,8 +507,20 @@ class linkdb implements Iterator, Countable, ArrayAccess
504 } 507 }
505 krsort($filtered); 508 krsort($filtered);
506 return $filtered; 509 return $filtered;
510 }
507 511
508 } 512 // Returns the list of all tags
513 // Output: associative array key=tags, value=0
514 public function allTags()
515 {
516 $tags=array();
517 foreach($this->links as $link)
518 foreach(explode(' ',$link['tags']) as $tag)
519 if (!empty($tag)) $tags[$tag]=0;
520 ksort($tags); // FIXME: sort by usage ? That would be better.
521 return $tags;
522 }
523
509} 524}
510 525
511// ------------------------------------------------------------------------------------------ 526// ------------------------------------------------------------------------------------------
@@ -545,6 +560,7 @@ function renderPage()
545 // -------- Display login form. 560 // -------- Display login form.
546 if (startswith($_SERVER["QUERY_STRING"],'do=login')) 561 if (startswith($_SERVER["QUERY_STRING"],'do=login'))
547 { 562 {
563 if (OPEN_SHAARLI) { header('Location: ?'); exit; } // No need to login for open Shaarli
548 if (!ban_canLogin()) 564 if (!ban_canLogin())
549 { 565 {
550 $loginform='<div id="headerform">You have been banned from login after too many failed attempts. Try later.</div>'; 566 $loginform='<div id="headerform">You have been banned from login after too many failed attempts. Try later.</div>';
@@ -907,7 +923,7 @@ function templateEditForm($link,$link_is_new=false)
907 <i>URL</i><br><input type="text" name="lf_url" value="{$url}" style="width:100%"><br> 923 <i>URL</i><br><input type="text" name="lf_url" value="{$url}" style="width:100%"><br>
908 <i>Title</i><br><input type="text" name="lf_title" value="{$title}" style="width:100%"><br> 924 <i>Title</i><br><input type="text" name="lf_title" value="{$title}" style="width:100%"><br>
909 <i>Description</i><br><textarea name="lf_description" rows="4" cols="25" style="width:100%">{$description}</textarea><br> 925 <i>Description</i><br><textarea name="lf_description" rows="4" cols="25" style="width:100%">{$description}</textarea><br>
910 <i>Tags</i><br><input type="text" name="lf_tags" value="{$tags}" style="width:100%"><br> 926 <i>Tags</i><br><input type="text" id="lf_tags" name="lf_tags" value="{$tags}" style="width:100%"><br>
911 <input type="checkbox" {$private} style="margin:7 0 10 0;" name="lf_private">&nbsp;<i>Private</i><br> 927 <input type="checkbox" {$private} style="margin:7 0 10 0;" name="lf_private">&nbsp;<i>Private</i><br>
912 <input type="submit" value="Save" name="save_edit" class="bigbutton" style="margin-left:40px;"> 928 <input type="submit" value="Save" name="save_edit" class="bigbutton" style="margin-left:40px;">
913 <input type="submit" value="Cancel" name="cancel_edit" class="bigbutton" style="margin-left:40px;"> 929 <input type="submit" value="Cancel" name="cancel_edit" class="bigbutton" style="margin-left:40px;">
@@ -1005,18 +1021,40 @@ function templatePage($data)
1005 global $STARTTIME; 1021 global $STARTTIME;
1006 global $LINKSDB; 1022 global $LINKSDB;
1007 $shaarli_version = shaarli_version; 1023 $shaarli_version = shaarli_version;
1008 $linkcount = count($LINKSDB); 1024 $linkcount = count($LINKSDB);
1009 $menu=(isLoggedIn() ? ' <a href="?do=logout">Logout</a> &nbsp;<a href="?do=tools">Tools</a> &nbsp;<a href="?do=addlink"><b>Add link</b></a>' : ' <a href="?do=login">Login</a>'); 1025 $open='';
1026 if (OPEN_SHAARLI)
1027 {
1028 $menu=' <a href="?do=tools">Tools</a> &nbsp;<a href="?do=addlink"><b>Add link</b></a>';
1029 $open='Open ';
1030 }
1031 else
1032 $menu=(isLoggedIn() ? ' <a href="?do=logout">Logout</a> &nbsp;<a href="?do=tools">Tools</a> &nbsp;<a href="?do=addlink"><b>Add link</b></a>' : ' <a href="?do=login">Login</a>');
1010 foreach(array('pageheader','body','onload') as $k) // make sure all required fields exist (put an empty string if not). 1033 foreach(array('pageheader','body','onload') as $k) // make sure all required fields exist (put an empty string if not).
1011 { 1034 {
1012 if (!array_key_exists($k,$data)) $data[$k]=''; 1035 if (!array_key_exists($k,$data)) $data[$k]='';
1013 } 1036 }
1037 $jsincludes=''; $jsincludes_bottom = '';
1038 if (OPEN_SHAARLI || isLoggedIn())
1039 {
1040 $jsincludes='<script language="JavaScript" src="jquery.min.js"></script><script language="JavaScript" src="jquery-ui.custom.min.js"></script>';
1041 $source = serverUrl().$_SERVER['SCRIPT_NAME'].'?ws=tags';
1042 $jsincludes_bottom = <<<JS
1043<script language="JavaScript">
1044$(document).ready(function()
1045{
1046 $('#lf_tags').autocomplete({source:'{$source}',minLength:0});
1047});
1048</script>
1049JS;
1050 }
1014 $feedurl=htmlspecialchars(serverUrl().$_SERVER['SCRIPT_NAME'].'?do=rss'); 1051 $feedurl=htmlspecialchars(serverUrl().$_SERVER['SCRIPT_NAME'].'?do=rss');
1015 echo <<<HTML 1052 echo <<<HTML
1016<html> 1053<html>
1017<head> 1054<head>
1018<title>Shaarli - Let's shaare your links...</title> 1055<title>{$open}Shaarli - Let's shaare your links...</title>
1019<link rel="alternate" type="application/rss+xml" href="{$feedurl}"> 1056<link rel="alternate" type="application/rss+xml" href="{$feedurl}">
1057{$jsincludes}
1020<style type="text/css"> 1058<style type="text/css">
1021<!-- 1059<!--
1022/* CSS Reset from Yahoo to cope with browsers CSS inconsistencies. */ 1060/* CSS Reset from Yahoo to cope with browsers CSS inconsistencies. */
@@ -1072,12 +1110,17 @@ border-bottom:1px solid #aaa; border-right:1px solid #aaa; }
1072.linktag a { color:#777; text-decoration:none; } 1110.linktag a { color:#777; text-decoration:none; }
1073.buttoneditform { display:inline; } 1111.buttoneditform { display:inline; }
1074#footer { font-size:8pt; text-align:center; border-top:1px solid #ddd; color: #888; } 1112#footer { font-size:8pt; text-align:center; border-top:1px solid #ddd; color: #888; }
1113
1114/* Minimal customisation for jQuery widgets */
1115.ui-autocomplete { background-color:#fff; padding-left:5px;}
1116.ui-state-hover { background-color: #604dff; color:#fff; }
1117
1075--> 1118-->
1076</style> 1119</style>
1077</head> 1120</head>
1078<body {$data['onload']}> 1121<body {$data['onload']}>
1079<div id="pageheader"><div style="float:right; font-style:italic; color:#bbb; text-align:right; padding:0 5 0 0;">Shaare your links...<br>{$linkcount} links</div> 1122<div id="pageheader"><div style="float:right; font-style:italic; color:#bbb; text-align:right; padding:0 5 0 0;">Shaare your links...<br>{$linkcount} links</div>
1080 <b><i>Shaarli {$shaarli_version}</i></b> - <a href="?">Home</a>&nbsp;{$menu}&nbsp;<a href="{$feedurl}" style="padding-left:30px;">RSS Feed</a> 1123 <b><i>{$open}Shaarli {$shaarli_version}</i></b> - <a href="?">Home</a>&nbsp;{$menu}&nbsp;<a href="{$feedurl}" style="padding-left:30px;">RSS Feed</a>
1081{$data['pageheader']} 1124{$data['pageheader']}
1082</div> 1125</div>
1083{$data['body']} 1126{$data['body']}
@@ -1086,7 +1129,7 @@ HTML;
1086 $exectime = round(microtime(true)-$STARTTIME,4); 1129 $exectime = round(microtime(true)-$STARTTIME,4);
1087 echo '<div id="footer"><b><a href="http://sebsauvage.net/wiki/doku.php?id=php:shaarli">Shaarli '.shaarli_version.'</a></b> - The personal, minimalist, super-fast, no-database delicious clone. By sebsauvage.net<br>Who gives a shit that this page was generated in '.$exectime.' seconds&nbsp;?</div>'; 1130 echo '<div id="footer"><b><a href="http://sebsauvage.net/wiki/doku.php?id=php:shaarli">Shaarli '.shaarli_version.'</a></b> - The personal, minimalist, super-fast, no-database delicious clone. By sebsauvage.net<br>Who gives a shit that this page was generated in '.$exectime.' seconds&nbsp;?</div>';
1088 if (isLoggedIn()) echo '<script language="JavaScript">function confirmDeleteLink() { var agree=confirm("Are you sure you want to delete this link ?"); if (agree) return true ; else return false ; }</script>'; 1131 if (isLoggedIn()) echo '<script language="JavaScript">function confirmDeleteLink() { var agree=confirm("Are you sure you want to delete this link ?"); if (agree) return true ; else return false ; }</script>';
1089 echo '</body></html>'; 1132 echo $jsincludes_bottom.'</body></html>';
1090} 1133}
1091 1134
1092// ----------------------------------------------------------------------------------------------- 1135// -----------------------------------------------------------------------------------------------
@@ -1101,7 +1144,11 @@ function install()
1101 $salt=sha1(uniqid('',true).'_'.mt_rand()); // Salt renders rainbow-tables attacks useless. 1144 $salt=sha1(uniqid('',true).'_'.mt_rand()); // Salt renders rainbow-tables attacks useless.
1102 $hash = sha1($_POST['setpassword'].$_POST['setlogin'].$salt); 1145 $hash = sha1($_POST['setpassword'].$_POST['setlogin'].$salt);
1103 $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).'); ?>'; 1146 $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).'); ?>';
1104 file_put_contents(CONFIG_FILE,$config); 1147 if (!file_put_contents(CONFIG_FILE,$config) || strcmp(file_get_contents(CONFIG_FILE),$config)!=0)
1148 {
1149 echo '<script language="JavaScript">alert("Shaarli could not create the config file. Please make sure Shaarli has the right to write in the folder is it installed in.");document.location=\'?\';</script>';
1150 exit;
1151 }
1105 echo '<script language="JavaScript">alert("Shaarli is now configured. Please enter your login/password and start shaaring your links !");document.location=\'?do=login\';</script>'; 1152 echo '<script language="JavaScript">alert("Shaarli is now configured. Please enter your login/password and start shaaring your links !");document.location=\'?do=login\';</script>';
1106 exit; 1153 exit;
1107 } 1154 }
@@ -1127,7 +1174,34 @@ HTML;
1127 exit; 1174 exit;
1128} 1175}
1129 1176
1130$LINKSDB=new linkdb(isLoggedIn()); // Read links from database (and filter private links if used it not logged in). 1177// Webservices (for use with jQuery/jQueryUI)
1178// eg. index.php?ws=tags&term=minecr
1179function processWS()
1180{
1181 if (empty($_GET['ws']) || empty($_GET['term'])) return;
1182 $term = $_GET['term'];
1183 global $LINKSDB;
1184 header('Content-Type: application/json; charset=utf-8');
1185
1186 // Search in tags
1187 if ($_GET['ws']=='tags')
1188 {
1189 $tags=explode(' ',$term); $last = array_pop($tags); // Get the last term ("a b c d" ==> "a b c", "d")
1190 $addtags=''; if ($tags) $addtags=implode(' ',$tags).' '; // We will pre-pend previous tags
1191 $suggested=array();
1192 /* To speed up things, we store list of tags in session */
1193 if (empty($_SESSION['tags'])) $_SESSION['tags'] = $LINKSDB->allTags();
1194 foreach($_SESSION['tags'] as $key=>$value)
1195 {
1196 if (startsWith($key,$last,$case=false)) $suggested[$addtags.$key.' ']=0;
1197 }
1198 echo json_encode(array_keys($suggested));
1199 exit;
1200 }
1201}
1202
1203$LINKSDB=new linkdb(isLoggedIn() || OPEN_SHAARLI); // Read links from database (and filter private links if used it not logged in).
1204if (startswith($_SERVER["QUERY_STRING"],'ws=')) { processWS(); exit; } // Webservices (for jQuery/jQueryUI)
1131if (!isset($_SESSION['LINKS_PER_PAGE'])) $_SESSION['LINKS_PER_PAGE']=LINKS_PER_PAGE; 1205if (!isset($_SESSION['LINKS_PER_PAGE'])) $_SESSION['LINKS_PER_PAGE']=LINKS_PER_PAGE;
1132if (startswith($_SERVER["QUERY_STRING"],'do=rss')) { showRSS(); exit; } 1206if (startswith($_SERVER["QUERY_STRING"],'do=rss')) { showRSS(); exit; }
1133renderPage(); 1207renderPage();