Merge remote-tracking branch 'origin/master'

Conflicts:
	tpl/linklist.html
This commit is contained in:
Knah Tsaeb 2013-02-28 14:45:11 +01:00
commit 1eacb94c3e
5 changed files with 110 additions and 29 deletions

View file

@ -1,3 +1,5 @@
![Shaarli logo](http://sebsauvage.net/wiki/lib/exe/fetch.php?media=php:php_shaarli:php_shaarli_logo_inkscape_w600_transp-nq8.png)
Shaarli 0.0.40 beta Shaarli 0.0.40 beta
The personal, minimalist, super-fast, no-database delicious clone. The personal, minimalist, super-fast, no-database delicious clone.

View file

@ -67,10 +67,26 @@ h1 { font-size:20pt; font-weight:bold; font-style:italic; margin-bottom:20px; }
} }
/* Edit/Delete buttons on links */ /* Small tab on the left of each link with edit/delete buttons. */
.button_edit, .button_delete { border-radius:0; box-shadow:none; border-style:none; border-width:0; padding:0; background:none; } .button_edit, .button_delete { border-radius:0; box-shadow:none; border-style:none; border-width:0; padding:0; background:none; }
.button_edit { margin-left:10px; } .linkeditbuttons {
position:absolute;
left:-1px;
padding:4px 2px 2px 2px;
background-color:#f0f0f0;
-webkit-border-radius:0px 6px 6px 0px;
-moz-border-radius:0px 6px 6px 0px;
-o-border-radius:0px 6px 6px 0px;
-ms-border-radius:0px 6px 6px 0px;
border-radius:0px 6px 6px 0px;
-webkit-box-shadow:0px 0px 3px 0px #333333;
-moz-box-shadow:0px 0px 3px 0px #333333;
-o-box-shadow:0px 0px 3px 0px #333333;
-ms-box-shadow:0px 0px 3px 0px #333333;
box-shadow:0px 0px 3px 0px #333333;
}
#pageheader #logo{ #pageheader #logo{
background-image: url('../images/logo.png'); background-image: url('../images/logo.png');
@ -211,6 +227,7 @@ cursor:pointer;
} }
*/ */
#linklist li.private { background: url('../images/private.png') no-repeat 10px center; padding-left:60px; } #linklist li.private { background: url('../images/private.png') no-repeat 10px center; padding-left:60px; }
#linklist li { padding-left:26px; }
.private .linktitle a {color:#969696;} .private .linktitle a {color:#969696;}
.linktitle { font-size:14pt; font-weight:bold; } .linktitle { font-size:14pt; font-weight:bold; }
.linktitle a { text-decoration: none; color:#80AD48; } .linktitle a { text-decoration: none; color:#80AD48; }
@ -445,4 +462,4 @@ div.dailyDate { font-size: 11pt;padding:0px; display:block; }
div.dailyEntryTitle { font-size:16pt; font-weight:bold;} div.dailyEntryTitle { font-size:16pt; font-weight:bold;}
div.dailyEntryDescription { font-size:10pt; } div.dailyEntryDescription { font-size:10pt; }
} }

View file

@ -17,14 +17,18 @@ pre code {
white-space: normal; white-space: normal;
} }
#linklist li {
padding: 4px 10px 10px 20px;
}
.linkInfo { .linkInfo {
float: left; float: left;
width: 17%; width: 220px;
margin-right: 1%;
} }
.linkcontainer { .linkcontainer {
margin-left: 17%; margin-left: 220px;
padding-left:1%;
} }
.linktaglist { .linktaglist {

View file

@ -37,6 +37,14 @@ $cookie=session_get_cookie_params();
$cookiedir = ''; if(dirname($_SERVER['SCRIPT_NAME'])!='/') $cookiedir=dirname($_SERVER["SCRIPT_NAME"]).'/'; $cookiedir = ''; if(dirname($_SERVER['SCRIPT_NAME'])!='/') $cookiedir=dirname($_SERVER["SCRIPT_NAME"]).'/';
session_set_cookie_params($cookie['lifetime'],$cookiedir); // Set default cookie expiration and path. session_set_cookie_params($cookie['lifetime'],$cookiedir); // Set default cookie expiration and path.
// Set session parameters on server side.
define('INACTIVITY_TIMEOUT',3600); // (in seconds). If the user does not access any page within this time, his/her session is considered expired.
ini_set('session.use_cookies', 1); // Use cookies to store session.
ini_set('session.use_only_cookies', 1); // Force cookies for session (phpsessionID forbidden in URL)
ini_set('session.use_trans_sid', false); // Prevent php to use sessionID in URL if cookies are disabled.
session_name('shaarli');
if (session_id() == '') session_start(); // Start session if needed (Some server auto-start sessions).
// PHP Settings // PHP Settings
ini_set('max_input_time','60'); // High execution time in case of problematic imports/exports. ini_set('max_input_time','60'); // High execution time in case of problematic imports/exports.
ini_set('memory_limit', '128M'); // Try to set max upload file size and read (May not work on some hosts). ini_set('memory_limit', '128M'); // Try to set max upload file size and read (May not work on some hosts).
@ -89,7 +97,6 @@ if (empty($GLOBALS['title'])) $GLOBALS['title']='Shared links on '.htmlspecialch
if (empty($GLOBALS['timezone'])) $GLOBALS['timezone']=date_default_timezone_get(); if (empty($GLOBALS['timezone'])) $GLOBALS['timezone']=date_default_timezone_get();
if (empty($GLOBALS['disablesessionprotection'])) $GLOBALS['disablesessionprotection']=false; if (empty($GLOBALS['disablesessionprotection'])) $GLOBALS['disablesessionprotection']=false;
autoLocale(); // Sniff browser language and set date format accordingly. autoLocale(); // Sniff browser language and set date format accordingly.
header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling. header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling.
@ -223,7 +230,7 @@ function smallHash($text)
function text2clickable($url) function text2clickable($url)
{ {
$redir = empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector']; $redir = empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'];
return preg_replace('!(((?:https?|ftp|file)://|apt:)\S+[[:alnum:]]/?)!si','<a href="'.$redir.'$1" rel="nofollow">$1</a>',$url); return preg_replace('!(((?:https?|ftp|file)://|apt:|magnet:)\S+[[:alnum:]]/?)!si','<a href="'.$redir.'$1" rel="nofollow">$1</a>',$url);
} }
// This function inserts &nbsp; where relevant so that multiple spaces are properly displayed in HTML // This function inserts &nbsp; where relevant so that multiple spaces are properly displayed in HTML
@ -265,12 +272,6 @@ function pubsubhub()
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// Session management // Session management
define('INACTIVITY_TIMEOUT',3600); // (in seconds). If the user does not access any page within this time, his/her session is considered expired.
ini_set('session.use_cookies', 1); // Use cookies to store session.
ini_set('session.use_only_cookies', 1); // Force cookies for session (phpsessionID forbidden in URL)
ini_set('session.use_trans_sid', false); // Prevent php to use sessionID in URL if cookies are disabled.
session_name('shaarli');
session_start();
// Returns the IP address of the client (Used to prevent session cookie hijacking.) // Returns the IP address of the client (Used to prevent session cookie hijacking.)
function allIPs() function allIPs()
@ -303,6 +304,8 @@ function check_auth($login,$password)
function isLoggedIn() function isLoggedIn()
{ {
if ($GLOBALS['config']['OPEN_SHAARLI']) return true; if ($GLOBALS['config']['OPEN_SHAARLI']) return true;
if (!isset($GLOBALS['login'])) return false; // Shaarli is not configured yet.
// If session does not exist on server side, or IP address has changed, or session has expired, logout. // If session does not exist on server side, or IP address has changed, or session has expired, logout.
if (empty($_SESSION['uid']) || ($GLOBALS['disablesessionprotection']==false && $_SESSION['ip']!=allIPs()) || time()>=$_SESSION['expires_on']) if (empty($_SESSION['uid']) || ($GLOBALS['disablesessionprotection']==false && $_SESSION['ip']!=allIPs()) || time()>=$_SESSION['expires_on'])
@ -434,7 +437,11 @@ function serverUrl()
// (eg. http://sebsauvage.net/links/) // (eg. http://sebsauvage.net/links/)
function indexUrl() function indexUrl()
{ {
return serverUrl() . ($_SERVER["SCRIPT_NAME"] == '/index.php' ? '/' : $_SERVER["SCRIPT_NAME"]); $scriptname = $_SERVER["SCRIPT_NAME"];
// If the script is named 'index.php', we remove it (for better looking URLs,
// eg. http://mysite.com/shaarli/?abcde instead of http://mysite.com/shaarli/index.php?abcde)
if (endswith($scriptname,'index.php')) $scriptname = substr($scriptname,0,strlen($scriptname)-9);
return serverUrl() . $scriptname;
} }
// Returns the absolute URL of current script, WITH the query. // Returns the absolute URL of current script, WITH the query.
@ -579,7 +586,7 @@ if (!isset($_SESSION['tokens'])) $_SESSION['tokens']=array(); // Token are atta
// Returns a token. // Returns a token.
function getToken() function getToken()
{ {
$rnd = sha1(uniqid('',true).'_'.mt_rand()); // We generate a random string. $rnd = sha1(uniqid('',true).'_'.mt_rand().$GLOBALS['salt']); // We generate a random string.
$_SESSION['tokens'][$rnd]=1; // Store it on the server side. $_SESSION['tokens'][$rnd]=1; // Store it on the server side.
return $rnd; return $rnd;
} }
@ -867,6 +874,10 @@ function showRSS()
{ {
header('Content-Type: application/rss+xml; charset=utf-8'); header('Content-Type: application/rss+xml; charset=utf-8');
// $usepermalink : If true, use permalink instead of final link.
// User just has to add 'permalink' in URL parameters. eg. http://mysite.com/shaarli/?do=rss&permalinks
$usepermalinks = isset($_GET['permalinks']);
// Cache system // Cache system
$query = $_SERVER["QUERY_STRING"]; $query = $_SERVER["QUERY_STRING"];
$cache = new pageCache(pageUrl(),startsWith($query,'do=rss') && !isLoggedIn()); $cache = new pageCache(pageUrl(),startsWith($query,'do=rss') && !isLoggedIn());
@ -901,13 +912,22 @@ function showRSS()
$rfc822date = linkdate2rfc822($link['linkdate']); $rfc822date = linkdate2rfc822($link['linkdate']);
$absurl = htmlspecialchars($link['url']); $absurl = htmlspecialchars($link['url']);
if (startsWith($absurl,'?')) $absurl=$pageaddr.$absurl; // make permalink URL absolute if (startsWith($absurl,'?')) $absurl=$pageaddr.$absurl; // make permalink URL absolute
echo '<item><title>'.htmlspecialchars($link['title']).'</title><guid>'.$guid.'</guid><link>'.$absurl.'</link>'; if ($usepermalinks===true)
echo '<item><title>'.htmlspecialchars($link['title']).'</title><guid>'.$guid.'</guid><link>'.$guid.'</link>';
else
echo '<item><title>'.htmlspecialchars($link['title']).'</title><guid>'.$guid.'</guid><link>'.$absurl.'</link>';
if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) echo '<pubDate>'.htmlspecialchars($rfc822date)."</pubDate>\n"; if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) echo '<pubDate>'.htmlspecialchars($rfc822date)."</pubDate>\n";
if ($link['tags']!='') // Adding tags to each RSS entry (as mentioned in RSS specification) if ($link['tags']!='') // Adding tags to each RSS entry (as mentioned in RSS specification)
{ {
foreach(explode(' ',$link['tags']) as $tag) { echo '<category domain="'.htmlspecialchars($pageaddr).'">'.htmlspecialchars($tag).'</category>'."\n"; } foreach(explode(' ',$link['tags']) as $tag) { echo '<category domain="'.htmlspecialchars($pageaddr).'">'.htmlspecialchars($tag).'</category>'."\n"; }
} }
echo '<description><![CDATA['.nl2br(keepMultipleSpaces(text2clickable(htmlspecialchars($link['description'])))).']]></description>'."\n</item>\n";
// Add permalink in description
$descriptionlink = '(<a href="'.$guid.'">Permalink</a>)';
// If user wants permalinks first, put the final link in description
if ($usepermalinks===true) $descriptionlink = '(<a href="'.$absurl.'">Link</a>)';
if (strlen($link['description'])>0) $descriptionlink = '<br>'.$descriptionlink;
echo '<description><![CDATA['.nl2br(keepMultipleSpaces(text2clickable(htmlspecialchars($link['description'])))).$descriptionlink.']]></description>'."\n</item>\n";
$i++; $i++;
} }
echo '</channel></rss>'; echo '</channel></rss>';
@ -923,6 +943,10 @@ function showATOM()
{ {
header('Content-Type: application/atom+xml; charset=utf-8'); header('Content-Type: application/atom+xml; charset=utf-8');
// $usepermalink : If true, use permalink instead of final link.
// User just has to add 'permalink' in URL parameters. eg. http://mysite.com/shaarli/?do=atom&permalinks
$usepermalinks = isset($_GET['permalinks']);
// Cache system // Cache system
$query = $_SERVER["QUERY_STRING"]; $query = $_SERVER["QUERY_STRING"];
$cache = new pageCache(pageUrl(),startsWith($query,'do=atom') && !isLoggedIn()); $cache = new pageCache(pageUrl(),startsWith($query,'do=atom') && !isLoggedIn());
@ -951,9 +975,20 @@ function showATOM()
$latestDate = max($latestDate,$iso8601date); $latestDate = max($latestDate,$iso8601date);
$absurl = htmlspecialchars($link['url']); $absurl = htmlspecialchars($link['url']);
if (startsWith($absurl,'?')) $absurl=$pageaddr.$absurl; // make permalink URL absolute if (startsWith($absurl,'?')) $absurl=$pageaddr.$absurl; // make permalink URL absolute
$entries.='<entry><title>'.htmlspecialchars($link['title']).'</title><link href="'.$absurl.'" /><id>'.$guid.'</id>'; $entries.='<entry><title>'.htmlspecialchars($link['title']).'</title>';
if ($usepermalinks===true)
$entries.='<link href="'.$guid.'" /><id>'.$guid.'</id>';
else
$entries.='<link href="'.$absurl.'" /><id>'.$guid.'</id>';
if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $entries.='<updated>'.htmlspecialchars($iso8601date).'</updated>'; if (!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()) $entries.='<updated>'.htmlspecialchars($iso8601date).'</updated>';
$entries.='<content type="html">'.htmlspecialchars(nl2br(keepMultipleSpaces(text2clickable(htmlspecialchars($link['description'])))))."</content>\n";
// Add permalink in description
$descriptionlink = htmlspecialchars('(<a href="'.$guid.'">Permalink</a>)');
// If user wants permalinks first, put the final link in description
if ($usepermalinks===true) $descriptionlink = htmlspecialchars('(<a href="'.$absurl.'">Link</a>)');
if (strlen($link['description'])>0) $descriptionlink = '&lt;br&gt;'.$descriptionlink;
$entries.='<content type="html">'.htmlspecialchars(nl2br(keepMultipleSpaces(text2clickable(htmlspecialchars($link['description']))))).$descriptionlink."</content>\n";
if ($link['tags']!='') // Adding tags to each ATOM entry (as mentioned in ATOM specification) if ($link['tags']!='') // Adding tags to each ATOM entry (as mentioned in ATOM specification)
{ {
foreach(explode(' ',$link['tags']) as $tag) foreach(explode(' ',$link['tags']) as $tag)
@ -1413,6 +1448,7 @@ function renderPage()
// If we are called from the bookmarklet, we must close the popup: // If we are called from the bookmarklet, we must close the popup:
if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script language="JavaScript">self.close();</script>'; exit; } if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script language="JavaScript">self.close();</script>'; exit; }
$returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
$returnurl .= '#'.smallHash($linkdate); // Scroll to the link which has been edited.
header('Location: '.$returnurl); // After saving the link, redirect to the page the user was on. header('Location: '.$returnurl); // After saving the link, redirect to the page the user was on.
exit; exit;
} }
@ -1423,6 +1459,7 @@ function renderPage()
// If we are called from the bookmarklet, we must close the popup; // If we are called from the bookmarklet, we must close the popup;
if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script language="JavaScript">self.close();</script>'; exit; } if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script language="JavaScript">self.close();</script>'; exit; }
$returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
$returnurl .= '#'.smallHash($_POST['lf_linkdate']); // Scroll to the link which has been edited.
header('Location: '.$returnurl); // After canceling, redirect to the page the user was on. header('Location: '.$returnurl); // After canceling, redirect to the page the user was on.
exit; exit;
} }
@ -1947,6 +1984,28 @@ function install()
// On free.fr host, make sure the /sessions directory exists, otherwise login will not work. // On free.fr host, make sure the /sessions directory exists, otherwise login will not work.
if (endsWith($_SERVER['SERVER_NAME'],'.free.fr') && !is_dir($_SERVER['DOCUMENT_ROOT'].'/sessions')) mkdir($_SERVER['DOCUMENT_ROOT'].'/sessions',0705); if (endsWith($_SERVER['SERVER_NAME'],'.free.fr') && !is_dir($_SERVER['DOCUMENT_ROOT'].'/sessions')) mkdir($_SERVER['DOCUMENT_ROOT'].'/sessions',0705);
// This part makes sure sessions works correctly.
// (Because on some hosts, session.save_path may not be set correctly,
// or we may not have write access to it.)
if (isset($_GET['test_session']) && ( !isset($_SESSION) || !isset($_SESSION['session_tested']) || $_SESSION['session_tested']!='Working'))
{ // Step 2: Check if data in session is correct.
echo '<pre>Sessions do not seem to work correctly on your server.<br>';
echo 'Make sure the variable session.save_path is set correctly in your php config, and that you have write access to it.<br>';
echo 'It currently points to '.session_save_path().'<br><br><a href="?">Click to try again.</a></pre>';
die;
}
if (!isset($_SESSION['session_tested']))
{ // Step 1 : Try to store data in session and reload page.
$_SESSION['session_tested'] = 'Working'; // Try to set a variable in session.
header('Location: '.indexUrl().'?test_session'); // Redirect to check stored data.
}
if (isset($_GET['test_session']))
{ // Step 3: Sessions are ok. Remove test parameter from URL.
header('Location: '.indexUrl());
}
if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) if (!empty($_POST['setlogin']) && !empty($_POST['setpassword']))
{ {
$tz = 'UTC'; $tz = 'UTC';
@ -2312,6 +2371,7 @@ function resizeImage($filepath)
imagejpeg($im2, $tempname, 90); imagejpeg($im2, $tempname, 90);
imagedestroy($im); imagedestroy($im);
imagedestroy($im2); imagedestroy($im2);
unlink($filepath);
rename($tempname,$filepath); // Overwrite original picture with thumbnail. rename($tempname,$filepath); // Overwrite original picture with thumbnail.
return true; return true;
} }

View file

@ -7,11 +7,11 @@
<div id="pageheader"> <div id="pageheader">
{include="page.header"} {include="page.header"}
<div id="headerform" style="width:100%; white-space:nowrap;"> <div id="headerform" style="width:100%; white-space:nowrap;">
<form method="GET" class="searchform" name="searchform" style="display:inline;"> <form method="get" class="searchform" name="searchform" style="display:inline;">
<input type="text" id="searchform_value" name="searchterm" style="width:30%" value=""> <input type="text" id="searchform_value" name="searchterm" style="width:30%" value="">
<input type="submit" value="Search" class="bigbutton"> <input type="submit" value="Search" class="bigbutton">
</form> </form>
<form method="GET" class="tagfilter" name="tagfilter" style="display:inline;margin-left:24px;"> <form method="get" class="tagfilter" name="tagfilter" style="display:inline;margin-left:24px;">
<input type="text" name="searchtags" id="tagfilter_value" style="width:10%" value=""> <input type="text" name="searchtags" id="tagfilter_value" style="width:10%" value="">
<input type="submit" value="Filter by tag" class="bigbutton"> <input type="submit" value="Filter by tag" class="bigbutton">
</form> </form>
@ -40,7 +40,7 @@
{/if} {/if}
<ul> <ul>
{loop="links"} {loop="links"}
<li{if="$value.class"} class="{$value.class}"{/if}> <li {if="$value.class"} class="{$value.class}"{/if}>
<div class="linkInfo"> <div class="linkInfo">
{if="$value.tags"} {if="$value.tags"}
<div class="linktaglist"> <div class="linktaglist">
@ -52,16 +52,15 @@
{else} {else}
<span class="linkdate" title="Short link here"><a href="?{$value.linkdate|smallHash}">permalink</a> - </span> <span class="linkdate" title="Short link here"><a href="?{$value.linkdate|smallHash}">permalink</a> - </span>
{/if} {/if}
<div style="position:relative;display:inline;"> <span>
<a href="http://invx.com/code/qrcode/?code={$scripturl|urlencode}%3F{$value.linkdate|smallHash}&width=200&height=200" onclick="return false;" class="qrcode"><img src="images/qrcode.png#" width="13" height="13" title="QR-Code"></a> <a href="http://invx.com/code/qrcode/?code={$scripturl|urlencode}%3F{$value.linkdate|smallHash}&width=200&height=200" onclick="return false;" class="qrcode"><img src="images/qrcode.png#" width="13" height="13" title="QR-Code"></a>
</div> </span>
- <span class="linkurl" title="Short link">{$value.url|htmlspecialchars}</span>
{if="$value.via"} {if="$value.via"}
- <span><a href="{$value.via}">@ via {$value.via|getJustDomain}</a></span> <span><a href="{$value.via}">@ via {$value.via|getJustDomain}</a></span>
{/if} {/if}
</div> </div>
<div class="linkcontainer"> <div class="linkcontainer">
<span class="linktitle"><a href="{$redirector}{$value.url}">{$value.title|htmlspecialchars}</a></span> <span class="linktitle"><a href="{$redirector}{$value.url}" name="{$value.linkdate|smallHash}" id="{$value.linkdate|smallHash}">{$value.title|htmlspecialchars}</a></span>
{if="isLoggedIn()"} {if="isLoggedIn()"}
<form method="GET" class="buttoneditform"> <form method="GET" class="buttoneditform">
<input type="hidden" name="edit_link" value="{$value.linkdate}"> <input type="hidden" name="edit_link" value="{$value.linkdate}">
@ -119,7 +118,6 @@
return false; return false;
} }
$('.selectAll').on('click', function() { $('.selectAll').on('click', function() {
selectText($(this).data('id')); selectText($(this).data('id'));
return false; return false;