diff options
-rw-r--r-- | index.php | 78 | ||||
-rw-r--r-- | shaarli.css | 3 |
2 files changed, 67 insertions, 14 deletions
@@ -1,5 +1,5 @@ | |||
1 | <?php | 1 | <?php |
2 | // Shaarli 0.0.15 beta - Shaare your links... | 2 | // Shaarli 0.0.16 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 |
@@ -16,9 +16,12 @@ define('IPBANS_FILENAME',DATADIR.'/ipbans.php'); // File storage for failures an | |||
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 | define('OPEN_SHAARLI',false); // If true, anyone can add/edit/delete links without having to login | 18 | define('OPEN_SHAARLI',false); // If true, anyone can add/edit/delete links without having to login |
19 | define('HIDE_TIMESTAMPS',false); // If true, the moment when links were saved are not shown to users that are not logged in. | ||
19 | 20 | ||
20 | // ----------------------------------------------------------------------------------------------- | 21 | // ----------------------------------------------------------------------------------------------- |
21 | // Program config (touch at your own risks !) | 22 | // Program config (touch at your own risks !) |
23 | define('UPDATECHECK_FILENAME',DATADIR.'/lastupdatecheck.txt'); // For updates check of Shaarli. | ||
24 | define('UPDATECHECK_INTERVAL',86400); // Updates check frequency for Shaarli. 86400 seconds=24 hours | ||
22 | ini_set('max_input_time','60'); // High execution time in case of problematic imports/exports. | 25 | ini_set('max_input_time','60'); // High execution time in case of problematic imports/exports. |
23 | ini_set('memory_limit', '128M'); // Try to set max upload file size and read (May not work on some hosts). | 26 | ini_set('memory_limit', '128M'); // Try to set max upload file size and read (May not work on some hosts). |
24 | ini_set('post_max_size', '16M'); | 27 | ini_set('post_max_size', '16M'); |
@@ -43,7 +46,7 @@ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |||
43 | header("Cache-Control: no-store, no-cache, must-revalidate"); | 46 | header("Cache-Control: no-store, no-cache, must-revalidate"); |
44 | header("Cache-Control: post-check=0, pre-check=0", false); | 47 | header("Cache-Control: post-check=0, pre-check=0", false); |
45 | header("Pragma: no-cache"); | 48 | header("Pragma: no-cache"); |
46 | define('shaarli_version','0.0.15 beta'); | 49 | define('shaarli_version','0.0.16 beta'); |
47 | if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); } | 50 | if (!is_dir(DATADIR)) { mkdir(DATADIR,0705); chmod(DATADIR,0705); } |
48 | if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. | 51 | if (!is_file(DATADIR.'/.htaccess')) { file_put_contents(DATADIR.'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. |
49 | if (!is_file(CONFIG_FILE)) install(); | 52 | if (!is_file(CONFIG_FILE)) install(); |
@@ -52,19 +55,38 @@ autoLocale(); // Sniff browser language and set date format accordingly. | |||
52 | header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling. | 55 | header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling. |
53 | $LINKSDB=false; | 56 | $LINKSDB=false; |
54 | 57 | ||
55 | // Check php version | 58 | // Check php version |
56 | function checkphpversion() | 59 | function checkphpversion() |
57 | { | 60 | { |
58 | $ver=phpversion(); | 61 | if (version_compare(PHP_VERSION, '5.1.0') < 0) |
59 | if (preg_match('!(\d+)\.(\d+)\.(\d+)!',$ver,$matches)) // (because phpversion() sometimes returns strings like "5.2.4-2ubuntu5.2") | ||
60 | { | 62 | { |
61 | list($match,$major,$minor,$release) = $matches; | ||
62 | if ($major>=5 && $minor>=1) return; // 5.1.x or higher is ok. | ||
63 | header('Content-Type: text/plain; charset=utf-8'); | 63 | header('Content-Type: text/plain; charset=utf-8'); |
64 | echo 'Your server supports php '.$ver.'. Shaarli requires at last php 5.1, and thus cannot run. Sorry.'; | 64 | echo 'Your server supports php '.PHP_VERSION.'. Shaarli requires at last php 5.1.0, and thus cannot run. Sorry.'; |
65 | exit; | 65 | exit; |
66 | } | ||
67 | } | ||
68 | |||
69 | // Checks if an update is available for Shaarli. | ||
70 | // (at most once a day, and only for registered user.) | ||
71 | // Output: '' = no new version. | ||
72 | // other= the available version. | ||
73 | function checkUpdate() | ||
74 | { | ||
75 | if (!isLoggedIn()) return ''; // Do not check versions for visitors. | ||
76 | |||
77 | // Get latest version number at most once a day. | ||
78 | if (!is_file(UPDATECHECK_FILENAME) || (filemtime(UPDATECHECK_FILENAME)<time()-(UPDATECHECK_INTERVAL))) | ||
79 | { | ||
80 | $version=shaarli_version; | ||
81 | list($httpstatus,$headers,$data) = getHTTP('http://sebsauvage.net/files/shaarli_version.txt',2); | ||
82 | if (strpos($httpstatus,'200 OK')) $version=$data; | ||
83 | // If failed, nevermind. We don't want to bother the user with that. | ||
84 | file_put_contents(UPDATECHECK_FILENAME,$version); // touch file date | ||
66 | } | 85 | } |
67 | // if cannot check php version... well, at your own risks. | 86 | // Compare versions: |
87 | $newestversion=file_get_contents(UPDATECHECK_FILENAME); | ||
88 | if ($newestversion!=shaarli_version) return $newestversion; | ||
89 | return ''; | ||
68 | } | 90 | } |
69 | 91 | ||
70 | // ----------------------------------------------------------------------------------------------- | 92 | // ----------------------------------------------------------------------------------------------- |
@@ -554,7 +576,8 @@ function showRSS() | |||
554 | { | 576 | { |
555 | $link = $linksToDisplay[$keys[$i]]; | 577 | $link = $linksToDisplay[$keys[$i]]; |
556 | $rfc822date = linkdate2rfc822($link['linkdate']); | 578 | $rfc822date = linkdate2rfc822($link['linkdate']); |
557 | echo '<item><title>'.htmlspecialchars($link['title']).'</title><guid>'.htmlspecialchars($link['url']).'</guid><link>'.htmlspecialchars($link['url']).'</link><pubDate>'.htmlspecialchars($rfc822date).'</pubDate>'; | 579 | echo '<item><title>'.htmlspecialchars($link['title']).'</title><guid>'.htmlspecialchars($link['url']).'</guid><link>'.htmlspecialchars($link['url']).'</link>'; |
580 | if (!HIDE_TIMESTAMPS || isLoggedIn()) echo '<pubDate>'.htmlspecialchars($rfc822date).'</pubDate>'; | ||
558 | echo '<description><![CDATA['.htmlspecialchars($link['description']).']]></description></item>'."\n"; | 581 | echo '<description><![CDATA['.htmlspecialchars($link['description']).']]></description></item>'."\n"; |
559 | $i++; | 582 | $i++; |
560 | } | 583 | } |
@@ -598,7 +621,29 @@ function renderPage() | |||
598 | logout(); | 621 | logout(); |
599 | header('Location: ?'); | 622 | header('Location: ?'); |
600 | exit; | 623 | exit; |
601 | } | 624 | } |
625 | |||
626 | // -------- Tag cloud | ||
627 | if (startswith($_SERVER["QUERY_STRING"],'do=tagcloud')) | ||
628 | { | ||
629 | $tags= $LINKSDB->allTags(); | ||
630 | // We sort tags alphabetically, when choose a font size according to count. | ||
631 | // First, find max value. | ||
632 | $maxcount=0; foreach($tags as $key=>$value) $maxcount=max($maxcount,$value); | ||
633 | ksort($tags); | ||
634 | $cloud=''; | ||
635 | foreach($tags as $key=>$value) | ||
636 | { | ||
637 | $size = max(40*$value/$maxcount,8); // Minimum size 8. | ||
638 | $colorvalue = 128-ceil(127*$value/$maxcount); | ||
639 | $color='rgb('.$colorvalue.','.$colorvalue.','.$colorvalue.')'; | ||
640 | $cloud.= '<span style="color:#99f; font-size:9pt; padding-left:5px; padding-right:2px;">'.$value.'</span><a href="?searchtags='.htmlspecialchars($key).'" style="font-size:'.$size.'pt; font-weight:bold; color:'.$color.';">'.htmlspecialchars($key).'</a> '; | ||
641 | } | ||
642 | $cloud='<div id="cloudtag">'.$cloud.'</div>'; | ||
643 | $data = array('pageheader'=>'','body'=>$cloud,'onload'=>''); | ||
644 | templatePage($data); | ||
645 | exit; | ||
646 | } | ||
602 | 647 | ||
603 | // -------- User clicks on a tag in a link: The tag is added to the list of searched tags (searchtags=...) | 648 | // -------- User clicks on a tag in a link: The tag is added to the list of searched tags (searchtags=...) |
604 | if (isset($_GET['addtag'])) | 649 | if (isset($_GET['addtag'])) |
@@ -1038,7 +1083,8 @@ function templateLinkList() | |||
1038 | 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> '; } | 1083 | 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> '; } |
1039 | $linklist.='<li '.$classprivate.'><span class="linktitle"><a href="'.htmlspecialchars($link['url']).'">'.htmlspecialchars($title).'</a></span>'.$actions.'<br>'; | 1084 | $linklist.='<li '.$classprivate.'><span class="linktitle"><a href="'.htmlspecialchars($link['url']).'">'.htmlspecialchars($title).'</a></span>'.$actions.'<br>'; |
1040 | if ($description!='') $linklist.='<div class="linkdescription">'.nl2br(htmlspecialchars($description)).'</div><br>'; | 1085 | if ($description!='') $linklist.='<div class="linkdescription">'.nl2br(htmlspecialchars($description)).'</div><br>'; |
1041 | $linklist.='<span class="linkdate">'.htmlspecialchars(linkdate2locale($link['linkdate'])).' - </span><span class="linkurl">'.htmlspecialchars($link['url']).'</span><br>'.$tags."</li>\n"; | 1086 | if (!HIDE_TIMESTAMPS || isLoggedIn()) $linklist.='<span class="linkdate">'.htmlspecialchars(linkdate2locale($link['linkdate'])).' - </span>'; |
1087 | $linklist.='<span class="linkurl">'.htmlspecialchars($link['url']).'</span><br>'.$tags."</li>\n"; | ||
1042 | $i++; | 1088 | $i++; |
1043 | } | 1089 | } |
1044 | 1090 | ||
@@ -1071,6 +1117,9 @@ function templatePage($data) | |||
1071 | global $STARTTIME; | 1117 | global $STARTTIME; |
1072 | global $LINKSDB; | 1118 | global $LINKSDB; |
1073 | $shaarli_version = shaarli_version; | 1119 | $shaarli_version = shaarli_version; |
1120 | |||
1121 | $newversion=checkUpdate(); | ||
1122 | if ($newversion!='') $newversion='<div id="newversion"><span style="text-decoration:blink;">●</span> Shaarli '.htmlspecialchars($newversion).' is <a href="http://sebsauvage.net/wiki/doku.php?id=php:shaarli#download">available</a>.</div>'; | ||
1074 | $linkcount = count($LINKSDB); | 1123 | $linkcount = count($LINKSDB); |
1075 | $open=''; | 1124 | $open=''; |
1076 | if (OPEN_SHAARLI) | 1125 | if (OPEN_SHAARLI) |
@@ -1107,10 +1156,11 @@ JS; | |||
1107 | <link type="text/css" rel="stylesheet" href="shaarli.css" /> | 1156 | <link type="text/css" rel="stylesheet" href="shaarli.css" /> |
1108 | {$jsincludes} | 1157 | {$jsincludes} |
1109 | </head> | 1158 | </head> |
1110 | <body {$data['onload']}> | 1159 | <body {$data['onload']}>{$newversion} |
1111 | <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> | 1160 | <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> |
1112 | <b><i>{$open}Shaarli {$shaarli_version}</i></b> - <a href="?">Home</a> {$menu} <a href="{$feedurl}" style="padding-left:30px;">RSS Feed</a> | 1161 | <b><i>{$open}Shaarli {$shaarli_version}</i></b> - <a href="?">Home</a> {$menu} <a href="{$feedurl}" style="padding-left:30px;">RSS Feed</a> |
1113 | {$data['pageheader']} | 1162 | <a href="?do=tagcloud">Tag cloud</a> |
1163 | {$data['pageheader']} | ||
1114 | </div> | 1164 | </div> |
1115 | {$data['body']} | 1165 | {$data['body']} |
1116 | 1166 | ||
diff --git a/shaarli.css b/shaarli.css index e9280684..0b261852 100644 --- a/shaarli.css +++ b/shaarli.css | |||
@@ -57,6 +57,9 @@ border-bottom:1px solid #aaa; border-right:1px solid #aaa; } | |||
57 | .linktag a { color:#777; text-decoration:none; } | 57 | .linktag a { color:#777; text-decoration:none; } |
58 | .buttoneditform { display:inline; } | 58 | .buttoneditform { display:inline; } |
59 | #footer { font-size:8pt; text-align:center; border-top:1px solid #ddd; color: #888; } | 59 | #footer { font-size:8pt; text-align:center; border-top:1px solid #ddd; color: #888; } |
60 | #newversion { background-color: #FFFFA0; color:#000; position:absolute; top:0;right:0; padding:2 7 2 7; font-size:9pt;} | ||
61 | #cloudtag { padding-left:10%; padding-right:10%; } | ||
62 | #cloudtag a { color:black; text-decoration:none; } | ||
60 | 63 | ||
61 | /* Minimal customisation for jQuery widgets */ | 64 | /* Minimal customisation for jQuery widgets */ |
62 | .ui-autocomplete { background-color:#fff; padding-left:5px;} | 65 | .ui-autocomplete { background-color:#fff; padding-left:5px;} |