aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--COPYING4
-rw-r--r--Makefile94
-rw-r--r--README.md9
-rw-r--r--composer.json14
-rw-r--r--inc/LICENSE120
-rw-r--r--inc/blazy-1.3.1.js232
-rw-r--r--inc/blazy-1.3.1.min.js6
-rw-r--r--inc/jquery.lazyload-1.9.3.js242
-rw-r--r--inc/jquery.lazyload-1.9.3.min.js2
-rw-r--r--inc/shaarli.css12
-rw-r--r--index.php27
-rw-r--r--shaarli_version.php1
-rw-r--r--shaarli_version.txt1
-rw-r--r--tpl/configure.html4
-rw-r--r--tpl/includes.html4
-rw-r--r--tpl/install.html25
-rw-r--r--tpl/picwall.html12
-rw-r--r--tpl/picwall2.html19
-rw-r--r--tpl/tools.html1
20 files changed, 412 insertions, 426 deletions
diff --git a/.gitignore b/.gitignore
index 6452c2c6..33d8a488 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,11 @@ pagecache
10.project 10.project
11 11
12# Ignore raintpl generated pages 12# Ignore raintpl generated pages
13*.rtpl.php \ No newline at end of file 13*.rtpl.php
14
15# Ignore test dependencies
16composer.lock
17/vendor/
18
19# Ignore test output
20phpmd.html
diff --git a/COPYING b/COPYING
index 715ba35a..ec4f7681 100644
--- a/COPYING
+++ b/COPYING
@@ -50,9 +50,9 @@ Files: Files: inc/jquery*.js, inc/jquery-ui*.js
50License: MIT License (http://opensource.org/licenses/MIT) 50License: MIT License (http://opensource.org/licenses/MIT)
51Copyright: (C) jQuery Foundation and other contributors,https://jquery.com/download/ 51Copyright: (C) jQuery Foundation and other contributors,https://jquery.com/download/
52 52
53Files: inc/jquery-lazyload*.js 53Files: inc/blazy*.js
54License: MIT License (http://opensource.org/licenses/MIT) 54License: MIT License (http://opensource.org/licenses/MIT)
55Copyright: (C) Mika Tuupola, https://github.com/tuupola 55Copyright: (C) Bjoern Klinggaard - @bklinggaard - http://dinbror.dk/blazy
56 56
57Files: inc/qr.js 57Files: inc/qr.js
58License: GPLv3 License (http://opensource.org/licenses/gpl-3.0) 58License: GPLv3 License (http://opensource.org/licenses/gpl-3.0)
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..e17c8628
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,94 @@
1# Shaarli, the personal, minimalist, super-fast, no-database delicious clone.
2#
3# Makefile for PHP code analysis & testing
4#
5# Prerequisites:
6# - install Composer, either:
7# - from your distro's package manager;
8# - from the official website (https://getcomposer.org/download/);
9# - install/update test dependencies:
10# $ composer install # 1st setup
11# $ composer update
12BIN = vendor/bin
13PHP_SOURCE = index.php
14MESS_DETECTOR_RULES = cleancode,codesize,controversial,design,naming,unusedcode
15
16all: static_analysis_summary
17
18##
19# Concise status of the project
20#
21# These targets are non-blocking: || exit 0
22##
23static_analysis_summary: code_sniffer_source copy_paste mess_detector_summary
24
25##
26# PHP_CodeSniffer
27#
28# Detects PHP syntax errors
29#
30# Documentation (usage, output formatting):
31# - http://pear.php.net/manual/en/package.php.php-codesniffer.usage.php
32# - http://pear.php.net/manual/en/package.php.php-codesniffer.reporting.php
33##
34code_sniffer: code_sniffer_full
35
36# - errors by Git author
37code_sniffer_blame:
38 @$(BIN)/phpcs $(PHP_SOURCE) --report-gitblame
39
40# - all errors/warnings
41code_sniffer_full:
42 @$(BIN)/phpcs $(PHP_SOURCE) --report-full --report-width=200
43
44# - errors grouped by kind
45code_sniffer_source:
46 @$(BIN)/phpcs $(PHP_SOURCE) --report-source || exit 0
47
48##
49# PHP Copy/Paste Detector
50#
51# Detects code redundancy
52#
53# Documentation: https://github.com/sebastianbergmann/phpcpd
54##
55copy_paste:
56 @echo "-----------------------"
57 @echo "PHP COPY/PASTE DETECTOR"
58 @echo "-----------------------"
59 @$(BIN)/phpcpd $(PHP_SOURCE) || exit 0
60 @echo
61
62##
63# PHP Mess Detector
64#
65# Detects PHP syntax errors, sorted by category
66#
67# Rules documentation: http://phpmd.org/rules/index.html
68#
69mess_title:
70 @echo "-----------------"
71 @echo "PHP MESS DETECTOR"
72 @echo "-----------------"
73
74# - all warnings
75mess_detector: mess_title
76 @$(BIN)/phpmd $(PHP_SOURCE) text $(MESS_DETECTOR_RULES) | sed 's_.*\/__'
77
78# - all warnings
79# the generated HTML contains links to PHPMD's documentation
80mess_detector_html:
81 @$(BIN)/phpmd $(PHP_SOURCE) html $(MESS_DETECTOR_RULES) \
82 --reportfile phpmd.html || exit 0
83
84# - warnings grouped by message, sorted by descending frequency order
85mess_detector_grouped: mess_title
86 @$(BIN)/phpmd $(PHP_SOURCE) text $(MESS_DETECTOR_RULES) \
87 | cut -f 2 | sort | uniq -c | sort -nr
88
89# - summary: number of warnings by rule set
90mess_detector_summary: mess_title
91 @for rule in $$(echo $(MESS_DETECTOR_RULES) | tr ',' ' '); do \
92 warnings=$$($(BIN)/phpmd $(PHP_SOURCE) text $$rule | wc -l); \
93 printf "$$warnings\t$$rule\n"; \
94 done;
diff --git a/README.md b/README.md
index 0397621a..7f0b7d5f 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ Shaarli, the personal, minimalist, super-fast, no-database delicious clone.
5You want to share the links you discover ? Shaarli is a minimalist delicious clone you can install on your own website. 5You want to share the links you discover ? Shaarli is a minimalist delicious clone you can install on your own website.
6It is designed to be personal (single-user), fast and handy. 6It is designed to be personal (single-user), fast and handy.
7 7
8[![Join the chat at https://gitter.im/shaarli/Shaarli](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/shaarli/Shaarli?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 8[![Join the chat at https://gitter.im/shaarli/Shaarli](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/shaarli/Shaarli) [![Bountysource](https://www.bountysource.com/badge/team?team_id=19583&style=bounties_received)](https://www.bountysource.com/teams/shaarli/issues)
9 9
10## Features: 10## Features:
11 11
@@ -51,7 +51,7 @@ It is designed to be personal (single-user), fast and handy.
51 51
52## Installing 52## Installing
53 53
54Shaarli requires php 5.1 54Shaarli requires php 5.1. `php-gd` is optional and provides thumbnail resizing.
55 55
56 * Download the latest stable release from https://github.com/shaarli/Shaarli/releases 56 * Download the latest stable release from https://github.com/shaarli/Shaarli/releases
57 * Unpack the archive in a directory on your web server 57 * Unpack the archive in a directory on your web server
@@ -63,9 +63,8 @@ _To get the development version, download https://github.com/shaarli/Shaarli/arc
63 63
64## Upgrading 64## Upgrading
65 65
66Delete all files and directories except the `data` directory, then unzip the new version of Shaarli. 66 * **If you installed from the zip:** Delete all files and directories except the `data` directory, then unzip the new version of Shaarli. You will not lose your links and you will not have to reconfigure it.
67You will not lose your links and you will not have to reconfigure it. 67 * **If you installed using `git clone`**: run `git pull` in your Shaarli directory.
68
69 68
70 69
71## About 70## About
diff --git a/composer.json b/composer.json
new file mode 100644
index 00000000..d1f613c1
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,14 @@
1{
2 "name": "shaarli/shaarli",
3 "description": "The personal, minimalist, super-fast, no-database delicious clone",
4 "license": "MIT",
5 "support": {
6 "issues": "https://github.com/shaarli/Shaarli/issues"
7 },
8 "require": {},
9 "require-dev": {
10 "phpmd/phpmd" : "@stable",
11 "sebastian/phpcpd": "*",
12 "squizlabs/php_codesniffer": "2.*"
13 }
14}
diff --git a/inc/LICENSE b/inc/LICENSE
deleted file mode 100644
index 8711a29a..00000000
--- a/inc/LICENSE
+++ /dev/null
@@ -1,120 +0,0 @@
1JQuery 1.11.2
2===============================================================================
3Copyright jQuery Foundation and other contributors, https://jquery.org/
4
5This software consists of voluntary contributions made by many
6individuals. For exact contribution history, see the revision history
7available at https://github.com/jquery/jquery
8
9The following license applies to all parts of this software except as
10documented below:
11
12====
13
14Permission is hereby granted, free of charge, to any person obtaining
15a copy of this software and associated documentation files (the
16"Software"), to deal in the Software without restriction, including
17without limitation the rights to use, copy, modify, merge, publish,
18distribute, sublicense, and/or sell copies of the Software, and to
19permit persons to whom the Software is furnished to do so, subject to
20the following conditions:
21
22The above copyright notice and this permission notice shall be
23included in all copies or substantial portions of the Software.
24
25THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
33====
34
35All files located in the node_modules and external directories are
36externally maintained libraries used by this software which have their
37own licenses; we recommend you read them, as their terms may differ from
38the terms above.
39
40
41
42JQuery UI 1.11.2
43===============================================================================
44Copyright jQuery Foundation and other contributors, https://jquery.org/
45
46This software consists of voluntary contributions made by many
47individuals. For exact contribution history, see the revision history
48available at https://github.com/jquery/jquery-ui
49
50The following license applies to all parts of this software except as
51documented below:
52
53====
54
55Permission is hereby granted, free of charge, to any person obtaining
56a copy of this software and associated documentation files (the
57"Software"), to deal in the Software without restriction, including
58without limitation the rights to use, copy, modify, merge, publish,
59distribute, sublicense, and/or sell copies of the Software, and to
60permit persons to whom the Software is furnished to do so, subject to
61the following conditions:
62
63The above copyright notice and this permission notice shall be
64included in all copies or substantial portions of the Software.
65
66THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
67EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
69NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
70LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
71OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
72WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
73
74====
75
76Copyright and related rights for sample code are waived via CC0. Sample
77code is defined as all source code contained within the demos directory.
78
79CC0: http://creativecommons.org/publicdomain/zero/1.0/
80
81====
82
83All files located in the node_modules and external directories are
84externally maintained libraries used by this software which have their
85own licenses; we recommend you read them, as their terms may differ from
86the terms above.
87
88
89
90QR.js 1.1.3
91===============================================================================
92Copyright (C) 2014 Alasdair Mercer, http://neocotic.com
93
94This program is free software: you can redistribute it and/or modify
95it under the terms of the GNU General Public License as published by
96the Free Software Foundation, either version 3 of the License, or
97(at your option) any later version.
98
99This program is distributed in the hope that it will be useful,
100but WITHOUT ANY WARRANTY; without even the implied warranty of
101MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
102GNU General Public License for more details.
103
104You should have received a copy of the GNU General Public License
105along with this program. If not, see <http://www.gnu.org/licenses/>.
106
107
108
109
110JQuery Lazyload 1.9.3
111===============================================================================
112By Mika Tuupola (https://github.com/tuupola)
113
114All code licensed under the MIT License[1]. All images licensed under
115Creative Commons Attribution 3.0 Unported License[2]. In other words you are
116basically free to do whatever you want. Just don’t remove my name from the
117source.
118
119[1]: http://opensource.org/licenses/mit-license.php
120[2]: http://creativecommons.org/licenses/by/3.0/deed.en_US \ No newline at end of file
diff --git a/inc/blazy-1.3.1.js b/inc/blazy-1.3.1.js
new file mode 100644
index 00000000..cfc2dbde
--- /dev/null
+++ b/inc/blazy-1.3.1.js
@@ -0,0 +1,232 @@
1/*!
2 hey, [be]Lazy.js - v1.3.1 - 2015.02.01
3 A lazy loading and multi-serving image script
4 (c) Bjoern Klinggaard - @bklinggaard - http://dinbror.dk/blazy
5*/
6;(function(root, blazy) {
7 if (typeof define === 'function' && define.amd) {
8 // AMD. Register bLazy as an anonymous module
9 define(blazy);
10 } else if (typeof exports === 'object') {
11 // Node. Does not work with strict CommonJS, but
12 // only CommonJS-like environments that support module.exports,
13 // like Node.
14 module.exports = blazy();
15 } else {
16 // Browser globals. Register bLazy on window
17 root.Blazy = blazy();
18 }
19})(this, function () {
20 'use strict';
21
22 //vars
23 var source, options, viewport, images, count, isRetina, destroyed;
24 //throttle vars
25 var validateT, saveViewportOffsetT;
26
27 // constructor
28 function Blazy(settings) {
29 //IE7- fallback for missing querySelectorAll support
30 if (!document.querySelectorAll) {
31 var s=document.createStyleSheet();
32 document.querySelectorAll = function(r, c, i, j, a) {
33 a=document.all, c=[], r = r.replace(/\[for\b/gi, '[htmlFor').split(',');
34 for (i=r.length; i--;) {
35 s.addRule(r[i], 'k:v');
36 for (j=a.length; j--;) a[j].currentStyle.k && c.push(a[j]);
37 s.removeRule(0);
38 }
39 return c;
40 };
41 }
42 //init vars
43 destroyed = true;
44 images = [];
45 viewport = {};
46 //options
47 options = settings || {};
48 options.error = options.error || false;
49 options.offset = options.offset || 100;
50 options.success = options.success || false;
51 options.selector = options.selector || '.b-lazy';
52 options.separator = options.separator || '|';
53 options.container = options.container ? document.querySelectorAll(options.container) : false;
54 options.errorClass = options.errorClass || 'b-error';
55 options.breakpoints = options.breakpoints || false;
56 options.successClass = options.successClass || 'b-loaded';
57 options.src = source = options.src || 'data-src';
58 isRetina = window.devicePixelRatio > 1;
59 viewport.top = 0 - options.offset;
60 viewport.left = 0 - options.offset;
61 //throttle, ensures that we don't call the functions too often
62 validateT = throttle(validate, 25);
63 saveViewportOffsetT = throttle(saveViewportOffset, 50);
64
65 saveViewportOffset();
66
67 //handle multi-served image src
68 each(options.breakpoints, function(object){
69 if(object.width >= window.screen.width) {
70 source = object.src;
71 return false;
72 }
73 });
74
75 // start lazy load
76 initialize();
77 }
78
79 /* public functions
80 ************************************/
81 Blazy.prototype.revalidate = function() {
82 initialize();
83 };
84 Blazy.prototype.load = function(element, force){
85 if(!isElementLoaded(element)) loadImage(element, force);
86 };
87 Blazy.prototype.destroy = function(){
88 if(options.container){
89 each(options.container, function(object){
90 unbindEvent(object, 'scroll', validateT);
91 });
92 }
93 unbindEvent(window, 'scroll', validateT);
94 unbindEvent(window, 'resize', validateT);
95 unbindEvent(window, 'resize', saveViewportOffsetT);
96 count = 0;
97 images.length = 0;
98 destroyed = true;
99 };
100
101 /* private helper functions
102 ************************************/
103 function initialize(){
104 // First we create an array of images to lazy load
105 createImageArray(options.selector);
106 // Then we bind resize and scroll events if not already binded
107 if(destroyed) {
108 destroyed = false;
109 if(options.container) {
110 each(options.container, function(object){
111 bindEvent(object, 'scroll', validateT);
112 });
113 }
114 bindEvent(window, 'resize', saveViewportOffsetT);
115 bindEvent(window, 'resize', validateT);
116 bindEvent(window, 'scroll', validateT);
117 }
118 // And finally, we start to lazy load. Should bLazy ensure domready?
119 validate();
120 }
121
122 function validate() {
123 for(var i = 0; i<count; i++){
124 var image = images[i];
125 if(elementInView(image) || isElementLoaded(image)) {
126 Blazy.prototype.load(image);
127 images.splice(i, 1);
128 count--;
129 i--;
130 }
131 }
132 if(count === 0) {
133 Blazy.prototype.destroy();
134 }
135 }
136
137 function loadImage(ele, force){
138 // if element is visible
139 if(force || (ele.offsetWidth > 0 && ele.offsetHeight > 0)) {
140 var dataSrc = ele.getAttribute(source) || ele.getAttribute(options.src); // fallback to default data-src
141 if(dataSrc) {
142 var dataSrcSplitted = dataSrc.split(options.separator);
143 var src = dataSrcSplitted[isRetina && dataSrcSplitted.length > 1 ? 1 : 0];
144 var img = new Image();
145 // cleanup markup, remove data source attributes
146 each(options.breakpoints, function(object){
147 ele.removeAttribute(object.src);
148 });
149 ele.removeAttribute(options.src);
150 img.onerror = function() {
151 if(options.error) options.error(ele, "invalid");
152 ele.className = ele.className + ' ' + options.errorClass;
153 };
154 img.onload = function() {
155 // Is element an image or should we add the src as a background image?
156 ele.nodeName.toLowerCase() === 'img' ? ele.src = src : ele.style.backgroundImage = 'url("' + src + '")';
157 ele.className = ele.className + ' ' + options.successClass;
158 if(options.success) options.success(ele);
159 };
160 img.src = src; //preload image
161 } else {
162 if(options.error) options.error(ele, "missing");
163 ele.className = ele.className + ' ' + options.errorClass;
164 }
165 }
166 }
167
168 function elementInView(ele) {
169 var rect = ele.getBoundingClientRect();
170
171 return (
172 // Intersection
173 rect.right >= viewport.left
174 && rect.bottom >= viewport.top
175 && rect.left <= viewport.right
176 && rect.top <= viewport.bottom
177 );
178 }
179
180 function isElementLoaded(ele) {
181 return (' ' + ele.className + ' ').indexOf(' ' + options.successClass + ' ') !== -1;
182 }
183
184 function createImageArray(selector) {
185 var nodelist = document.querySelectorAll(selector);
186 count = nodelist.length;
187 //converting nodelist to array
188 for(var i = count; i--; images.unshift(nodelist[i])){}
189 }
190
191 function saveViewportOffset(){
192 viewport.bottom = (window.innerHeight || document.documentElement.clientHeight) + options.offset;
193 viewport.right = (window.innerWidth || document.documentElement.clientWidth) + options.offset;
194 }
195
196 function bindEvent(ele, type, fn) {
197 if (ele.attachEvent) {
198 ele.attachEvent && ele.attachEvent('on' + type, fn);
199 } else {
200 ele.addEventListener(type, fn, false);
201 }
202 }
203
204 function unbindEvent(ele, type, fn) {
205 if (ele.detachEvent) {
206 ele.detachEvent && ele.detachEvent('on' + type, fn);
207 } else {
208 ele.removeEventListener(type, fn, false);
209 }
210 }
211
212 function each(object, fn){
213 if(object && fn) {
214 var l = object.length;
215 for(var i = 0; i<l && fn(object[i], i) !== false; i++){}
216 }
217 }
218
219 function throttle(fn, minDelay) {
220 var lastCall = 0;
221 return function() {
222 var now = +new Date();
223 if (now - lastCall < minDelay) {
224 return;
225 }
226 lastCall = now;
227 fn.apply(images, arguments);
228 };
229 }
230
231 return Blazy;
232});
diff --git a/inc/blazy-1.3.1.min.js b/inc/blazy-1.3.1.min.js
new file mode 100644
index 00000000..55cdc2d5
--- /dev/null
+++ b/inc/blazy-1.3.1.min.js
@@ -0,0 +1,6 @@
1/*!
2 hey, [be]Lazy.js - v1.3.1 - 2015.02.01
3 A lazy loading and multi-serving image script
4 (c) Bjoern Klinggaard - @bklinggaard - http://dinbror.dk/blazy
5*/
6 (function(d,h){"function"===typeof define&&define.amd?define(h):"object"===typeof exports?module.exports=h():d.Blazy=h()})(this,function(){function d(b){if(!document.querySelectorAll){var g=document.createStyleSheet();document.querySelectorAll=function(b,a,e,d,f){f=document.all;a=[];b=b.replace(/\[for\b/gi,"[htmlFor").split(",");for(e=b.length;e--;){g.addRule(b[e],"k:v");for(d=f.length;d--;)f[d].currentStyle.k&&a.push(f[d]);g.removeRule(0)}return a}}m=!0;k=[];e={};a=b||{};a.error=a.error||!1;a.offset=a.offset||100;a.success=a.success||!1;a.selector=a.selector||".b-lazy";a.separator=a.separator||"|";a.container=a.container?document.querySelectorAll(a.container):!1;a.errorClass=a.errorClass||"b-error";a.breakpoints=a.breakpoints||!1;a.successClass=a.successClass||"b-loaded";a.src=r=a.src||"data-src";u=1<window.devicePixelRatio;e.top=0-a.offset;e.left=0-a.offset;f=v(w,25);t=v(x,50);x();n(a.breakpoints,function(b){if(b.width>=window.screen.width)return r=b.src,!1});h()}function h(){y(a.selector);m&&(m=!1,a.container&&n(a.container,function(b){p(b,"scroll",f)}),p(window,"resize",t),p(window,"resize",f),p(window,"scroll",f));w()}function w(){for(var b=0;b<l;b++){var g=k[b],c=g.getBoundingClientRect();if(c.right>=e.left&&c.bottom>=e.top&&c.left<=e.right&&c.top<=e.bottom||-1!==(" "+g.className+" ").indexOf(" "+a.successClass+" "))d.prototype.load(g),k.splice(b,1),l--,b--}0===l&&d.prototype.destroy()}function z(b,g){if(g||0<b.offsetWidth&&0<b.offsetHeight){var c=b.getAttribute(r)||b.getAttribute(a.src);if(c){var c=c.split(a.separator),d=c[u&&1<c.length?1:0],c=new Image;n(a.breakpoints,function(a){b.removeAttribute(a.src)});b.removeAttribute(a.src);c.onerror=function(){a.error&&a.error(b,"invalid");b.className=b.className+" "+a.errorClass};c.onload=function(){"img"===b.nodeName.toLowerCase()?b.src=d:b.style.backgroundImage='url("'+d+'")';b.className=b.className+" "+a.successClass;a.success&&a.success(b)};c.src=d}else a.error&&a.error(b,"missing"),b.className=b.className+" "+a.errorClass}}function y(b){b=document.querySelectorAll(b);for(var a=l=b.length;a--;k.unshift(b[a]));}function x(){e.bottom=(window.innerHeight||document.documentElement.clientHeight)+a.offset;e.right=(window.innerWidth||document.documentElement.clientWidth)+a.offset}function p(b,a,c){b.attachEvent?b.attachEvent&&b.attachEvent("on"+a,c):b.addEventListener(a,c,!1)}function q(b,a,c){b.detachEvent?b.detachEvent&&b.detachEvent("on"+a,c):b.removeEventListener(a,c,!1)}function n(a,d){if(a&&d)for(var c=a.length,e=0;e<c&&!1!==d(a[e],e);e++);}function v(a,d){var c=0;return function(){var e=+new Date;e-c<d||(c=e,a.apply(k,arguments))}}var r,a,e,k,l,u,m,f,t;d.prototype.revalidate=function(){h()};d.prototype.load=function(b,d){-1===(" "+b.className+" ").indexOf(" "+a.successClass+" ")&&z(b,d)};d.prototype.destroy=function(){a.container&&n(a.container,function(a){q(a,"scroll",f)});q(window,"scroll",f);q(window,"resize",f);q(window,"resize",t);l=0;k.length=0;m=!0};return d}); \ No newline at end of file
diff --git a/inc/jquery.lazyload-1.9.3.js b/inc/jquery.lazyload-1.9.3.js
deleted file mode 100644
index 5a22d8ea..00000000
--- a/inc/jquery.lazyload-1.9.3.js
+++ /dev/null
@@ -1,242 +0,0 @@
1/*
2 * Lazy Load - jQuery plugin for lazy loading images
3 *
4 * Copyright (c) 2007-2013 Mika Tuupola
5 *
6 * Licensed under the MIT license:
7 * http://www.opensource.org/licenses/mit-license.php
8 *
9 * Project home:
10 * http://www.appelsiini.net/projects/lazyload
11 *
12 * Version: 1.9.3
13 *
14 */
15
16(function($, window, document, undefined) {
17 var $window = $(window);
18
19 $.fn.lazyload = function(options) {
20 var elements = this;
21 var $container;
22 var settings = {
23 threshold : 0,
24 failure_limit : 0,
25 event : "scroll",
26 effect : "show",
27 container : window,
28 data_attribute : "original",
29 skip_invisible : true,
30 appear : null,
31 load : null,
32 placeholder : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"
33 };
34
35 function update() {
36 var counter = 0;
37
38 elements.each(function() {
39 var $this = $(this);
40 if (settings.skip_invisible && !$this.is(":visible")) {
41 return;
42 }
43 if ($.abovethetop(this, settings) ||
44 $.leftofbegin(this, settings)) {
45 /* Nothing. */
46 } else if (!$.belowthefold(this, settings) &&
47 !$.rightoffold(this, settings)) {
48 $this.trigger("appear");
49 /* if we found an image we'll load, reset the counter */
50 counter = 0;
51 } else {
52 if (++counter > settings.failure_limit) {
53 return false;
54 }
55 }
56 });
57
58 }
59
60 if(options) {
61 /* Maintain BC for a couple of versions. */
62 if (undefined !== options.failurelimit) {
63 options.failure_limit = options.failurelimit;
64 delete options.failurelimit;
65 }
66 if (undefined !== options.effectspeed) {
67 options.effect_speed = options.effectspeed;
68 delete options.effectspeed;
69 }
70
71 $.extend(settings, options);
72 }
73
74 /* Cache container as jQuery as object. */
75 $container = (settings.container === undefined ||
76 settings.container === window) ? $window : $(settings.container);
77
78 /* Fire one scroll event per scroll. Not one scroll event per image. */
79 if (0 === settings.event.indexOf("scroll")) {
80 $container.bind(settings.event, function() {
81 return update();
82 });
83 }
84
85 this.each(function() {
86 var self = this;
87 var $self = $(self);
88
89 self.loaded = false;
90
91 /* If no src attribute given use data:uri. */
92 if ($self.attr("src") === undefined || $self.attr("src") === false) {
93 if ($self.is("img")) {
94 $self.attr("src", settings.placeholder);
95 }
96 }
97
98 /* When appear is triggered load original image. */
99 $self.one("appear", function() {
100 if (!this.loaded) {
101 if (settings.appear) {
102 var elements_left = elements.length;
103 settings.appear.call(self, elements_left, settings);
104 }
105 $("<img />")
106 .bind("load", function() {
107
108 var original = $self.attr("data-" + settings.data_attribute);
109 $self.hide();
110 if ($self.is("img")) {
111 $self.attr("src", original);
112 } else {
113 $self.css("background-image", "url('" + original + "')");
114 }
115 $self[settings.effect](settings.effect_speed);
116
117 self.loaded = true;
118
119 /* Remove image from array so it is not looped next time. */
120 var temp = $.grep(elements, function(element) {
121 return !element.loaded;
122 });
123 elements = $(temp);
124
125 if (settings.load) {
126 var elements_left = elements.length;
127 settings.load.call(self, elements_left, settings);
128 }
129 })
130 .attr("src", $self.attr("data-" + settings.data_attribute));
131 }
132 });
133
134 /* When wanted event is triggered load original image */
135 /* by triggering appear. */
136 if (0 !== settings.event.indexOf("scroll")) {
137 $self.bind(settings.event, function() {
138 if (!self.loaded) {
139 $self.trigger("appear");
140 }
141 });
142 }
143 });
144
145 /* Check if something appears when window is resized. */
146 $window.bind("resize", function() {
147 update();
148 });
149
150 /* With IOS5 force loading images when navigating with back button. */
151 /* Non optimal workaround. */
152 if ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) {
153 $window.bind("pageshow", function(event) {
154 if (event.originalEvent && event.originalEvent.persisted) {
155 elements.each(function() {
156 $(this).trigger("appear");
157 });
158 }
159 });
160 }
161
162 /* Force initial check if images should appear. */
163 $(document).ready(function() {
164 update();
165 });
166
167 return this;
168 };
169
170 /* Convenience methods in jQuery namespace. */
171 /* Use as $.belowthefold(element, {threshold : 100, container : window}) */
172
173 $.belowthefold = function(element, settings) {
174 var fold;
175
176 if (settings.container === undefined || settings.container === window) {
177 fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop();
178 } else {
179 fold = $(settings.container).offset().top + $(settings.container).height();
180 }
181
182 return fold <= $(element).offset().top - settings.threshold;
183 };
184
185 $.rightoffold = function(element, settings) {
186 var fold;
187
188 if (settings.container === undefined || settings.container === window) {
189 fold = $window.width() + $window.scrollLeft();
190 } else {
191 fold = $(settings.container).offset().left + $(settings.container).width();
192 }
193
194 return fold <= $(element).offset().left - settings.threshold;
195 };
196
197 $.abovethetop = function(element, settings) {
198 var fold;
199
200 if (settings.container === undefined || settings.container === window) {
201 fold = $window.scrollTop();
202 } else {
203 fold = $(settings.container).offset().top;
204 }
205
206 return fold >= $(element).offset().top + settings.threshold + $(element).height();
207 };
208
209 $.leftofbegin = function(element, settings) {
210 var fold;
211
212 if (settings.container === undefined || settings.container === window) {
213 fold = $window.scrollLeft();
214 } else {
215 fold = $(settings.container).offset().left;
216 }
217
218 return fold >= $(element).offset().left + settings.threshold + $(element).width();
219 };
220
221 $.inviewport = function(element, settings) {
222 return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) &&
223 !$.belowthefold(element, settings) && !$.abovethetop(element, settings);
224 };
225
226 /* Custom selectors for your convenience. */
227 /* Use as $("img:below-the-fold").something() or */
228 /* $("img").filter(":below-the-fold").something() which is faster */
229
230 $.extend($.expr[":"], {
231 "below-the-fold" : function(a) { return $.belowthefold(a, {threshold : 0}); },
232 "above-the-top" : function(a) { return !$.belowthefold(a, {threshold : 0}); },
233 "right-of-screen": function(a) { return $.rightoffold(a, {threshold : 0}); },
234 "left-of-screen" : function(a) { return !$.rightoffold(a, {threshold : 0}); },
235 "in-viewport" : function(a) { return $.inviewport(a, {threshold : 0}); },
236 /* Maintain BC for couple of versions. */
237 "above-the-fold" : function(a) { return !$.belowthefold(a, {threshold : 0}); },
238 "right-of-fold" : function(a) { return $.rightoffold(a, {threshold : 0}); },
239 "left-of-fold" : function(a) { return !$.rightoffold(a, {threshold : 0}); }
240 });
241
242})(jQuery, window, document);
diff --git a/inc/jquery.lazyload-1.9.3.min.js b/inc/jquery.lazyload-1.9.3.min.js
deleted file mode 100644
index 615b90e5..00000000
--- a/inc/jquery.lazyload-1.9.3.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
1/*! Lazy Load 1.9.3 - MIT license - Copyright 2010-2013 Mika Tuupola */
2!function(a,b,c,d){var e=a(b);a.fn.lazyload=function(f){function g(){var b=0;i.each(function(){var c=a(this);if(!j.skip_invisible||c.is(":visible"))if(a.abovethetop(this,j)||a.leftofbegin(this,j));else if(a.belowthefold(this,j)||a.rightoffold(this,j)){if(++b>j.failure_limit)return!1}else c.trigger("appear"),b=0})}var h,i=this,j={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!0,appear:null,load:null,placeholder:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"};return f&&(d!==f.failurelimit&&(f.failure_limit=f.failurelimit,delete f.failurelimit),d!==f.effectspeed&&(f.effect_speed=f.effectspeed,delete f.effectspeed),a.extend(j,f)),h=j.container===d||j.container===b?e:a(j.container),0===j.event.indexOf("scroll")&&h.bind(j.event,function(){return g()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,(c.attr("src")===d||c.attr("src")===!1)&&c.is("img")&&c.attr("src",j.placeholder),c.one("appear",function(){if(!this.loaded){if(j.appear){var d=i.length;j.appear.call(b,d,j)}a("<img />").bind("load",function(){var d=c.attr("data-"+j.data_attribute);c.hide(),c.is("img")?c.attr("src",d):c.css("background-image","url('"+d+"')"),c[j.effect](j.effect_speed),b.loaded=!0;var e=a.grep(i,function(a){return!a.loaded});if(i=a(e),j.load){var f=i.length;j.load.call(b,f,j)}}).attr("src",c.attr("data-"+j.data_attribute))}}),0!==j.event.indexOf("scroll")&&c.bind(j.event,function(){b.loaded||c.trigger("appear")})}),e.bind("resize",function(){g()}),/(?:iphone|ipod|ipad).*os 5/gi.test(navigator.appVersion)&&e.bind("pageshow",function(b){b.originalEvent&&b.originalEvent.persisted&&i.each(function(){a(this).trigger("appear")})}),a(c).ready(function(){g()}),this},a.belowthefold=function(c,f){var g;return g=f.container===d||f.container===b?(b.innerHeight?b.innerHeight:e.height())+e.scrollTop():a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return g=f.container===d||f.container===b?e.width()+e.scrollLeft():a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollTop():a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollLeft():a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!(a.rightoffold(b,c)||a.leftofbegin(b,c)||a.belowthefold(b,c)||a.abovethetop(b,c))},a.extend(a.expr[":"],{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})}(jQuery,window,document); \ No newline at end of file
diff --git a/inc/shaarli.css b/inc/shaarli.css
index bb564e99..a88143ca 100644
--- a/inc/shaarli.css
+++ b/inc/shaarli.css
@@ -647,9 +647,21 @@ a.qrcode img {
647 float: left; 647 float: left;
648} 648}
649 649
650.b-lazy {
651 -webkit-transition: opacity 500ms ease-in-out;
652 -moz-transition: opacity 500ms ease-in-out;
653 -o-transition: opacity 500ms ease-in-out;
654 transition: opacity 500ms ease-in-out;
655 opacity: 0;
656}
657.b-lazy.b-loaded {
658 opacity: 1;
659}
660
650.picwall_pictureframe img { 661.picwall_pictureframe img {
651 max-width: 100%; 662 max-width: 100%;
652 height: auto; 663 height: auto;
664 color: transparent;
653} /* Adapt the width of the image */ 665} /* Adapt the width of the image */
654 666
655.picwall_pictureframe a { 667.picwall_pictureframe a {
diff --git a/index.php b/index.php
index c87b9449..066058e6 100644
--- a/index.php
+++ b/index.php
@@ -178,13 +178,14 @@ function checkphpversion()
178function checkUpdate() 178function checkUpdate()
179{ 179{
180 if (!isLoggedIn()) return ''; // Do not check versions for visitors. 180 if (!isLoggedIn()) return ''; // Do not check versions for visitors.
181 if (empty($GLOBALS['config']['ENABLE_UPDATECHECK'])) return ''; // Do not check if the user doesn't want to.
181 182
182 // Get latest version number at most once a day. 183 // Get latest version number at most once a day.
183 if (!is_file($GLOBALS['config']['UPDATECHECK_FILENAME']) || (filemtime($GLOBALS['config']['UPDATECHECK_FILENAME'])<time()-($GLOBALS['config']['UPDATECHECK_INTERVAL']))) 184 if (!is_file($GLOBALS['config']['UPDATECHECK_FILENAME']) || (filemtime($GLOBALS['config']['UPDATECHECK_FILENAME'])<time()-($GLOBALS['config']['UPDATECHECK_INTERVAL'])))
184 { 185 {
185 $version=shaarli_version; 186 $version=shaarli_version;
186 list($httpstatus,$headers,$data) = getHTTP('https://raw.githubusercontent.com/shaarli/Shaarli/master/shaarli_version.txt',2); 187 list($httpstatus,$headers,$data) = getHTTP('https://raw.githubusercontent.com/shaarli/Shaarli/master/shaarli_version.php',2);
187 if (strpos($httpstatus,'200 OK')!==false) $version=$data; 188 if (strpos($httpstatus,'200 OK')!==false) $version=str_replace(' */ ?>','',str_replace('<?php /* ','',$data));
188 // If failed, never mind. We don't want to bother the user with that. 189 // If failed, never mind. We don't want to bother the user with that.
189 file_put_contents($GLOBALS['config']['UPDATECHECK_FILENAME'],$version); // touch file date 190 file_put_contents($GLOBALS['config']['UPDATECHECK_FILENAME'],$version); // touch file date
190 } 191 }
@@ -1462,6 +1463,7 @@ function renderPage()
1462 $GLOBALS['disablejquery']=!empty($_POST['disablejquery']); 1463 $GLOBALS['disablejquery']=!empty($_POST['disablejquery']);
1463 $GLOBALS['privateLinkByDefault']=!empty($_POST['privateLinkByDefault']); 1464 $GLOBALS['privateLinkByDefault']=!empty($_POST['privateLinkByDefault']);
1464 $GLOBALS['config']['ENABLE_RSS_PERMALINKS']= !empty($_POST['enableRssPermalinks']); 1465 $GLOBALS['config']['ENABLE_RSS_PERMALINKS']= !empty($_POST['enableRssPermalinks']);
1466 $GLOBALS['config']['ENABLE_UPDATECHECK'] = !empty($_POST['updateCheck']);
1465 writeConfig(); 1467 writeConfig();
1466 echo '<script>alert("Configuration was saved.");document.location=\'?do=tools\';</script>'; 1468 echo '<script>alert("Configuration was saved.");document.location=\'?do=tools\';</script>';
1467 exit; 1469 exit;
@@ -1558,6 +1560,7 @@ function renderPage()
1558 if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script>self.close();</script>'; exit; } 1560 if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo '<script>self.close();</script>'; exit; }
1559 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); 1561 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
1560 $returnurl .= '#'.smallHash($linkdate); // Scroll to the link which has been edited. 1562 $returnurl .= '#'.smallHash($linkdate); // Scroll to the link which has been edited.
1563 if (strstr($returnurl, "do=addlink")) { $returnurl = '?'; } //if we come from ?do=addlink, set returnurl to homepage instead
1561 header('Location: '.$returnurl); // After saving the link, redirect to the page the user was on. 1564 header('Location: '.$returnurl); // After saving the link, redirect to the page the user was on.
1562 exit; 1565 exit;
1563 } 1566 }
@@ -1640,10 +1643,13 @@ function renderPage()
1640 { 1643 {
1641 $url=$_GET['post']; 1644 $url=$_GET['post'];
1642 1645
1643 // We remove the annoying parameters added by FeedBurner and GoogleFeedProxy (?utm_source=...) 1646
1644 $i=strpos($url,'&utm_source='); if ($i!==false) $url=substr($url,0,$i); 1647 // We remove the annoying parameters added by FeedBurner, GoogleFeedProxy, Facebook...
1645 $i=strpos($url,'?utm_source='); if ($i!==false) $url=substr($url,0,$i); 1648 $annoyingpatterns = array('/[\?&]utm_source=[^&]*/', '/[\?&]utm_campaign=[^&]*/', '/[\?&]utm_medium=[^&]*/', '/#xtor=RSS-[^&]*/', '/[\?&]fb_[^&]*/', '/[\?&]__scoop[^&]*/', '/#tk\.rss_all\?/', '/[\?&]action_ref_map=[^&]*/', '/[\?&]action_type_map=[^&]*/', '/[\?&]action_object_map=[^&]*/');
1646 $i=strpos($url,'#xtor=RSS-'); if ($i!==false) $url=substr($url,0,$i); 1649 foreach($annoyingpatterns as $pattern)
1650 {
1651 $url = preg_replace($pattern, "", $url);
1652 }
1647 1653
1648 $link_is_new = false; 1654 $link_is_new = false;
1649 $link = $LINKSDB->getLinkFromUrl($url); // Check if URL is not already in database (in this case, we will edit the existing link) 1655 $link = $LINKSDB->getLinkFromUrl($url); // Check if URL is not already in database (in this case, we will edit the existing link)
@@ -2123,11 +2129,8 @@ function lazyThumbnail($url,$href=false)
2123 2129
2124 $html='<a href="'.htmlspecialchars($t['href']).'">'; 2130 $html='<a href="'.htmlspecialchars($t['href']).'">';
2125 2131
2126 // Lazy image (only loaded by JavaScript when in the viewport). 2132 // Lazy image
2127 if (!empty($GLOBALS['disablejquery'])) // (except if jQuery is disabled) 2133 $html.='<img class="b-lazy" src="#" data-src="'.htmlspecialchars($t['src']).'"';
2128 $html.='<img class="lazyimage" src="'.htmlspecialchars($t['src']).'"';
2129 else
2130 $html.='<img class="lazyimage" src="#" data-original="'.htmlspecialchars($t['src']).'"';
2131 2134
2132 if (!empty($t['width'])) $html.=' width="'.htmlspecialchars($t['width']).'"'; 2135 if (!empty($t['width'])) $html.=' width="'.htmlspecialchars($t['width']).'"';
2133 if (!empty($t['height'])) $html.=' height="'.htmlspecialchars($t['height']).'"'; 2136 if (!empty($t['height'])) $html.=' height="'.htmlspecialchars($t['height']).'"';
@@ -2191,6 +2194,7 @@ function install()
2191 $GLOBALS['salt'] = sha1(uniqid('',true).'_'.mt_rand()); // Salt renders rainbow-tables attacks useless. 2194 $GLOBALS['salt'] = sha1(uniqid('',true).'_'.mt_rand()); // Salt renders rainbow-tables attacks useless.
2192 $GLOBALS['hash'] = sha1($_POST['setpassword'].$GLOBALS['login'].$GLOBALS['salt']); 2195 $GLOBALS['hash'] = sha1($_POST['setpassword'].$GLOBALS['login'].$GLOBALS['salt']);
2193 $GLOBALS['title'] = (empty($_POST['title']) ? 'Shared links on '.htmlspecialchars(indexUrl()) : $_POST['title'] ); 2196 $GLOBALS['title'] = (empty($_POST['title']) ? 'Shared links on '.htmlspecialchars(indexUrl()) : $_POST['title'] );
2197 $GLOBALS['config']['ENABLE_UPDATECHECK'] = !empty($_POST['updateCheck']);
2194 writeConfig(); 2198 writeConfig();
2195 echo '<script>alert("Shaarli is now configured. Please enter your login/password and start shaaring your links!");document.location=\'?do=login\';</script>'; 2199 echo '<script>alert("Shaarli is now configured. Please enter your login/password and start shaaring your links!");document.location=\'?do=login\';</script>';
2196 exit; 2200 exit;
@@ -2359,6 +2363,7 @@ function writeConfig()
2359 $config .= '$GLOBALS[\'disablejquery\']='.var_export($GLOBALS['disablejquery'],true).'; '; 2363 $config .= '$GLOBALS[\'disablejquery\']='.var_export($GLOBALS['disablejquery'],true).'; ';
2360 $config .= '$GLOBALS[\'privateLinkByDefault\']='.var_export($GLOBALS['privateLinkByDefault'],true).'; '; 2364 $config .= '$GLOBALS[\'privateLinkByDefault\']='.var_export($GLOBALS['privateLinkByDefault'],true).'; ';
2361 $config .= '$GLOBALS[\'config\'][\'ENABLE_RSS_PERMALINKS\']='.var_export($GLOBALS['config']['ENABLE_RSS_PERMALINKS'], true).'; '; 2365 $config .= '$GLOBALS[\'config\'][\'ENABLE_RSS_PERMALINKS\']='.var_export($GLOBALS['config']['ENABLE_RSS_PERMALINKS'], true).'; ';
2366 $config .= '$GLOBALS[\'config\'][\'ENABLE_UPDATECHECK\']='.var_export($GLOBALS['config']['ENABLE_UPDATECHECK'], true).'; ';
2362 $config .= ' ?>'; 2367 $config .= ' ?>';
2363 if (!file_put_contents($GLOBALS['config']['CONFIG_FILE'],$config) || strcmp(file_get_contents($GLOBALS['config']['CONFIG_FILE']),$config)!=0) 2368 if (!file_put_contents($GLOBALS['config']['CONFIG_FILE'],$config) || strcmp(file_get_contents($GLOBALS['config']['CONFIG_FILE']),$config)!=0)
2364 { 2369 {
diff --git a/shaarli_version.php b/shaarli_version.php
new file mode 100644
index 00000000..d266380a
--- /dev/null
+++ b/shaarli_version.php
@@ -0,0 +1 @@
<?php /* 0.0.43beta */ ?>
diff --git a/shaarli_version.txt b/shaarli_version.txt
deleted file mode 100644
index b6cffb3a..00000000
--- a/shaarli_version.txt
+++ /dev/null
@@ -1 +0,0 @@
10.0.43beta
diff --git a/tpl/configure.html b/tpl/configure.html
index c096018b..887be327 100644
--- a/tpl/configure.html
+++ b/tpl/configure.html
@@ -30,6 +30,10 @@
30 <input type="checkbox" name="enableRssPermalinks" id="enableRssPermalinks" {if="!empty($GLOBALS['config']['ENABLE_RSS_PERMALINKS'])"}checked{/if}/><label for="enableRssPermalinks">&nbsp;Switches the RSS feed URLs between full URLs and shortlinks. Enabling it will show a permalink in the description, and the feed item will be linked to the absolute URL. Disabling it swaps this behaviour around (permalink in title and link in description). RSS Permalinks are currently <b>{if="$GLOBALS['config']['ENABLE_RSS_PERMALINKS']"}enabled{else}disabled{/if}</b></label> 30 <input type="checkbox" name="enableRssPermalinks" id="enableRssPermalinks" {if="!empty($GLOBALS['config']['ENABLE_RSS_PERMALINKS'])"}checked{/if}/><label for="enableRssPermalinks">&nbsp;Switches the RSS feed URLs between full URLs and shortlinks. Enabling it will show a permalink in the description, and the feed item will be linked to the absolute URL. Disabling it swaps this behaviour around (permalink in title and link in description). RSS Permalinks are currently <b>{if="$GLOBALS['config']['ENABLE_RSS_PERMALINKS']"}enabled{else}disabled{/if}</b></label>
31 </td> 31 </td>
32 </tr> 32 </tr>
33 <tr><td valign="top"><b>Update:</b></td><td>
34 <input type="checkbox" name="updateCheck" id="updateCheck" {if="!empty($GLOBALS['config']['ENABLE_UPDATECHECK'])"}checked{/if}/>
35 <label for="updateCheck">&nbsp;Notify me when a new release is ready</label></td>
36 </tr>
33 <tr><td></td><td class="right"><input type="submit" name="Save" value="Save config" class="bigbutton"></td></tr> 37 <tr><td></td><td class="right"><input type="submit" name="Save" value="Save config" class="bigbutton"></td></tr>
34 </table> 38 </table>
35 </form> 39 </form>
diff --git a/tpl/includes.html b/tpl/includes.html
index 93cdfd5a..623e19ed 100644
--- a/tpl/includes.html
+++ b/tpl/includes.html
@@ -6,5 +6,5 @@
6<link rel="alternate" type="application/atom+xml" href="{$feedurl}?do=atom{$searchcrits}#" title="ATOM Feed" /> 6<link rel="alternate" type="application/atom+xml" href="{$feedurl}?do=atom{$searchcrits}#" title="ATOM Feed" />
7<link href="images/favicon.ico#" rel="shortcut icon" type="image/x-icon" /> 7<link href="images/favicon.ico#" rel="shortcut icon" type="image/x-icon" />
8<link type="text/css" rel="stylesheet" href="../inc/reset.css" /> 8<link type="text/css" rel="stylesheet" href="../inc/reset.css" />
9<link type="text/css" rel="stylesheet" href="inc/shaarli.css?version={$version|urlencode}#" /> 9<link type="text/css" rel="stylesheet" href="../inc/shaarli.css" />
10{if="is_file('inc/user.css')"}<link type="text/css" rel="stylesheet" href="inc/user.css?version={$version|urlencode}#" />{/if} 10{if="is_file('inc/user.css')"}<link type="text/css" rel="stylesheet" href="../inc/user.css" />{/if}
diff --git a/tpl/install.html b/tpl/install.html
index df42bf6d..88eb540e 100644
--- a/tpl/install.html
+++ b/tpl/install.html
@@ -3,17 +3,20 @@
3<head>{include="includes"}{$timezone_js}</head> 3<head>{include="includes"}{$timezone_js}</head>
4<body onload="document.installform.setlogin.focus();"> 4<body onload="document.installform.setlogin.focus();">
5<div id="install"> 5<div id="install">
6<h1>Shaarli</h1> 6 <h1>Shaarli</h1>
7It looks like it's the first time you run Shaarli. Please configure it:<br> 7 It looks like it's the first time you run Shaarli. Please configure it:<br>
8<form method="POST" action="#" name="installform" id="installform"> 8 <form method="POST" action="#" name="installform" id="installform">
9<table> 9 <table>
10<tr><td><b>Login:</b></td><td><input type="text" name="setlogin" size="30"></td></tr> 10 <tr><td><b>Login:</b></td><td><input type="text" name="setlogin" size="30"></td></tr>
11<tr><td><b>Password:</b></td><td><input type="password" name="setpassword" size="30"></td></tr> 11 <tr><td><b>Password:</b></td><td><input type="password" name="setpassword" size="30"></td></tr>
12{$timezone_html} 12 {$timezone_html}
13<tr><td><b>Page title:</b></td><td><input type="text" name="title" size="30"></td></tr> 13 <tr><td><b>Page title:</b></td><td><input type="text" name="title" size="30"></td></tr>
14<tr><td colspan="2"><input type="submit" name="Save" value="Save config" class="bigbutton"></td></tr> 14 <tr><td valign="top"><b>Update:</b></td><td>
15</table> 15 <input type="checkbox" name="updateCheck" id="updateCheck" checked="checked"><label for="updateCheck">&nbsp;Notify me when a new release is ready</label></td>
16</form> 16 </tr>
17 <tr><td colspan="2"><input type="submit" name="Save" value="Save config" class="bigbutton"></td></tr>
18 </table>
19 </form>
17</div> 20</div>
18{include="page.footer"} 21{include="page.footer"}
19</body> 22</body>
diff --git a/tpl/picwall.html b/tpl/picwall.html
index d3cabb2d..ea1ef420 100644
--- a/tpl/picwall.html
+++ b/tpl/picwall.html
@@ -1,11 +1,7 @@
1<!DOCTYPE html> 1<!DOCTYPE html>
2<html> 2<html>
3<head>{include="includes"} 3<head>{include="includes"}
4{if="empty($GLOBALS['disablejquery'])"} 4<script src="inc/blazy-1.3.1.min.js#"></script>
5<script src="inc/jquery-1.11.2.min.js#"></script>
6<script src="inc/jquery-ui-1.11.2.min.js#"></script>
7<script src="inc/jquery.lazyload-1.9.3.min.js#"></script>
8{/if}
9</head> 5</head>
10<body> 6<body>
11<div id="pageheader">{include="page.header"}</div> 7<div id="pageheader">{include="page.header"}</div>
@@ -20,12 +16,8 @@
20</div> 16</div>
21{include="page.footer"} 17{include="page.footer"}
22 18
23{if="empty($GLOBALS['disablejquery'])"}
24<script> 19<script>
25$(document).ready(function() { 20 var bLazy = new Blazy();
26 $("img.lazyimage").show().lazyload();
27});
28</script> 21</script>
29{/if}
30</body> 22</body>
31</html> \ No newline at end of file 23</html> \ No newline at end of file
diff --git a/tpl/picwall2.html b/tpl/picwall2.html
deleted file mode 100644
index 44d08b0c..00000000
--- a/tpl/picwall2.html
+++ /dev/null
@@ -1,19 +0,0 @@
1<!DOCTYPE html>
2<html>
3<head>{include="includes"}</head>
4<body>
5<div id="pageheader">{include="page.header"}</div>
6<div style="background-color:#003;">
7 {loop="linksToDisplay"}
8 <div style="float:left;width:48%;border-right:2px solid white;height:120px;overflow:hide;">
9 <div style="float:left;width:120px;text-align:center">{$value.thumbnail}</div>
10 <a href="{$value.permalink}" style="color:yellow;font-weight:bold;text-decoration:none;">{$value.title|htmlspecialchars}</a><br>
11 <span style="font-size:8pt;color:#eee;">{$value.description|htmlspecialchars}</span>
12 <div style="clear:both;"></div>
13 </div><br>
14 {/loop}
15</div>
16
17{include="page.footer"}
18</body>
19</html> \ No newline at end of file
diff --git a/tpl/tools.html b/tpl/tools.html
index bf0539b1..e912f615 100644
--- a/tpl/tools.html
+++ b/tpl/tools.html
@@ -11,6 +11,7 @@
11 <a href="?do=import"><b>Import</b> <span>: Import Netscape html bookmarks (as exported from Firefox, Chrome, Opera, delicious...)</span></a> <br><br> 11 <a href="?do=import"><b>Import</b> <span>: Import Netscape html bookmarks (as exported from Firefox, Chrome, Opera, delicious...)</span></a> <br><br>
12 <a href="?do=export"><b>Export</b> <span>: Export Netscape html bookmarks (which can be imported in Firefox, Chrome, Opera, delicious...)</span></a><br><br> 12 <a href="?do=export"><b>Export</b> <span>: Export Netscape html bookmarks (which can be imported in Firefox, Chrome, Opera, delicious...)</span></a><br><br>
13 <a class="smallbutton" onclick="alert('Drag this link to your bookmarks toolbar, or right-click it and choose Bookmark This Link...');return false;" href="javascript:javascript:(function(){var%20url%20=%20location.href;var%20title%20=%20document.title%20||%20url;window.open('{$pageabsaddr}?post='%20+%20encodeURIComponent(url)+'&amp;title='%20+%20encodeURIComponent(title)+'&amp;description='%20+%20encodeURIComponent(document.getSelection())+'&amp;source=bookmarklet','_blank','menubar=no,height=390,width=600,toolbar=no,scrollbars=no,status=no,dialog=1');})();"><b>✚Shaare link</b></a> <a href="#" style="clear:none;"><span>&#x21D0; Drag this link to your bookmarks toolbar (or right-click it and choose Bookmark This Link....).<br>&nbsp;&nbsp;&nbsp;&nbsp;Then click "✚Shaare link" button in any page you want to share.</span></a><br><br> 13 <a class="smallbutton" onclick="alert('Drag this link to your bookmarks toolbar, or right-click it and choose Bookmark This Link...');return false;" href="javascript:javascript:(function(){var%20url%20=%20location.href;var%20title%20=%20document.title%20||%20url;window.open('{$pageabsaddr}?post='%20+%20encodeURIComponent(url)+'&amp;title='%20+%20encodeURIComponent(title)+'&amp;description='%20+%20encodeURIComponent(document.getSelection())+'&amp;source=bookmarklet','_blank','menubar=no,height=390,width=600,toolbar=no,scrollbars=no,status=no,dialog=1');})();"><b>✚Shaare link</b></a> <a href="#" style="clear:none;"><span>&#x21D0; Drag this link to your bookmarks toolbar (or right-click it and choose Bookmark This Link....).<br>&nbsp;&nbsp;&nbsp;&nbsp;Then click "✚Shaare link" button in any page you want to share.</span></a><br><br>
14 <a class="smallbutton" onclick="alert('Drag this link to your bookmarks toolbar, or right-click it and choose Bookmark This Link...');return false;" href="?private=1&post="><b>✚Add Note</b></a> <a href="#" style="clear:none;"><span>&#x21D0; Drag this link to your bookmarks toolbar (or right-click it and choose Bookmark This Link....).<br>&nbsp;&nbsp;&nbsp;&nbsp;Then click "✚Add Note" button anytime to start composing a (default private) Note (text post) to your Shaarli.</span></a><br><br>
14 <div class="clear"></div> 15 <div class="clear"></div>
15 </div> 16 </div>
16</div> 17</div>