Merge commit '1826e383ecf501302974132fd443cf1ca06e10f6' into v0.10
This commit is contained in:
commit
43c77f658a
98 changed files with 1166 additions and 1185 deletions
68
Makefile
68
Makefile
|
@ -2,8 +2,6 @@
|
|||
# Makefile for PHP code analysis & testing, documentation and release generation
|
||||
|
||||
BIN = vendor/bin
|
||||
PHP_SOURCE = index.php application tests plugins
|
||||
PHP_COMMA_SOURCE = index.php,application,tests,plugins
|
||||
|
||||
all: static_analysis_summary check_permissions test
|
||||
|
||||
|
@ -17,14 +15,6 @@ docker_%:
|
|||
rsync -az /shaarli/ ~/shaarli/
|
||||
cd ~/shaarli && make $*
|
||||
|
||||
##
|
||||
# Concise status of the project
|
||||
# These targets are non-blocking: || exit 0
|
||||
##
|
||||
|
||||
static_analysis_summary: code_sniffer_source copy_paste mess_detector_summary
|
||||
@echo
|
||||
|
||||
##
|
||||
# PHP_CodeSniffer
|
||||
# Detects PHP syntax errors
|
||||
|
@ -32,70 +22,26 @@ static_analysis_summary: code_sniffer_source copy_paste mess_detector_summary
|
|||
# - http://pear.php.net/manual/en/package.php.php-codesniffer.usage.php
|
||||
# - http://pear.php.net/manual/en/package.php.php-codesniffer.reporting.php
|
||||
##
|
||||
PHPCS := $(BIN)/phpcs
|
||||
|
||||
code_sniffer: code_sniffer_full
|
||||
code_sniffer:
|
||||
@$(PHPCS)
|
||||
|
||||
### - errors filtered by coding standard: PEAR, PSR1, PSR2, Zend...
|
||||
PHPCS_%:
|
||||
@$(BIN)/phpcs $(PHP_SOURCE) --report-full --report-width=200 --standard=$*
|
||||
@$(PHPCS) --report-full --report-width=200 --standard=$*
|
||||
|
||||
### - errors by Git author
|
||||
code_sniffer_blame:
|
||||
@$(BIN)/phpcs $(PHP_SOURCE) --report-gitblame
|
||||
@$(PHPCS) --report-gitblame
|
||||
|
||||
### - all errors/warnings
|
||||
code_sniffer_full:
|
||||
@$(BIN)/phpcs $(PHP_SOURCE) --report-full --report-width=200
|
||||
@$(PHPCS) --report-full --report-width=200
|
||||
|
||||
### - errors grouped by kind
|
||||
code_sniffer_source:
|
||||
@$(BIN)/phpcs $(PHP_SOURCE) --report-source || exit 0
|
||||
|
||||
##
|
||||
# PHP Copy/Paste Detector
|
||||
# Detects code redundancy
|
||||
# Documentation: https://github.com/sebastianbergmann/phpcpd
|
||||
##
|
||||
|
||||
copy_paste:
|
||||
@echo "-----------------------"
|
||||
@echo "PHP COPY/PASTE DETECTOR"
|
||||
@echo "-----------------------"
|
||||
@$(BIN)/phpcpd $(PHP_SOURCE) || exit 0
|
||||
@echo
|
||||
|
||||
##
|
||||
# PHP Mess Detector
|
||||
# Detects PHP syntax errors, sorted by category
|
||||
# Rules documentation: http://phpmd.org/rules/index.html
|
||||
##
|
||||
MESS_DETECTOR_RULES = cleancode,codesize,controversial,design,naming,unusedcode
|
||||
|
||||
mess_title:
|
||||
@echo "-----------------"
|
||||
@echo "PHP MESS DETECTOR"
|
||||
@echo "-----------------"
|
||||
|
||||
### - all warnings
|
||||
mess_detector: mess_title
|
||||
@$(BIN)/phpmd $(PHP_COMMA_SOURCE) text $(MESS_DETECTOR_RULES) | sed 's_.*\/__'
|
||||
|
||||
### - all warnings + HTML output contains links to PHPMD's documentation
|
||||
mess_detector_html:
|
||||
@$(BIN)/phpmd $(PHP_COMMA_SOURCE) html $(MESS_DETECTOR_RULES) \
|
||||
--reportfile phpmd.html || exit 0
|
||||
|
||||
### - warnings grouped by message, sorted by descending frequency order
|
||||
mess_detector_grouped: mess_title
|
||||
@$(BIN)/phpmd $(PHP_SOURCE) text $(MESS_DETECTOR_RULES) \
|
||||
| cut -f 2 | sort | uniq -c | sort -nr
|
||||
|
||||
### - summary: number of warnings by rule set
|
||||
mess_detector_summary: mess_title
|
||||
@for rule in $$(echo $(MESS_DETECTOR_RULES) | tr ',' ' '); do \
|
||||
warnings=$$($(BIN)/phpmd $(PHP_COMMA_SOURCE) text $$rule | wc -l); \
|
||||
printf "$$warnings\t$$rule\n"; \
|
||||
done;
|
||||
@$(PHPCS) --report-source || exit 0
|
||||
|
||||
##
|
||||
# Checks source file & script permissions
|
||||
|
|
|
@ -9,7 +9,7 @@ _It is designed to be personal (single-user), fast and handy._
|
|||
[![](https://img.shields.io/badge/stable-v0.9.7-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.9.7)
|
||||
[![](https://img.shields.io/travis/shaarli/Shaarli/stable.svg?label=stable)](https://travis-ci.org/shaarli/Shaarli)
|
||||
•
|
||||
[![](https://img.shields.io/badge/latest-v0.10.1-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.10.1)
|
||||
[![](https://img.shields.io/badge/latest-v0.10.2-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.10.2)
|
||||
[![](https://img.shields.io/travis/shaarli/Shaarli/latest.svg?label=latest)](https://travis-ci.org/shaarli/Shaarli)
|
||||
•
|
||||
[![](https://img.shields.io/badge/master-v0.10.x-blue.svg)](https://github.com/shaarli/Shaarli)
|
||||
|
|
|
@ -86,13 +86,14 @@ public static function getVersion($remote, $timeout = 2)
|
|||
*
|
||||
* @return mixed the new version code if available and greater, else 'false'
|
||||
*/
|
||||
public static function checkUpdate($currentVersion,
|
||||
public static function checkUpdate(
|
||||
$currentVersion,
|
||||
$updateFile,
|
||||
$checkInterval,
|
||||
$enableCheck,
|
||||
$isLoggedIn,
|
||||
$branch='stable')
|
||||
{
|
||||
$branch = 'stable'
|
||||
) {
|
||||
// Do not check versions for visitors
|
||||
// Do not check if the user doesn't want to
|
||||
// Do not check with dev version
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Shaarli;
|
||||
|
||||
|
||||
/**
|
||||
* URL-safe Base64 operations
|
||||
*
|
||||
|
@ -17,7 +16,8 @@ class Base64Url
|
|||
*
|
||||
* @return string Base64Url-encoded data
|
||||
*/
|
||||
public static function encode($data) {
|
||||
public static function encode($data)
|
||||
{
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,8 @@ public static function encode($data) {
|
|||
*
|
||||
* @return string Decoded data
|
||||
*/
|
||||
public static function decode($data) {
|
||||
public static function decode($data)
|
||||
{
|
||||
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,7 +163,8 @@ protected function buildItem($link, $pageaddr)
|
|||
$upDate = $link['updated'];
|
||||
$link['up_iso_date'] = $this->getIsoDate($upDate, DateTime::ATOM);
|
||||
} else {
|
||||
$link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM);;
|
||||
$link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM);
|
||||
;
|
||||
}
|
||||
|
||||
// Save the more recent item.
|
||||
|
@ -261,7 +262,6 @@ protected function getIsoDate(DateTime $date, $format = false)
|
|||
}
|
||||
if ($this->feedType == self::$FEED_RSS) {
|
||||
return $date->format(DateTime::RSS);
|
||||
|
||||
}
|
||||
return $date->format(DateTime::ATOM);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
* @param int $timeout network timeout (in seconds)
|
||||
* @param int $maxBytes maximum downloaded bytes (default: 4 MiB)
|
||||
* @param callable|string $curlWriteFunction Optional callback called during the download (cURL CURLOPT_WRITEFUNCTION).
|
||||
* Can be used to add download conditions on the headers (response code, content type, etc.).
|
||||
* Can be used to add download conditions on the
|
||||
* headers (response code, content type, etc.).
|
||||
*
|
||||
* @return array HTTP response headers, downloaded content
|
||||
*
|
||||
|
@ -84,9 +85,10 @@ function get_http_response($url, $timeout = 30, $maxBytes = 4194304, $curlWriteF
|
|||
// Max download size management
|
||||
curl_setopt($ch, CURLOPT_BUFFERSIZE, 1024*16);
|
||||
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
|
||||
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION,
|
||||
function($arg0, $arg1, $arg2, $arg3, $arg4 = 0) use ($maxBytes)
|
||||
{
|
||||
curl_setopt(
|
||||
$ch,
|
||||
CURLOPT_PROGRESSFUNCTION,
|
||||
function ($arg0, $arg1, $arg2, $arg3, $arg4 = 0) use ($maxBytes) {
|
||||
if (version_compare(phpversion(), '5.5', '<')) {
|
||||
// PHP version lower than 5.5
|
||||
// Callback has 4 arguments
|
||||
|
@ -232,7 +234,6 @@ function get_redirected_headers($url, $redirectionLimit = 3)
|
|||
&& !empty($headers)
|
||||
&& (strpos($headers[0], '301') !== false || strpos($headers[0], '302') !== false)
|
||||
&& !empty($headers['Location'])) {
|
||||
|
||||
$redirection = is_array($headers['Location']) ? end($headers['Location']) : $headers['Location'];
|
||||
if ($redirection != $url) {
|
||||
$redirection = getAbsoluteUrl($url, $redirection);
|
||||
|
|
|
@ -125,7 +125,8 @@ protected function initPhpTranslator()
|
|||
$translations = $translations->addFromPoFile('inc/languages/'. $this->language .'/LC_MESSAGES/shaarli.po');
|
||||
$translations->setDomain('shaarli');
|
||||
$this->translator->loadTranslations($translations);
|
||||
} catch (\InvalidArgumentException $e) {}
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
|
||||
// Default extension translation from the current theme
|
||||
$theme = $this->conf->get('theme');
|
||||
|
@ -137,7 +138,8 @@ protected function initPhpTranslator()
|
|||
);
|
||||
$translations->setDomain($theme);
|
||||
$this->translator->loadTranslations($translations);
|
||||
} catch (\InvalidArgumentException $e) {}
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Extension translations (plugins, themes, etc.).
|
||||
|
@ -147,10 +149,13 @@ protected function initPhpTranslator()
|
|||
}
|
||||
|
||||
try {
|
||||
$extension = Translations::fromPoFile($translationPath . $this->language .'/LC_MESSAGES/'. $domain .'.po');
|
||||
$extension = Translations::fromPoFile(
|
||||
$translationPath . $this->language .'/LC_MESSAGES/'. $domain .'.po'
|
||||
);
|
||||
$extension->setDomain($domain);
|
||||
$this->translator->loadTranslations($extension);
|
||||
} catch (\InvalidArgumentException $e) {}
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,8 +107,7 @@ public function __construct(
|
|||
$hidePublicLinks,
|
||||
$redirector = '',
|
||||
$redirectorEncode = true
|
||||
)
|
||||
{
|
||||
) {
|
||||
$this->datastore = $datastore;
|
||||
$this->loggedIn = $isLoggedIn;
|
||||
$this->hidePublicLinks = $hidePublicLinks;
|
||||
|
@ -250,11 +249,14 @@ private function check()
|
|||
'id' => 1,
|
||||
'title'=> t('The personal, minimalist, super-fast, database free, bookmarking service'),
|
||||
'url'=>'https://shaarli.readthedocs.io',
|
||||
'description'=>t('Welcome to Shaarli! This is your first public bookmark. To edit or delete me, you must first login.
|
||||
'description'=>t(
|
||||
'Welcome to Shaarli! This is your first public bookmark. '
|
||||
.'To edit or delete me, you must first login.
|
||||
|
||||
To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page.
|
||||
|
||||
You use the community supported version of the original Shaarli project, by Sebastien Sauvage.'),
|
||||
You use the community supported version of the original Shaarli project, by Sebastien Sauvage.'
|
||||
),
|
||||
'private'=>0,
|
||||
'created'=> new DateTime(),
|
||||
'tags'=>'opensource software'
|
||||
|
@ -317,8 +319,7 @@ private function read()
|
|||
} else {
|
||||
$link['real_url'] .= $link['url'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$link['real_url'] = $link['url'];
|
||||
}
|
||||
|
||||
|
@ -403,7 +404,8 @@ public function filterHash($request)
|
|||
*
|
||||
* @return array list of shaare found.
|
||||
*/
|
||||
public function filterDay($request) {
|
||||
public function filterDay($request)
|
||||
{
|
||||
$linkFilter = new LinkFilter($this->links);
|
||||
return $linkFilter->filter(LinkFilter::$FILTER_DAY, $request);
|
||||
}
|
||||
|
@ -420,8 +422,12 @@ public function filterDay($request) {
|
|||
*
|
||||
* @return array filtered links, all links if no suitable filter was provided.
|
||||
*/
|
||||
public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all', $untaggedonly = false)
|
||||
{
|
||||
public function filterSearch(
|
||||
$filterRequest = array(),
|
||||
$casesensitive = false,
|
||||
$visibility = 'all',
|
||||
$untaggedonly = false
|
||||
) {
|
||||
// Filter link database according to parameters.
|
||||
$searchtags = isset($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : '';
|
||||
$searchterm = isset($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : '';
|
||||
|
@ -492,8 +498,7 @@ public function renameTag($from, $to)
|
|||
$delete = empty($to);
|
||||
// True for case-sensitive tag search.
|
||||
$linksToAlter = $this->filterSearch(['searchtags' => $from], true);
|
||||
foreach($linksToAlter as $key => &$value)
|
||||
{
|
||||
foreach ($linksToAlter as $key => &$value) {
|
||||
$tags = preg_split('/\s+/', trim($value['tags']));
|
||||
if (($pos = array_search($from, $tags)) !== false) {
|
||||
if ($delete) {
|
||||
|
@ -537,6 +542,9 @@ public function reorder($order = 'DESC')
|
|||
$order = $order === 'ASC' ? -1 : 1;
|
||||
// Reorder array by dates.
|
||||
usort($this->links, function ($a, $b) use ($order) {
|
||||
if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) {
|
||||
return $a['sticky'] ? -1 : 1;
|
||||
}
|
||||
return $a['created'] < $b['created'] ? 1 * $order : -1 * $order;
|
||||
});
|
||||
|
||||
|
|
|
@ -205,7 +205,6 @@ private function filterFulltext($searchterms, $visibility = 'all')
|
|||
|
||||
// Iterate over every stored link.
|
||||
foreach ($this->links as $id => $link) {
|
||||
|
||||
// ignore non private links when 'privatonly' is on.
|
||||
if ($visibility !== 'all') {
|
||||
if (! $link['private'] && $visibility === 'private') {
|
||||
|
|
|
@ -201,7 +201,8 @@ function space2nbsp($text)
|
|||
|
||||
* @return string formatted description.
|
||||
*/
|
||||
function format_description($description, $redirector = '', $urlEncode = true, $indexUrl = '') {
|
||||
function format_description($description, $redirector = '', $urlEncode = true, $indexUrl = '')
|
||||
{
|
||||
return nl2br(space2nbsp(hashtag_autolink(text2clickable($description, $redirector, $urlEncode), $indexUrl)));
|
||||
}
|
||||
|
||||
|
|
|
@ -76,14 +76,16 @@ private static function importStatus(
|
|||
$overwriteCount = 0,
|
||||
$skipCount = 0,
|
||||
$duration = 0
|
||||
)
|
||||
{
|
||||
) {
|
||||
$status = sprintf(t('File %s (%d bytes) '), $filename, $filesize);
|
||||
if ($importCount == 0 && $overwriteCount == 0 && $skipCount == 0) {
|
||||
$status .= t('has an unknown file format. Nothing was imported.');
|
||||
} else {
|
||||
$status .= vsprintf(
|
||||
t('was successfully processed in %d seconds: %d links imported, %d links overwritten, %d links skipped.'),
|
||||
t(
|
||||
'was successfully processed in %d seconds: '
|
||||
.'%d links imported, %d links overwritten, %d links skipped.'
|
||||
),
|
||||
[$duration, $importCount, $overwriteCount, $skipCount]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,6 @@ private function initialize()
|
|||
);
|
||||
$this->tpl->assign('newVersion', escape($version));
|
||||
$this->tpl->assign('versionError', '');
|
||||
|
||||
} catch (Exception $exc) {
|
||||
logm($this->conf->get('resource.log'), $_SERVER['REMOTE_ADDR'], $exc->getMessage());
|
||||
$this->tpl->assign('newVersion', '');
|
||||
|
@ -101,7 +100,7 @@ private function initialize()
|
|||
'version_hash',
|
||||
ApplicationUtils::getVersionHash(SHAARLI_VERSION, $this->conf->get('credentials.salt'))
|
||||
);
|
||||
$this->tpl->assign('scripturl', index_url($_SERVER));
|
||||
$this->tpl->assign('index_url', index_url($_SERVER));
|
||||
$visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '';
|
||||
$this->tpl->assign('visibility', $visibility);
|
||||
$this->tpl->assign('untaggedonly', !empty($_SESSION['untaggedonly']));
|
||||
|
|
|
@ -75,8 +75,7 @@ public function load($authorizedPlugins)
|
|||
|
||||
try {
|
||||
$this->loadPlugin($dirs[$index], $plugin);
|
||||
}
|
||||
catch (PluginFileNotFoundException $e) {
|
||||
} catch (PluginFileNotFoundException $e) {
|
||||
error_log($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ class Router
|
|||
|
||||
public static $PAGE_DELETELINK = 'delete_link';
|
||||
|
||||
public static $PAGE_PINLINK = 'pin';
|
||||
|
||||
public static $PAGE_EXPORT = 'export';
|
||||
|
||||
public static $PAGE_IMPORT = 'import';
|
||||
|
@ -146,6 +148,10 @@ public static function findPage($query, $get, $loggedIn)
|
|||
return self::$PAGE_DELETELINK;
|
||||
}
|
||||
|
||||
if (startsWith($query, 'do='. self::$PAGE_PINLINK)) {
|
||||
return self::$PAGE_PINLINK;
|
||||
}
|
||||
|
||||
if (startsWith($query, 'do='. self::$PAGE_EXPORT)) {
|
||||
return self::$PAGE_EXPORT;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,10 @@ public function __construct($conf)
|
|||
$this->conf->set('thumbnails.enabled', false);
|
||||
$this->conf->write(true);
|
||||
// TODO: create a proper error handling system able to catch exceptions...
|
||||
die(t('php-gd extension must be loaded to use thumbnails. Thumbnails are now disabled. Please reload the page.'));
|
||||
die(t(
|
||||
'php-gd extension must be loaded to use thumbnails. '
|
||||
.'Thumbnails are now disabled. Please reload the page.'
|
||||
));
|
||||
}
|
||||
|
||||
$this->wt = new WebThumbnailer();
|
||||
|
|
|
@ -517,6 +517,26 @@ public function updateMethodWebThumbnailer()
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set sticky = false on all links
|
||||
*
|
||||
* @return bool true if the update is successful, false otherwise.
|
||||
*/
|
||||
public function updateMethodSetSticky()
|
||||
{
|
||||
foreach ($this->linkDB as $key => $link) {
|
||||
if (isset($link['sticky'])) {
|
||||
return true;
|
||||
}
|
||||
$link['sticky'] = false;
|
||||
$this->linkDB[$key] = $link;
|
||||
}
|
||||
|
||||
$this->linkDB->save($this->conf->get('resource.page_cache'));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -269,7 +269,8 @@ public function idnToAscii()
|
|||
*
|
||||
* @return string the URL scheme or false if none is provided.
|
||||
*/
|
||||
public function getScheme() {
|
||||
public function getScheme()
|
||||
{
|
||||
if (!isset($this->parts['scheme'])) {
|
||||
return false;
|
||||
}
|
||||
|
@ -281,7 +282,8 @@ public function getScheme() {
|
|||
*
|
||||
* @return string the URL host or false if none is provided.
|
||||
*/
|
||||
public function getHost() {
|
||||
public function getHost()
|
||||
{
|
||||
if (empty($this->parts['host'])) {
|
||||
return false;
|
||||
}
|
||||
|
@ -293,7 +295,8 @@ public function getHost() {
|
|||
*
|
||||
* @return true is HTTP, false otherwise.
|
||||
*/
|
||||
public function isHttp() {
|
||||
public function isHttp()
|
||||
{
|
||||
return strpos(strtolower($this->parts['scheme']), 'http') !== false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -356,9 +356,12 @@ function return_bytes($val)
|
|||
$last = strtolower($val[strlen($val)-1]);
|
||||
$val = intval(substr($val, 0, -1));
|
||||
switch ($last) {
|
||||
case 'g': $val *= 1024;
|
||||
case 'm': $val *= 1024;
|
||||
case 'k': $val *= 1024;
|
||||
case 'g':
|
||||
$val *= 1024;
|
||||
case 'm':
|
||||
$val *= 1024;
|
||||
case 'k':
|
||||
$val *= 1024;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
@ -452,6 +455,7 @@ function alphabetical_sort(&$data, $reverse = false, $byKeys = false)
|
|||
*
|
||||
* @return string Text translated.
|
||||
*/
|
||||
function t($text, $nText = '', $nb = 1, $domain = 'shaarli') {
|
||||
function t($text, $nText = '', $nb = 1, $domain = 'shaarli')
|
||||
{
|
||||
return dn__($domain, $text, $nText, $nb);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,8 @@ protected function checkRequest($request)
|
|||
*
|
||||
* @throws ApiAuthorizationException The token couldn't be validated.
|
||||
*/
|
||||
protected function checkToken($request) {
|
||||
protected function checkToken($request)
|
||||
{
|
||||
if (! $request->hasHeader('Authorization')) {
|
||||
throw new ApiAuthorizationException('JWT token not provided');
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ public function getHistory($request, $response)
|
|||
$offset = $request->getParam('offset');
|
||||
if (empty($offset)) {
|
||||
$offset = 0;
|
||||
}
|
||||
elseif (ctype_digit($offset)) {
|
||||
} elseif (ctype_digit($offset)) {
|
||||
$offset = (int) $offset;
|
||||
} else {
|
||||
throw new ApiBadParametersException('Invalid offset');
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
* Parent Exception related to the API, able to generate a valid Response (ResponseInterface).
|
||||
* Also can include various information in debug mode.
|
||||
*/
|
||||
abstract class ApiException extends \Exception {
|
||||
abstract class ApiException extends \Exception
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Response instance from Slim.
|
||||
|
@ -27,7 +28,7 @@ abstract class ApiException extends \Exception {
|
|||
*
|
||||
* @return Response Final response to give.
|
||||
*/
|
||||
public abstract function getApiResponse();
|
||||
abstract public function getApiResponse();
|
||||
|
||||
/**
|
||||
* Creates ApiResponse body.
|
||||
|
@ -36,7 +37,8 @@ public abstract function getApiResponse();
|
|||
*
|
||||
* @return array|string response body
|
||||
*/
|
||||
protected function getApiResponseBody() {
|
||||
protected function getApiResponseBody()
|
||||
{
|
||||
if ($this->debug !== true) {
|
||||
return $this->getMessage();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Shaarli\Api\Exceptions;
|
||||
|
||||
|
||||
use Slim\Http\Response;
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Shaarli\Api\Exceptions;
|
||||
|
||||
|
||||
use Slim\Http\Response;
|
||||
|
||||
/**
|
||||
|
|
|
@ -104,12 +104,20 @@ public function write($filepath, $conf)
|
|||
|
||||
// Store all $conf['config']
|
||||
foreach ($conf['config'] as $key => $value) {
|
||||
$configStr .= '$GLOBALS[\'config\'][\''. $key .'\'] = '.var_export($conf['config'][$key], true).';'. PHP_EOL;
|
||||
$configStr .= '$GLOBALS[\'config\'][\''
|
||||
. $key
|
||||
.'\'] = '
|
||||
.var_export($conf['config'][$key], true).';'
|
||||
. PHP_EOL;
|
||||
}
|
||||
|
||||
if (isset($conf['plugins'])) {
|
||||
foreach ($conf['plugins'] as $key => $value) {
|
||||
$configStr .= '$GLOBALS[\'plugins\'][\''. $key .'\'] = '.var_export($conf['plugins'][$key], true).';'. PHP_EOL;
|
||||
$configStr .= '$GLOBALS[\'plugins\'][\''
|
||||
. $key
|
||||
.'\'] = '
|
||||
.var_export($conf['plugins'][$key], true).';'
|
||||
. PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,7 @@ function save_plugin_config($formData)
|
|||
// If there is no order, it means a disabled plugin has been enabled.
|
||||
if (isset($formData['order_' . $key])) {
|
||||
$plugins[(int) $formData['order_' . $key]] = $key;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$newEnabledPlugins[] = $key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,6 @@ public function checkLoginState($cookie, $clientIpId)
|
|||
// The user client has a valid stay-signed-in cookie
|
||||
// Session information is updated with the current client information
|
||||
$this->sessionManager->storeLoginInfo($clientIpId);
|
||||
|
||||
} elseif ($this->sessionManager->hasSessionExpired()
|
||||
|| $this->sessionManager->hasClientIpChanged($clientIpId)
|
||||
) {
|
||||
|
|
|
@ -422,12 +422,12 @@ function init(description) {
|
|||
/**
|
||||
* Bulk actions
|
||||
*/
|
||||
const linkCheckboxes = document.querySelectorAll('.delete-checkbox');
|
||||
const linkCheckboxes = document.querySelectorAll('.link-checkbox');
|
||||
const bar = document.getElementById('actions');
|
||||
[...linkCheckboxes].forEach((checkbox) => {
|
||||
checkbox.style.display = 'inline-block';
|
||||
checkbox.addEventListener('click', () => {
|
||||
const linkCheckedCheckboxes = document.querySelectorAll('.delete-checkbox:checked');
|
||||
checkbox.addEventListener('change', () => {
|
||||
const linkCheckedCheckboxes = document.querySelectorAll('.link-checkbox:checked');
|
||||
const count = [...linkCheckedCheckboxes].length;
|
||||
if (count === 0 && bar.classList.contains('open')) {
|
||||
bar.classList.toggle('open');
|
||||
|
@ -444,7 +444,7 @@ function init(description) {
|
|||
event.preventDefault();
|
||||
|
||||
const links = [];
|
||||
const linkCheckedCheckboxes = document.querySelectorAll('.delete-checkbox:checked');
|
||||
const linkCheckedCheckboxes = document.querySelectorAll('.link-checkbox:checked');
|
||||
[...linkCheckedCheckboxes].forEach((checkbox) => {
|
||||
links.push({
|
||||
id: checkbox.value,
|
||||
|
@ -466,6 +466,25 @@ function init(description) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all button
|
||||
*/
|
||||
const selectAllButtons = document.querySelectorAll('.select-all-button');
|
||||
[...selectAllButtons].forEach((selectAllButton) => {
|
||||
selectAllButton.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
const checked = selectAllButton.classList.contains('filter-off');
|
||||
[...selectAllButtons].forEach((selectAllButton2) => {
|
||||
selectAllButton2.classList.toggle('filter-off');
|
||||
selectAllButton2.classList.toggle('filter-on');
|
||||
});
|
||||
[...linkCheckboxes].forEach((linkCheckbox) => {
|
||||
linkCheckbox.checked = checked;
|
||||
linkCheckbox.dispatchEvent(new Event('change'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tag list operations
|
||||
*
|
||||
|
@ -548,7 +567,7 @@ function init(description) {
|
|||
event.preventDefault();
|
||||
const block = findParent(event.target, 'div', { class: 'tag-list-item' });
|
||||
const tag = block.getAttribute('data-tag');
|
||||
const refreshedToken = document.getElementById('token');
|
||||
const refreshedToken = document.getElementById('token').value;
|
||||
|
||||
if (confirm(`Are you sure you want to delete the tag "${tag}"?`)) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
|
|
@ -381,8 +381,6 @@ body,
|
|||
box-shadow: 0 1px 0 $light-shadow, 0 1px 4px $dark-shadow inset;
|
||||
background: $almost-white;
|
||||
padding: 5px 5px 3px 15px;
|
||||
width: 20%;
|
||||
height: 20px;
|
||||
color: $dark-grey;
|
||||
}
|
||||
|
||||
|
@ -742,7 +740,7 @@ body,
|
|||
font-size: 1em;
|
||||
}
|
||||
|
||||
.delete-checkbox {
|
||||
.link-checkbox {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -757,6 +755,14 @@ body,
|
|||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.pin-link {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.pinned-link {
|
||||
color: $blue !important;
|
||||
}
|
||||
|
||||
.linklist-item-description {
|
||||
position: relative;
|
||||
padding: 0 10px;
|
||||
|
@ -850,6 +856,10 @@ body,
|
|||
margin: 0 7px;
|
||||
}
|
||||
|
||||
.ctrl-delete {
|
||||
margin: 0 7px 0 0;
|
||||
}
|
||||
|
||||
// 64em -> lg
|
||||
@media screen and (max-width: 64em) {
|
||||
.linklist-item-infos-url {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
},
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"shaarli/netscape-bookmark-parser": "^2.0",
|
||||
"shaarli/netscape-bookmark-parser": "^2.1",
|
||||
"erusev/parsedown": "^1.6",
|
||||
"slim/slim": "^3.0",
|
||||
"arthurhoaro/web-thumbnailer": "^1.1",
|
||||
|
@ -24,11 +24,9 @@
|
|||
"gettext/gettext": "^4.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpmd/phpmd" : "@stable",
|
||||
"phpunit/phpcov": "*",
|
||||
"phpunit/phpunit": "^5.0",
|
||||
"sebastian/phpcpd": "*",
|
||||
"squizlabs/php_codesniffer": "2.*",
|
||||
"phpunit/phpcov": "*"
|
||||
"squizlabs/php_codesniffer": "2.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
434
composer.lock
generated
434
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "da7a0c081b61d949154c5d2e5370cbab",
|
||||
"content-hash": "3876b34296fedb365517b785af8384de",
|
||||
"packages": [
|
||||
{
|
||||
"name": "arthurhoaro/web-thumbnailer",
|
||||
|
@ -133,16 +133,16 @@
|
|||
},
|
||||
{
|
||||
"name": "gettext/gettext",
|
||||
"version": "v4.6.0",
|
||||
"version": "v4.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/oscarotero/Gettext.git",
|
||||
"reference": "cae84aff39a87e07bd6e5cddb5adb720a0ffa357"
|
||||
"reference": "854ff5f5aaf92d2af7080ba8fc15718b27b5c89a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/oscarotero/Gettext/zipball/cae84aff39a87e07bd6e5cddb5adb720a0ffa357",
|
||||
"reference": "cae84aff39a87e07bd6e5cddb5adb720a0ffa357",
|
||||
"url": "https://api.github.com/repos/oscarotero/Gettext/zipball/854ff5f5aaf92d2af7080ba8fc15718b27b5c89a",
|
||||
"reference": "854ff5f5aaf92d2af7080ba8fc15718b27b5c89a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -191,7 +191,7 @@
|
|||
"po",
|
||||
"translation"
|
||||
],
|
||||
"time": "2018-06-26T16:51:09+00:00"
|
||||
"time": "2018-08-27T15:40:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "gettext/languages",
|
||||
|
@ -593,15 +593,16 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pubsubhubbub/php-publisher.git",
|
||||
"reference": "5008fc529b057251b48f4d17a10fdb20047ea8f5"
|
||||
"reference": "047b0faf6219071527a45942d6fef4dbc6d1d884"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pubsubhubbub/php-publisher/zipball/5008fc529b057251b48f4d17a10fdb20047ea8f5",
|
||||
"reference": "5008fc529b057251b48f4d17a10fdb20047ea8f5",
|
||||
"url": "https://api.github.com/repos/pubsubhubbub/php-publisher/zipball/047b0faf6219071527a45942d6fef4dbc6d1d884",
|
||||
"reference": "047b0faf6219071527a45942d6fef4dbc6d1d884",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"php": "~5.4 || ~7.0"
|
||||
},
|
||||
"type": "library",
|
||||
|
@ -626,30 +627,31 @@
|
|||
"data",
|
||||
"feeds",
|
||||
"publishers",
|
||||
"pubsubhubbub"
|
||||
"pubsubhubbub",
|
||||
"websub"
|
||||
],
|
||||
"time": "2018-05-22T11:56:26+00:00"
|
||||
"time": "2018-10-09T05:20:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "shaarli/netscape-bookmark-parser",
|
||||
"version": "v2.0.5",
|
||||
"version": "v2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/shaarli/netscape-bookmark-parser.git",
|
||||
"reference": "ea6911a0ea3dd372fa7002593c5aef9c15a49315"
|
||||
"reference": "819008ee42c4dd7e45d988176a4a22d6ed689577"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/shaarli/netscape-bookmark-parser/zipball/ea6911a0ea3dd372fa7002593c5aef9c15a49315",
|
||||
"reference": "ea6911a0ea3dd372fa7002593c5aef9c15a49315",
|
||||
"url": "https://api.github.com/repos/shaarli/netscape-bookmark-parser/zipball/819008ee42c4dd7e45d988176a4a22d6ed689577",
|
||||
"reference": "819008ee42c4dd7e45d988176a4a22d6ed689577",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"katzgrau/klogger": "~1.0",
|
||||
"php": ">=5.3.4"
|
||||
"php": ">=5.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.8.*"
|
||||
"phpunit/phpunit": "^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
@ -681,22 +683,22 @@
|
|||
"bookmark",
|
||||
"link",
|
||||
"netscape",
|
||||
"parse"
|
||||
"parser"
|
||||
],
|
||||
"time": "2018-01-30T17:34:48+00:00"
|
||||
"time": "2018-10-06T14:43:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "3.10.0",
|
||||
"version": "3.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim.git",
|
||||
"reference": "d8aabeacc3688b25e2f2dd2db91df91ec6fdd748"
|
||||
"reference": "d378e70431e78ee92ee32ddde61ecc72edf5dc0a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/d8aabeacc3688b25e2f2dd2db91df91ec6fdd748",
|
||||
"reference": "d8aabeacc3688b25e2f2dd2db91df91ec6fdd748",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/d378e70431e78ee92ee32ddde61ecc72edf5dc0a",
|
||||
"reference": "d378e70431e78ee92ee32ddde61ecc72edf5dc0a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -754,7 +756,7 @@
|
|||
"micro",
|
||||
"router"
|
||||
],
|
||||
"time": "2018-04-19T19:29:08+00:00"
|
||||
"time": "2018-09-16T10:54:21+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
@ -857,46 +859,6 @@
|
|||
],
|
||||
"time": "2017-10-19T19:58:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pdepend/pdepend",
|
||||
"version": "2.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pdepend/pdepend.git",
|
||||
"reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pdepend/pdepend/zipball/9daf26d0368d4a12bed1cacae1a9f3a6f0adf239",
|
||||
"reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.7",
|
||||
"symfony/config": "^2.3.0|^3|^4",
|
||||
"symfony/dependency-injection": "^2.3.0|^3|^4",
|
||||
"symfony/filesystem": "^2.3.0|^3|^4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8|^5.7",
|
||||
"squizlabs/php_codesniffer": "^2.0.0"
|
||||
},
|
||||
"bin": [
|
||||
"src/bin/pdepend"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PDepend\\": "src/main/php/PDepend"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Official version of pdepend to be handled with Composer",
|
||||
"time": "2017-12-13T13:21:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
"version": "1.0.1",
|
||||
|
@ -1043,72 +1005,6 @@
|
|||
],
|
||||
"time": "2017-07-14T14:27:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpmd/phpmd",
|
||||
"version": "2.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpmd/phpmd.git",
|
||||
"reference": "4e9924b2c157a3eb64395460fcf56b31badc8374"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpmd/phpmd/zipball/4e9924b2c157a3eb64395460fcf56b31badc8374",
|
||||
"reference": "4e9924b2c157a3eb64395460fcf56b31badc8374",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-xml": "*",
|
||||
"pdepend/pdepend": "^2.5",
|
||||
"php": ">=5.3.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^2.0"
|
||||
},
|
||||
"bin": [
|
||||
"src/bin/phpmd"
|
||||
],
|
||||
"type": "project",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"PHPMD\\": "src/main/php"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Manuel Pichler",
|
||||
"email": "github@manuel-pichler.de",
|
||||
"homepage": "https://github.com/manuelpichler",
|
||||
"role": "Project Founder"
|
||||
},
|
||||
{
|
||||
"name": "Other contributors",
|
||||
"homepage": "https://github.com/phpmd/phpmd/graphs/contributors",
|
||||
"role": "Contributors"
|
||||
},
|
||||
{
|
||||
"name": "Marc Würth",
|
||||
"email": "ravage@bluewin.ch",
|
||||
"homepage": "https://github.com/ravage84",
|
||||
"role": "Project Maintainer"
|
||||
}
|
||||
],
|
||||
"description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.",
|
||||
"homepage": "http://phpmd.org/",
|
||||
"keywords": [
|
||||
"mess detection",
|
||||
"mess detector",
|
||||
"pdepend",
|
||||
"phpmd",
|
||||
"pmd"
|
||||
],
|
||||
"time": "2017-01-20T14:41:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "1.8.0",
|
||||
|
@ -1987,56 +1883,6 @@
|
|||
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
||||
"time": "2017-02-18T15:18:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/phpcpd",
|
||||
"version": "3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpcpd.git",
|
||||
"reference": "dfed51c1288790fc957c9433e2f49ab152e8a564"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/dfed51c1288790fc957c9433e2f49ab152e8a564",
|
||||
"reference": "dfed51c1288790fc957c9433e2f49ab152e8a564",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.6|^7.0",
|
||||
"phpunit/php-timer": "^1.0.6",
|
||||
"sebastian/finder-facade": "^1.1",
|
||||
"sebastian/version": "^1.0|^2.0",
|
||||
"symfony/console": "^2.7|^3.0|^4.0"
|
||||
},
|
||||
"bin": [
|
||||
"phpcpd"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Copy/Paste Detector (CPD) for PHP code.",
|
||||
"homepage": "https://github.com/sebastianbergmann/phpcpd",
|
||||
"time": "2017-11-16T08:49:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/recursion-context",
|
||||
"version": "2.0.0",
|
||||
|
@ -2253,82 +2099,18 @@
|
|||
],
|
||||
"time": "2017-05-22T02:43:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
"version": "v3.4.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/config.git",
|
||||
"reference": "7b08223b7f6abd859651c56bcabf900d1627d085"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/7b08223b7f6abd859651c56bcabf900d1627d085",
|
||||
"reference": "7b08223b7f6abd859651c56bcabf900d1627d085",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"symfony/filesystem": "~2.8|~3.0|~4.0",
|
||||
"symfony/polyfill-ctype": "~1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/dependency-injection": "<3.3",
|
||||
"symfony/finder": "<3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/dependency-injection": "~3.3|~4.0",
|
||||
"symfony/event-dispatcher": "~3.3|~4.0",
|
||||
"symfony/finder": "~3.3|~4.0",
|
||||
"symfony/yaml": "~3.0|~4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/yaml": "To use the yaml reference dumper"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Config\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Config Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T11:19:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v3.4.14",
|
||||
"version": "v3.4.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73"
|
||||
"reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/6b217594552b9323bcdcfc14f8a0ce126e84cd73",
|
||||
"reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b",
|
||||
"reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2384,20 +2166,20 @@
|
|||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T11:19:56+00:00"
|
||||
"time": "2018-10-02T16:33:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/debug",
|
||||
"version": "v3.4.14",
|
||||
"version": "v3.4.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/debug.git",
|
||||
"reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc"
|
||||
"reference": "0a612e9dfbd2ccce03eb174365f31ecdca930ff6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/d5a058ff6ecad26b30c1ba452241306ea34c65cc",
|
||||
"reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/0a612e9dfbd2ccce03eb174365f31ecdca930ff6",
|
||||
"reference": "0a612e9dfbd2ccce03eb174365f31ecdca930ff6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2440,141 +2222,20 @@
|
|||
],
|
||||
"description": "Symfony Debug Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T11:19:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dependency-injection",
|
||||
"version": "v3.4.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dependency-injection.git",
|
||||
"reference": "1c0e679e522591fd744fdf242fec41a43d62b2b1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/1c0e679e522591fd744fdf242fec41a43d62b2b1",
|
||||
"reference": "1c0e679e522591fd744fdf242fec41a43d62b2b1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<3.3.7",
|
||||
"symfony/finder": "<3.3",
|
||||
"symfony/proxy-manager-bridge": "<3.4",
|
||||
"symfony/yaml": "<3.4"
|
||||
},
|
||||
"provide": {
|
||||
"psr/container-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/config": "~3.3|~4.0",
|
||||
"symfony/expression-language": "~2.8|~3.0|~4.0",
|
||||
"symfony/yaml": "~3.4|~4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/config": "",
|
||||
"symfony/expression-language": "For using expressions in service container configuration",
|
||||
"symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required",
|
||||
"symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
|
||||
"symfony/yaml": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\DependencyInjection\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony DependencyInjection Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-29T15:19:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v3.4.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "a59f917e3c5d82332514cb4538387638f5bde2d6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/a59f917e3c5d82332514cb4538387638f5bde2d6",
|
||||
"reference": "a59f917e3c5d82332514cb4538387638f5bde2d6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"symfony/polyfill-ctype": "~1.8"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Filesystem\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T11:19:56+00:00"
|
||||
"time": "2018-10-02T16:33:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v3.4.14",
|
||||
"version": "v3.4.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a"
|
||||
"reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/8a84fcb207451df0013b2c74cbbf1b62d47b999a",
|
||||
"reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/54ba444dddc5bd5708a34bd095ea67c6eb54644d",
|
||||
"reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2610,7 +2271,7 @@
|
|||
],
|
||||
"description": "Symfony Finder Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T11:19:56+00:00"
|
||||
"time": "2018-10-03T08:46:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
|
@ -2731,16 +2392,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v3.4.14",
|
||||
"version": "v3.4.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2"
|
||||
"reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/810af2d35fc72b6cf5c01116806d2b65ccaaf2e2",
|
||||
"reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/640b6c27fed4066d64b64d5903a86043f4a4de7f",
|
||||
"reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2786,7 +2447,7 @@
|
|||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T11:19:56+00:00"
|
||||
"time": "2018-10-02T16:33:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/fdomdocument",
|
||||
|
@ -2882,8 +2543,7 @@
|
|||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"pubsubhubbub/publisher": 20,
|
||||
"phpmd/phpmd": 0
|
||||
"pubsubhubbub/publisher": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
|
|
23
doc/custom_theme/main.html
Normal file
23
doc/custom_theme/main.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{#
|
||||
The entry point for the ReadTheDocs Theme.
|
||||
|
||||
Any theme customisations should override this file to redefine blocks defined in
|
||||
the various templates. The custom theme should only need to define a main.html
|
||||
which `{% extends "base.html" %}` and defines various blocks which will replace
|
||||
the blocks defined in base.html and its included child templates.
|
||||
#}
|
||||
|
||||
{%- block site_meta %}
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
{%- if 'media.readthedocs.org' not in config.extra_css[0] %}
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
{%- endif %}
|
||||
|
||||
{% if page and page.is_homepage %}<meta name="description" content="{{ config.site_description }}">{% endif %}
|
||||
{% if config.site_author %}<meta name="author" content="{{ config.site_author }}">{% endif %}
|
||||
{%- endblock %}
|
|
@ -51,7 +51,7 @@ See [Theming](Theming) for a list of community-contributed themes, and an instal
|
|||
- [Shaarlo](https://github.com/DMeloni/shaarlo) - An aggregator for shaarlis with many features (a very popular running instance among French shaarliers: [shaarli.fr](http://shaarli.fr/))
|
||||
- [Shaarlimages](https://github.com/BoboTiG/shaarlimages) - An image-oriented aggregator for Shaarlis
|
||||
- [mknexen/shaarli-api](https://github.com/mknexen/shaarli-api) - A REST API for Shaarli
|
||||
- [Self dead link](https://github.com/qwertygc/shaarli-dev-code/blob/master/self-dead-link.php) - Detect dead links on shaarli. This version use the database of shaarli. [Another version](https://github.com/qwertygc/shaarli-dev-code/blob/master/dead-link.php), can be used for other shaarli instances (but is more resource consuming).
|
||||
- [Self dead link](https://framagit.org/qwertygc/shaarli-dev-code/blob/master/self-dead-link.php) - Detect dead links on shaarli. This version use the database of shaarli. [Another version](https://framagit.org/qwertygc/shaarli-dev-code/blob/master/dead-link.php), can be used for other shaarli instances (but is more resource consuming).
|
||||
- [Bookmark Archiver](https://github.com/pirate/bookmark-archiver) - Save an archived copy of all websites starred using browser bookmarks/Shaarli/Delicious/Instapaper/Unmark.it/Pocket/Pinboard. Outputs browseable html.
|
||||
|
||||
## Alternatives to Shaarli
|
||||
|
|
|
@ -18,7 +18,7 @@ Version | Status | Shaarli compatibility
|
|||
7.2 | Supported | Yes
|
||||
7.1 | Supported | Yes
|
||||
7.0 | Supported | Yes
|
||||
5.6 | Supported | Yes
|
||||
5.6 | EOL: 2018-12-31 | Yes (up to Shaarli 0.10.x)
|
||||
5.5 | EOL: 2016-07-10 | Yes
|
||||
5.4 | EOL: 2015-09-14 | Yes (up to Shaarli 0.8.x)
|
||||
5.3 | EOL: 2014-08-14 | Yes (up to Shaarli 0.8.x)
|
||||
|
@ -397,6 +397,7 @@ http {
|
|||
```
|
||||
|
||||
## Proxies
|
||||
|
||||
If Shaarli is served behind a proxy (i.e. there is a proxy server between clients and the web server hosting Shaarli), please refer to the proxy server documentation for proper configuration. In particular, you have to ensure that the following server variables are properly set:
|
||||
|
||||
- `X-Forwarded-Proto`
|
||||
|
@ -405,6 +406,12 @@ If Shaarli is served behind a proxy (i.e. there is a proxy server between client
|
|||
|
||||
See also [proxy-related](https://github.com/shaarli/Shaarli/issues?utf8=%E2%9C%93&q=label%3Aproxy+) issues.
|
||||
|
||||
## Robots and crawlers
|
||||
|
||||
Shaarli disallows indexing and crawling of your local documentation pages by search engines, using `<meta name="robots">` HTML tags.
|
||||
Your Shaarli instance and other pages you host may still be indexed by various robots on the public Internet.
|
||||
You may want to setup a robots.txt file or other crawler control mechanism on your server.
|
||||
See [[1]](https://en.wikipedia.org/wiki/Robots_exclusion_standard), [[2]](https://support.google.com/webmasters/answer/6062608?hl=en) and [[3]](https://developers.google.com/search/reference/robots_meta_tag)
|
||||
|
||||
## See also
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ While logged in to your Shaarli, you can add new Shaares in several ways:
|
|||
|
||||
* [+Shaare button](#shaare-button)
|
||||
* [Bookmarklet](#bookmarklet)
|
||||
* [Firefox Share](#firefox-share)
|
||||
* Third-party [apps and browser addons](Community-&-Related-software.md#mobile-apps)
|
||||
* [REST API](https://shaarli.github.io/api-documentation/)
|
||||
|
||||
|
@ -52,22 +51,6 @@ bookmarklet in your browser! The same `New Shaare` dialog as above is displayed.
|
|||
![](images/bookmarklet.png)
|
||||
|
||||
|
||||
### Firefox Share
|
||||
|
||||
Before using Firefox Share, you must first add Shaarli as a sharing provider:
|
||||
|
||||
- Click the `Tools` button in the top bar
|
||||
- Click the `✚Add to Firefox social` button and accept the activation.
|
||||
|
||||
Once this is done, you can share any URL you are visiting by clicking the Firefox
|
||||
_Share_ button ![images/firefoxshare.png](images/firefoxshare.png)
|
||||
|
||||
| Note | Firefox Share is no longer available for Firefox 57 and later versions. |
|
||||
|---------|---------|
|
||||
|
||||
| Note | Your Shaarli instance must be hosted on an HTTPS (SSL/TLS secure connection) enabled server for Firefox Share to work. Firefox Share will not work over plaintext HTTP connections. |
|
||||
|---------|---------|
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## Editing Shaares
|
||||
|
|
BIN
doc/md/images/icon.png
Normal file
BIN
doc/md/images/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
120
doc/md/index.md
120
doc/md/index.md
|
@ -1,25 +1,19 @@
|
|||
# [Shaarli](https://github.com/shaarli/Shaarli/) documentation
|
||||
# <img src="images/icon.png" width="20px" height="20px"> Shaarli
|
||||
|
||||
The personal, minimalist, super-fast, database free, bookmarking service.
|
||||
|
||||
Do you want to share the links you discover?
|
||||
Shaarli is a minimalist link sharing service that you can install on your own server.
|
||||
Shaarli is a minimalist bookmark manager and link sharing service that you can install on your own server.
|
||||
It is designed to be personal (single-user), fast and handy.
|
||||
|
||||
<!-- TODO screenshots -->
|
||||
|
||||
Here you can find some info on how to use, configure, tweak and solve problems with your Shaarli.
|
||||
For general information, read the [README](https://github.com/shaarli/Shaarli/blob/master/README.md).
|
||||
Visit the pages in the sidebar to find information on how to setup, use, configure, tweak and troubleshoot Shaarli.
|
||||
|
||||
If you have any questions or ideas, please join the [chat](https://gitter.im/shaarli/Shaarli) (also reachable via [IRC](https://irc.gitter.im/)), post them in our [general discussion](https://github.com/shaarli/Shaarli/issues/308) or read the current [issues](https://github.com/shaarli/Shaarli/issues).
|
||||
|
||||
If you've found a bug, please create a [new issue](https://github.com/shaarli/Shaarli/issues/new).
|
||||
|
||||
If you would like a feature added to Shaarli, check the issues labeled [`feature`](https://github.com/shaarli/Shaarli/labels/feature), [`enhancement`](https://github.com/shaarli/Shaarli/labels/enhancement), and [`plugin`](https://github.com/shaarli/Shaarli/labels/plugin).
|
||||
|
||||
* [GitHub project page](https://github.com/shaarli/Shaarli)
|
||||
* [Online documentation](https://shaarli.readthedocs.io/) (this page)
|
||||
* [Latest Shaarli releases](https://github.com/shaarli/Shaarli/releases)
|
||||
* [Online documentation](https://shaarli.readthedocs.io/)
|
||||
* [Latest releases](https://github.com/shaarli/Shaarli/releases)
|
||||
* [Changelog](https://github.com/shaarli/Shaarli/blob/master/CHANGELOG.md)
|
||||
|
||||
|
||||
|
@ -30,87 +24,70 @@ It runs the latest development version of Shaarli and is updated/reset daily.
|
|||
|
||||
Login: `demo`; Password: `demo`
|
||||
|
||||
<!-- TODO review everything below this point -->
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
Shaarli can be used:
|
||||
|
||||
- to share, comment and save interesting links and news.
|
||||
- to bookmark useful/frequent personal links (as private links) and share them between computers.
|
||||
- as a minimal blog/microblog/writing platform (no character limit).
|
||||
- as a read-it-later list (for example items tagged `readlater`).
|
||||
- to draft and save articles/posts/ideas.
|
||||
- to keep code snippets.
|
||||
- to keep notes and documentation.
|
||||
- as a shared clipboard/notepad/pastebin between machines.
|
||||
- as a todo list.
|
||||
- to store playlists (e.g. with the `music` or `video` tags).
|
||||
- to share, comment and save interesting links and news
|
||||
- to bookmark useful/frequent links and share them between computers
|
||||
- as a minimal blog/microblog/writing platform
|
||||
- as a read-it-later list
|
||||
- to draft and save articles/posts/ideas
|
||||
- to keep notes, documentation and code snippets
|
||||
- as a shared clipboard/notepad/pastebin between machines
|
||||
- as a todo list
|
||||
- to store media playlists
|
||||
- to keep extracts/comments from webpages that may disappear.
|
||||
- to keep track of ongoing discussions (for example items tagged `discussion`).
|
||||
- [to feed RSS aggregators](http://shaarli.chassegnouf.net/?9Efeiw) (planets) with specific tags.
|
||||
- to feed other social networks, blogs... using RSS feeds and external services (dlvr.it, ifttt.com ...).
|
||||
- to keep track of ongoing discussions
|
||||
- to feed other blogs, aggregators, social networks... using RSS feeds
|
||||
|
||||
### Interface
|
||||
### Edit, view and search your links
|
||||
|
||||
- minimalist design (simple is beautiful)
|
||||
- Minimalist design
|
||||
- FAST
|
||||
- ATOM and RSS feeds
|
||||
- views:
|
||||
- paginated link list (with image and video thumbnails)
|
||||
- tag cloud
|
||||
- picture wall: image and video thumbnails (with lazy loading)
|
||||
- daily: newspaper-like daily digest
|
||||
- daily RSS feed
|
||||
- permalinks for easy reference
|
||||
- links can be public or private
|
||||
- thumbnail generation for images and video services
|
||||
- Customizable link titles and descriptions
|
||||
- Tags to organize your links (features tag autocompletion, renaming, merging and deletion)
|
||||
- Search by tag or using the full-text search
|
||||
- Public and private links (visible only to logged-in users)
|
||||
- Unique permalinks for easy reference
|
||||
- Paginated link list (with image and video thumbnails)
|
||||
- Tag cloud and list views
|
||||
- Picture wall: image and video thumbnails view (with lazy loading)
|
||||
- ATOM and RSS feeds (can also be filtered using tags or text search)
|
||||
- Daily: newspaper-like daily digest (and daily RSS feed)
|
||||
- URL cleanup: automatic removal of `?utm_source=...`, `fb=...`
|
||||
- extensible through [plugins](https://shaarli.readthedocs.io/en/master/Plugins/#plugin-usage)
|
||||
|
||||
### Tag, view and search your links
|
||||
|
||||
- add a custom title and description to archived links
|
||||
- add tags to classify and search links
|
||||
- features tag autocompletion, renaming, merging and deletion
|
||||
- full-text and tag search
|
||||
- Extensible through [plugins](https://shaarli.readthedocs.io/en/master/Plugins/#plugin-usage)
|
||||
|
||||
### Easy setup
|
||||
|
||||
- dead-simple installation: drop the files, open the page
|
||||
- links are stored in a file
|
||||
- compact storage
|
||||
- no database required
|
||||
- easy backup: simply copy the datastore file
|
||||
- import and export links as Netscape bookmarks
|
||||
- Dead-simple installation: drop the files, open the page
|
||||
- Links are stored in a file (no database required, easy backup: simply copy the datastore file)
|
||||
- Import and export links as Netscape bookmarks compatible with most Web browsers
|
||||
|
||||
### Accessibility
|
||||
|
||||
- bookmarlet to share links in one click
|
||||
- support for mobile browsers
|
||||
- degrades gracefully with Javascript disabled
|
||||
- easy page customization through HTML/CSS/RainTPL
|
||||
- Bookmarklet and other tools to share links in one click
|
||||
- Support for mobile browsers
|
||||
- Degrades gracefully with Javascript disabled
|
||||
- Easy page customization through HTML/CSS/RainTPL
|
||||
|
||||
### Security
|
||||
|
||||
- discreet pop-up notification when a new release is available
|
||||
- bruteforce protection on the login form
|
||||
- protected against [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) and session cookie hijacking
|
||||
- Discreet pop-up notification when a new release is available
|
||||
- Bruteforce protection on the login form
|
||||
- Protected against [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) and session cookie hijacking
|
||||
|
||||
<!-- TODO Limitations -->
|
||||
|
||||
### REST API
|
||||
|
||||
Easily extensible by any client using the REST API exposed by Shaarli.
|
||||
|
||||
See the [API documentation](http://shaarli.github.io/api-documentation/).
|
||||
- Easily extensible by any client using the REST API exposed by Shaarli ([API documentation](http://shaarli.github.io/api-documentation/)).
|
||||
|
||||
## About
|
||||
|
||||
### Shaarli community fork
|
||||
|
||||
This friendly fork is maintained by the Shaarli community at https://github.com/shaarli/Shaarli
|
||||
This friendly fork is maintained by the Shaarli community at <https://github.com/shaarli/Shaarli>
|
||||
|
||||
This is a community fork of the original [Shaarli](https://github.com/sebsauvage/Shaarli/) project by [Sébastien Sauvage](http://sebsauvage.net/).
|
||||
|
||||
|
@ -123,16 +100,15 @@ in this repository, and will keep maintaining the project for the foreseeable
|
|||
future, while keeping Shaarli simple and efficient.
|
||||
|
||||
|
||||
### Contributing
|
||||
### Contributing and getting help
|
||||
|
||||
If you'd like to help, please:
|
||||
Feedback is very appreciated!
|
||||
|
||||
- have a look at the open [issues](https://github.com/shaarli/Shaarli/issues)
|
||||
and [pull requests](https://github.com/shaarli/Shaarli/pulls)
|
||||
- feel free to report bugs (feedback is much appreciated)
|
||||
- suggest new features and improvements to both code and [documentation](https://github.com/shaarli/Shaarli/tree/master/doc/md/)
|
||||
- propose solutions to existing problems
|
||||
- submit pull requests :-)
|
||||
- If you have any questions or ideas, please join the [chat](https://gitter.im/shaarli/Shaarli) (also reachable via [IRC](https://irc.gitter.im/)), post them in our [general discussion](https://github.com/shaarli/Shaarli/issues/308) or read the current [issues](https://github.com/shaarli/Shaarli/issues).
|
||||
- Have a look at the open [issues](https://github.com/shaarli/Shaarli/issues) and [pull requests](https://github.com/shaarli/Shaarli/pulls)
|
||||
- If you would like a feature added to Shaarli, check the issues labeled [`feature`](https://github.com/shaarli/Shaarli/labels/feature), [`enhancement`](https://github.com/shaarli/Shaarli/labels/enhancement), and [`plugin`](https://github.com/shaarli/Shaarli/labels/plugin).
|
||||
- If you've found a bug, please create a [new issue](https://github.com/shaarli/Shaarli/issues/new).
|
||||
- Feel free to propose solutions to existing problems, help us improve the documentation and translations, and submit pull requests :-)
|
||||
|
||||
|
||||
### License
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Shaarli\n"
|
||||
"POT-Creation-Date: 2018-07-17 13:04+0200\n"
|
||||
"PO-Revision-Date: 2018-07-17 13:07+0200\n"
|
||||
"POT-Creation-Date: 2018-10-06 13:08+0200\n"
|
||||
"PO-Revision-Date: 2018-10-06 13:08+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Shaarli\n"
|
||||
"Language: fr_FR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.9\n"
|
||||
"X-Generator: Poedit 2.1.1\n"
|
||||
"X-Poedit-Basepath: ../../../..\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
|
@ -98,17 +98,15 @@ msgstr "Vous devez utiliser un entier comme clé."
|
|||
|
||||
#: application/LinkDB.php:145
|
||||
msgid "Array offset and link ID must be equal."
|
||||
msgstr "La clé du tableau et l'ID du lien doivent être égaux."
|
||||
msgstr "La clé du tableau et l'ID du lien doivent être identiques."
|
||||
|
||||
#: application/LinkDB.php:251
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48
|
||||
msgid ""
|
||||
"The personal, minimalist, super-fast, database free, bookmarking service"
|
||||
msgstr ""
|
||||
"Le gestionnaire de marque-page personnel, minimaliste, et sans base de "
|
||||
"Le gestionnaire de marque-pages personnel, minimaliste, et sans base de "
|
||||
"données"
|
||||
|
||||
#: application/LinkDB.php:253
|
||||
|
@ -125,11 +123,11 @@ msgstr ""
|
|||
"Bienvenue sur Shaarli ! Ceci est votre premier marque-page public. Pour me "
|
||||
"modifier ou me supprimer, vous devez d'abord vous connecter.\n"
|
||||
"\n"
|
||||
"Pour apprendre comment utiliser Shaarli, consultez le lien « Documentation » "
|
||||
"en bas de page.\n"
|
||||
"Pour apprendre à utiliser Shaarli, consultez le lien « Documentation » en "
|
||||
"bas de page.\n"
|
||||
"\n"
|
||||
"Vous utilisez la version supportée par la communauté du projet original "
|
||||
"Shaarli, de Sébastien Sauvage."
|
||||
"Shaarli de Sébastien Sauvage."
|
||||
|
||||
#: application/LinkDB.php:267
|
||||
msgid "My secret stuff... - Pastebin.com"
|
||||
|
@ -185,14 +183,14 @@ msgid ""
|
|||
"php-gd extension must be loaded to use thumbnails. Thumbnails are now "
|
||||
"disabled. Please reload the page."
|
||||
msgstr ""
|
||||
"php-gd extension must be loaded to use thumbnails. Thumbnails are now "
|
||||
"disabled. Please reload the page."
|
||||
"l'extension php-gd doit être chargée pour utiliser les miniatures. Les "
|
||||
"miniatures sont désormais désactivées. Rechargez la page."
|
||||
|
||||
#: application/Updater.php:86
|
||||
msgid "Couldn't retrieve Updater class methods."
|
||||
msgstr "Impossible de récupérer les méthodes de la classe Updater."
|
||||
|
||||
#: application/Updater.php:514 index.php:1023
|
||||
#: application/Updater.php:514 index.php:1022
|
||||
msgid ""
|
||||
"You have enabled or changed thumbnails mode. <a href=\"?do=thumbs_update"
|
||||
"\">Please synchronize them</a>."
|
||||
|
@ -200,17 +198,17 @@ msgstr ""
|
|||
"Vous avez activé ou changé le mode de miniatures. <a href=\"?do=thumbs_update"
|
||||
"\">Merci de les synchroniser</a>."
|
||||
|
||||
#: application/Updater.php:566
|
||||
#: application/Updater.php:586
|
||||
msgid "An error occurred while running the update "
|
||||
msgstr "Une erreur s'est produite lors de l'exécution de la mise à jour "
|
||||
|
||||
#: application/Updater.php:606
|
||||
#: application/Updater.php:626
|
||||
msgid "Updates file path is not set, can't write updates."
|
||||
msgstr ""
|
||||
"Le chemin vers le fichier de mise à jour n'est pas défini, impossible "
|
||||
"d'écrire les mises à jour."
|
||||
|
||||
#: application/Updater.php:611
|
||||
#: application/Updater.php:631
|
||||
msgid "Unable to write updates in "
|
||||
msgstr "Impossible d'écrire les mises à jour dans "
|
||||
|
||||
|
@ -286,74 +284,66 @@ msgstr "NON. Vous êtes banni pour le moment. Revenez plus tard."
|
|||
|
||||
#: index.php:273
|
||||
msgid "Wrong login/password."
|
||||
msgstr "Nom d'utilisateur ou mot de passe incorrects."
|
||||
msgstr "Nom d'utilisateur ou mot de passe incorrect(s)."
|
||||
|
||||
#: index.php:483 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:46
|
||||
#: index.php:482 tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:46
|
||||
msgid "Daily"
|
||||
msgstr "Quotidien"
|
||||
|
||||
#: index.php:589 tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28
|
||||
#: index.php:588 tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28
|
||||
#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:75
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:99
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:75
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:99
|
||||
msgid "Login"
|
||||
msgstr "Connexion"
|
||||
|
||||
#: index.php:606 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:41
|
||||
#: index.php:605 tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:41
|
||||
msgid "Picture wall"
|
||||
msgstr "Mur d'images"
|
||||
|
||||
#: index.php:683 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:36
|
||||
#: index.php:682 tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:36
|
||||
#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19
|
||||
msgid "Tag cloud"
|
||||
msgstr "Nuage de tags"
|
||||
|
||||
#: index.php:716 tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19
|
||||
#: index.php:715 tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19
|
||||
msgid "Tag list"
|
||||
msgstr "Liste des tags"
|
||||
|
||||
#: index.php:941 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:31
|
||||
#: index.php:940 tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:31
|
||||
msgid "Tools"
|
||||
msgstr "Outils"
|
||||
|
||||
#: index.php:950
|
||||
#: index.php:949
|
||||
msgid "You are not supposed to change a password on an Open Shaarli."
|
||||
msgstr ""
|
||||
"Vous n'êtes pas censé modifier le mot de passe d'un Shaarli en mode ouvert."
|
||||
|
||||
#: index.php:955 index.php:997 index.php:1085 index.php:1116 index.php:1221
|
||||
#: index.php:954 index.php:996 index.php:1084 index.php:1116 index.php:1221
|
||||
msgid "Wrong token."
|
||||
msgstr "Jeton invalide."
|
||||
|
||||
#: index.php:960
|
||||
#: index.php:959
|
||||
msgid "The old password is not correct."
|
||||
msgstr "L'ancien mot de passe est incorrect."
|
||||
|
||||
#: index.php:980
|
||||
#: index.php:979
|
||||
msgid "Your password has been changed"
|
||||
msgstr "Votre mot de passe a été modifié"
|
||||
|
||||
#: index.php:985
|
||||
#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29
|
||||
#: index.php:984 tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29
|
||||
msgid "Change password"
|
||||
msgstr "Modification du mot de passe"
|
||||
msgstr "Modifier le mot de passe"
|
||||
|
||||
#: index.php:1043
|
||||
#: index.php:1042
|
||||
msgid "Configuration was saved."
|
||||
msgstr "La configuration a été sauvegardé."
|
||||
msgstr "La configuration a été sauvegardée."
|
||||
|
||||
#: index.php:1068 tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24
|
||||
#: index.php:1067 tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24
|
||||
msgid "Configure"
|
||||
msgstr "Configurer"
|
||||
|
||||
#: index.php:1079 tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13
|
||||
#: index.php:1078 tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36
|
||||
msgid "Manage tags"
|
||||
msgstr "Gérer les tags"
|
||||
|
@ -381,7 +371,6 @@ msgid "Edit"
|
|||
msgstr "Modifier"
|
||||
|
||||
#: index.php:1281 index.php:1351
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:26
|
||||
msgid "Shaare"
|
||||
msgstr "Shaare"
|
||||
|
@ -390,15 +379,19 @@ msgstr "Shaare"
|
|||
msgid "Note: "
|
||||
msgstr "Note : "
|
||||
|
||||
#: index.php:1360 tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65
|
||||
#: index.php:1359
|
||||
msgid "Invalid link ID provided"
|
||||
msgstr ""
|
||||
|
||||
#: index.php:1379
|
||||
msgid "Export"
|
||||
msgstr "Exporter"
|
||||
|
||||
#: index.php:1422 tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:83
|
||||
#: index.php:1441
|
||||
msgid "Import"
|
||||
msgstr "Importer"
|
||||
|
||||
#: index.php:1432
|
||||
#: index.php:1451
|
||||
#, php-format
|
||||
msgid ""
|
||||
"The file you are trying to upload is probably bigger than what this "
|
||||
|
@ -408,20 +401,20 @@ msgstr ""
|
|||
"le serveur web peut accepter (%s). Merci de l'envoyer en parties plus "
|
||||
"légères."
|
||||
|
||||
#: index.php:1471 tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26
|
||||
#: index.php:1490 tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22
|
||||
msgid "Plugin administration"
|
||||
msgstr "Administration des extensions"
|
||||
msgstr "Administration des plugins"
|
||||
|
||||
#: index.php:1523 tmp/thumbnails.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14
|
||||
#: index.php:1542 tmp/thumbnails.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14
|
||||
msgid "Thumbnails update"
|
||||
msgstr "Mise à jour des miniatures"
|
||||
|
||||
#: index.php:1695
|
||||
#: index.php:1714
|
||||
msgid "Search: "
|
||||
msgstr "Recherche : "
|
||||
|
||||
#: index.php:1735
|
||||
#: index.php:1754
|
||||
#, php-format
|
||||
msgid ""
|
||||
"<pre>Sessions do not seem to work correctly on your server.<br>Make sure the "
|
||||
|
@ -431,16 +424,16 @@ msgid ""
|
|||
"custom hostname without a dot causes cookie storage to fail. We recommend "
|
||||
"accessing your server via it's IP address or Fully Qualified Domain Name.<br>"
|
||||
msgstr ""
|
||||
"<pre>Les sesssions ne semble pas fonctionner sur ce serveur.<br>Assurez vous "
|
||||
"que la variable « session.save_path » est correctement définie dans votre "
|
||||
"fichier de configuration PHP, et que vous y avez les droits d'écriture."
|
||||
"<br>Ce paramètre pointe actuellement sur %s.<br>Sur certains navigateurs, "
|
||||
"accéder à votre serveur depuis un nom d'hôte comme « localhost » ou autre "
|
||||
"nom personnalisé sans point '.' entraine l'échec de la sauvegarde des "
|
||||
"cookies. Nous vous recommandons d'accéder à votre serveur depuis son adresse "
|
||||
"IP ou un <em>Fully Qualified Domain Name</em>.<br>"
|
||||
"<pre>Les sesssions ne semblent pas fonctionner sur ce serveur.<br>Assurez "
|
||||
"vous que la variable « session.save_path » est correctement définie dans "
|
||||
"votre fichier de configuration PHP, et que vous avez les droits d'écriture "
|
||||
"dessus.<br>Ce paramètre pointe actuellement sur %s.<br>Sur certains "
|
||||
"navigateurs, accéder à votre serveur depuis un nom d'hôte comme « localhost "
|
||||
"» ou autre nom personnalisé sans point '.' entraine l'échec de la sauvegarde "
|
||||
"des cookies. Nous vous recommandons d'accéder à votre serveur depuis son "
|
||||
"adresse IP ou un <em>Fully Qualified Domain Name</em>.<br>"
|
||||
|
||||
#: index.php:1745
|
||||
#: index.php:1764
|
||||
msgid "Click to try again."
|
||||
msgstr "Cliquer ici pour réessayer."
|
||||
|
||||
|
@ -455,7 +448,7 @@ msgstr "Shaare"
|
|||
|
||||
#: plugins/addlink_toolbar/addlink_toolbar.php:50
|
||||
msgid "Adds the addlink input on the linklist page."
|
||||
msgstr "Ajout le formulaire d'ajout de liens sur la page principale."
|
||||
msgstr "Ajoute le formulaire d'ajout de liens sur la page principale."
|
||||
|
||||
#: plugins/archiveorg/archiveorg.php:23
|
||||
msgid "View on archive.org"
|
||||
|
@ -471,7 +464,7 @@ msgid ""
|
|||
"developers."
|
||||
msgstr ""
|
||||
"Une extension de démonstration couvrant tous les cas d'utilisation pour les "
|
||||
"designers et les développeurs."
|
||||
"designers de thèmes et les développeurs d'extensions."
|
||||
|
||||
#: plugins/isso/isso.php:20
|
||||
msgid ""
|
||||
|
@ -481,12 +474,13 @@ msgstr ""
|
|||
"Erreur de l'extension Isso : Merci de définir le paramètre « ISSO_SERVER » "
|
||||
"dans la page d'administration des extensions."
|
||||
|
||||
#: plugins/isso/isso.php:63
|
||||
#: plugins/isso/isso.php:90
|
||||
msgid "Let visitor comment your shaares on permalinks with Isso."
|
||||
msgstr ""
|
||||
"Permet aux visiteurs de commenter vos shaares sur les permaliens avec Isso."
|
||||
"Permettre aux visiteurs de commenter vos shaares sur les permaliens avec "
|
||||
"Isso."
|
||||
|
||||
#: plugins/isso/isso.php:64
|
||||
#: plugins/isso/isso.php:91
|
||||
msgid "Isso server URL (without 'http://')"
|
||||
msgstr "URL du serveur Isso (sans 'http://')"
|
||||
|
||||
|
@ -578,7 +572,7 @@ msgstr "Active la publication de flux vers PubSubHubbub."
|
|||
|
||||
#: plugins/qrcode/qrcode.php:69 plugins/wallabag/wallabag.php:68
|
||||
msgid "For each link, add a QRCode icon."
|
||||
msgstr "Pour chaque liens, ajouter une icône de QRCode."
|
||||
msgstr "Pour chaque lien, ajouter une icône de QRCode."
|
||||
|
||||
#: plugins/wallabag/wallabag.php:21
|
||||
msgid ""
|
||||
|
@ -603,35 +597,17 @@ msgstr "Version de l'API Wallabag (1 ou 2)"
|
|||
#: tests/LanguagesTest.php:214 tests/LanguagesTest.php:227
|
||||
#: tests/languages/fr/LanguagesFrTest.php:160
|
||||
#: tests/languages/fr/LanguagesFrTest.php:173
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:85
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:85
|
||||
msgid "Search"
|
||||
msgid_plural "Search"
|
||||
msgstr[0] "Rechercher"
|
||||
msgstr[1] "Rechercher"
|
||||
|
||||
#: tmp/404.b91ef64efc3688266305ea9b42e5017e.rtpl.php:12
|
||||
msgid "Sorry, nothing to see here."
|
||||
msgstr "Désolé, il y a rien à voir ici."
|
||||
|
||||
#: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16
|
||||
msgid "URL or leave empty to post a note"
|
||||
msgstr "URL ou laisser vide pour créer une note"
|
||||
|
||||
#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16
|
||||
msgid "Current password"
|
||||
msgstr "Mot de passe actuel"
|
||||
|
||||
#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19
|
||||
msgid "New password"
|
||||
msgstr "Nouveau mot de passe"
|
||||
|
||||
#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23
|
||||
msgid "Change"
|
||||
msgstr "Changer"
|
||||
|
||||
#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:77
|
||||
msgid "Tag"
|
||||
msgstr "Tag"
|
||||
|
||||
|
@ -661,6 +637,34 @@ msgstr "Vous pouvez aussi modifier les tags dans la"
|
|||
msgid "tag list"
|
||||
msgstr "liste des tags"
|
||||
|
||||
#: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:143
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:296
|
||||
msgid "All"
|
||||
msgstr "Tous"
|
||||
|
||||
#: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:147
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:300
|
||||
msgid "Only common media hosts"
|
||||
msgstr "Seulement les hébergeurs de média connus"
|
||||
|
||||
#: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:151
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:304
|
||||
msgid "None"
|
||||
msgstr "Aucune"
|
||||
|
||||
#: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:158
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:281
|
||||
msgid "You need to enable the extension <code>php-gd</code> to use thumbnails."
|
||||
msgstr ""
|
||||
"Vous devez activer l'extension <code>php-gd</code> pour utiliser les "
|
||||
"miniatures."
|
||||
|
||||
#: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:162
|
||||
#, fuzzy
|
||||
#| msgid "Enable thumbnails"
|
||||
msgid "Synchonize thumbnails"
|
||||
msgstr "Activer les miniatures"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29
|
||||
msgid "title"
|
||||
msgstr "titre"
|
||||
|
@ -678,22 +682,18 @@ msgid "Theme"
|
|||
msgstr "Thème"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:87
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:78
|
||||
msgid "Language"
|
||||
msgstr "Langue"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:116
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102
|
||||
msgid "Timezone"
|
||||
msgstr "Fuseau horaire"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:103
|
||||
msgid "Continent"
|
||||
msgstr "Continent"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:103
|
||||
msgid "City"
|
||||
msgstr "Ville"
|
||||
|
||||
|
@ -734,25 +734,21 @@ msgid "Do not show any links if the user is not logged in"
|
|||
msgstr "N'afficher aucun lien sans être connecté"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:231
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150
|
||||
msgid "Check updates"
|
||||
msgstr "Vérifier les mises à jour"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:232
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:152
|
||||
msgid "Notify me when a new release is ready"
|
||||
msgstr "Me notifier lorsqu'une nouvelle version est disponible"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:247
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169
|
||||
msgid "Enable REST API"
|
||||
msgstr "Activer l'API REST"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:248
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:170
|
||||
msgid "Allow third party software to use Shaarli such as mobile application"
|
||||
msgstr ""
|
||||
"Permets aux applications tierces d'utiliser Shaarli, par exemple les "
|
||||
"Permet aux applications tierces d'utiliser Shaarli, par exemple les "
|
||||
"applications mobiles"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:263
|
||||
|
@ -763,30 +759,11 @@ msgstr "Clé d'API secrète"
|
|||
msgid "Enable thumbnails"
|
||||
msgstr "Activer les miniatures"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:281
|
||||
msgid "You need to enable the extension <code>php-gd</code> to use thumbnails."
|
||||
msgstr ""
|
||||
"Vous devez activer l'extension <code>php-gd</code> pour utiliser les "
|
||||
"miniatures."
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:285
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:56
|
||||
msgid "Synchronize thumbnails"
|
||||
msgstr "Synchroniser les miniatures"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:296
|
||||
#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31
|
||||
msgid "All"
|
||||
msgstr "Tous"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:300
|
||||
msgid "Only common media hosts"
|
||||
msgstr "Seulement les hébergeurs de média connus"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:304
|
||||
msgid "None"
|
||||
msgstr "Aucune"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:312
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72
|
||||
#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139
|
||||
|
@ -847,107 +824,13 @@ msgid "Tags"
|
|||
msgstr "Tags"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:57
|
||||
#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:167
|
||||
msgid "Private"
|
||||
msgstr "Privé"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72
|
||||
msgid "Apply Changes"
|
||||
msgstr "Appliquer"
|
||||
|
||||
#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16
|
||||
msgid "Export Database"
|
||||
msgstr "Exporter les données"
|
||||
|
||||
#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24
|
||||
msgid "Selection"
|
||||
msgstr "Choisir"
|
||||
|
||||
#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
|
||||
msgid "Public"
|
||||
msgstr "Publics"
|
||||
|
||||
#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:52
|
||||
msgid "Prepend note permalinks with this Shaarli instance's URL"
|
||||
msgstr "Préfixer les liens de notes avec l'URL de l'instance de Shaarli"
|
||||
|
||||
#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:53
|
||||
msgid "Useful to import bookmarks in a web browser"
|
||||
msgstr "Utile pour importer les marques-pages dans un navigateur"
|
||||
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16
|
||||
msgid "Import Database"
|
||||
msgstr "Importer des données"
|
||||
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23
|
||||
msgid "Maximum size allowed:"
|
||||
msgstr "Taille maximum autorisée :"
|
||||
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29
|
||||
msgid "Visibility"
|
||||
msgstr "Visibilité"
|
||||
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36
|
||||
msgid "Use values from the imported file, default to public"
|
||||
msgstr ""
|
||||
"Utiliser les valeurs présentes dans le fichier d'import, public par défaut"
|
||||
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
|
||||
msgid "Import all bookmarks as private"
|
||||
msgstr "Importer tous les liens comme privés"
|
||||
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46
|
||||
msgid "Import all bookmarks as public"
|
||||
msgstr "Importer tous les liens comme publics"
|
||||
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:57
|
||||
msgid "Overwrite existing bookmarks"
|
||||
msgstr "Remplacer les liens existants"
|
||||
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58
|
||||
msgid "Duplicates based on URL"
|
||||
msgstr "Les doublons s'appuient sur les URL"
|
||||
|
||||
#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72
|
||||
msgid "Add default tags"
|
||||
msgstr "Ajouter des tags par défaut"
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22
|
||||
msgid "Install Shaarli"
|
||||
msgstr "Installation de Shaarli"
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:25
|
||||
msgid "It looks like it's the first time you run Shaarli. Please configure it."
|
||||
msgstr ""
|
||||
"Il semblerait que ça soit la première fois que vous lancez Shaarli. Merci de "
|
||||
"le configurer."
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:33
|
||||
#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:151
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:151
|
||||
msgid "Username"
|
||||
msgstr "Nom d'utilisateur"
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
|
||||
#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:152
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:152
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:63
|
||||
msgid "Shaarli title"
|
||||
msgstr "Titre du Shaarli"
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:69
|
||||
msgid "My links"
|
||||
msgstr "Mes liens"
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:182
|
||||
msgid "Install"
|
||||
msgstr "Installer"
|
||||
msgstr "Appliquer les changements"
|
||||
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:79
|
||||
|
@ -964,13 +847,11 @@ msgstr[0] "lien privé"
|
|||
msgstr[1] "liens privés"
|
||||
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:121
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:121
|
||||
msgid "Search text"
|
||||
msgstr "Recherche texte"
|
||||
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:37
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:128
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:128
|
||||
#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36
|
||||
#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:64
|
||||
|
@ -1011,7 +892,6 @@ msgid "without any tag"
|
|||
msgstr "sans tag"
|
||||
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:173
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:42
|
||||
msgid "Fold"
|
||||
msgstr "Replier"
|
||||
|
@ -1028,36 +908,36 @@ msgstr "permalien"
|
|||
msgid "Add tag"
|
||||
msgstr "Ajouter un tag"
|
||||
|
||||
#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:183
|
||||
msgid "Toggle sticky"
|
||||
msgstr "Changer statut épinglé"
|
||||
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:185
|
||||
msgid "Sticky"
|
||||
msgstr "Épinglé"
|
||||
|
||||
#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:7
|
||||
msgid "Filters"
|
||||
msgstr "Filtres"
|
||||
|
||||
#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:12
|
||||
#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:12
|
||||
msgid "Only display private links"
|
||||
msgstr "Afficher uniquement les liens privés"
|
||||
|
||||
#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15
|
||||
#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:15
|
||||
msgid "Only display public links"
|
||||
msgstr "Afficher uniquement les liens publics"
|
||||
|
||||
#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:20
|
||||
#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:20
|
||||
msgid "Filter untagged links"
|
||||
msgstr "Filtrer par liens privés"
|
||||
|
||||
#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24
|
||||
#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76
|
||||
#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:24
|
||||
#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:76
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:43
|
||||
msgid "Fold all"
|
||||
msgstr "Replier tout"
|
||||
|
||||
#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:69
|
||||
#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:69
|
||||
msgid "Links per page"
|
||||
msgstr "Liens par page"
|
||||
|
@ -1066,62 +946,59 @@ msgstr "Liens par page"
|
|||
msgid ""
|
||||
"You have been banned after too many failed login attempts. Try again later."
|
||||
msgstr ""
|
||||
"Vous avez été banni après trop d'échec d'authentification. Merci de "
|
||||
"Vous avez été banni après trop d'échecs d'authentification. Merci de "
|
||||
"réessayer plus tard."
|
||||
|
||||
#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:151
|
||||
msgid "Username"
|
||||
msgstr "Nom d'utilisateur"
|
||||
|
||||
#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:152
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:155
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:155
|
||||
msgid "Remember me"
|
||||
msgstr "Rester connecté"
|
||||
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48
|
||||
msgid "by the Shaarli community"
|
||||
msgstr "par la communauté Shaarli"
|
||||
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:15
|
||||
msgid "Documentation"
|
||||
msgstr "Documentation"
|
||||
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:44
|
||||
msgid "Expand"
|
||||
msgstr "Déplier"
|
||||
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:45
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:45
|
||||
msgid "Expand all"
|
||||
msgstr "Déplier tout"
|
||||
|
||||
#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46
|
||||
#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:46
|
||||
msgid "Are you sure you want to delete this link?"
|
||||
msgstr "Êtes-vous sûr de vouloir supprimer ce lien ?"
|
||||
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:90
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:65
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:90
|
||||
msgid "RSS Feed"
|
||||
msgstr "Flux RSS"
|
||||
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:70
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:106
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:70
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:106
|
||||
msgid "Logout"
|
||||
msgstr "Déconnexion"
|
||||
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:173
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:173
|
||||
msgid "is available"
|
||||
msgstr "est disponible"
|
||||
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:180
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:180
|
||||
msgid "Error"
|
||||
msgstr "Erreur"
|
||||
|
@ -1221,22 +1098,18 @@ msgstr "tags"
|
|||
msgid "List all links with those tags"
|
||||
msgstr "Lister tous les liens avec ces tags"
|
||||
|
||||
#: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:3
|
||||
#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:3
|
||||
msgid "Sort by:"
|
||||
msgstr "Trier par :"
|
||||
|
||||
#: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:5
|
||||
#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:5
|
||||
msgid "Cloud"
|
||||
msgstr "Nuage"
|
||||
|
||||
#: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:6
|
||||
#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:6
|
||||
msgid "Most used"
|
||||
msgstr "Plus utilisés"
|
||||
|
||||
#: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7
|
||||
#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:7
|
||||
msgid "Alphabetical"
|
||||
msgstr "Alphabétique"
|
||||
|
@ -1251,7 +1124,7 @@ msgstr "Changer les paramètres de Shaarli : titre, fuseau horaire, etc."
|
|||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17
|
||||
msgid "Configure your Shaarli"
|
||||
msgstr "Conguration de Shaarli"
|
||||
msgstr "Configurer Shaarli"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21
|
||||
msgid "Enable, disable and configure plugins"
|
||||
|
@ -1259,31 +1132,39 @@ msgstr "Activer, désactiver et configurer les extensions"
|
|||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28
|
||||
msgid "Change your password"
|
||||
msgstr "Modification du mot de passe"
|
||||
msgstr "Modifier le mot de passe"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35
|
||||
msgid "Rename or delete a tag in all links"
|
||||
msgstr "Rename or delete a tag in all links"
|
||||
msgstr "Renommer ou supprimer un tag dans tous les liens"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, "
|
||||
#| "delicious…)"
|
||||
msgid ""
|
||||
"Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, "
|
||||
"delicious...)"
|
||||
msgstr ""
|
||||
"Importer des marques pages au format Netscape HTML (comme exportés depuis "
|
||||
"Firefox, Chrome, Opera, delicious...)"
|
||||
"Firefox, Chrome, Opera, delicious…)"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42
|
||||
msgid "Import links"
|
||||
msgstr "Importer des liens"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, "
|
||||
#| "Opera, delicious…)"
|
||||
msgid ""
|
||||
"Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, "
|
||||
"Opera, delicious...)"
|
||||
msgstr ""
|
||||
"Exporter les marques pages au format Netscape HTML (comme exportés depuis "
|
||||
"Firefox, Chrome, Opera, delicious...)"
|
||||
"Firefox, Chrome, Opera, delicious…)"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
|
||||
msgid "Export database"
|
||||
|
@ -1298,13 +1179,13 @@ msgid ""
|
|||
"Drag one of these button to your bookmarks toolbar or right-click it and "
|
||||
"\"Bookmark This Link\""
|
||||
msgstr ""
|
||||
"Glisser un de ces bouttons dans votre barre de favoris ou cliquer droit "
|
||||
"Glisser un de ces boutons dans votre barre de favoris ou cliquer droit "
|
||||
"dessus et « Ajouter aux favoris »"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:82
|
||||
msgid "then click on the bookmarklet in any page you want to share."
|
||||
msgstr ""
|
||||
"puis cliquer sur le marque page depuis un site que vous souhaitez partager."
|
||||
"puis cliquer sur le marque-page depuis un site que vous souhaitez partager."
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:110
|
||||
|
@ -1339,33 +1220,16 @@ msgstr ""
|
|||
msgid "Add Note"
|
||||
msgstr "Ajouter une Note"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139
|
||||
msgid ""
|
||||
"You need to browse your Shaarli over <strong>HTTPS</strong> to use this "
|
||||
"functionality."
|
||||
msgstr ""
|
||||
"Vous devez utiliser Shaarli en <strong>HTTPS</strong> pour utiliser cette "
|
||||
"fonctionalité."
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:144
|
||||
msgid "Add to"
|
||||
msgstr "Ajouter à"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:155
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:136
|
||||
msgid "3rd party"
|
||||
msgstr "Applications tierces"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:157
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:163
|
||||
msgid "Plugin"
|
||||
msgstr "Extension"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:158
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:164
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:144
|
||||
msgid "plugin"
|
||||
msgstr "extension"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:191
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169
|
||||
msgid ""
|
||||
"Drag this link to your bookmarks toolbar, or right-click it and choose "
|
||||
"Bookmark This Link"
|
||||
|
@ -1373,10 +1237,91 @@ msgstr ""
|
|||
"Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « "
|
||||
"Ajouter aux favoris »"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Enable thumbnails"
|
||||
#~ msgid "Synchonize thumbnails"
|
||||
#~ msgstr "Activer les miniatures"
|
||||
#~ msgid "Sorry, nothing to see here."
|
||||
#~ msgstr "Désolé, il y a rien à voir ici."
|
||||
|
||||
#~ msgid "Current password"
|
||||
#~ msgstr "Mot de passe actuel"
|
||||
|
||||
#~ msgid "New password"
|
||||
#~ msgstr "Nouveau mot de passe"
|
||||
|
||||
#~ msgid "Change"
|
||||
#~ msgstr "Changer"
|
||||
|
||||
#~ msgid "Export Database"
|
||||
#~ msgstr "Exporter les données"
|
||||
|
||||
#~ msgid "Selection"
|
||||
#~ msgstr "Choisir"
|
||||
|
||||
#~ msgid "Public"
|
||||
#~ msgstr "Publics"
|
||||
|
||||
#~ msgid "Prepend note permalinks with this Shaarli instance's URL"
|
||||
#~ msgstr "Préfixer les liens de note avec l'URL de l'instance de Shaarli"
|
||||
|
||||
#~ msgid "Useful to import bookmarks in a web browser"
|
||||
#~ msgstr "Utile pour importer les marques-pages dans un navigateur"
|
||||
|
||||
#~ msgid "Import Database"
|
||||
#~ msgstr "Importer des données"
|
||||
|
||||
#~ msgid "Maximum size allowed:"
|
||||
#~ msgstr "Taille maximum autorisée :"
|
||||
|
||||
#~ msgid "Visibility"
|
||||
#~ msgstr "Visibilité"
|
||||
|
||||
#~ msgid "Use values from the imported file, default to public"
|
||||
#~ msgstr ""
|
||||
#~ "Utiliser les valeurs présentes dans le fichier d'import, public par défaut"
|
||||
|
||||
#~ msgid "Import all bookmarks as private"
|
||||
#~ msgstr "Importer tous les liens comme privés"
|
||||
|
||||
#~ msgid "Import all bookmarks as public"
|
||||
#~ msgstr "Importer tous les liens comme publics"
|
||||
|
||||
#~ msgid "Overwrite existing bookmarks"
|
||||
#~ msgstr "Remplacer les liens existants"
|
||||
|
||||
#~ msgid "Duplicates based on URL"
|
||||
#~ msgstr "Les doublons s'appuient sur les URL"
|
||||
|
||||
#~ msgid "Add default tags"
|
||||
#~ msgstr "Ajouter des tags par défaut"
|
||||
|
||||
#~ msgid "Install Shaarli"
|
||||
#~ msgstr "Installation de Shaarli"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "It looks like it's the first time you run Shaarli. Please configure it."
|
||||
#~ msgstr ""
|
||||
#~ "Il semblerait que ça soit la première fois que vous lancez Shaarli. Merci "
|
||||
#~ "de le configurer."
|
||||
|
||||
#~ msgid "Shaarli title"
|
||||
#~ msgstr "Titre du Shaarli"
|
||||
|
||||
#~ msgid "My links"
|
||||
#~ msgstr "Mes liens"
|
||||
|
||||
#~ msgid "Install"
|
||||
#~ msgstr "Installer"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "You need to browse your Shaarli over <strong>HTTPS</strong> to use this "
|
||||
#~ "functionality."
|
||||
#~ msgstr ""
|
||||
#~ "Vous devez utiliser Shaarli en <strong>HTTPS</strong> pour utiliser cette "
|
||||
#~ "fonctionalité."
|
||||
|
||||
#~ msgid "Add to"
|
||||
#~ msgstr "Ajouter à"
|
||||
|
||||
#~ msgid "Plugin"
|
||||
#~ msgstr "Extension"
|
||||
|
||||
#~ msgid "Warning: "
|
||||
#~ msgstr "Attention : "
|
||||
|
@ -1450,7 +1395,8 @@ msgstr ""
|
|||
#~ "\n"
|
||||
|
||||
#~ msgid "Sessions do not seem to work correctly on your server."
|
||||
#~ msgstr "Les sessions ne semblent "
|
||||
#~ msgstr ""
|
||||
#~ "Les sessions ne semblent pas fonctionner correctement sur votre serveur."
|
||||
|
||||
#~ msgid "Tag was renamed in "
|
||||
#~ msgstr "Le tag a été renommé dans "
|
||||
|
|
260
index.php
260
index.php
|
@ -111,7 +111,7 @@
|
|||
|
||||
session_name('shaarli');
|
||||
// Start session if needed (Some server auto-start sessions).
|
||||
if (session_id() == '') {
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,6 @@ function isLoggedIn()
|
|||
$expirationTime,
|
||||
WEB_PATH
|
||||
);
|
||||
|
||||
} else {
|
||||
// Standard session expiration (=when browser closes)
|
||||
$expirationTime = 0;
|
||||
|
@ -257,7 +256,8 @@ function isLoggedIn()
|
|||
exit;
|
||||
}
|
||||
}
|
||||
header('Location: ?'); exit;
|
||||
header('Location: ?');
|
||||
exit;
|
||||
} else {
|
||||
$loginManager->handleFailedLogin($_SERVER);
|
||||
$redir = '&username='. urlencode($_POST['login']);
|
||||
|
@ -278,7 +278,9 @@ function isLoggedIn()
|
|||
// ------------------------------------------------------------------------------------------
|
||||
// Token management for XSRF protection
|
||||
// Token should be used in any form which acts on data (create,update,delete,import...).
|
||||
if (!isset($_SESSION['tokens'])) $_SESSION['tokens']=array(); // Token are attached to the session.
|
||||
if (!isset($_SESSION['tokens'])) {
|
||||
$_SESSION['tokens']=array(); // Token are attached to the session.
|
||||
}
|
||||
|
||||
/**
|
||||
* Daily RSS feed: 1 RSS entry per day giving all the links on that day.
|
||||
|
@ -288,7 +290,8 @@ function isLoggedIn()
|
|||
* @param ConfigManager $conf Configuration Manager instance
|
||||
* @param LoginManager $loginManager LoginManager instance
|
||||
*/
|
||||
function showDailyRSS($conf, $loginManager) {
|
||||
function showDailyRSS($conf, $loginManager)
|
||||
{
|
||||
// Cache system
|
||||
$query = $_SERVER['QUERY_STRING'];
|
||||
$cache = new CachedPage(
|
||||
|
@ -492,7 +495,8 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
* @param ConfigManager $conf Configuration Manager instance.
|
||||
* @param PluginManager $pluginManager Plugin Manager instance.
|
||||
*/
|
||||
function showLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager) {
|
||||
function showLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
|
||||
{
|
||||
buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager);
|
||||
$PAGE->renderPage('linklist');
|
||||
}
|
||||
|
@ -524,8 +528,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$updater->getDoneUpdates()
|
||||
);
|
||||
}
|
||||
}
|
||||
catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
die($e->getMessage());
|
||||
}
|
||||
|
||||
|
@ -538,8 +541,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$query = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : '';
|
||||
$targetPage = Router::findPage($query, $_GET, $loginManager->isLoggedIn());
|
||||
|
||||
if (
|
||||
// if the user isn't logged in
|
||||
if (// if the user isn't logged in
|
||||
!$loginManager->isLoggedIn() &&
|
||||
// and Shaarli doesn't have public content...
|
||||
$conf->get('privacy.hide_public_links') &&
|
||||
|
@ -565,7 +567,9 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
|
||||
foreach ($common_hooks as $name) {
|
||||
$plugin_data = array();
|
||||
$pluginManager->executeHooks('render_' . $name, $plugin_data,
|
||||
$pluginManager->executeHooks(
|
||||
'render_' . $name,
|
||||
$plugin_data,
|
||||
array(
|
||||
'target' => $targetPage,
|
||||
'loggedin' => $loginManager->isLoggedIn()
|
||||
|
@ -575,9 +579,11 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Display login form.
|
||||
if ($targetPage == Router::$PAGE_LOGIN)
|
||||
{
|
||||
if ($conf->get('security.open_shaarli')) { header('Location: ?'); exit; } // No need to login for open Shaarli
|
||||
if ($targetPage == Router::$PAGE_LOGIN) {
|
||||
if ($conf->get('security.open_shaarli')) {
|
||||
header('Location: ?');
|
||||
exit;
|
||||
} // No need to login for open Shaarli
|
||||
if (isset($_GET['username'])) {
|
||||
$PAGE->assign('username', escape($_GET['username']));
|
||||
}
|
||||
|
@ -590,8 +596,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
exit;
|
||||
}
|
||||
// -------- User wants to logout.
|
||||
if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=logout'))
|
||||
{
|
||||
if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=logout')) {
|
||||
invalidateCaches($conf->get('resource.page_cache'));
|
||||
$sessionManager->logout();
|
||||
setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, 'false', 0, WEB_PATH);
|
||||
|
@ -600,8 +605,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Picture wall
|
||||
if ($targetPage == Router::$PAGE_PICWALL)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_PICWALL) {
|
||||
$PAGE->assign('pagetitle', t('Picture wall') .' - '. $conf->get('general.title', 'Shaarli'));
|
||||
if (! $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) === Thumbnailer::MODE_NONE) {
|
||||
$PAGE->assign('linksToDisplay', []);
|
||||
|
@ -615,8 +619,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
|
||||
// Get only links which have a thumbnail.
|
||||
// Note: we do not retrieve thumbnails here, the request is too heavy.
|
||||
foreach($links as $key => $link)
|
||||
{
|
||||
foreach ($links as $key => $link) {
|
||||
if (isset($link['thumbnail']) && $link['thumbnail'] !== false) {
|
||||
$linksToDisplay[] = $link; // Add to array.
|
||||
}
|
||||
|
@ -637,8 +640,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Tag cloud
|
||||
if ($targetPage == Router::$PAGE_TAGCLOUD)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_TAGCLOUD) {
|
||||
$visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '';
|
||||
$filteringTags = isset($_GET['searchtags']) ? explode(' ', $_GET['searchtags']) : [];
|
||||
$tags = $LINKSDB->linksCountPerTag($filteringTags, $visibility);
|
||||
|
@ -685,8 +687,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Tag list
|
||||
if ($targetPage == Router::$PAGE_TAGLIST)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_TAGLIST) {
|
||||
$visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '';
|
||||
$filteringTags = isset($_GET['searchtags']) ? explode(' ', $_GET['searchtags']) : [];
|
||||
$tags = $LINKSDB->linksCountPerTag($filteringTags, $visibility);
|
||||
|
@ -770,10 +771,13 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User clicks on a tag in a link: The tag is added to the list of searched tags (searchtags=...)
|
||||
if (isset($_GET['addtag']))
|
||||
{
|
||||
if (isset($_GET['addtag'])) {
|
||||
// Get previous URL (http_referer) and add the tag to the searchtags parameters in query.
|
||||
if (empty($_SERVER['HTTP_REFERER'])) { header('Location: ?searchtags='.urlencode($_GET['addtag'])); exit; } // In case browser does not send HTTP_REFERER
|
||||
if (empty($_SERVER['HTTP_REFERER'])) {
|
||||
// In case browser does not send HTTP_REFERER
|
||||
header('Location: ?searchtags='.urlencode($_GET['addtag']));
|
||||
exit;
|
||||
}
|
||||
parse_str(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY), $params);
|
||||
|
||||
// Prevent redirection loop
|
||||
|
@ -798,12 +802,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
// Append the tag if necessary
|
||||
if (empty($params['searchtags'])) {
|
||||
$params['searchtags'] = trim($_GET['addtag']);
|
||||
}
|
||||
elseif ($addtag) {
|
||||
} elseif ($addtag) {
|
||||
$params['searchtags'] = trim($params['searchtags']).' '.trim($_GET['addtag']);
|
||||
}
|
||||
|
||||
unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different)
|
||||
// We also remove page (keeping the same page has no sense, since the
|
||||
// results are different)
|
||||
unset($params['page']);
|
||||
|
||||
header('Location: ?'.http_build_query($params));
|
||||
exit;
|
||||
}
|
||||
|
@ -834,7 +840,9 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
unset($params['searchtags']);
|
||||
}
|
||||
|
||||
unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different)
|
||||
// We also remove page (keeping the same page has no sense, since
|
||||
// the results are different)
|
||||
unset($params['page']);
|
||||
}
|
||||
header('Location: ?'.http_build_query($params));
|
||||
exit;
|
||||
|
@ -897,12 +905,10 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Handle other actions allowed for non-logged in users:
|
||||
if (!$loginManager->isLoggedIn())
|
||||
{
|
||||
if (!$loginManager->isLoggedIn()) {
|
||||
// User tries to post new link but is not logged in:
|
||||
// Show login screen, then redirect to ?post=...
|
||||
if (isset($_GET['post']))
|
||||
{
|
||||
if (isset($_GET['post'])) {
|
||||
header( // Redirect to login page, then back to post link.
|
||||
'Location: ?do=login&post='.urlencode($_GET['post']).
|
||||
(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').
|
||||
|
@ -925,8 +931,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
// -------- All other functions are reserved for the registered user:
|
||||
|
||||
// -------- Display the Tools menu if requested (import/export/bookmarklet...)
|
||||
if ($targetPage == Router::$PAGE_TOOLS)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_TOOLS) {
|
||||
$data = [
|
||||
'pageabsaddr' => index_url($_SERVER),
|
||||
'sslenabled' => is_https($_SERVER),
|
||||
|
@ -943,30 +948,40 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User wants to change his/her password.
|
||||
if ($targetPage == Router::$PAGE_CHANGEPASSWORD)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_CHANGEPASSWORD) {
|
||||
if ($conf->get('security.open_shaarli')) {
|
||||
die(t('You are not supposed to change a password on an Open Shaarli.'));
|
||||
}
|
||||
|
||||
if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword']))
|
||||
{
|
||||
if (!$sessionManager->checkToken($_POST['token'])) die(t('Wrong token.')); // Go away!
|
||||
if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) {
|
||||
if (!$sessionManager->checkToken($_POST['token'])) {
|
||||
die(t('Wrong token.')); // Go away!
|
||||
}
|
||||
|
||||
// Make sure old password is correct.
|
||||
$oldhash = sha1($_POST['oldpassword'].$conf->get('credentials.login').$conf->get('credentials.salt'));
|
||||
$oldhash = sha1(
|
||||
$_POST['oldpassword'].$conf->get('credentials.login').$conf->get('credentials.salt')
|
||||
);
|
||||
if ($oldhash != $conf->get('credentials.hash')) {
|
||||
echo '<script>alert("'. t('The old password is not correct.') .'");document.location=\'?do=changepasswd\';</script>';
|
||||
echo '<script>alert("'
|
||||
. t('The old password is not correct.')
|
||||
.'");document.location=\'?do=changepasswd\';</script>';
|
||||
exit;
|
||||
}
|
||||
// Save new password
|
||||
// Salt renders rainbow-tables attacks useless.
|
||||
$conf->set('credentials.salt', sha1(uniqid('', true) .'_'. mt_rand()));
|
||||
$conf->set('credentials.hash', sha1($_POST['setpassword'] . $conf->get('credentials.login') . $conf->get('credentials.salt')));
|
||||
$conf->set(
|
||||
'credentials.hash',
|
||||
sha1(
|
||||
$_POST['setpassword']
|
||||
. $conf->get('credentials.login')
|
||||
. $conf->get('credentials.salt')
|
||||
)
|
||||
);
|
||||
try {
|
||||
$conf->write($loginManager->isLoggedIn());
|
||||
}
|
||||
catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
error_log(
|
||||
'ERROR while writing config file after changing password.' . PHP_EOL .
|
||||
$e->getMessage()
|
||||
|
@ -978,9 +993,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
echo '<script>alert("'. t('Your password has been changed') .'");document.location=\'?do=tools\';</script>';
|
||||
exit;
|
||||
}
|
||||
else // show the change password form.
|
||||
{
|
||||
} else {
|
||||
// show the change password form.
|
||||
$PAGE->assign('pagetitle', t('Change password') .' - '. $conf->get('general.title', 'Shaarli'));
|
||||
$PAGE->renderPage('changepassword');
|
||||
exit;
|
||||
|
@ -988,10 +1002,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User wants to change configuration
|
||||
if ($targetPage == Router::$PAGE_CONFIGURE)
|
||||
{
|
||||
if (!empty($_POST['title']) )
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_CONFIGURE) {
|
||||
if (!empty($_POST['title'])) {
|
||||
if (!$sessionManager->checkToken($_POST['token'])) {
|
||||
die(t('Wrong token.')); // Go away!
|
||||
}
|
||||
|
@ -1019,7 +1031,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
&& $thumbnailsMode !== $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)
|
||||
) {
|
||||
$_SESSION['warnings'][] = t(
|
||||
'You have enabled or changed thumbnails mode. <a href="?do=thumbs_update">Please synchronize them</a>.'
|
||||
'You have enabled or changed thumbnails mode. '
|
||||
.'<a href="?do=thumbs_update">Please synchronize them</a>.'
|
||||
);
|
||||
}
|
||||
$conf->set('thumbnails.mode', $thumbnailsMode);
|
||||
|
@ -1028,8 +1041,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$conf->write($loginManager->isLoggedIn());
|
||||
$history->updateSettings();
|
||||
invalidateCaches($conf->get('resource.page_cache'));
|
||||
}
|
||||
catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
error_log(
|
||||
'ERROR while writing config file after configuration update.' . PHP_EOL .
|
||||
$e->getMessage()
|
||||
|
@ -1041,9 +1053,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
echo '<script>alert("'. t('Configuration was saved.') .'");document.location=\'?do=configure\';</script>';
|
||||
exit;
|
||||
}
|
||||
else // Show the configuration form.
|
||||
{
|
||||
} else {
|
||||
// Show the configuration form.
|
||||
$PAGE->assign('title', $conf->get('general.title'));
|
||||
$PAGE->assign('theme', $conf->get('resource.theme'));
|
||||
$PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl')));
|
||||
|
@ -1071,8 +1082,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User wants to rename a tag or delete it
|
||||
if ($targetPage == Router::$PAGE_CHANGETAG)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_CHANGETAG) {
|
||||
if (empty($_POST['fromtag']) || (empty($_POST['totag']) && isset($_POST['renametag']))) {
|
||||
$PAGE->assign('fromtag', ! empty($_GET['fromtag']) ? escape($_GET['fromtag']) : '');
|
||||
$PAGE->assign('pagetitle', t('Manage tags') .' - '. $conf->get('general.title', 'Shaarli'));
|
||||
|
@ -1084,7 +1094,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
die(t('Wrong token.'));
|
||||
}
|
||||
|
||||
$alteredLinks = $LINKSDB->renameTag(escape($_POST['fromtag']), escape($_POST['totag']));
|
||||
$toTag = isset($_POST['totag']) ? escape($_POST['totag']) : null;
|
||||
$alteredLinks = $LINKSDB->renameTag(escape($_POST['fromtag']), $toTag);
|
||||
$LINKSDB->save($conf->get('resource.page_cache'));
|
||||
foreach ($alteredLinks as $link) {
|
||||
$history->updateLink($link);
|
||||
|
@ -1100,16 +1111,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User wants to add a link without using the bookmarklet: Show form.
|
||||
if ($targetPage == Router::$PAGE_ADDLINK)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_ADDLINK) {
|
||||
$PAGE->assign('pagetitle', t('Shaare a new link') .' - '. $conf->get('general.title', 'Shaarli'));
|
||||
$PAGE->renderPage('addlink');
|
||||
exit;
|
||||
}
|
||||
|
||||
// -------- User clicked the "Save" button when editing a link: Save link to database.
|
||||
if (isset($_POST['save_edit']))
|
||||
{
|
||||
if (isset($_POST['save_edit'])) {
|
||||
// Go away!
|
||||
if (! $sessionManager->checkToken($_POST['token'])) {
|
||||
die(t('Wrong token.'));
|
||||
|
@ -1196,14 +1205,16 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User clicked the "Cancel" button when editing a link.
|
||||
if (isset($_POST['cancel_edit']))
|
||||
{
|
||||
if (isset($_POST['cancel_edit'])) {
|
||||
$id = isset($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : false;
|
||||
if (! isset($LINKSDB[$id])) {
|
||||
header('Location: ?');
|
||||
}
|
||||
// If we are called from the bookmarklet, we must close the popup:
|
||||
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
|
||||
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
|
||||
echo '<script>self.close();</script>';
|
||||
exit;
|
||||
}
|
||||
$link = $LINKSDB[$id];
|
||||
$returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
|
||||
// Scroll to the link which has been edited.
|
||||
|
@ -1214,8 +1225,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User clicked the "Delete" button when editing a link: Delete link from database.
|
||||
if ($targetPage == Router::$PAGE_DELETELINK)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_DELETELINK) {
|
||||
if (! $sessionManager->checkToken($_GET['token'])) {
|
||||
die(t('Wrong token.'));
|
||||
}
|
||||
|
@ -1236,13 +1246,16 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$id = (int) escape($id);
|
||||
$link = $LINKSDB[$id];
|
||||
$pluginManager->executeHooks('delete_link', $link);
|
||||
$history->deleteLink($link);
|
||||
unset($LINKSDB[$id]);
|
||||
}
|
||||
$LINKSDB->save($conf->get('resource.page_cache')); // save to disk
|
||||
$history->deleteLink($link);
|
||||
|
||||
// If we are called from the bookmarklet, we must close the popup:
|
||||
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
|
||||
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
|
||||
echo '<script>self.close();</script>';
|
||||
exit;
|
||||
}
|
||||
|
||||
$location = '?';
|
||||
if (isset($_SERVER['HTTP_REFERER'])) {
|
||||
|
@ -1259,11 +1272,13 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User clicked the "EDIT" button on a link: Display link edit form.
|
||||
if (isset($_GET['edit_link']))
|
||||
{
|
||||
if (isset($_GET['edit_link'])) {
|
||||
$id = (int) escape($_GET['edit_link']);
|
||||
$link = $LINKSDB[$id]; // Read database
|
||||
if (!$link) { header('Location: ?'); exit; } // Link not found in database.
|
||||
if (!$link) {
|
||||
header('Location: ?');
|
||||
exit;
|
||||
} // Link not found in database.
|
||||
$link['linkdate'] = $link['created']->format(LinkDB::LINK_DATE_FORMAT);
|
||||
$data = array(
|
||||
'link' => $link,
|
||||
|
@ -1289,8 +1304,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$link_is_new = false;
|
||||
// Check if URL is not already in database (in this case, we will edit the existing link)
|
||||
$link = $LINKSDB->getLinkFromUrl($url);
|
||||
if (! $link)
|
||||
{
|
||||
if (! $link) {
|
||||
$link_is_new = true;
|
||||
$linkdate = strval(date(LinkDB::LINK_DATE_FORMAT));
|
||||
// Get title if it was provided in URL (by the bookmarklet).
|
||||
|
@ -1299,7 +1313,9 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$description = empty($_GET['description']) ? '' : escape($_GET['description']);
|
||||
$tags = empty($_GET['tags']) ? '' : escape($_GET['tags']);
|
||||
$private = !empty($_GET['private']) && $_GET['private'] === "1" ? 1 : 0;
|
||||
// If this is an HTTP(S) link, we try go get the page to extract the title (otherwise we will to straight to the edit form.)
|
||||
|
||||
// If this is an HTTP(S) link, we try go get the page to extract
|
||||
// the title (otherwise we will to straight to the edit form.)
|
||||
if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) {
|
||||
// Short timeout to keep the application responsive
|
||||
// The callback will fill $charset and $title with data from the downloaded page.
|
||||
|
@ -1352,6 +1368,25 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
exit;
|
||||
}
|
||||
|
||||
if ($targetPage == Router::$PAGE_PINLINK) {
|
||||
if (! isset($_GET['id']) || empty($LINKSDB[$_GET['id']])) {
|
||||
// FIXME! Use a proper error system.
|
||||
$msg = t('Invalid link ID provided');
|
||||
echo '<script>alert("'. $msg .'");document.location=\''. index_url($_SERVER) .'\';</script>';
|
||||
exit;
|
||||
}
|
||||
if (! $sessionManager->checkToken($_GET['token'])) {
|
||||
die('Wrong token.');
|
||||
}
|
||||
|
||||
$link = $LINKSDB[$_GET['id']];
|
||||
$link['sticky'] = ! $link['sticky'];
|
||||
$LINKSDB[(int) $_GET['id']] = $link;
|
||||
$LINKSDB->save($conf->get('resource.page_cache'));
|
||||
header('Location: '.index_url($_SERVER));
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($targetPage == Router::$PAGE_EXPORT) {
|
||||
// Export links as a Netscape Bookmarks file
|
||||
|
||||
|
@ -1456,14 +1491,20 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$pluginMeta = $pluginManager->getPluginsMeta();
|
||||
|
||||
// Split plugins into 2 arrays: ordered enabled plugins and disabled.
|
||||
$enabledPlugins = array_filter($pluginMeta, function($v) { return $v['order'] !== false; });
|
||||
$enabledPlugins = array_filter($pluginMeta, function ($v) {
|
||||
return $v['order'] !== false;
|
||||
});
|
||||
// Load parameters.
|
||||
$enabledPlugins = load_plugin_parameter_values($enabledPlugins, $conf->get('plugins', array()));
|
||||
uasort(
|
||||
$enabledPlugins,
|
||||
function($a, $b) { return $a['order'] - $b['order']; }
|
||||
function ($a, $b) {
|
||||
return $a['order'] - $b['order'];
|
||||
}
|
||||
);
|
||||
$disabledPlugins = array_filter($pluginMeta, function($v) { return $v['order'] === false; });
|
||||
$disabledPlugins = array_filter($pluginMeta, function ($v) {
|
||||
return $v['order'] === false;
|
||||
});
|
||||
|
||||
$PAGE->assign('enabledPlugins', $enabledPlugins);
|
||||
$PAGE->assign('disabledPlugins', $disabledPlugins);
|
||||
|
@ -1480,21 +1521,23 @@ function($a, $b) { return $a['order'] - $b['order']; }
|
|||
foreach ($_POST as $param => $value) {
|
||||
$conf->set('plugins.'. $param, escape($value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$conf->set('general.enabled_plugins', save_plugin_config($_POST));
|
||||
}
|
||||
$conf->write($loginManager->isLoggedIn());
|
||||
$history->updateSettings();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
error_log(
|
||||
'ERROR while saving plugin configuration:.' . PHP_EOL .
|
||||
$e->getMessage()
|
||||
);
|
||||
|
||||
// TODO: do not handle exceptions/errors in JS.
|
||||
echo '<script>alert("'. $e->getMessage() .'");document.location=\'?do='. Router::$PAGE_PLUGINSADMIN .'\';</script>';
|
||||
echo '<script>alert("'
|
||||
. $e->getMessage()
|
||||
.'");document.location=\'?do='
|
||||
. Router::$PAGE_PLUGINSADMIN
|
||||
.'\';</script>';
|
||||
exit;
|
||||
}
|
||||
header('Location: ?do='. Router::$PAGE_PLUGINSADMIN);
|
||||
|
@ -1615,8 +1658,7 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
}
|
||||
|
||||
$linkDisp = array();
|
||||
while ($i<$end && $i<count($keys))
|
||||
{
|
||||
while ($i<$end && $i<count($keys)) {
|
||||
$link = $linksToDisplay[$keys[$i]];
|
||||
$link['description'] = format_description(
|
||||
$link['description'],
|
||||
|
@ -1719,16 +1761,19 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
* @param SessionManager $sessionManager SessionManager instance
|
||||
* @param LoginManager $loginManager LoginManager instance
|
||||
*/
|
||||
function install($conf, $sessionManager, $loginManager) {
|
||||
function install($conf, $sessionManager, $loginManager)
|
||||
{
|
||||
// On free.fr host, make sure the /sessions directory exists, otherwise login will not work.
|
||||
if (endsWith($_SERVER['HTTP_HOST'],'.free.fr') && !is_dir($_SERVER['DOCUMENT_ROOT'].'/sessions')) mkdir($_SERVER['DOCUMENT_ROOT'].'/sessions',0705);
|
||||
if (endsWith($_SERVER['HTTP_HOST'], '.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'))
|
||||
{
|
||||
if (isset($_GET['test_session'])
|
||||
&& ( !isset($_SESSION) || !isset($_SESSION['session_tested']) || $_SESSION['session_tested']!='Working')) {
|
||||
// Step 2: Check if data in session is correct.
|
||||
$msg = t(
|
||||
'<pre>Sessions do not seem to work correctly on your server.<br>'.
|
||||
|
@ -1744,19 +1789,18 @@ function install($conf, $sessionManager, $loginManager) {
|
|||
echo '<br><a href="?">'. t('Click to try again.') .'</a></pre>';
|
||||
die;
|
||||
}
|
||||
if (!isset($_SESSION['session_tested']))
|
||||
{ // Step 1 : Try to store data in session and reload page.
|
||||
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: '.index_url($_SERVER).'?test_session'); // Redirect to check stored data.
|
||||
}
|
||||
if (isset($_GET['test_session']))
|
||||
{ // Step 3: Sessions are OK. Remove test parameter from URL.
|
||||
if (isset($_GET['test_session'])) {
|
||||
// Step 3: Sessions are OK. Remove test parameter from URL.
|
||||
header('Location: '.index_url($_SERVER));
|
||||
}
|
||||
|
||||
|
||||
if (!empty($_POST['setlogin']) && !empty($_POST['setpassword']))
|
||||
{
|
||||
if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) {
|
||||
$tz = 'UTC';
|
||||
if (!empty($_POST['continent']) && !empty($_POST['city'])
|
||||
&& isTimeZoneValid($_POST['continent'], $_POST['city'])
|
||||
|
@ -1787,8 +1831,7 @@ function install($conf, $sessionManager, $loginManager) {
|
|||
try {
|
||||
// Everything is ok, let's create config file.
|
||||
$conf->write($loginManager->isLoggedIn());
|
||||
}
|
||||
catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
error_log(
|
||||
'ERROR while writing config file after installation.' . PHP_EOL .
|
||||
$e->getMessage()
|
||||
|
@ -1798,7 +1841,10 @@ function install($conf, $sessionManager, $loginManager) {
|
|||
echo '<script>alert("'. $e->getMessage() .'");document.location=\'?\';</script>';
|
||||
exit;
|
||||
}
|
||||
echo '<script>alert("Shaarli is now configured. Please enter your login/password and start shaaring your links!");document.location=\'?do=login\';</script>';
|
||||
echo '<script>alert('
|
||||
.'"Shaarli is now configured. '
|
||||
.'Please enter your login/password and start shaaring your links!"'
|
||||
.');document.location=\'?do=login\';</script>';
|
||||
exit;
|
||||
}
|
||||
|
||||
|
@ -1858,6 +1904,7 @@ function install($conf, $sessionManager, $loginManager) {
|
|||
})->add('\Shaarli\Api\ApiMiddleware');
|
||||
|
||||
$response = $app->run(true);
|
||||
|
||||
// Hack to make Slim and Shaarli router work together:
|
||||
// If a Slim route isn't found and NOT API call, we call renderPage().
|
||||
if ($response->getStatusCode() == 404 && strpos($_SERVER['REQUEST_URI'], '/api/v1') === false) {
|
||||
|
@ -1865,5 +1912,12 @@ function install($conf, $sessionManager, $loginManager) {
|
|||
header('Content-Type: text/html; charset=utf-8');
|
||||
renderPage($conf, $pluginManager, $linkDb, $history, $sessionManager, $loginManager);
|
||||
} else {
|
||||
$response = $response
|
||||
->withHeader('Access-Control-Allow-Origin', '*')
|
||||
->withHeader(
|
||||
'Access-Control-Allow-Headers',
|
||||
'X-Requested-With, Content-Type, Accept, Origin, Authorization'
|
||||
)
|
||||
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||||
$app->respond($response);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ site_name: Shaarli Documentation
|
|||
repo_url: https://github.com/shaarli/Shaarli
|
||||
edit_uri: edit/master/doc/md
|
||||
site_description: The personal, minimalist, super-fast, database free, bookmarking service
|
||||
theme: readthedocs
|
||||
theme:
|
||||
name: readthedocs
|
||||
custom_dir: doc/custom_theme/
|
||||
docs_dir: doc/md
|
||||
site_dir: doc/html
|
||||
# Disable strict mode until ReadTheDocs provides up-to-date MkDocs settings:
|
||||
|
|
17
phpcs.xml
Normal file
17
phpcs.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0"?>
|
||||
<ruleset name="Shaarli">
|
||||
<description>The Shaarli coding standards</description>
|
||||
|
||||
<file>index.php</file>
|
||||
<file>application</file>
|
||||
<file>plugins</file>
|
||||
<file>tests</file>
|
||||
|
||||
<exclude-pattern>*/*.css</exclude-pattern>
|
||||
<exclude-pattern>*/*.js</exclude-pattern>
|
||||
|
||||
<arg name="colors"/>
|
||||
|
||||
<rule ref="PSR1"/>
|
||||
<rule ref="PSR2"/>
|
||||
</ruleset>
|
|
@ -73,7 +73,6 @@ function hook_demo_plugin_render_header($data)
|
|||
{
|
||||
// Only execute when linklist is rendered.
|
||||
if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) {
|
||||
|
||||
// If loggedin
|
||||
if ($data['_LOGGEDIN_'] === true) {
|
||||
/*
|
||||
|
@ -448,8 +447,7 @@ function hook_demo_plugin_render_feed($data)
|
|||
foreach ($data['links'] as &$link) {
|
||||
if ($data['_PAGE_'] == Router::$PAGE_FEED_ATOM) {
|
||||
$link['description'] .= ' - ATOM Feed' ;
|
||||
}
|
||||
elseif ($data['_PAGE_'] == Router::$PAGE_FEED_RSS) {
|
||||
} elseif ($data['_PAGE_'] == Router::$PAGE_FEED_RSS) {
|
||||
$link['description'] .= ' - RSS Feed';
|
||||
}
|
||||
}
|
||||
|
|
BIN
plugins/isso/comment.png
Normal file
BIN
plugins/isso/comment.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 277 B |
|
@ -46,9 +46,36 @@ function hook_isso_render_linklist($data, $conf)
|
|||
|
||||
$isso = sprintf($issoHtml, $issoUrl, $issoUrl, $link['id'], $link['id']);
|
||||
$data['plugin_end_zone'][] = $isso;
|
||||
} else {
|
||||
$button = '<span><a href="?%s#isso-thread">';
|
||||
// For the default theme we use a FontAwesome icon which is better than an image
|
||||
if ($conf->get('resource.theme') === 'default') {
|
||||
$button .= '<i class="linklist-plugin-icon fa fa-comment"></i>';
|
||||
} else {
|
||||
$button .= '<img class="linklist-plugin-icon" src="plugins/isso/comment.png" ';
|
||||
$button .= 'title="Comment on this shaare" alt="Comments" />';
|
||||
}
|
||||
$button .= '</a></span>';
|
||||
foreach ($data['links'] as &$value) {
|
||||
$commentLink = sprintf($button, $value['shorturl']);
|
||||
$value['link_plugin'][] = $commentLink;
|
||||
}
|
||||
}
|
||||
|
||||
// Hackish way to include this CSS file only when necessary.
|
||||
$data['plugins_includes']['css_files'][] = PluginManager::$PLUGINS_PATH . '/isso/isso.css';
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* When linklist is displayed, include isso CSS file.
|
||||
*
|
||||
* @param array $data - header data.
|
||||
*
|
||||
* @return mixed - header data with isso CSS file added.
|
||||
*/
|
||||
function hook_isso_render_includes($data)
|
||||
{
|
||||
if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) {
|
||||
$data['css_files'][] = PluginManager::$PLUGINS_PATH . '/isso/isso.css';
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
|
5
plugins/isso/isso_button.html
Normal file
5
plugins/isso/isso_button.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
<span>
|
||||
<a href="?%s#isso-thread">
|
||||
<img class="linklist-plugin-icon" src="plugins/archiveorg/internetarchive.png" title="%s" alt="archive.org" />
|
||||
</a>
|
||||
</span>
|
|
@ -28,6 +28,7 @@ function hook_markdown_render_linklist($data, $conf)
|
|||
$value = stripNoMarkdownTag($value);
|
||||
continue;
|
||||
}
|
||||
$value['description_src'] = $value['description'];
|
||||
$value['description'] = process_markdown(
|
||||
$value['description'],
|
||||
$conf->get('security.markdown_escape', true),
|
||||
|
@ -138,7 +139,6 @@ function hook_markdown_render_includes($data)
|
|||
|| $data['_PAGE_'] == Router::$PAGE_DAILY
|
||||
|| $data['_PAGE_'] == Router::$PAGE_EDITLINK
|
||||
) {
|
||||
|
||||
$data['css_files'][] = PluginManager::$PLUGINS_PATH . '/markdown/markdown.css';
|
||||
}
|
||||
|
||||
|
@ -194,8 +194,7 @@ function reverse_text2clickable($description)
|
|||
// Detect and toggle block of code
|
||||
if (!$codeBlockOn) {
|
||||
$codeBlockOn = preg_match('/^```/', $descriptionLine) > 0;
|
||||
}
|
||||
elseif (preg_match('/^```/', $descriptionLine) > 0) {
|
||||
} elseif (preg_match('/^```/', $descriptionLine) > 0) {
|
||||
$codeBlockOn = false;
|
||||
}
|
||||
|
||||
|
@ -215,6 +214,15 @@ function reverse_text2clickable($description)
|
|||
$descriptionLine
|
||||
);
|
||||
|
||||
// Make hashtag links markdown ready, otherwise the links will be ignored with escape set to true
|
||||
if (!$codeBlockOn && !$codeLineOn) {
|
||||
$descriptionLine = preg_replace(
|
||||
'#<a href="([^ ]*)"'. $hashtagTitle .'>([^<]+)</a>#m',
|
||||
'[$2]($1)',
|
||||
$descriptionLine
|
||||
);
|
||||
}
|
||||
|
||||
$descriptionOut .= $descriptionLine;
|
||||
if ($lineCount++ < count($descriptionLines) - 1) {
|
||||
$descriptionOut .= PHP_EOL;
|
||||
|
@ -292,13 +300,17 @@ function sanitize_html($description)
|
|||
foreach ($escapeTags as $tag) {
|
||||
$description = preg_replace_callback(
|
||||
'#<\s*'. $tag .'[^>]*>(.*</\s*'. $tag .'[^>]*>)?#is',
|
||||
function ($match) { return escape($match[0]); },
|
||||
$description);
|
||||
function ($match) {
|
||||
return escape($match[0]);
|
||||
},
|
||||
$description
|
||||
);
|
||||
}
|
||||
$description = preg_replace(
|
||||
'#(<[^>]+\s)on[a-z]*="?[^ "]*"?#is',
|
||||
'$1',
|
||||
$description);
|
||||
$description
|
||||
);
|
||||
return $description;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,8 @@ function hook_pubsubhubbub_save_link($data, $conf)
|
|||
*
|
||||
* @throws Exception An error occurred.
|
||||
*/
|
||||
function nocurl_http_post($url, $postString) {
|
||||
function nocurl_http_post($url, $postString)
|
||||
{
|
||||
$params = array('http' => array(
|
||||
'method' => 'POST',
|
||||
'content' => $postString,
|
||||
|
|
|
@ -17,7 +17,8 @@ function hook_qrcode_render_linklist($data)
|
|||
$qrcode_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/qrcode/qrcode.html');
|
||||
|
||||
foreach ($data['links'] as &$value) {
|
||||
$qrcode = sprintf($qrcode_html,
|
||||
$qrcode = sprintf(
|
||||
$qrcode_html,
|
||||
urlencode($value['url']),
|
||||
$value['url'],
|
||||
PluginManager::$PLUGINS_PATH
|
||||
|
|
|
@ -69,4 +69,3 @@ function wallabag_dummy_translation()
|
|||
t('Wallabag API URL');
|
||||
t('Wallabag API version (1 or 2)');
|
||||
}
|
||||
|
||||
|
|
|
@ -82,8 +82,8 @@ public function testRSSBuildData()
|
|||
$this->assertFalse($data['usepermalinks']);
|
||||
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
|
||||
|
||||
// Test first link (note link)
|
||||
$link = reset($data['links']);
|
||||
// Test first not pinned link (note link)
|
||||
$link = $data['links'][array_keys($data['links'])[2]];
|
||||
$this->assertEquals(41, $link['id']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
|
||||
$this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
|
||||
|
@ -119,7 +119,7 @@ public function testAtomBuildData()
|
|||
$data = $feedBuilder->buildData();
|
||||
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
|
||||
$this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['last_update']);
|
||||
$link = reset($data['links']);
|
||||
$link = $data['links'][array_keys($data['links'])[2]];
|
||||
$this->assertRegExp('/2015-03-10T11:46:51\+\d{2}:\d{2}/', $link['pub_iso_date']);
|
||||
$this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['links'][8]['up_iso_date']);
|
||||
}
|
||||
|
@ -148,13 +148,13 @@ public function testBuildDataFiltered()
|
|||
public function testBuildDataCount()
|
||||
{
|
||||
$criteria = array(
|
||||
'nb' => '1',
|
||||
'nb' => '3',
|
||||
);
|
||||
$feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, $criteria, false);
|
||||
$feedBuilder->setLocale(self::$LOCALE);
|
||||
$data = $feedBuilder->buildData();
|
||||
$this->assertEquals(1, count($data['links']));
|
||||
$link = array_shift($data['links']);
|
||||
$this->assertEquals(3, count($data['links']));
|
||||
$link = $data['links'][array_keys($data['links'])[2]];
|
||||
$this->assertEquals(41, $link['id']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ public function testBuildDataPermalinks()
|
|||
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
|
||||
$this->assertTrue($data['usepermalinks']);
|
||||
// First link is a permalink
|
||||
$link = array_shift($data['links']);
|
||||
$link = $data['links'][array_keys($data['links'])[2]];
|
||||
$this->assertEquals(41, $link['id']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
|
||||
$this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
|
||||
|
@ -179,7 +179,7 @@ public function testBuildDataPermalinks()
|
|||
$this->assertContains('Direct link', $link['description']);
|
||||
$this->assertContains('http://host.tld/?WDWyig', $link['description']);
|
||||
// Second link is a direct link
|
||||
$link = array_shift($data['links']);
|
||||
$link = $data['links'][array_keys($data['links'])[3]];
|
||||
$this->assertEquals(8, $link['id']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114633'), $link['created']);
|
||||
$this->assertEquals('http://host.tld/?RttfEw', $link['guid']);
|
||||
|
@ -237,7 +237,7 @@ public function testBuildDataServerSubdir()
|
|||
);
|
||||
|
||||
// Test first link (note link)
|
||||
$link = array_shift($data['links']);
|
||||
$link = $data['links'][array_keys($data['links'])[2]];
|
||||
$this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['guid']);
|
||||
$this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['url']);
|
||||
$this->assertContains('http://host.tld:8080/~user/shaarli/?addtag=hashtag', $link['description']);
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
/**
|
||||
* Unitary tests for getIpAddressFromProxy()
|
||||
*/
|
||||
class GetIpAdressFromProxyTest extends PHPUnit_Framework_TestCase {
|
||||
class GetIpAdressFromProxyTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Test without proxy
|
||||
|
|
|
@ -239,12 +239,12 @@ public function testCountHiddenPublic()
|
|||
public function testDays()
|
||||
{
|
||||
$this->assertEquals(
|
||||
array('20100310', '20121206', '20130614', '20150310'),
|
||||
array('20100309', '20100310', '20121206', '20121207', '20130614', '20150310'),
|
||||
self::$publicLinkDB->days()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('20100310', '20121206', '20130614', '20141125', '20150310'),
|
||||
array('20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'),
|
||||
self::$privateLinkDB->days()
|
||||
);
|
||||
}
|
||||
|
@ -475,13 +475,15 @@ public function testFilterHashInValid()
|
|||
public function testReorderLinksDesc()
|
||||
{
|
||||
self::$privateLinkDB->reorder('ASC');
|
||||
$linkIds = array(42, 4, 9, 1, 0, 7, 6, 8, 41);
|
||||
$stickyIds = [11, 10];
|
||||
$standardIds = [42, 4, 9, 1, 0, 7, 6, 8, 41];
|
||||
$linkIds = array_merge($stickyIds, $standardIds);
|
||||
$cpt = 0;
|
||||
foreach (self::$privateLinkDB as $key => $value) {
|
||||
$this->assertEquals($linkIds[$cpt++], $key);
|
||||
}
|
||||
self::$privateLinkDB->reorder('DESC');
|
||||
$linkIds = array_reverse($linkIds);
|
||||
$linkIds = array_merge(array_reverse($stickyIds), array_reverse($standardIds));
|
||||
$cpt = 0;
|
||||
foreach (self::$privateLinkDB as $key => $value) {
|
||||
$this->assertEquals($linkIds[$cpt++], $key);
|
||||
|
|
|
@ -76,7 +76,15 @@ public function testFilter()
|
|||
|
||||
$this->assertEquals(
|
||||
self::$refDB->countUntaggedLinks(),
|
||||
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, /*$request=*/'', /*$casesensitive=*/false, /*$visibility=*/'all', /*$untaggedonly=*/true))
|
||||
count(
|
||||
self::$linkFilter->filter(
|
||||
LinkFilter::$FILTER_TAG,
|
||||
/*$request=*/'',
|
||||
/*$casesensitive=*/false,
|
||||
/*$visibility=*/'all',
|
||||
/*$untaggedonly=*/true
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
|
|
|
@ -83,7 +83,9 @@ public function testCurlDownloadCallbackOk()
|
|||
'Date: Sat, 28 Oct 2017 12:01:33 GMT',
|
||||
'Content-Type: text/html; charset=utf-8',
|
||||
'Status: 200 OK',
|
||||
'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea',
|
||||
'end' => 'th=device-width">'
|
||||
.'<title>Refactoring · GitHub</title>'
|
||||
.'<link rel="search" type="application/opensea',
|
||||
'<title>ignored</title>',
|
||||
];
|
||||
foreach ($data as $key => $line) {
|
||||
|
@ -106,7 +108,9 @@ public function testCurlDownloadCallbackOkNoCharset()
|
|||
$callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset');
|
||||
$data = [
|
||||
'HTTP/1.1 200 OK',
|
||||
'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea',
|
||||
'end' => 'th=device-width">'
|
||||
.'<title>Refactoring · GitHub</title>'
|
||||
.'<link rel="search" type="application/opensea',
|
||||
'<title>ignored</title>',
|
||||
];
|
||||
foreach ($data as $key => $line) {
|
||||
|
@ -126,7 +130,9 @@ public function testCurlDownloadCallbackOkHtmlCharset()
|
|||
$data = [
|
||||
'HTTP/1.1 200 OK',
|
||||
'<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
|
||||
'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea',
|
||||
'end' => 'th=device-width">'
|
||||
.'<title>Refactoring · GitHub</title>'
|
||||
.'<link rel="search" type="application/opensea',
|
||||
'<title>ignored</title>',
|
||||
];
|
||||
foreach ($data as $key => $line) {
|
||||
|
@ -211,23 +217,26 @@ public function testCountPrivateLinks()
|
|||
public function testText2clickableWithoutRedirector()
|
||||
{
|
||||
$text = 'stuff http://hello.there/is=someone#here otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here">http://hello.there/is=someone#here</a> otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here">'
|
||||
.'http://hello.there/is=someone#here</a> otherstuff';
|
||||
$processedText = text2clickable($text, '');
|
||||
$this->assertEquals($expectedText, $processedText);
|
||||
|
||||
$text = 'stuff http://hello.there/is=someone#here(please) otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)">http://hello.there/is=someone#here(please)</a> otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)">'
|
||||
.'http://hello.there/is=someone#here(please)</a> otherstuff';
|
||||
$processedText = text2clickable($text, '');
|
||||
$this->assertEquals($expectedText, $processedText);
|
||||
|
||||
$text = 'stuff http://hello.there/is=someone#here(please)&no otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)&no">http://hello.there/is=someone#here(please)&no</a> otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)&no">'
|
||||
.'http://hello.there/is=someone#here(please)&no</a> otherstuff';
|
||||
$processedText = text2clickable($text, '');
|
||||
$this->assertEquals($expectedText, $processedText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test text2clickable a redirector set.
|
||||
* Test text2clickable with a redirector set.
|
||||
*/
|
||||
public function testText2clickableWithRedirector()
|
||||
{
|
||||
|
@ -410,4 +419,3 @@ function ut_curl_getinfo_rs_ct_ko($ch, $type)
|
|||
return 'text/plain';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ public function testFilterAndFormatDoNotPrependNoteUrl()
|
|||
$links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, '');
|
||||
$this->assertEquals(
|
||||
'?WDWyig',
|
||||
$links[0]['url']
|
||||
$links[2]['url']
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ public function testFilterAndFormatPrependNoteUrl()
|
|||
);
|
||||
$this->assertEquals(
|
||||
$indexUrl . '?WDWyig',
|
||||
$links[0]['url']
|
||||
$links[2]['url']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,7 +218,6 @@ public function testFindPageChangepasswdValid()
|
|||
Router::$PAGE_CHANGEPASSWORD,
|
||||
Router::findPage('do=changepasswd&stuff', array(), true)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -98,17 +98,19 @@ public function testThumbnailNotValid()
|
|||
ini_set('error_log', $oldlog);
|
||||
}
|
||||
|
||||
protected function rrmdirContent($dir) {
|
||||
protected function rrmdirContent($dir)
|
||||
{
|
||||
if (is_dir($dir)) {
|
||||
$objects = scandir($dir);
|
||||
foreach ($objects as $object) {
|
||||
if ($object != "." && $object != "..") {
|
||||
if (is_dir($dir."/".$object))
|
||||
if (is_dir($dir."/".$object)) {
|
||||
$this->rrmdirContent($dir."/".$object);
|
||||
else
|
||||
} else {
|
||||
unlink($dir."/".$object);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public function __construct($doneUpdates, $linkDB, $conf, $isLoggedIn)
|
|||
*
|
||||
* @return bool true.
|
||||
*/
|
||||
private final function updateMethodDummy1()
|
||||
final private function updateMethodDummy1()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ private final function updateMethodDummy1()
|
|||
*
|
||||
* @return bool true.
|
||||
*/
|
||||
private final function updateMethodDummy2()
|
||||
final private function updateMethodDummy2()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ private final function updateMethodDummy2()
|
|||
*
|
||||
* @return bool true.
|
||||
*/
|
||||
private final function updateMethodDummy3()
|
||||
final private function updateMethodDummy3()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ private final function updateMethodDummy3()
|
|||
*
|
||||
* @throws Exception error.
|
||||
*/
|
||||
private final function updateMethodException()
|
||||
final private function updateMethodException()
|
||||
{
|
||||
throw new Exception('whatever');
|
||||
}
|
||||
|
|
|
@ -393,20 +393,32 @@ public function testDatastoreIds()
|
|||
$this->assertEquals('Naming conventions... #private', $linkDB[0]['description']);
|
||||
$this->assertEquals('samba cartoon web', $linkDB[0]['tags']);
|
||||
$this->assertTrue($linkDB[0]['private']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_142300'), $linkDB[0]['created']);
|
||||
$this->assertEquals(
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_142300'),
|
||||
$linkDB[0]['created']
|
||||
);
|
||||
|
||||
$this->assertTrue(isset($linkDB[1]));
|
||||
$this->assertFalse(isset($linkDB[1]['linkdate']));
|
||||
$this->assertEquals(1, $linkDB[1]['id']);
|
||||
$this->assertEquals('UserFriendly - Samba', $linkDB[1]['title']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_172539'), $linkDB[1]['created']);
|
||||
$this->assertEquals(
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_172539'),
|
||||
$linkDB[1]['created']
|
||||
);
|
||||
|
||||
$this->assertTrue(isset($linkDB[2]));
|
||||
$this->assertFalse(isset($linkDB[2]['linkdate']));
|
||||
$this->assertEquals(2, $linkDB[2]['id']);
|
||||
$this->assertEquals('Geek and Poke', $linkDB[2]['title']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_182539'), $linkDB[2]['created']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_190301'), $linkDB[2]['updated']);
|
||||
$this->assertEquals(
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_182539'),
|
||||
$linkDB[2]['created']
|
||||
);
|
||||
$this->assertEquals(
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_190301'),
|
||||
$linkDB[2]['updated']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -688,6 +700,7 @@ public function testUpdateMethodDownloadSizeAndTimeoutConfOnlyTimeout()
|
|||
}
|
||||
|
||||
/**
|
||||
<<<<<<< HEAD
|
||||
* Test updateMethodWebThumbnailer with thumbnails enabled.
|
||||
*/
|
||||
public function testUpdateMethodWebThumbnailerEnabled()
|
||||
|
@ -732,4 +745,64 @@ public function testUpdateMethodWebThumbnailerNothingToDo()
|
|||
$this->assertEquals(53, $this->conf->get('thumbnails.height'));
|
||||
$this->assertTrue(empty($_SESSION['warnings']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test updateMethodSetSticky().
|
||||
*/
|
||||
public function testUpdateStickyValid()
|
||||
{
|
||||
$blank = [
|
||||
'id' => 1,
|
||||
'url' => 'z',
|
||||
'title' => '',
|
||||
'description' => '',
|
||||
'tags' => '',
|
||||
'created' => new DateTime(),
|
||||
];
|
||||
$links = [
|
||||
1 => ['id' => 1] + $blank,
|
||||
2 => ['id' => 2] + $blank,
|
||||
];
|
||||
$refDB = new ReferenceLinkDB();
|
||||
$refDB->setLinks($links);
|
||||
$refDB->write(self::$testDatastore);
|
||||
$linkDB = new LinkDB(self::$testDatastore, true, false);
|
||||
|
||||
$updater = new Updater(array(), $linkDB, $this->conf, true);
|
||||
$this->assertTrue($updater->updateMethodSetSticky());
|
||||
|
||||
$linkDB = new LinkDB(self::$testDatastore, true, false);
|
||||
foreach ($linkDB as $link) {
|
||||
$this->assertFalse($link['sticky']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test updateMethodSetSticky().
|
||||
*/
|
||||
public function testUpdateStickyNothingToDo()
|
||||
{
|
||||
$blank = [
|
||||
'id' => 1,
|
||||
'url' => 'z',
|
||||
'title' => '',
|
||||
'description' => '',
|
||||
'tags' => '',
|
||||
'created' => new DateTime(),
|
||||
];
|
||||
$links = [
|
||||
1 => ['id' => 1, 'sticky' => true] + $blank,
|
||||
2 => ['id' => 2] + $blank,
|
||||
];
|
||||
$refDB = new ReferenceLinkDB();
|
||||
$refDB->setLinks($links);
|
||||
$refDB->write(self::$testDatastore);
|
||||
$linkDB = new LinkDB(self::$testDatastore, true, false);
|
||||
|
||||
$updater = new Updater(array(), $linkDB, $this->conf, true);
|
||||
$this->assertTrue($updater->updateMethodSetSticky());
|
||||
|
||||
$linkDB = new LinkDB(self::$testDatastore, true, false);
|
||||
$this->assertTrue($linkDB[1]['sticky']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,4 +107,3 @@ public function testCleanupUrlQueryFragment()
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,4 +28,3 @@ public function testGetUrlScheme()
|
|||
$this->assertEquals('git', get_url_scheme('git://domain.tld/push?pull=clone#checkout'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,4 +28,3 @@ public function testUnparseFull()
|
|||
$this->assertEquals($ref, unparse_url(parse_url($ref)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -135,13 +135,13 @@ public function testCleanupMixedContent()
|
|||
'about://reader?url=' . urlencode(self::$baseUrl .'?my=stuff&is=kept')
|
||||
);
|
||||
$this->assertEquals(self::$baseUrl.'?my=stuff&is=kept', $url->cleanup());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test default http scheme.
|
||||
*/
|
||||
public function testDefaultScheme() {
|
||||
public function testDefaultScheme()
|
||||
{
|
||||
$url = new Url(self::$baseUrl);
|
||||
$this->assertEquals('http', $url->getScheme());
|
||||
$url = new Url('domain.tld');
|
||||
|
|
|
@ -187,7 +187,8 @@ public function testCheckInvalidDateFormat()
|
|||
/**
|
||||
* Test generate location with valid data.
|
||||
*/
|
||||
public function testGenerateLocation() {
|
||||
public function testGenerateLocation()
|
||||
{
|
||||
$ref = 'http://localhost/?test';
|
||||
$this->assertEquals($ref, generateLocation($ref, 'localhost'));
|
||||
$ref = 'http://localhost:8080/?test';
|
||||
|
@ -199,7 +200,8 @@ public function testGenerateLocation() {
|
|||
/**
|
||||
* Test generate location - anti loop.
|
||||
*/
|
||||
public function testGenerateLocationLoop() {
|
||||
public function testGenerateLocationLoop()
|
||||
{
|
||||
$ref = 'http://localhost/?test';
|
||||
$this->assertEquals('?', generateLocation($ref, 'localhost', array('test')));
|
||||
}
|
||||
|
@ -207,7 +209,8 @@ public function testGenerateLocationLoop() {
|
|||
/**
|
||||
* Test generate location - from other domain.
|
||||
*/
|
||||
public function testGenerateLocationOut() {
|
||||
public function testGenerateLocationOut()
|
||||
{
|
||||
$ref = 'http://somewebsite.com/?test';
|
||||
$this->assertEquals('?', generateLocation($ref, 'localhost'));
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
use Shaarli\Base64Url;
|
||||
|
||||
|
||||
/**
|
||||
* Class ApiUtilsTest
|
||||
*/
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
namespace Shaarli\Api\Controllers;
|
||||
|
||||
|
||||
use Shaarli\Config\ConfigManager;
|
||||
use Slim\Container;
|
||||
use Slim\Http\Environment;
|
||||
|
|
|
@ -95,7 +95,7 @@ public function testGetLinks()
|
|||
$this->assertEquals($this->refDB->countLinks(), count($data));
|
||||
|
||||
// Check order
|
||||
$order = [41, 8, 6, 7, 0, 1, 9, 4, 42];
|
||||
$order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
|
||||
$cpt = 0;
|
||||
foreach ($data as $link) {
|
||||
$this->assertEquals(self::NB_FIELDS_LINK, count($link));
|
||||
|
@ -103,7 +103,7 @@ public function testGetLinks()
|
|||
}
|
||||
|
||||
// Check first element fields
|
||||
$first = $data[0];
|
||||
$first = $data[2];
|
||||
$this->assertEquals('http://domain.tld/?WDWyig', $first['url']);
|
||||
$this->assertEquals('WDWyig', $first['shorturl']);
|
||||
$this->assertEquals('Link title: @website', $first['title']);
|
||||
|
@ -120,7 +120,7 @@ public function testGetLinks()
|
|||
$this->assertEmpty($first['updated']);
|
||||
|
||||
// Multi tags
|
||||
$link = $data[1];
|
||||
$link = $data[3];
|
||||
$this->assertEquals(7, count($link['tags']));
|
||||
|
||||
// Update date
|
||||
|
@ -138,7 +138,7 @@ public function testGetLinksOffsetLimit()
|
|||
{
|
||||
$env = Environment::mock([
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'QUERY_STRING' => 'offset=1&limit=1'
|
||||
'QUERY_STRING' => 'offset=3&limit=1'
|
||||
]);
|
||||
$request = Request::createFromEnvironment($env);
|
||||
$response = $this->controller->getLinks($request, new Response());
|
||||
|
@ -164,7 +164,7 @@ public function testGetLinksLimitAll()
|
|||
$data = json_decode((string) $response->getBody(), true);
|
||||
$this->assertEquals($this->refDB->countLinks(), count($data));
|
||||
// Check order
|
||||
$order = [41, 8, 6, 7, 0, 1, 9, 4, 42];
|
||||
$order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
|
||||
$cpt = 0;
|
||||
foreach ($data as $link) {
|
||||
$this->assertEquals(self::NB_FIELDS_LINK, count($link));
|
||||
|
@ -205,7 +205,8 @@ public function testGetLinksVisibilityAll()
|
|||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$data = json_decode((string)$response->getBody(), true);
|
||||
$this->assertEquals($this->refDB->countLinks(), count($data));
|
||||
$this->assertEquals(41, $data[0]['id']);
|
||||
$this->assertEquals(10, $data[0]['id']);
|
||||
$this->assertEquals(41, $data[2]['id']);
|
||||
$this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
|
||||
}
|
||||
|
||||
|
@ -243,7 +244,8 @@ public function testGetLinksVisibilityPublic()
|
|||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$data = json_decode((string)$response->getBody(), true);
|
||||
$this->assertEquals($this->refDB->countPublicLinks(), count($data));
|
||||
$this->assertEquals(41, $data[0]['id']);
|
||||
$this->assertEquals(10, $data[0]['id']);
|
||||
$this->assertEquals(41, $data[2]['id']);
|
||||
$this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
|
||||
}
|
||||
|
||||
|
@ -413,8 +415,9 @@ public function testGetLinksSearchTags()
|
|||
$response = $this->controller->getLinks($request, new Response());
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$data = json_decode((string) $response->getBody(), true);
|
||||
$this->assertEquals(9, count($data));
|
||||
$this->assertEquals(41, $data[0]['id']);
|
||||
$this->assertEquals(\ReferenceLinkDB::$NB_LINKS_TOTAL, count($data));
|
||||
$this->assertEquals(10, $data[0]['id']);
|
||||
$this->assertEquals(41, $data[2]['id']);
|
||||
|
||||
// wildcard: optional ('*' does not need to expand)
|
||||
$env = Environment::mock([
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Shaarli\Api\Controllers;
|
||||
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shaarli\Config\ConfigManager;
|
||||
use Slim\Container;
|
||||
|
@ -128,7 +127,9 @@ public function testPostLinkMinimal()
|
|||
$this->assertEquals('', $data['description']);
|
||||
$this->assertEquals([], $data['tags']);
|
||||
$this->assertEquals(false, $data['private']);
|
||||
$this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created']));
|
||||
$this->assertTrue(
|
||||
new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
|
||||
);
|
||||
$this->assertEquals('', $data['updated']);
|
||||
|
||||
$historyEntry = $this->history->getHistory()[0];
|
||||
|
@ -171,7 +172,9 @@ public function testPostLinkFull()
|
|||
$this->assertEquals($link['description'], $data['description']);
|
||||
$this->assertEquals($link['tags'], $data['tags']);
|
||||
$this->assertEquals(true, $data['private']);
|
||||
$this->assertTrue(new \DateTime('2 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created']));
|
||||
$this->assertTrue(
|
||||
new \DateTime('2 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
|
||||
);
|
||||
$this->assertEquals('', $data['updated']);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
namespace Shaarli\Api\Controllers;
|
||||
|
||||
|
||||
use Shaarli\Config\ConfigManager;
|
||||
use Slim\Container;
|
||||
use Slim\Http\Environment;
|
||||
|
@ -115,7 +114,9 @@ public function testPutLinkMinimal()
|
|||
\DateTime::createFromFormat('Ymd_His', '20150310_114651'),
|
||||
\DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
|
||||
);
|
||||
$this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated']));
|
||||
$this->assertTrue(
|
||||
new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
|
||||
);
|
||||
|
||||
$historyEntry = $this->history->getHistory()[0];
|
||||
$this->assertEquals(\History::UPDATED, $historyEntry['event']);
|
||||
|
@ -160,7 +161,9 @@ public function testPutLinkWithValues()
|
|||
\DateTime::createFromFormat('Ymd_His', '20150310_114651'),
|
||||
\DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
|
||||
);
|
||||
$this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated']));
|
||||
$this->assertTrue(
|
||||
new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
namespace Shaarli\Api\Controllers;
|
||||
|
||||
|
||||
use Shaarli\Api\Exceptions\ApiBadParametersException;
|
||||
use Shaarli\Config\ConfigManager;
|
||||
use Slim\Container;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
namespace Shaarli;
|
||||
|
||||
|
||||
use Shaarli\Config\ConfigManager;
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,7 @@ public function setUp()
|
|||
/**
|
||||
* Test Isso init without errors.
|
||||
*/
|
||||
public function testWallabagInitNoError()
|
||||
public function testIssoInitNoError()
|
||||
{
|
||||
$conf = new ConfigManager('');
|
||||
$conf->set('plugins.ISSO_SERVER', 'value');
|
||||
|
@ -32,7 +32,7 @@ public function testWallabagInitNoError()
|
|||
/**
|
||||
* Test Isso init with errors.
|
||||
*/
|
||||
public function testWallabagInitError()
|
||||
public function testIssoInitError()
|
||||
{
|
||||
$conf = new ConfigManager('');
|
||||
$errors = isso_init($conf);
|
||||
|
@ -96,19 +96,22 @@ public function testIssoMultipleLinks()
|
|||
array(
|
||||
'id' => 12,
|
||||
'url' => $str,
|
||||
'shorturl' => $short1 = 'abcd',
|
||||
'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $date1),
|
||||
),
|
||||
array(
|
||||
'id' => 13,
|
||||
'url' => $str . '2',
|
||||
'shorturl' => $short2 = 'efgh',
|
||||
'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $date2),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$processed = hook_isso_render_linklist($data, $conf);
|
||||
// data shouldn't be altered
|
||||
$this->assertEquals($data, $processed);
|
||||
// link_plugin should be added for the icon
|
||||
$this->assertContains('<a href="?'. $short1 .'#isso-thread">', $processed['links'][0]['link_plugin'][0]);
|
||||
$this->assertContains('<a href="?'. $short2 .'#isso-thread">', $processed['links'][1]['link_plugin'][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,6 +130,7 @@ public function testIssoNotDisplayedWhenSearch()
|
|||
array(
|
||||
'id' => 12,
|
||||
'url' => $str,
|
||||
'shorturl' => $short1 = 'abcd',
|
||||
'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $date),
|
||||
)
|
||||
),
|
||||
|
@ -135,8 +139,8 @@ public function testIssoNotDisplayedWhenSearch()
|
|||
|
||||
$processed = hook_isso_render_linklist($data, $conf);
|
||||
|
||||
// data shouldn't be altered
|
||||
$this->assertEquals($data, $processed);
|
||||
// link_plugin should be added for the icon
|
||||
$this->assertContains('<a href="?'. $short1 .'#isso-thread">', $processed['links'][0]['link_plugin'][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,6 +47,8 @@ public function testMarkdownLinklist()
|
|||
$data = hook_markdown_render_linklist($data, $this->conf);
|
||||
$this->assertNotFalse(strpos($data['links'][0]['description'], '<h1>'));
|
||||
$this->assertNotFalse(strpos($data['links'][0]['description'], '<p>'));
|
||||
|
||||
$this->assertEquals($markdown, $data['links'][0]['description_src']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,6 +108,18 @@ public function testReverseText2clickable()
|
|||
$this->assertEquals($text, $reversedText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test reverse_text2clickable().
|
||||
*/
|
||||
public function testReverseText2clickableHashtags()
|
||||
{
|
||||
$text = file_get_contents('tests/plugins/resources/hashtags.raw');
|
||||
$md = file_get_contents('tests/plugins/resources/hashtags.md');
|
||||
$clickableText = hashtag_autolink($text);
|
||||
$reversedText = reverse_text2clickable($clickableText);
|
||||
$this->assertEquals($md, $reversedText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test reverse_nl2br().
|
||||
*/
|
||||
|
@ -246,7 +260,7 @@ public function testMarkdownGlobalProcessDescription()
|
|||
$this->conf->get('security.markdown_escape', true),
|
||||
$this->conf->get('security.allowed_protocols')
|
||||
);
|
||||
$this->assertEquals($html, $data);
|
||||
$this->assertEquals($html, $data . PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,7 +15,8 @@ class PluginQrcodeTest extends PHPUnit_Framework_TestCase
|
|||
/**
|
||||
* Reset plugin path
|
||||
*/
|
||||
public function setUp() {
|
||||
public function setUp()
|
||||
{
|
||||
PluginManager::$PLUGINS_PATH = 'plugins';
|
||||
}
|
||||
|
||||
|
|
10
tests/plugins/resources/hashtags.md
Normal file
10
tests/plugins/resources/hashtags.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
[#lol](?addtag=lol)
|
||||
|
||||
#test
|
||||
|
||||
`#test2`
|
||||
|
||||
```
|
||||
bla #bli blo
|
||||
#bla
|
||||
```
|
10
tests/plugins/resources/hashtags.raw
Normal file
10
tests/plugins/resources/hashtags.raw
Normal file
|
@ -0,0 +1,10 @@
|
|||
#lol
|
||||
|
||||
#test
|
||||
|
||||
`#test2`
|
||||
|
||||
```
|
||||
bla #bli blo
|
||||
#bla
|
||||
```
|
|
@ -12,11 +12,11 @@
|
|||
<li><a href="http://link.tld">two</a></li>
|
||||
<li><a href="http://link.tld">three</a></li>
|
||||
<li><a href="http://link.tld">four</a></li>
|
||||
<li>foo <a href="?addtag=foobar" title="Hashtag foobar">#foobar</a></li>
|
||||
<li>foo <a href="?addtag=foobar">#foobar</a></li>
|
||||
</ol></li>
|
||||
</ol>
|
||||
<p><a href="?addtag=foobar" title="Hashtag foobar">#foobar</a> foo <code>lol #foo</code> <a href="?addtag=bar" title="Hashtag bar">#bar</a></p>
|
||||
<p>fsdfs <a href="http://link.tld">http://link.tld</a> <a href="?addtag=foobar" title="Hashtag foobar">#foobar</a> <code>http://link.tld</code></p>
|
||||
<p><a href="?addtag=foobar">#foobar</a> foo <code>lol #foo</code> <a href="?addtag=bar">#bar</a></p>
|
||||
<p>fsdfs <a href="http://link.tld">http://link.tld</a> <a href="?addtag=foobar">#foobar</a> <code>http://link.tld</code></p>
|
||||
<pre><code>http://link.tld #foobar
|
||||
next #foo</code></pre>
|
||||
<p>Block:</p>
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
use \Shaarli\Security\SessionManager;
|
||||
use \PHPUnit\Framework\TestCase;
|
||||
|
||||
|
||||
/**
|
||||
* Test coverage for SessionManager
|
||||
*/
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
class ReferenceLinkDB
|
||||
{
|
||||
public static $NB_LINKS_TOTAL = 9;
|
||||
public static $NB_LINKS_TOTAL = 11;
|
||||
|
||||
private $_links = array();
|
||||
private $_publicCount = 0;
|
||||
|
@ -15,6 +15,32 @@ class ReferenceLinkDB
|
|||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->addLink(
|
||||
11,
|
||||
'Pined older',
|
||||
'?PCRizQ',
|
||||
'This is an older pinned link',
|
||||
0,
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20100309_101010'),
|
||||
'',
|
||||
null,
|
||||
'PCRizQ',
|
||||
true
|
||||
);
|
||||
|
||||
$this->addLink(
|
||||
10,
|
||||
'Pined',
|
||||
'?0gCTjQ',
|
||||
'This is a pinned link',
|
||||
0,
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121207_152312'),
|
||||
'',
|
||||
null,
|
||||
'0gCTjQ',
|
||||
true
|
||||
);
|
||||
|
||||
$this->addLink(
|
||||
41,
|
||||
'Link title: @website',
|
||||
|
@ -114,8 +140,18 @@ public function __construct()
|
|||
/**
|
||||
* Adds a new link
|
||||
*/
|
||||
protected function addLink($id, $title, $url, $description, $private, $date, $tags, $updated = '', $shorturl = '')
|
||||
{
|
||||
protected function addLink(
|
||||
$id,
|
||||
$title,
|
||||
$url,
|
||||
$description,
|
||||
$private,
|
||||
$date,
|
||||
$tags,
|
||||
$updated = '',
|
||||
$shorturl = '',
|
||||
$pinned = false
|
||||
) {
|
||||
$link = array(
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
|
@ -126,6 +162,7 @@ protected function addLink($id, $title, $url, $description, $private, $date, $ta
|
|||
'created' => $date,
|
||||
'updated' => $updated,
|
||||
'shorturl' => $shorturl ? $shorturl : smallHash($date->format(LinkDB::LINK_DATE_FORMAT) . $id),
|
||||
'sticky' => $pinned
|
||||
);
|
||||
$this->_links[$id] = $link;
|
||||
|
||||
|
@ -165,6 +202,10 @@ public function reorder($order = 'DESC')
|
|||
$order = $order === 'ASC' ? -1 : 1;
|
||||
// Reorder array by dates.
|
||||
usort($this->_links, function ($a, $b) use ($order) {
|
||||
if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) {
|
||||
return $a['sticky'] ? -1 : 1;
|
||||
}
|
||||
|
||||
return $a['created'] < $b['created'] ? 1 * $order : -1 * $order;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
<h2 class="window-title">{"Shaare a new link"|t}</h2>
|
||||
<form method="GET" action="#" name="addform" class="addform">
|
||||
<div>
|
||||
<input type="text" name="post" placeholder="{'URL or leave empty to post a note'|t}" class="autofocus">
|
||||
<label for="shaare">{'URL or leave empty to post a note'|t}</label>
|
||||
<input type="text" name="post" id="shaare" class="autofocus">
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" value="{'Add link'|t}">
|
||||
|
|
|
@ -72,7 +72,7 @@ <h3 class="window-subtitle">{function="format_date($dayDate, false)"}</h3>
|
|||
{if="$thumbnails_enabled && !empty($link.thumbnail)"}
|
||||
<div class="daily-entry-thumbnail">
|
||||
<img data-src="{$link.thumbnail}#" class="b-lazy"
|
||||
src="#"
|
||||
src=""
|
||||
alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" />
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -15,3 +15,23 @@
|
|||
<link type="text/css" rel="stylesheet" href="data/user.css#" />
|
||||
{/if}
|
||||
<link rel="search" type="application/opensearchdescription+xml" href="?do=opensearch#" title="Shaarli search - {$shaarlititle}"/>
|
||||
{if="! empty($links) && count($links) === 1"}
|
||||
{$link=reset($links)}
|
||||
<meta property="og:title" content="{$link.title}" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:url" content="{$index_url}?{$link.shorturl}" />
|
||||
{$ogDescription=isset($link.description_src) ? $link.description_src : $link.description}
|
||||
<meta property="og:description" content="{function="substr($ogDescription, 0, 300)"}" />
|
||||
{if="$link.thumbnail"}
|
||||
<meta property="og:image" content="{$index_url}{$link.thumbnail}" />
|
||||
{/if}
|
||||
{if="!$hide_timestamps || $is_logged_in"}
|
||||
<meta property="article:published_time" content="{$link.created->format(DateTime::ATOM)}" />
|
||||
{if="$link.updated"}
|
||||
<meta property="article:modified_time" content="{$link.updated->format(DateTime::ATOM)}" />
|
||||
{/if}
|
||||
{/if}
|
||||
{loop="link.taglist"}
|
||||
<meta property="article:tag" content="{$value}" />
|
||||
{/loop}
|
||||
{/if}
|
||||
|
|
|
@ -125,6 +125,8 @@
|
|||
{$strPermalink=t('Permalink')}
|
||||
{$strPermalinkLc=t('permalink')}
|
||||
{$strAddTag=t('Add tag')}
|
||||
{$strToggleSticky=t('Toggle sticky')}
|
||||
{$strSticky=t('Sticky')}
|
||||
{ignore}End of translations{/ignore}
|
||||
{loop="links"}
|
||||
<div class="anchor" id="{$value.shorturl}"></div>
|
||||
|
@ -137,7 +139,7 @@
|
|||
<a href="{$value.real_url}">
|
||||
{ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore}
|
||||
<img data-src="{$value.thumbnail}#" class="b-lazy"
|
||||
src="#"
|
||||
src=""
|
||||
alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" />
|
||||
</a>
|
||||
</div>
|
||||
|
@ -190,7 +192,7 @@ <h2>
|
|||
{if="$is_logged_in"}
|
||||
<div class="linklist-item-infos-controls-group pure-u-0 pure-u-lg-visible">
|
||||
<span class="linklist-item-infos-controls-item ctrl-checkbox">
|
||||
<input type="checkbox" class="delete-checkbox" value="{$value.id}">
|
||||
<input type="checkbox" class="link-checkbox" value="{$value.id}">
|
||||
</span>
|
||||
<span class="linklist-item-infos-controls-item ctrl-edit">
|
||||
<a href="?edit_link={$value.id}" title="{$strEdit}"><i class="fa fa-pencil-square-o edit-link"></i></a>
|
||||
|
@ -201,7 +203,23 @@ <h2>
|
|||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</span>
|
||||
<span class="linklist-item-infos-controls-item ctrl-pin">
|
||||
<a href="?do=pin&id={$value.id}&token={$token}"
|
||||
title="{$strToggleSticky}" class="pin-link {if="$value.sticky"}pinned-link{/if} pure-u-0 pure-u-lg-visible">
|
||||
<i class="fa fa-thumb-tack"></i>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
{else}
|
||||
{if="$value.sticky"}
|
||||
<div class="linklist-item-infos-controls-group pure-u-0 pure-u-lg-visible">
|
||||
<span class="linklist-item-infos-controls-item ctrl-pin">
|
||||
<span title="{$strSticky}" class="pin-link pinned-link pure-u-0 pure-u-lg-visible">
|
||||
<i class="fa fa-thumb-tack"></i>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
<a href="?{$value.shorturl}" title="{$strPermalink}">
|
||||
{if="!$hide_timestamps || $is_logged_in"}
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
<a href="?untaggedonly" title="{'Filter untagged links'|t}"
|
||||
class={if="$untaggedonly"}"filter-on"{else}"filter-off"{/if}
|
||||
><i class="fa fa-tag"></i></a>
|
||||
<a href="#" title="{'Select all'|t}"
|
||||
class="filter-off select-all-button"
|
||||
><i class="fa fa-check-square-o"></i></a>
|
||||
<a href="#" class="filter-off fold-all pure-u-lg-0" title="{'Fold all'|t}">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
<div id="actions" class="subheader-form">
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1">
|
||||
<a href="" id="actions-delete" class="button">Delete</a>
|
||||
<a href="" id="actions-delete" class="button">{'Delete'|t}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -37,7 +37,7 @@ <h2 class="window-title">{'Picture Wall'|t} - {$countPics} {'pics'|t}</h2>
|
|||
<div class="picwall-pictureframe">
|
||||
{ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore}
|
||||
<img data-src="{$value.thumbnail}#" class="b-lazy"
|
||||
src="#"
|
||||
src=""
|
||||
alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" />
|
||||
<a href="{$value.real_url}"><span class="info">{$value.title}</span></a>
|
||||
{loop="$value.picwall_plugin"}
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
{if="$thumbnails_enabled && !empty($link.thumbnail)"}
|
||||
<div class="dailyEntryThumbnail">
|
||||
<img data-src="{$link.thumbnail}#" class="b-lazy"
|
||||
src="#"
|
||||
src=""
|
||||
alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" />
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -12,3 +12,23 @@
|
|||
{/loop}
|
||||
{if="is_file('data/user.css')"}<link type="text/css" rel="stylesheet" href="data/user.css#" />{/if}
|
||||
<link rel="search" type="application/opensearchdescription+xml" href="?do=opensearch#" title="Shaarli search - {$shaarlititle|htmlspecialchars}"/>
|
||||
{if="! empty($links) && count($links) === 1"}
|
||||
{$link=reset($links)}
|
||||
<meta property="og:title" content="{$link.title}" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:url" content="{$index_url}?{$link.shorturl}" />
|
||||
{$ogDescription=isset($link.description_src) ? $link.description_src : $link.description}
|
||||
<meta property="og:description" content="{function="mb_substr($ogDescription, 0, 300)"}" />
|
||||
{if="$link.thumbnail"}
|
||||
<meta property="og:image" content="{$index_url}{$link.thumbnail}" />
|
||||
{/if}
|
||||
{if="!$hide_timestamps || $is_logged_in"}
|
||||
<meta property="article:published_time" content="{$link.created->format(DateTime::ATOM)}" />
|
||||
{if="$link.updated"}
|
||||
<meta property="article:modified_time" content="{$link.updated->format(DateTime::ATOM)}" />
|
||||
{/if}
|
||||
{/if}
|
||||
{loop="link.taglist"}
|
||||
<meta property="article:tag" content="{$value}" />
|
||||
{/loop}
|
||||
{/if}
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
<a href="{$value.real_url}">
|
||||
{ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore}
|
||||
<img data-src="{$value.thumbnail}#" class="b-lazy"
|
||||
src="#"
|
||||
src=""
|
||||
alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" />
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<div class="picwall_pictureframe">
|
||||
{ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore}
|
||||
<img data-src="{$value.thumbnail}#" class="b-lazy"
|
||||
src="#"
|
||||
src=""
|
||||
alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" />
|
||||
<a href="{$value.real_url}"><span class="info">{$value.title}</span></a>
|
||||
{loop="$value.picwall_plugin"}
|
||||
|
|
Loading…
Reference in a new issue