From: nodiscc Date: Thu, 13 Nov 2014 00:48:52 +0000 (+0100) Subject: Merge pull request #59 from tst2005/master X-Git-Tag: v0.0.43beta~27 X-Git-Url: https://git.immae.eu/?a=commitdiff_plain;h=9362352e124151a0fa8a145fe1dba4e6256b35c7;hp=ae22a12b8adcc5788406b8637ab4db48085681fe;p=github%2Fshaarli%2FShaarli.git Merge pull request #59 from tst2005/master uniform if syntax --- diff --git a/.gitignore b/.gitignore index bcd745e4..6452c2c6 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,7 @@ pagecache # Eclipse project files .settings .buildpath -.project \ No newline at end of file +.project + +# Ignore raintpl generated pages +*.rtpl.php \ No newline at end of file diff --git a/COPYING b/COPYING index d9731d27..91ef0340 100644 --- a/COPYING +++ b/COPYING @@ -1,6 +1,52 @@ -Shaarli is distributed under the zlib/libpng License: +Files: * +License: zlib/libpng +Copyright: (c) 2011-2014 Sébastien SAUVAGE + (c) 2011-2014 Alexandre Alapetite + (c) 2011-2014 David Sferruzza + (c) 2011-2014 Christophe HENRY + (c) 2011-2014 Mathieu Chabanon + (c) 2011-2014 BoboTiG + (c) 2011-2014 Bronco + (c) 2011-2014 Emilien Klein + (c) 2011-2014 Knah Tsaeb + (c) 2011-2014 Lionel Martin + (c) 2011-2014 lehollandaisvolant + (c) 2011-2014 timo van neerden + (c) 2011-2014 nodiscc + + + +Files: images/calendar.png, images/edit_icon.png, images/feed-icon-14x14.png, images/private.png, images/private_16x16.png, images/private_16x16_active.png, images/qrcode.png, images/tag_blue.png +License: CC-BY (http://creativecommons.org/licenses/by/3.0/) +Copyright: (c) 2014 Yusuke Kamiyamane +Source: http://p.yusukekamiyamane.com/ + +Files: images/delete_icon.png +License: CC-BY (http://creativecommons.org/licenses/by/3.0/) +Copyright: (c) 2014 Designmodo +Source: http://designmodo.com/linecons-free/ + + +Files: images/floral_left.png, images/floral_right.png, images/squiggle.png, images/squiggle2.png, images/squiggle_closing.png +Licence: Public Domain +Source: https://openclipart.org/people/j4p4n/j4p4n_ornimental_bookend_-_left.svg + + +Files: images/Paper_texture_v5_by_bashcorpo_w1000.jpg +Licence: Public Domain +Source: http://bashcorpo.deviantart.com/art/Grungy-paper-texture-v-5-22966998 + +Files: images/logo.png +License: zlib/libpng +Copyright: (c) 2011-2014 idleman idleman@idleman.fr + +Files: ins/qr.min.js +License: GPLv3 +Copyright: (C) 2014 Alasdair Mercer, http://neocotic.com + +-------------------------------------------------------- +ZLIB/LIBPNG LICENSE -Copyright (c) 2011 Sébastien SAUVAGE (sebsauvage.net) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from @@ -19,3 +65,19 @@ freely, subject to the following restrictions: not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. + +---------------------------------------------------- +GPLv3 LICENSE + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . \ No newline at end of file diff --git a/README.md b/README.md index cff718cf..d0743783 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,76 @@ -![Shaarli logo](http://sebsauvage.net/wiki/lib/exe/fetch.php?media=php:php_shaarli:php_shaarli_logo_inkscape_w600_transp-nq8.png) +![Shaarli logo](https://cdn.mediacru.sh/W2NGCIHB3quT.png) Shaarli, the personal, minimalist, super-fast, no-database delicious clone. You want to share the links you discover ? Shaarli is a minimalist delicious clone you can install on your own website. -It is designed to be personal (single-user), fast and handy. +It is designed to be personal (single-user), fast and handy. -Features: +## Features: * Minimalist design (simple is beautiful) * **FAST** * Dead-simple installation: Drop the files, open the page. No database required. - * Easy to use: Single button in your browser to bookmark a page - * Save url, title, description (unlimited size). Classify links with tags (with autocomplete) - * Tag renaming, merging and deletion. - * Automatic thumbnails for various services (imgur, imageshack.us, flickr, youtube, vimeo, dailymotion…) - * Automatic conversion of URLs to clickable links in descriptions. Support for http/ftp/file/apt/magnet protocols. - * Save links as public or private - * 1-clic access to your private links/notes - * Browse links by page, filter by tag or use the full text search engine - * Permalinks (with QR-Code) for easy reference - * RSS and ATOM feeds (which can be filtered by tag or text search) - * Tag cloud - * Picture wall (which can be filtered by tag or text search) - * “Links of the day” Newspaper-like digest, browsable by day. - * “Daily” RSS feed: Get each day a digest of all new links. - * [PubSubHubbub](https://code.google.com/p/pubsubhubbub/) protocol support + * Easy to use: Single button in your browser to bookmark a page (**bookmarklet**) + * Save **URL, title, description** (unlimited size). + * Classify, search and filter links with **tags**. + * Tag autocompletion, renaming, merging and deletion. + * Save links as **public or private** + * Browse links by page, filter by tag or use the **full text search engine** + * **Tag cloud** + * **Picture wall** (which can be filtered by tag or text search) + * **“Daily”** Newspaper-like digest, browsable by day. + * **Permalinks** (with QR-Code) for easy reference + * **RSS** and ATOM feeds + * Can be filtered by tag or text search! + * “Daily” RSS feed: Get each day a digest of all new links. + * Can **import/export** Netscape bookmarks (for import/export from/to Firefox, Opera, Chrome, Delicious…) + * Automatic **image/video thumbnails** for various services (imgur, imageshack.us, flickr, youtube, vimeo, dailymotion…) + * Support for http/ftp/file/apt/magnet protocol links + * URLs in descriptions are automatically converted to clickable links in descriptions * Easy backup (Data stored in a single file) + * 1-click access to your private links/notes * Compact storage (1315 links stored in 150 kb) * Mobile browsers support * Also works with javascript disabled - * Can import/export Netscape bookmarks (for import/export from/to Firefox, Opera, Chrome, Delicious…) * Brute force protected login form - * Protected against [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery), session cookie hijacking. + * [PubSubHubbub](https://code.google.com/p/pubsubhubbub/) protocol support * Automatic removal of annoying FeedBurner/Google FeedProxy parameters in URL (?utm_source…) - * Shaarli is a bookmarking application, but you can use it for micro-blogging (like Twitter), a pastebin, an online notepad, a snippet repository, etc. - * You will be automatically notified by a discreet popup if a new version is available * Pages are easy to customize (using CSS and simple RainTPL templates) + * Protected against [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery), session cookie hijacking. + * You will be automatically notified by a discreet popup if a new version is available + * **Shaarli is a bookmarking application, but you can use it for micro-blogging (like Twitter), a pastebin, an online notepad, a snippet repository, etc. See [Usage examples](https://github.com/shaarli/Shaarli/wiki#usage-examples)** + +## Links + * **[Wiki/documentation](https://github.com/shaarli/Shaarli/wiki)** + * [Bugs/Feature requests/Discussion](https://github.com/shaarli/Shaarli/issues/) + +## Installing +Shaarli requires php 5.1 -Requires php 5.1 + * Download the latest stable release from https://github.com/shaarli/Shaarli/releases + * Unpack the archive in a directory on your web server + * Visit this directory from a web browser. + * Choose login, password, timezone and page title. Save. -More information on the project page: -http://sebsauvage.net/wiki/doku.php?id=php:shaarli +_To get the development version, download https://github.com/shaarli/Shaarli/archive/master.zip or `git clone https://github.com/shaarli/Shaarli`_ ------------------------------------------------------------------------------- +## Upgrading +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. -Shaarli is distributed under the zlib/libpng License: -Copyright (c) 2011 Sébastien SAUVAGE (sebsauvage.net) +## Screenshots -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from -the use of this software. +[![](https://cdn.mediacru.sh/AjZc6-emICeO.png)](https://cdn.mediacru.sh/kE8SyD-PvGuC.png) [![](https://cdn.mediacru.sh/MfC-DzklMYs2.png)](https://cdn.mediacru.sh/iqTvO1-yP9pU.png) [![](https://cdn.mediacru.sh/dxmXskaubYcg.png)](https://cdn.mediacru.sh/mMoi31f94wdL.png) [![](https://cdn.mediacru.sh/-ptB2veFivBp.png)](https://cdn.mediacru.sh/GcoZPZmCZ-DR.png) [![](https://cdn.mediacru.sh/QmRdTAr8x427.png)](https://cdn.mediacru.sh/TDDujpMWT31q.png) -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: +## About - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would - be appreciated but is not required. +Original Project page: http://sebsauvage.net/wiki/doku.php?id=php:shaarli +Shaarli is developed by [Sébastien SAUVAGE](http://sebsauvage.net) and [contributors](COPYING). - 2. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. +Shaarli is [Free Software](https://en.wikipedia.org/wiki/Free_software) distributed under the [zlib/libpng License](http://www.gzip.org/zlib/zlib_license.html) - 3. This notice may not be removed or altered from any source distribution. +This friendly fork is maintained by the community at https://github.com/shaarli/Shaarli ------------------------------------------------------------------------------- diff --git a/cache/.htaccess b/cache/.htaccess new file mode 100644 index 00000000..b584d98c --- /dev/null +++ b/cache/.htaccess @@ -0,0 +1,2 @@ +Allow from none +Deny from all diff --git a/data/.htaccess b/data/.htaccess new file mode 100644 index 00000000..b584d98c --- /dev/null +++ b/data/.htaccess @@ -0,0 +1,2 @@ +Allow from none +Deny from all diff --git a/images/calendar.png b/images/calendar.png index 65891385..81c74519 100644 Binary files a/images/calendar.png and b/images/calendar.png differ diff --git a/images/delete_icon.png b/images/delete_icon.png index 55e388b4..810b94d8 100644 Binary files a/images/delete_icon.png and b/images/delete_icon.png differ diff --git a/images/edit_icon.png b/images/edit_icon.png index 5cff5743..16c440c8 100644 Binary files a/images/edit_icon.png and b/images/edit_icon.png differ diff --git a/images/feed-icon-14x14.png b/images/feed-icon-14x14.png index b3c949d2..10161702 100644 Binary files a/images/feed-icon-14x14.png and b/images/feed-icon-14x14.png differ diff --git a/images/floral_left.png b/images/floral_left.png index 5a4ad89b..f09a861d 100644 Binary files a/images/floral_left.png and b/images/floral_left.png differ diff --git a/images/floral_right.png b/images/floral_right.png index cb7b201f..0dfb6112 100644 Binary files a/images/floral_right.png and b/images/floral_right.png differ diff --git a/images/private.png b/images/private.png index 5cea272a..1364b355 100644 Binary files a/images/private.png and b/images/private.png differ diff --git a/images/private_16x16.png b/images/private_16x16.png index d58c4823..8bb34d7d 100644 Binary files a/images/private_16x16.png and b/images/private_16x16.png differ diff --git a/images/private_16x16_active.png b/images/private_16x16_active.png index dd43baf2..af990d2c 100644 Binary files a/images/private_16x16_active.png and b/images/private_16x16_active.png differ diff --git a/images/qrcode.png b/images/qrcode.png index 99f25267..c2cfa476 100644 Binary files a/images/qrcode.png and b/images/qrcode.png differ diff --git a/images/squiggle.png b/images/squiggle.png index 9fd2129d..a6ce218c 100644 Binary files a/images/squiggle.png and b/images/squiggle.png differ diff --git a/images/squiggle2.png b/images/squiggle2.png index 23409ce3..c795f0a3 100644 Binary files a/images/squiggle2.png and b/images/squiggle2.png differ diff --git a/images/squiggle_closing.png b/images/squiggle_closing.png index 901fff5f..3f9d02b1 100644 Binary files a/images/squiggle_closing.png and b/images/squiggle_closing.png differ diff --git a/images/tag_blue.png b/images/tag_blue.png index 9757fc6e..7ec902fc 100644 Binary files a/images/tag_blue.png and b/images/tag_blue.png differ diff --git a/inc/qr.min.js b/inc/qr.min.js index 663ce930..19d704e1 100644 --- a/inc/qr.min.js +++ b/inc/qr.min.js @@ -1,9 +1,5 @@ -// [qr.js](http://neocotic.com/qr.js) 1.0.3 -// (c) 2011 Alasdair Mercer -// Freely distributable under the MIT license. -// Based on jsqrencode -// (c) 2010 tz@execpc.com -// Licensed under the GPL Version 3 license. -// For all details and documentation: -// http://neocotic.com/qr.js -(function(a){function Q(a){var c,h,i,j,k,m,n,u;k=a.length;C=0;do{C++;i=(r-1)*4+(C-1)*16;z=d[i++];A=d[i++];o=d[i++];p=d[i];i=o*(z+A)+A-3+(C<=9);if(k<=i)break}while(C<40);D=17+4*C;m=o+(o+p)*(z+A)+A;for(k=0;k1){k=b[C];u=D-7;for(;;){n=D-7;while(n>k-3){J(n,u);if(n6){k=l[C-7];i=17;for(n=0;n<6;n++){for(u=0;u<3;u++,i--){if(1&(i>11?C>>i-12:k>>i)){s[5-n+D*(2-u+D-11)]=1;s[2-u+D-11+D*(5-n)]=1}else{I(5-n,2-u+D-11);I(2-u+D-11,5-n)}}}}for(u=0;u=n-2){m=n-2;if(C>9)m--}c=m;if(C>9){B[c+2]=0;B[c+3]=0;while(c--){k=B[c];B[c+3]|=255&k<<4;B[c+2]=k>>4}B[2]|=255&m<<4;B[1]=m>>4;B[0]=64|m>>12}else{B[c+1]=0;B[c+2]=0;while(c--){k=B[c];B[c+2]|=255&k<<4;B[c+1]=k>>4}B[1]|=255&m<<4;B[0]=64|m>>4}c=m+3-(C<10);while(c0;h--){x[h]=x[h]?x[h-1]^f[K(g[x[h]]+c)]:x[h-1]}x[0]=f[K(g[x[0]]+c)]}for(c=0;c<=p;c++)x[c]=g[x[c]];i=n;u=0;for(c=0;c>=1){if(u&1){s[D-1-i+D*8]=1;if(i<6){s[8+D*i]=1}else{s[8+D*(i+1)]=1}}}for(i=0;i<7;i++,u>>=1){if(u&1){s[8+D*(D-7+i)]=1;if(i){s[6-i+D*8]=1}else{s[7+D*8]=1}}}return s}function P(){var a,b,c,d,e,f,g=0,h=0,j=0;for(f=0;fD*D){c-=D*D;j++}g+=j*k;for(e=0;e=5)b+=h+m[c]-5}for(c=3;ca||m[c-3]*3>=m[c]*4||m[c+3]*3>=m[c]*4)){b+=j}}return b}function N(a){var b,c,d,e;switch(a){case 0:for(c=0;c>1&1,b=0;bb){c=a;a=b;b=c}c=b;c+=b*b;c>>=1;c+=a;return t[c]}function L(a,b,c,d){var e,h,i;for(h=0;h=255){a-=255;a=(a>>8)+(a&255)}return a}function J(a,b){var c;s[a+D*b]=1;for(c=-2;c<2;c++){s[a+c+D*(b-2)]=1;s[a-2+D*(b+c+1)]=1;s[a+2+D*(b+c)]=1;s[a+c+1+D*(b+2)]=1}for(c=0;c<2;c++){I(a-1,b+c);I(a+1,b-c);I(a-c,b-1);I(a+c,b+1)}}function I(a,b){var c;if(a>b){c=a;a=b;b=c}c=b;c*=b;c+=b;c>>=1;c+=a;t[c]=1}function H(a,b,c){try{var d=a.apply(c||this);if(typeof b==="function")return b(null,d);return d}catch(e){if(typeof b==="function")return b(e);throw e}}function G(){for(var a=arguments.length;a>=0;--a){if(typeof arguments[a]==="function")return arguments[a]}}function F(){return w?new v:a.document.createElement("img")}function E(){return w?new n:a.document.createElement("canvas")}var b=[0,11,15,19,23,27,31,16,18,20,22,24,26,28,20,22,24,24,26,28,28,22,24,24,26,26,28,28,24,24,26,26,26,28,28,24,26,26,26,28,28],c="image/octet-stream",d=[1,0,19,7,1,0,16,10,1,0,13,13,1,0,9,17,1,0,34,10,1,0,28,16,1,0,22,22,1,0,16,28,1,0,55,15,1,0,44,26,2,0,17,18,2,0,13,22,1,0,80,20,2,0,32,18,2,0,24,26,4,0,9,16,1,0,108,26,2,0,43,24,2,2,15,18,2,2,11,22,2,0,68,18,4,0,27,16,4,0,19,24,4,0,15,28,2,0,78,20,4,0,31,18,2,4,14,18,4,1,13,26,2,0,97,24,2,2,38,22,4,2,18,22,4,2,14,26,2,0,116,30,3,2,36,22,4,4,16,20,4,4,12,24,2,2,68,18,4,1,43,26,6,2,19,24,6,2,15,28,4,0,81,20,1,4,50,30,4,4,22,28,3,8,12,24,2,2,92,24,6,2,36,22,4,6,20,26,7,4,14,28,4,0,107,26,8,1,37,22,8,4,20,24,12,4,11,22,3,1,115,30,4,5,40,24,11,5,16,20,11,5,12,24,5,1,87,22,5,5,41,24,5,7,24,30,11,7,12,24,5,1,98,24,7,3,45,28,15,2,19,24,3,13,15,30,1,5,107,28,10,1,46,28,1,15,22,28,2,17,14,28,5,1,120,30,9,4,43,26,17,1,22,28,2,19,14,28,3,4,113,28,3,11,44,26,17,4,21,26,9,16,13,26,3,5,107,28,3,13,41,26,15,5,24,30,15,10,15,28,4,4,116,28,17,0,42,26,17,6,22,28,19,6,16,30,2,7,111,28,17,0,46,28,7,16,24,30,34,0,13,24,4,5,121,30,4,14,47,28,11,14,24,30,16,14,15,30,6,4,117,30,6,14,45,28,11,16,24,30,30,2,16,30,8,4,106,26,8,13,47,28,7,22,24,30,22,13,15,30,10,2,114,28,19,4,46,28,28,6,22,28,33,4,16,30,8,4,122,30,22,3,45,28,8,26,23,30,12,28,15,30,3,10,117,30,3,23,45,28,4,31,24,30,11,31,15,30,7,7,116,30,21,7,45,28,1,37,23,30,19,26,15,30,5,10,115,30,19,10,47,28,15,25,24,30,23,25,15,30,13,3,115,30,2,29,46,28,42,1,24,30,23,28,15,30,17,0,115,30,10,23,46,28,10,35,24,30,19,35,15,30,17,1,115,30,14,21,46,28,29,19,24,30,11,46,15,30,13,6,115,30,14,23,46,28,44,7,24,30,59,1,16,30,12,7,121,30,12,26,47,28,39,14,24,30,22,41,15,30,6,14,121,30,6,34,47,28,46,10,24,30,2,64,15,30,17,4,122,30,29,14,46,28,49,10,24,30,24,46,15,30,4,18,122,30,13,32,46,28,48,14,24,30,42,32,15,30,20,4,117,30,40,7,47,28,43,22,24,30,10,67,15,30,19,6,118,30,18,31,47,28,34,34,24,30,20,61,15,30],e=[30660,29427,32170,30877,26159,25368,27713,26998,21522,20773,24188,23371,17913,16590,20375,19104,13663,12392,16177,14854,9396,8579,11994,11245,5769,5054,7399,6608,1890,597,3340,2107],f=[1,2,4,8,16,32,64,128,29,58,116,232,205,135,19,38,76,152,45,90,180,117,234,201,143,3,6,12,24,48,96,192,157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,35,70,140,5,10,20,40,80,160,93,186,105,210,185,111,222,161,95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,129,31,62,124,248,237,199,147,59,118,236,197,151,51,102,204,133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,130,25,50,100,200,141,7,14,28,56,112,224,221,167,83,166,81,162,89,178,121,242,249,239,195,155,43,86,172,69,138,9,18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,88,176,125,250,233,207,131,27,54,108,216,173,71,142,0],g=[255,0,1,25,2,50,26,198,3,223,51,238,27,104,199,75,4,100,224,14,52,141,239,129,28,193,105,248,200,8,76,113,5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,29,181,194,125,106,39,249,185,201,154,9,120,77,228,114,166,6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,54,208,148,206,143,150,219,189,241,210,19,92,131,56,70,64,30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,94,155,159,10,21,121,43,78,212,229,172,115,243,167,87,7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,227,165,153,119,38,184,180,124,17,68,146,217,35,32,137,46,55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,162,31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,59,82,41,157,85,170,251,96,134,177,187,204,62,90,203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,79,174,213,233,230,231,173,232,116,214,244,234,168,80,88,175],h=3,i=3,j=40,k=10,l=[3220,1468,2713,1235,3062,1890,2119,1549,2344,2936,1117,2583,1330,2470,1667,2249,2028,3780,481,4011,142,3098,831,3445,592,2517,1776,2234,1951,2827,1070,2660,1345,3177];var m=[],n,o,p,q=[],r=1,s=[],t=[],u,v,w=false,x=[],y=a.qr,z,A,B=[],C,D;var R={VERSION:"1.0.3",canvas:function(a,b){b=G(a,b);return H(function c(){switch(typeof a){case"object":break;case"string":a={value:a};break;default:a={};break}var b,c,d,e,f,g,h=4,i=25;if(a.size>=1&&a.size<=10)h=a.size;h*=i;b=a.canvas||E();c=b.getContext("2d");c.canvas.width=h;c.canvas.height=h;c.fillStyle=a.background||"#fff";c.fillRect(0,0,h,h);if(a.level){switch(a.level.toUpperCase()){case"L":r=1;break;case"M":r=2;break;case"Q":r=3;break;case"H":r=4;break}}g=Q(a.value||"");c.lineWidth=1;f=h;f/=D;f=Math.round(f-.5);c.clearRect(0,0,h,h);c.fillStyle=a.background||"#fff";c.fillRect(0,0,f*(D+8),f*(D+8));c.fillStyle=a.foreground||"#000";for(d=0;db&&(c=a,a=b,b=c),c=b,c*=b,c+=b,c>>=1,c+=a,S[c]=1}function j(a,b){var c;for(R[a+z*b]=1,c=-2;2>c;c++)R[a+c+z*(b-2)]=1,R[a-2+z*(b+c+1)]=1,R[a+2+z*(b+c)]=1,R[a+c+1+z*(b+2)]=1;for(c=0;2>c;c++)i(a-1,b+c),i(a+1,b-c),i(a-c,b-1),i(a+c,b+1)}function k(a){for(;a>=255;)a-=255,a=(a>>8)+(255&a);return a}function l(a,b,c,d){var e,f,g;for(f=0;d>f;f++)W[c+f]=0;for(f=0;b>f;f++){if(e=H[W[a+f]^W[c]],255!==e)for(g=1;d>g;g++)W[c+g-1]=W[c+g]^G[k(e+U[d-g])];else for(g=c;c+d>g;g++)W[g]=W[g+1];W[c+d-1]=255===e?0:G[k(e+U[0])]}}function m(a,b){var c;return a>b&&(c=a,a=b,b=c),c=b,c+=b*b,c>>=1,c+=a,1===S[c]}function n(a){var b,c,d,e;switch(a){case 0:for(c=0;z>c;c++)for(b=0;z>b;b++)b+c&1||m(b,c)||(R[b+c*z]^=1);break;case 1:for(c=0;z>c;c++)for(b=0;z>b;b++)1&c||m(b,c)||(R[b+c*z]^=1);break;case 2:for(c=0;z>c;c++)for(d=0,b=0;z>b;b++,d++)3===d&&(d=0),d||m(b,c)||(R[b+c*z]^=1);break;case 3:for(e=0,c=0;z>c;c++,e++)for(3===e&&(e=0),d=e,b=0;z>b;b++,d++)3===d&&(d=0),d||m(b,c)||(R[b+c*z]^=1);break;case 4:for(c=0;z>c;c++)for(d=0,e=c>>1&1,b=0;z>b;b++,d++)3===d&&(d=0,e=!e),e||m(b,c)||(R[b+c*z]^=1);break;case 5:for(e=0,c=0;z>c;c++,e++)for(3===e&&(e=0),d=0,b=0;z>b;b++,d++)3===d&&(d=0),(b&c&1)+!(!d|!e)||m(b,c)||(R[b+c*z]^=1);break;case 6:for(e=0,c=0;z>c;c++,e++)for(3===e&&(e=0),d=0,b=0;z>b;b++,d++)3===d&&(d=0),(b&c&1)+(d&&d===e)&1||m(b,c)||(R[b+c*z]^=1);break;case 7:for(e=0,c=0;z>c;c++,e++)for(3===e&&(e=0),d=0,b=0;z>b;b++,d++)3===d&&(d=0),(d&&d===e)+(b+c&1)&1||m(b,c)||(R[b+c*z]^=1)}}function o(a){var b,c=0;for(b=0;a>=b;b++)O[b]>=5&&(c+=I+O[b]-5);for(b=3;a-1>b;b+=2)O[b-2]===O[b+2]&&O[b+2]===O[b-1]&&O[b-1]===O[b+1]&&3*O[b-1]===O[b]&&(0===O[b-3]||b+3>a||3*O[b-3]>=4*O[b]||3*O[b+3]>=4*O[b])&&(c+=K);return c}function p(){var a,b,c,d,e,f,g,h,i;for(c=e=f=0,i=0;z-1>i;i++)for(h=0;z-1>h;h++)(R[h+z*i]&&R[h+1+z*i]&&R[h+z*(i+1)]&&R[h+1+z*(i+1)]||!(R[h+z*i]||R[h+1+z*i]||R[h+z*(i+1)]||R[h+1+z*(i+1)]))&&(c+=J);for(i=0;z>i;i++){for(O[0]=0,g=a=h=0;z>h;h++)(b=R[h+z*i])===a?O[g]++:O[++g]=1,a=b,e+=a?1:-1;c+=o(g)}for(0>e&&(e=-e),d=e,d+=d<<2,d<<=1;d>z*z;)d-=z*z,f++;for(c+=f*L,h=0;z>h;h++){for(O[0]=0,g=a=i=0;z>i;i++)(b=R[h+z*i])===a?O[g]++:O[++g]=1,a=b;c+=o(g)}return c}function q(a){var b,c,d,e,f,g,h,o;f=a.length,y=0;do if(y++,d=4*(Q-1)+16*(y-1),u=D[d++],v=D[d++],s=D[d++],t=D[d],d=s*(u+v)+v-3+(9>=y),d>=f)break;while(40>y);for(z=17+4*y,g=s+(s+t)*(u+v)+v,f=0;g>f;f++)P[f]=0;for(W=a.slice(0),f=0;z*z>f;f++)R[f]=0;for(f=0;(z*(z+1)+1)/2>f;f++)S[f]=0;for(f=0;3>f;f++){for(d=o=0,1===f&&(d=z-7),2===f&&(o=z-7),R[o+3+z*(d+3)]=1,h=0;6>h;h++)R[o+h+z*d]=1,R[o+z*(d+h+1)]=1,R[o+6+z*(d+h)]=1,R[o+h+1+z*(d+6)]=1;for(h=1;5>h;h++)i(o+h,d+1),i(o+1,d+h+1),i(o+5,d+h),i(o+h+1,d+5);for(h=2;4>h;h++)R[o+h+z*(d+2)]=1,R[o+2+z*(d+h+1)]=1,R[o+4+z*(d+h)]=1,R[o+h+1+z*(d+4)]=1}if(y>1)for(f=A[y],o=z-7;;){for(h=z-7;h>f-3&&(j(h,o),!(f>h));)h-=f;if(f+9>=o)break;o-=f,j(6,o),j(o,6)}for(R[8+z*(z-8)]=1,o=0;7>o;o++)i(7,o),i(z-8,o),i(7,o+z-7);for(h=0;8>h;h++)i(h,7),i(h+z-8,7),i(h,z-8);for(h=0;9>h;h++)i(h,8);for(h=0;8>h;h++)i(h+z-8,8),i(8,h);for(o=0;7>o;o++)i(8,o+z-7);for(h=0;z-14>h;h++)1&h?(i(8+h,6),i(6,8+h)):(R[8+h+6*z]=1,R[6+z*(8+h)]=1);if(y>6)for(f=M[y-7],d=17,h=0;6>h;h++)for(o=0;3>o;o++,d--)1&(d>11?y>>d-12:f>>d)?(R[5-h+z*(2-o+z-11)]=1,R[2-o+z-11+z*(5-h)]=1):(i(5-h,2-o+z-11),i(2-o+z-11,5-h));for(o=0;z>o;o++)for(h=0;o>=h;h++)R[h+z*o]&&i(h,o);for(g=W.length,b=0;g>b;b++)P[b]=W.charCodeAt(b);if(W=P.slice(0),h=s*(u+v)+v,g>=h-2&&(g=h-2,y>9&&g--),b=g,y>9){for(W[b+2]=0,W[b+3]=0;b--;)f=W[b],W[b+3]|=255&f<<4,W[b+2]=f>>4;W[2]|=255&g<<4,W[1]=g>>4,W[0]=64|g>>12}else{for(W[b+1]=0,W[b+2]=0;b--;)f=W[b],W[b+2]|=255&f<<4,W[b+1]=f>>4;W[1]|=255&g<<4,W[0]=64|g>>4}for(b=g+3-(10>y);h>b;)W[b++]=236,W[b++]=17;for(U[0]=1,b=0;t>b;b++){for(U[b+1]=1,c=b;c>0;c--)U[c]=U[c]?U[c-1]^G[k(H[U[c]]+b)]:U[c-1];U[0]=G[k(H[U[0]]+b)]}for(b=0;t>=b;b++)U[b]=H[U[b]];for(d=h,o=0,b=0;u>b;b++)l(o,s,d,t),o+=s,d+=t;for(b=0;v>b;b++)l(o,s+1,d,t),o+=s+1,d+=t;for(o=0,b=0;s>b;b++){for(c=0;u>c;c++)P[o++]=W[b+c*s];for(c=0;v>c;c++)P[o++]=W[u*s+b+c*(s+1)]}for(c=0;v>c;c++)P[o++]=W[u*s+b+c*(s+1)];for(b=0;t>b;b++)for(c=0;u+v>c;c++)P[o++]=W[h+b+c*t];for(W=P,h=o=z-1,d=g=1,e=(s+t)*(u+v)+v,b=0;e>b;b++)for(f=W[b],c=0;8>c;c++,f<<=1){128&f&&(R[h+z*o]=1);do g?h--:(h++,d?0!==o?o--:(h-=2,d=!d,6===h&&(h--,o=9)):o!==z-1?o++:(h-=2,d=!d,6===h&&(h--,o-=8))),g=!g;while(m(h,o))}for(W=R.slice(0),f=0,o=3e4,d=0;8>d&&(n(d),h=p(),o>h&&(o=h,f=d),7!==f);d++)R=W.slice(0);for(f!==d&&n(f),o=F[f+(Q-1<<3)],d=0;8>d;d++,o>>=1)1&o&&(R[z-1-d+8*z]=1,6>d?R[8+z*d]=1:R[8+z*(d+1)]=1);for(d=0;7>d;d++,o>>=1)1&o&&(R[8+z*(z-7+d)]=1,d?R[6-d+8*z]=1:R[7+8*z]=1);return R}var r,s,t,u,v,w,x,y,z,A=[0,11,15,19,23,27,31,16,18,20,22,24,26,28,20,22,24,24,26,28,28,22,24,24,26,26,28,28,24,24,26,26,26,28,28,24,26,26,26,28,28],B="image/png",C="image/octet-stream",D=[1,0,19,7,1,0,16,10,1,0,13,13,1,0,9,17,1,0,34,10,1,0,28,16,1,0,22,22,1,0,16,28,1,0,55,15,1,0,44,26,2,0,17,18,2,0,13,22,1,0,80,20,2,0,32,18,2,0,24,26,4,0,9,16,1,0,108,26,2,0,43,24,2,2,15,18,2,2,11,22,2,0,68,18,4,0,27,16,4,0,19,24,4,0,15,28,2,0,78,20,4,0,31,18,2,4,14,18,4,1,13,26,2,0,97,24,2,2,38,22,4,2,18,22,4,2,14,26,2,0,116,30,3,2,36,22,4,4,16,20,4,4,12,24,2,2,68,18,4,1,43,26,6,2,19,24,6,2,15,28,4,0,81,20,1,4,50,30,4,4,22,28,3,8,12,24,2,2,92,24,6,2,36,22,4,6,20,26,7,4,14,28,4,0,107,26,8,1,37,22,8,4,20,24,12,4,11,22,3,1,115,30,4,5,40,24,11,5,16,20,11,5,12,24,5,1,87,22,5,5,41,24,5,7,24,30,11,7,12,24,5,1,98,24,7,3,45,28,15,2,19,24,3,13,15,30,1,5,107,28,10,1,46,28,1,15,22,28,2,17,14,28,5,1,120,30,9,4,43,26,17,1,22,28,2,19,14,28,3,4,113,28,3,11,44,26,17,4,21,26,9,16,13,26,3,5,107,28,3,13,41,26,15,5,24,30,15,10,15,28,4,4,116,28,17,0,42,26,17,6,22,28,19,6,16,30,2,7,111,28,17,0,46,28,7,16,24,30,34,0,13,24,4,5,121,30,4,14,47,28,11,14,24,30,16,14,15,30,6,4,117,30,6,14,45,28,11,16,24,30,30,2,16,30,8,4,106,26,8,13,47,28,7,22,24,30,22,13,15,30,10,2,114,28,19,4,46,28,28,6,22,28,33,4,16,30,8,4,122,30,22,3,45,28,8,26,23,30,12,28,15,30,3,10,117,30,3,23,45,28,4,31,24,30,11,31,15,30,7,7,116,30,21,7,45,28,1,37,23,30,19,26,15,30,5,10,115,30,19,10,47,28,15,25,24,30,23,25,15,30,13,3,115,30,2,29,46,28,42,1,24,30,23,28,15,30,17,0,115,30,10,23,46,28,10,35,24,30,19,35,15,30,17,1,115,30,14,21,46,28,29,19,24,30,11,46,15,30,13,6,115,30,14,23,46,28,44,7,24,30,59,1,16,30,12,7,121,30,12,26,47,28,39,14,24,30,22,41,15,30,6,14,121,30,6,34,47,28,46,10,24,30,2,64,15,30,17,4,122,30,29,14,46,28,49,10,24,30,24,46,15,30,4,18,122,30,13,32,46,28,48,14,24,30,42,32,15,30,20,4,117,30,40,7,47,28,43,22,24,30,10,67,15,30,19,6,118,30,18,31,47,28,34,34,24,30,20,61,15,30],E={L:1,M:2,Q:3,H:4},F=[30660,29427,32170,30877,26159,25368,27713,26998,21522,20773,24188,23371,17913,16590,20375,19104,13663,12392,16177,14854,9396,8579,11994,11245,5769,5054,7399,6608,1890,597,3340,2107],G=[1,2,4,8,16,32,64,128,29,58,116,232,205,135,19,38,76,152,45,90,180,117,234,201,143,3,6,12,24,48,96,192,157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,35,70,140,5,10,20,40,80,160,93,186,105,210,185,111,222,161,95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,129,31,62,124,248,237,199,147,59,118,236,197,151,51,102,204,133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,130,25,50,100,200,141,7,14,28,56,112,224,221,167,83,166,81,162,89,178,121,242,249,239,195,155,43,86,172,69,138,9,18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,88,176,125,250,233,207,131,27,54,108,216,173,71,142,0],H=[255,0,1,25,2,50,26,198,3,223,51,238,27,104,199,75,4,100,224,14,52,141,239,129,28,193,105,248,200,8,76,113,5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,29,181,194,125,106,39,249,185,201,154,9,120,77,228,114,166,6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,54,208,148,206,143,150,219,189,241,210,19,92,131,56,70,64,30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,94,155,159,10,21,121,43,78,212,229,172,115,243,167,87,7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,227,165,153,119,38,184,180,124,17,68,146,217,35,32,137,46,55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,162,31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,59,82,41,157,85,170,251,96,134,177,187,204,62,90,203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,79,174,213,233,230,231,173,232,116,214,244,234,168,80,88,175],I=3,J=3,K=40,L=10,M=[3220,1468,2713,1235,3062,1890,2119,1549,2344,2936,1117,2583,1330,2470,1667,2249,2028,3780,481,4011,142,3098,831,3445,592,2517,1776,2234,1951,2827,1070,2660,1345,3177],N=parseInt("0666",8),O=[],P=[],Q=1,R=[],S=[],T=!1,U=[],V=a.qr,W=[],X={VERSION:"1.1.3",canvas:function(a){a=e(a);var c=a.size>=1&&a.size<=10?a.size:4;c*=25;var d=a.canvas||b(),f=d.getContext("2d");f.canvas.width=c,f.canvas.height=c,f.fillStyle=a.background||"#fff",f.fillRect(0,0,c,c),Q=E[a.level&&a.level.toUpperCase()||"L"];var g=q(a.value||"");f.lineWidth=1;var h=c;h/=z,h=Math.floor(h),f.clearRect(0,0,c,c),f.fillStyle=a.background||"#fff",f.fillRect(0,0,h*(z+8),h*(z+8)),f.fillStyle=a.foreground||"#000";var i,j;for(i=0;z>i;i++)for(j=0;z>j;j++)g[j*z+i]&&f.fillRect(h*i,h*j,h,h);return d},image:function(a){a=e(a);var b=this.canvas(a),d=a.image||c();return d.src=b.toDataURL(a.mime||B),d.height=b.height,d.width=b.width,d},save:function(a,b,c){function f(a){h||(h=!0,c(a))}switch(a=e(a),typeof b){case"function":c=b,b=null;break;case"string":a.path=b}if("function"!=typeof c)throw new TypeError("Invalid callback type: "+typeof c);var h=!1,i=this.canvas(a);T?g(i,a,f):d(i,a,f)},saveSync:function(a,b){a=e(a),"string"==typeof b&&(a.path=b);var c=this.canvas(a);T?h(c,a):d(c,a)},toDataURL:function(a){return a=e(a),this.canvas(a).toDataURL(a.mime||B)},noConflict:function(){return a.qr=V,this}};"undefined"!=typeof exports?(T=!0,"undefined"!=typeof module&&module.exports&&(exports=module.exports=X),exports.qr=X,r=require("canvas"),x=r.Image,w=require("fs")):"function"==typeof define&&define.amd?define(function(){return X}):(a.HTMLCanvasElement||f(X),a.qr=X)}(this); +//# sourceMappingURL=qr.min.map \ No newline at end of file diff --git a/inc/shaarli.css b/inc/shaarli.css index 52a48208..28394ed5 100644 --- a/inc/shaarli.css +++ b/inc/shaarli.css @@ -1,4 +1,4 @@ -/* CSS Stylsheet for Shaarli - http://sebsauvage.net/wiki/doku.php?id=php:shaarli */ +/* Cascading Stylesheet for Shaarli - http://sebsauvage.net/wiki/doku.php?id=php:shaarli */ /* CSS Reset from Yahoo to cope with browsers CSS inconsistencies. */ /* @@ -7,7 +7,7 @@ version: 2.8.2r1 */ html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;} -body { font-family: "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif; font-size:10pt; background-color: #ffffff; } +body { font-family: "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif; font-size:10pt; background-color: #ffffff; word-wrap: break-word; } input, textarea { background-color: #dedede; background: -webkit-gradient(linear, 0 0, 0 bottom, from(#dedede), to(#ffffff)); @@ -232,14 +232,15 @@ cursor:pointer; .linktitle { font-size:14pt; font-weight:bold; } .linktitle a { text-decoration: none; color:#80AD48; } .linktitle a:hover { color:#F57900; } -.linkdate { font-size:8pt; color:#888; } -.linkdate a { background-image:url('../images/calendar.png');padding:2px 0 3px 20px;background-repeat:no-repeat;text-decoration: none; color:#E28E3F; } -.linkdate a:hover { color: #F57900 } +.linkdate, .linkarchive { font-size:8pt; color:#888; } +.linkdate a, .linkarchive a { color:#E28E3F; } +.linkdate a {background-image:url('../images/calendar.png');padding:2px 0 3px 20px;background-repeat:no-repeat;text-decoration: none; } +.linkdate a:hover, .linkarchive a:hover { color: #F57900 } .linkurl { font-size:8pt; color:#4BAA74; } .linkdescription { color:#000; margin-top:0; margin-bottom:12px; font-weight:normal; max-height:400px; overflow:auto; } .linkdescription a { text-decoration: none; color:#3465A4; } .linkdescription a:hover { color:#F57900; } -.linktaglist { padding-top:10px;} +.linktaglist { padding-top:10px; line-height:200%;} .linktag { font-size:9pt; @@ -408,13 +409,13 @@ div.dailyEntryDescription overflow:auto; } -/* Common css screwdriver */ +/* Common CSS screwdriver */ .clear{ clear:both; } /* For lazy images loading in picture wall. - using http://www.appelsiini.net/projects/lazyload + Using http://www.appelsiini.net/projects/lazyload */ .lazyimage { display:none; } @@ -451,7 +452,7 @@ a {color:#000!important;text-decoration:none!important;} #searchform_value { width:70% !important; } #tagfilter_value { width:70% !important; } div.qrcode { position:relative; float:left; top:-10px; left:0px; } -#paging_privatelinks { float;none; } +#paging_privatelinks { float:none; } #paging_linksperpage { float:none; margin-bottom:10px; font-size:smaller;} #paging_older,#paging_newer,#paging_linksperpage a { border: 1px solid black; padding:3px 5px 3px 5px; background-color:#666; color:#fff; border-radius: 5px 5px 5px 5px;} .thumbnail { float:none; height:auto; margin: 0px; text-align:center;} diff --git a/index.php b/index.php index 0465a4e5..1d523a33 100644 --- a/index.php +++ b/index.php @@ -1,9 +1,9 @@ '); // Suffix to encapsulate data in php code. +define('shaarli_version','0.0.42 beta'); +define('PHPPREFIX',''); // Suffix to encapsulate data in PHP code. +// http://server.com/x/shaarli --> /shaarli/ +define('WEB_PATH', substr($_SERVER["REQUEST_URI"], 0, 1+strrpos($_SERVER["REQUEST_URI"], '/', 0))); // Force cookie path (but do not change lifetime) $cookie=session_get_cookie_params(); @@ -46,8 +52,8 @@ session_set_cookie_params($cookie['lifetime'],$cookiedir,$_SERVER['HTTP_HOST']); // Set session parameters on server side. define('INACTIVITY_TIMEOUT',3600); // (in seconds). If the user does not access any page within this time, his/her session is considered expired. ini_set('session.use_cookies', 1); // Use cookies to store session. -ini_set('session.use_only_cookies', 1); // Force cookies for session (phpsessionID forbidden in URL) -ini_set('session.use_trans_sid', false); // Prevent php to use sessionID in URL if cookies are disabled. +ini_set('session.use_only_cookies', 1); // Force cookies for session (phpsessionID forbidden in URL). +ini_set('session.use_trans_sid', false); // Prevent PHP form using sessionID in URL if cookies are disabled. session_name('shaarli'); if (session_id() == '') session_start(); // Start session if needed (Some server auto-start sessions). @@ -61,9 +67,8 @@ error_reporting(E_ALL^E_WARNING); // See all error except warnings. //error_reporting(-1); // See all errors (for debugging only) include "inc/rain.tpl.class.php"; //include Rain TPL -raintpl::$tpl_dir = "tpl/"; // template directory -if (!is_dir('tmp')) { mkdir('tmp',0705); chmod('tmp',0705); } -raintpl::$cache_dir = "tmp/"; // cache directory +raintpl::$tpl_dir = $GLOBALS['config']['RAINTPL_TPL']; // template directory +raintpl::$cache_dir = $GLOBALS['config']['RAINTPL_TMP']; // cache directory ob_start(); // Output buffering for the page cache. @@ -83,18 +88,8 @@ header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); -// Directories creations (Note that your web host may require differents rights than 705.) +// Directories creations (Note that your web host may require different rights than 705.) if (!is_writable(realpath(dirname(__FILE__)))) die('
ERROR: Shaarli does not have the right to write in its own directory ('.realpath(dirname(__FILE__)).').
'); -if (!is_dir($GLOBALS['config']['DATADIR'])) { mkdir($GLOBALS['config']['DATADIR'],0705); chmod($GLOBALS['config']['DATADIR'],0705); } -if (!is_dir('tmp')) { mkdir('tmp',0705); chmod('tmp',0705); } // For RainTPL temporary files. -if (!is_file($GLOBALS['config']['DATADIR'].'/.htaccess')) { file_put_contents($GLOBALS['config']['DATADIR'].'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. -// Second check to see if Shaarli can write in its directory, because on some hosts is_writable() is not reliable. -if (!is_file($GLOBALS['config']['DATADIR'].'/.htaccess')) die('
ERROR: Shaarli does not have the right to write in its data directory ('.realpath($GLOBALS['config']['DATADIR']).').
'); -if ($GLOBALS['config']['ENABLE_LOCALCACHE']) -{ - if (!is_dir($GLOBALS['config']['CACHEDIR'])) { mkdir($GLOBALS['config']['CACHEDIR'],0705); chmod($GLOBALS['config']['CACHEDIR'],0705); } - if (!is_file($GLOBALS['config']['CACHEDIR'].'/.htaccess')) { file_put_contents($GLOBALS['config']['CACHEDIR'].'/.htaccess',"Allow from none\nDeny from all\n"); } // Protect data files. -} // Handling of old config file which do not have the new parameters. if (empty($GLOBALS['title'])) $GLOBALS['title']='Shared links on '.htmlspecialchars(indexUrl()); @@ -103,6 +98,7 @@ if (empty($GLOBALS['redirector'])) $GLOBALS['redirector']=''; if (empty($GLOBALS['disablesessionprotection'])) $GLOBALS['disablesessionprotection']=false; if (empty($GLOBALS['disablejquery'])) $GLOBALS['disablejquery']=false; if (empty($GLOBALS['privateLinkByDefault'])) $GLOBALS['privateLinkByDefault']=false; +if (empty($GLOBALS['titleLink'])) $GLOBALS['titleLink']='?'; // I really need to rewrite Shaarli with a proper configuation manager. // Run config screen if first run: @@ -110,17 +106,19 @@ if (!is_file($GLOBALS['config']['CONFIG_FILE'])) install(); require $GLOBALS['config']['CONFIG_FILE']; // Read login/password hash into $GLOBALS. +// a token depending of deployment salt, user password, and the current ip +define('STAY_SIGNED_IN_TOKEN', sha1($GLOBALS['hash'].$_SERVER["REMOTE_ADDR"].$GLOBALS['salt'])); autoLocale(); // Sniff browser language and set date format accordingly. header('Content-Type: text/html; charset=utf-8'); // We use UTF-8 for proper international characters handling. -// Check php version +// Check PHP version function checkphpversion() { if (version_compare(PHP_VERSION, '5.1.0') < 0) { header('Content-Type: text/plain; charset=utf-8'); - echo 'Your server supports php '.PHP_VERSION.'. Shaarli requires at least php 5.1.0, and thus cannot run. Sorry.'; + echo 'Your server supports PHP '.PHP_VERSION.'. Shaarli requires at least php 5.1.0, and thus cannot run. Sorry.'; exit; } } @@ -137,9 +135,9 @@ function checkUpdate() if (!is_file($GLOBALS['config']['UPDATECHECK_FILENAME']) || (filemtime($GLOBALS['config']['UPDATECHECK_FILENAME'])shouldBeCached) return; - if (!is_dir($GLOBALS['config']['PAGECACHE'])) { mkdir($GLOBALS['config']['PAGECACHE'],0705); chmod($GLOBALS['config']['PAGECACHE'],0705); } file_put_contents($this->filename,$page); } @@ -221,8 +218,8 @@ function nl2br_escaped($html) return str_replace('>','>',str_replace('<','<',nl2br($html))); } -/* Returns the small hash of a string - eg. smallHash('20111006_131924') --> yZH23w +/* Returns the small hash of a string, using RFC 4648 base64url format + e.g. smallHash('20111006_131924') --> yZH23w Small hashes: - are unique (well, as unique as crc32, at last) - are always 6 characters long. @@ -233,13 +230,10 @@ function nl2br_escaped($html) function smallHash($text) { $t = rtrim(base64_encode(hash('crc32',$text,true)),'='); - $t = str_replace('+','-',$t); // Get rid of characters which need encoding in URLs. - $t = str_replace('/','_',$t); - $t = str_replace('=','@',$t); - return $t; + return strtr($t, '+/', '-_'); } -// In a string, converts urls to clickable links. +// In a string, converts URLs to clickable links. // Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722 function text2clickable($url) { @@ -260,8 +254,8 @@ function keepMultipleSpaces($text) function autoLocale() { $loc='en_US'; // Default if browser does not send HTTP_ACCEPT_LANGUAGE - if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) // eg. "fr,fr-fr;q=0.8,en;q=0.5,en-us;q=0.3" - { // (It's a bit crude, but it works very well. Prefered language is always presented first.) + if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) // e.g. "fr,fr-fr;q=0.8,en;q=0.5,en-us;q=0.3" + { // (It's a bit crude, but it works very well. Preferred language is always presented first.) if (preg_match('/([a-z]{2}(-[a-z]{2})?)/i',$_SERVER['HTTP_ACCEPT_LANGUAGE'],$matches)) $loc=$matches[1]; } setlocale(LC_TIME,$loc); // LC_TIME = Set local for date/time format only. @@ -297,16 +291,20 @@ function allIPs() return $ip; } +function fillSessionInfo() { + $_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand()); // Generate unique random number (different than phpsessionid) + $_SESSION['ip']=allIPs(); // We store IP address(es) of the client to make sure session is not hijacked. + $_SESSION['username']=$GLOBALS['login']; + $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT; // Set session expiration. +} + // Check that user/password is correct. function check_auth($login,$password) { $hash = sha1($password.$login.$GLOBALS['salt']); if ($login==$GLOBALS['login'] && $hash==$GLOBALS['hash']) { // Login/password is correct. - $_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand()); // generate unique random number (different than phpsessionid) - $_SESSION['ip']=allIPs(); // We store IP address(es) of the client to make sure session is not hijacked. - $_SESSION['username']=$login; - $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT; // Set session expiration. + fillSessionInfo(); logm('Login successful'); return True; } @@ -321,6 +319,11 @@ function isLoggedIn() if (!isset($GLOBALS['login'])) return false; // Shaarli is not configured yet. + if (@$_COOKIE['shaarli_staySignedIn']===STAY_SIGNED_IN_TOKEN) + { + fillSessionInfo(); + return true; + } // If session does not exist on server side, or IP address has changed, or session has expired, logout. if (empty($_SESSION['uid']) || ($GLOBALS['disablesessionprotection']==false && $_SESSION['ip']!=allIPs()) || time()>=$_SESSION['expires_on']) { @@ -334,7 +337,9 @@ function isLoggedIn() } // Force logout. -function logout() { if (isset($_SESSION)) { unset($_SESSION['uid']); unset($_SESSION['ip']); unset($_SESSION['username']); unset($_SESSION['privateonly']); } } +function logout() { if (isset($_SESSION)) { unset($_SESSION['uid']); unset($_SESSION['ip']); unset($_SESSION['username']); unset($_SESSION['privateonly']); } +setcookie('shaarli_staySignedIn', FALSE, 0, WEB_PATH); +} // ------------------------------------------------------------------------------------------ @@ -391,17 +396,18 @@ if (isset($_POST['login'])) { if (!ban_canLogin()) die('I said: NO. You are banned for the moment. Go away.'); if (isset($_POST['password']) && tokenOk($_POST['token']) && (check_auth($_POST['login'], $_POST['password']))) - { // Login/password is ok. + { // Login/password is OK. ban_loginOk(); // If user wants to keep the session cookie even after the browser closes: if (!empty($_POST['longlastingsession'])) { + setcookie('shaarli_staySignedIn', STAY_SIGNED_IN_TOKEN, time()+31536000, WEB_PATH); $_SESSION['longlastingsession']=31536000; // (31536000 seconds = 1 year) $_SESSION['expires_on']=time()+$_SESSION['longlastingsession']; // Set session expiration on server-side. $cookiedir = ''; if(dirname($_SERVER['SCRIPT_NAME'])!='/') $cookiedir=dirname($_SERVER["SCRIPT_NAME"]).'/'; session_set_cookie_params($_SESSION['longlastingsession'],$cookiedir,$_SERVER['HTTP_HOST']); // Set session cookie expiration on client side - // Note: Never forget the trailing slash on the cookie path ! + // Note: Never forget the trailing slash on the cookie path! session_regenerate_id(true); // Send cookie with new expiration date to browser. } else // Standard session expiration (=when browser closes) @@ -411,7 +417,7 @@ if (isset($_POST['login'])) session_regenerate_id(true); } // Optional redirect after login: - if (isset($_GET['post'])) { header('Location: ?post='.urlencode($_GET['post']).(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').(!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'')); exit; } + if (isset($_GET['post'])) { header('Location: ?post='.urlencode($_GET['post']).(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').(!empty($_GET['description'])?'&description='.urlencode($_GET['description']):'').(!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'')); exit; } if (isset($_POST['returnurl'])) { if (endsWith($_POST['returnurl'],'?do=login')) { header('Location: ?'); exit; } // Prevent loops over login screen. @@ -423,7 +429,7 @@ if (isset($_POST['login'])) { ban_loginFailed(); $redir = ''; - if (isset($_GET['post'])) { $redir = '&post='.urlencode($_GET['post']).(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').(!empty($_GET['source'])?'&source='.urlencode($_GET['source']):''); } + if (isset($_GET['post'])) { $redir = '&post='.urlencode($_GET['post']).(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').(!empty($_GET['description'])?'&description='.urlencode($_GET['description']):'').(!empty($_GET['source'])?'&source='.urlencode($_GET['source']):''); } echo ''; // Redirect to login screen. exit; } @@ -433,7 +439,7 @@ if (isset($_POST['login'])) // Misc utility functions: // Returns the server URL (including port and http/https), without path. -// eg. "http://myserver.com:8080" +// e.g. "http://myserver.com:8080" // You can append $_SERVER['SCRIPT_NAME'] to get the current script URL. function serverUrl() { @@ -443,24 +449,24 @@ function serverUrl() } // Returns the absolute URL of current script, without the query. -// (eg. http://sebsauvage.net/links/) +// (e.g. http://sebsauvage.net/links/) function indexUrl() { $scriptname = $_SERVER["SCRIPT_NAME"]; // If the script is named 'index.php', we remove it (for better looking URLs, - // eg. http://mysite.com/shaarli/?abcde instead of http://mysite.com/shaarli/index.php?abcde) + // e.g. http://mysite.com/shaarli/?abcde instead of http://mysite.com/shaarli/index.php?abcde) if (endswith($scriptname,'index.php')) $scriptname = substr($scriptname,0,strlen($scriptname)-9); return serverUrl() . $scriptname; } // Returns the absolute URL of current script, WITH the query. -// (eg. http://sebsauvage.net/links/?toto=titi&spamspamspam=humbug) +// (e.g. http://sebsauvage.net/links/?toto=titi&spamspamspam=humbug) function pageUrl() { return indexUrl().(!empty($_SERVER["QUERY_STRING"]) ? '?'.$_SERVER["QUERY_STRING"] : ''); } -// Convert post_max_size/upload_max_filesize (eg.'16M') parameters to bytes. +// Convert post_max_size/upload_max_filesize (e.g. '16M') parameters to bytes. function return_bytes($val) { $val = trim($val); $last=strtolower($val[strlen($val)-1]); @@ -481,7 +487,7 @@ function getMaxFileSize() $size2 = return_bytes(ini_get('upload_max_filesize')); // Return the smaller of two: $maxsize = min($size1,$size2); - // FIXME: Then convert back to readable notations ? (eg. 2M instead of 2000000) + // FIXME: Then convert back to readable notations ? (e.g. 2M instead of 2000000) return $maxsize; } @@ -529,7 +535,7 @@ function linkdate2iso8601($linkdate) function linkdate2locale($linkdate) { return utf8_encode(strftime('%c',linkdate2timestamp($linkdate))); // %c is for automatic date format according to locale. - // Note that if you use a local which is not installed on your webserver, + // Note that if you use a locale which is not installed on your webserver, // the date will not be displayed in the chosen locale, but probably in US notation. } @@ -551,10 +557,10 @@ function http_parse_headers_shaarli( $headers ) } /* GET an URL. - Input: $url : url to get (http://...) + Input: $url : URL to get (http://...) $timeout : Network timeout (will wait this many seconds for an anwser before giving up). - Output: An array. [0] = HTTP status message (eg. "HTTP/1.1 200 OK") or error message - [1] = associative array containing HTTP response headers (eg. echo getHTTP($url)[1]['Content-Type']) + Output: An array. [0] = HTTP status message (e.g. "HTTP/1.1 200 OK") or error message + [1] = associative array containing HTTP response headers (e.g. echo getHTTP($url)[1]['Content-Type']) [2] = data Example: list($httpstatus,$headers,$data) = getHTTP('http://sebauvage.net/'); if (strpos($httpstatus,'200 OK')!==false) @@ -570,11 +576,11 @@ function getHTTP($url,$timeout=30) $context = stream_context_create($options); $data=file_get_contents($url,false,$context,-1, 4000000); // We download at most 4 Mb from source. if (!$data) { return array('HTTP Error',array(),''); } - $httpStatus=$http_response_header[0]; // eg. "HTTP/1.1 200 OK" + $httpStatus=$http_response_header[0]; // e.g. "HTTP/1.1 200 OK" $responseHeaders=http_parse_headers_shaarli($http_response_header); return array($httpStatus,$responseHeaders,$data); } - catch (Exception $e) // getHTTP *can* fail silentely (we don't care if the title cannot be fetched) + catch (Exception $e) // getHTTP *can* fail silently (we don't care if the title cannot be fetched) { return array($e->getMessage(),'',''); } @@ -600,14 +606,14 @@ function getToken() return $rnd; } -// Tells if a token is ok. Using this function will destroy the token. -// true=token is ok. +// Tells if a token is OK. Using this function will destroy the token. +// true=token is OK. function tokenOk($token) { if (isset($_SESSION['tokens'][$token])) { unset($_SESSION['tokens'][$token]); // Token is used: destroy it. - return true; // Token is ok. + return true; // Token is OK. } return false; // Wrong token, or already used. } @@ -642,8 +648,9 @@ class pageBuilder $this->tpl->assign('version',shaarli_version); $this->tpl->assign('scripturl',indexUrl()); $this->tpl->assign('pagetitle','Shaarli'); - $this->tpl->assign('privateonly',!empty($_SESSION['privateonly'])); // Show only private links ? + $this->tpl->assign('privateonly',!empty($_SESSION['privateonly'])); // Show only private links? if (!empty($GLOBALS['title'])) $this->tpl->assign('pagetitle',$GLOBALS['title']); + if (!empty($GLOBALS['titleLink'])) $this->tpl->assign('titleLink',$GLOBALS['titleLink']); if (!empty($GLOBALS['pagetitle'])) $this->tpl->assign('pagetitle',$GLOBALS['pagetitle']); $this->tpl->assign('shaarlititle',empty($GLOBALS['title']) ? 'Shaarli': $GLOBALS['title'] ); return; @@ -657,7 +664,7 @@ class pageBuilder } // Render a specific page (using a template). - // eg. pb.renderPage('picwall') + // e.g. pb.renderPage('picwall') public function renderPage($page) { if ($this->tpl===false) $this->initialize(); // Lazy initialization @@ -676,10 +683,10 @@ class pageBuilder Available keys: title : Title of the link - url : URL of the link. Can be absolute or relative. Relative URLs are permalinks (eg.'?m-ukcw') + url : URL of the link. Can be absolute or relative. Relative URLs are permalinks (e.g.'?m-ukcw') description : description of the entry - private : Is this link private ? 0=no, other value=yes - linkdate : date of the creation of this entry, in the form YYYYMMDD_HHMMSS (eg.'20110914_192317') + private : Is this link private? 0=no, other value=yes + linkdate : date of the creation of this entry, in the form YYYYMMDD_HHMMSS (e.g.'20110914_192317') tags : tags attached to this entry (separated by spaces) We implement 3 interfaces: @@ -689,15 +696,15 @@ class pageBuilder */ class linkdb implements Iterator, Countable, ArrayAccess { - private $links; // List of links (associative array. Key=linkdate (eg. "20110823_124546"), value= associative array (keys:title,description...) + private $links; // List of links (associative array. Key=linkdate (e.g. "20110823_124546"), value= associative array (keys:title,description...) private $urls; // List of all recorded URLs (key=url, value=linkdate) for fast reserve search (url-->linkdate) private $keys; // List of linkdate keys (for the Iterator interface implementation) private $position; // Position in the $this->keys array. (for the Iterator interface implementation.) - private $loggedin; // Is the used logged in ? (used to filter private links) + private $loggedin; // Is the user logged in? (used to filter private links) // Constructor: function __construct($isLoggedIn) - // Input : $isLoggedIn : is the used logged in ? + // Input : $isLoggedIn : is the user logged in? { $this->loggedin = $isLoggedIn; $this->checkdb(); // Make sure data file exists. @@ -711,7 +718,7 @@ class linkdb implements Iterator, Countable, ArrayAccess public function offsetSet($offset, $value) { if (!$this->loggedin) die('You are not authorized to add a link.'); - if (empty($value['linkdate']) || empty($value['url'])) die('Internal Error: A link should always have a linkdate and url.'); + if (empty($value['linkdate']) || empty($value['url'])) die('Internal Error: A link should always have a linkdate and URL.'); if (empty($offset)) die('You must specify a key.'); $this->links[$offset] = $value; $this->urls[$value['url']]=$offset; @@ -774,19 +781,19 @@ class linkdb implements Iterator, Countable, ArrayAccess invalidateCaches(); } - // Returns the link for a given URL (if it exists). false it does not exist. + // Returns the link for a given URL (if it exists). False if it does not exist. public function getLinkFromUrl($url) { if (isset($this->urls[$url])) return $this->links[$this->urls[$url]]; return false; } - // Case insentitive search among links (in url, title and description). Returns filtered list of links. - // eg. print_r($mydb->filterFulltext('hollandais')); + // Case insensitive search among links (in the URLs, title and description). Returns filtered list of links. + // e.g. print_r($mydb->filterFulltext('hollandais')); public function filterFulltext($searchterms) { // FIXME: explode(' ',$searchterms) and perform a AND search. - // FIXME: accept double-quotes to search for a string "as is" ? + // FIXME: accept double-quotes to search for a string "as is"? $filtered=array(); $s = strtolower($searchterms); foreach($this->links as $l) @@ -803,7 +810,7 @@ class linkdb implements Iterator, Countable, ArrayAccess // Filter by tag. // You can specify one or more tags (tags can be separated by space or comma). - // eg. print_r($mydb->filterTags('linux programming')); + // e.g. print_r($mydb->filterTags('linux programming')); public function filterTags($tags,$casesensitive=false) { $t = str_replace(',',' ',($casesensitive?$tags:strtolower($tags))); @@ -819,9 +826,9 @@ class linkdb implements Iterator, Countable, ArrayAccess return $filtered; } - // Filter by day. Day must be in the form 'YYYYMMDD' (eg. '20120125') + // Filter by day. Day must be in the form 'YYYYMMDD' (e.g. '20120125') // Sort order is: older articles first. - // eg. print_r($mydb->filterDay('20120125')); + // e.g. print_r($mydb->filterDay('20120125')); public function filterDay($day) { $filtered=array(); @@ -876,13 +883,13 @@ class linkdb implements Iterator, Countable, ArrayAccess } // ------------------------------------------------------------------------------------------ -// Ouput the last N links in RSS 2.0 format. +// Output the last N links in RSS 2.0 format. function showRSS() { header('Content-Type: application/rss+xml; charset=utf-8'); // $usepermalink : If true, use permalink instead of final link. - // User just has to add 'permalink' in URL parameters. eg. http://mysite.com/shaarli/?do=rss&permalinks + // User just has to add 'permalink' in URL parameters. e.g. http://mysite.com/shaarli/?do=rss&permalinks $usepermalinks = isset($_GET['permalinks']); // Cache system @@ -891,9 +898,9 @@ function showRSS() $cached = $cache->cachedVersion(); if (!empty($cached)) { echo $cached; exit; } // If cached was not found (or not usable), then read the database and build the response: - $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in). + $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if user it not logged in). - // Optionnaly filter the results: + // Optionally filter the results: $linksToDisplay=array(); if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']); elseif (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); @@ -942,7 +949,7 @@ function showRSS() echo ''."\n\n"; $i++; } - echo ''; + echo ''; $cache->cache(ob_get_contents()); ob_end_flush(); @@ -950,13 +957,13 @@ function showRSS() } // ------------------------------------------------------------------------------------------ -// Ouput the last N links in ATOM format. +// Output the last N links in ATOM format. function showATOM() { header('Content-Type: application/atom+xml; charset=utf-8'); // $usepermalink : If true, use permalink instead of final link. - // User just has to add 'permalink' in URL parameters. eg. http://mysite.com/shaarli/?do=atom&permalinks + // User just has to add 'permalink' in URL parameters. e.g. http://mysite.com/shaarli/?do=atom&permalinks $usepermalinks = isset($_GET['permalinks']); // Cache system @@ -968,7 +975,7 @@ function showATOM() $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in). - // Optionnaly filter the results: + // Optionally filter the results: $linksToDisplay=array(); if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']); elseif (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); @@ -1027,7 +1034,7 @@ function showATOM() $feed.=''.htmlspecialchars($pageaddr).''.htmlspecialchars($pageaddr).''; $feed.=''.htmlspecialchars($pageaddr).''."\n\n"; // Yes, I know I should use a real IRI (RFC3987), but the site URL will do. $feed.=$entries; - $feed.=''; + $feed.=''; echo $feed; $cache->cache(ob_get_contents()); @@ -1064,7 +1071,7 @@ function showDailyRSS() if (empty($days[$day])) $days[$day]=array(); $days[$day][]=$linkdate; } - if (count($days)>$nb_of_days) break; // Have we collected enough days ? + if (count($days)>$nb_of_days) break; // Have we collected enough days? } // Build the RSS feed. @@ -1104,7 +1111,7 @@ function showDailyRSS() echo ''."\n\n\n"; } - echo ''; + echo ''; $cache->cache(ob_get_contents()); ob_end_flush(); @@ -1143,7 +1150,7 @@ function showDaily() } /* We need to spread the articles on 3 columns. - I did not want to use a javascript lib like http://masonry.desandro.com/ + I did not want to use a JavaScript lib like http://masonry.desandro.com/ so I manually spread entries with a simple method: I roughly evaluate the height of a div according to title and description length. */ @@ -1154,7 +1161,7 @@ function showDaily() // Roughly estimate length of entry (by counting characters) // Title: 30 chars = 1 line. 1 line is 30 pixels height. // Description: 836 characters gives roughly 342 pixel height. - // This is not perfect, but it's usually ok. + // This is not perfect, but it's usually OK. $length=strlen($link['title'])+(342*strlen($link['description']))/836; if ($link['thumbnail']) $length +=100; // 1 thumbnails roughly takes 100 pixels height. // Then put in column which is the less filled: @@ -1207,7 +1214,7 @@ function renderPage() // -------- Picture wall if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=picwall')) { - // Optionnaly filter the results: + // Optionally filter the results: $links=array(); if (!empty($_GET['searchterm'])) $links = $LINKSDB->filterFulltext($_GET['searchterm']); elseif (!empty($_GET['searchtags'])) $links = $LINKSDB->filterTags(trim($_GET['searchtags'])); @@ -1287,7 +1294,7 @@ function renderPage() if (isset($_GET['linksperpage'])) { if (is_numeric($_GET['linksperpage'])) { $_SESSION['LINKS_PER_PAGE']=abs(intval($_GET['linksperpage'])); } - // Make sure the referer is from Shaarli itself. + // Make sure the referrer is Shaarli itself. $referer = '?'; if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['HTTP_HOST'])==0) $referer = $_SERVER['HTTP_REFERER']; @@ -1306,7 +1313,7 @@ function renderPage() { unset($_SESSION['privateonly']); // See all links } - // Make sure the referer is from Shaarli itself. + // Make sure the referrer is Shaarli itself. $referer = '?'; if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['HTTP_HOST'])==0) $referer = $_SERVER['HTTP_REFERER']; @@ -1317,17 +1324,17 @@ function renderPage() // -------- Handle other actions allowed for non-logged in users: if (!isLoggedIn()) { - // User tries to post new link but is not loggedin: + // User tries to post new link but is not logged in: // Show login screen, then redirect to ?post=... if (isset($_GET['post'])) { - header('Location: ?do=login&post='.urlencode($_GET['post']).(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').(!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'')); // Redirect to login page, then back to post link. + header('Location: ?do=login&post='.urlencode($_GET['post']).(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').(!empty($_GET['description'])?'&description='.urlencode($_GET['description']):'').(!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'')); // Redirect to login page, then back to post link. exit; } $PAGE = new pageBuilder; buildLinkList($PAGE,$LINKSDB); // Compute list of links to display $PAGE->renderPage('linklist'); - exit; // Never remove this one ! All operations below are reserved for logged in user. + exit; // Never remove this one! All operations below are reserved for logged in user. } // -------- All other functions are reserved for the registered user: @@ -1348,7 +1355,7 @@ function renderPage() if ($GLOBALS['config']['OPEN_SHAARLI']) die('You are not supposed to change a password on an Open Shaarli.'); if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) { - if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away ! + if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away! // Make sure old password is correct. $oldhash = sha1($_POST['oldpassword'].$GLOBALS['login'].$GLOBALS['salt']); @@ -1375,13 +1382,14 @@ function renderPage() { if (!empty($_POST['title']) ) { - if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away ! + if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away! $tz = 'UTC'; if (!empty($_POST['continent']) && !empty($_POST['city'])) if (isTZvalid($_POST['continent'],$_POST['city'])) $tz = $_POST['continent'].'/'.$_POST['city']; $GLOBALS['timezone'] = $tz; $GLOBALS['title']=$_POST['title']; + $GLOBALS['titleLink']=$_POST['titleLink']; $GLOBALS['redirector']=$_POST['redirector']; $GLOBALS['disablesessionprotection']=!empty($_POST['disablesessionprotection']); $GLOBALS['disablejquery']=!empty($_POST['disablejquery']); @@ -1398,7 +1406,7 @@ function renderPage() $PAGE->assign('title',htmlspecialchars( empty($GLOBALS['title']) ? '' : $GLOBALS['title'] , ENT_QUOTES)); $PAGE->assign('redirector',htmlspecialchars( empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'] , ENT_QUOTES)); list($timezone_form,$timezone_js) = templateTZform($GLOBALS['timezone']); - $PAGE->assign('timezone_form',$timezone_form); // FIXME: put entire tz form generation in template ? + $PAGE->assign('timezone_form',$timezone_form); // FIXME: Put entire tz form generation in template? $PAGE->assign('timezone_js',$timezone_js); $PAGE->renderPage('configure'); exit; @@ -1422,7 +1430,7 @@ function renderPage() if (!empty($_POST['deletetag']) && !empty($_POST['fromtag'])) { $needle=trim($_POST['fromtag']); - $linksToAlter = $LINKSDB->filterTags($needle,true); // true for case-sensitive tag search. + $linksToAlter = $LINKSDB->filterTags($needle,true); // True for case-sensitive tag search. foreach($linksToAlter as $key=>$value) { $tags = explode(' ',trim($value['tags'])); @@ -1430,7 +1438,7 @@ function renderPage() $value['tags']=trim(implode(' ',$tags)); $LINKSDB[$key]=$value; } - $LINKSDB->savedb(); // save to disk + $LINKSDB->savedb(); // Save to disk. echo ''; exit; } @@ -1443,17 +1451,17 @@ function renderPage() foreach($linksToAlter as $key=>$value) { $tags = explode(' ',trim($value['tags'])); - $tags[array_search($needle,$tags)] = trim($_POST['totag']); // Remplace tags value. + $tags[array_search($needle,$tags)] = trim($_POST['totag']); // Replace tags value. $value['tags']=trim(implode(' ',$tags)); $LINKSDB[$key]=$value; } - $LINKSDB->savedb(); // save to disk + $LINKSDB->savedb(); // Save to disk. echo ''; exit; } } - // -------- User wants to add a link without using the bookmarklet: show form. + // -------- User wants to add a link without using the bookmarklet: Show form. if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=addlink')) { $PAGE = new pageBuilder; @@ -1465,7 +1473,7 @@ function renderPage() // -------- User clicked the "Save" button when editing a link: Save link to database. if (isset($_POST['save_edit'])) { - if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away ! + if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away! $tags = trim(preg_replace('/\s\s+/',' ', $_POST['lf_tags'])); // Remove multiple spaces. $linkdate=$_POST['lf_linkdate']; $url = trim($_POST['lf_url']); @@ -1475,7 +1483,7 @@ function renderPage() 'linkdate'=>$linkdate,'tags'=>str_replace(',',' ',$tags)); if ($link['title']=='') $link['title']=$link['url']; // If title is empty, use the URL as title. $LINKSDB[$linkdate] = $link; - $LINKSDB->savedb(); // save to disk + $LINKSDB->savedb(); // Save to disk. pubsubhub(); // If we are called from the bookmarklet, we must close the popup: @@ -1489,7 +1497,7 @@ function renderPage() // -------- User clicked the "Cancel" button when editing a link. if (isset($_POST['cancel_edit'])) { - // If we are called from the bookmarklet, we must close the popup; + // If we are called from the bookmarklet, we must close the popup: if (isset($_GET['source']) && $_GET['source']=='bookmarklet') { echo ''; exit; } $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); $returnurl .= '#'.smallHash($_POST['lf_linkdate']); // Scroll to the link which has been edited. @@ -1497,12 +1505,12 @@ function renderPage() exit; } - // -------- User clicked the "Delete" button when editing a link : Delete link from database. + // -------- User clicked the "Delete" button when editing a link: Delete link from database. if (isset($_POST['delete_link'])) { if (!tokenOk($_POST['token'])) die('Wrong token.'); // We do not need to ask for confirmation: - // - confirmation is handled by javascript + // - confirmation is handled by JavaScript // - we are protected from XSRF by the token. $linkdate=$_POST['lf_linkdate']; unset($LINKSDB[$linkdate]); @@ -1552,7 +1560,7 @@ function renderPage() $tags = (empty($_GET['tags']) ? '' : $_GET['tags'] ); // Get tags if it was provided in URL $private = (!empty($_GET['private']) && $_GET['private'] === "1" ? 1 : 0); // Get private if it was provided in URL if (($url!='') && parse_url($url,PHP_URL_SCHEME)=='') $url = 'http://'.$url; - // If this is an HTTP link, we try go get the page to extact the title (otherwise we will to straight to the edit form.) + // If this is an HTTP link, we try go get the page to extract the title (otherwise we will to straight to the edit form.) if (empty($title) && parse_url($url,PHP_URL_SCHEME)=='http') { list($status,$headers,$data) = getHTTP($url,4); // Short timeout to keep the application responsive. @@ -1581,7 +1589,11 @@ function renderPage() } } } - if ($url=='') $url='?'.smallHash($linkdate); // In case of empty URL, this is just a text (with a link that point to itself) + if ($url=='') // In case of empty URL, this is just a text (with a link that points to itself) + { + $url='?'.smallHash($linkdate); + $title='Note: '; + } $link = array('linkdate'=>$linkdate,'title'=>$title,'url'=>$url,'description'=>$description,'tags'=>$tags,'private'=>$private); } @@ -1606,7 +1618,7 @@ function renderPage() exit; } $exportWhat=$_GET['what']; - if (!array_intersect(array('all','public','private'),array($exportWhat))) die('What are you trying to export ???'); + if (!array_intersect(array('all','public','private'),array($exportWhat))) die('What are you trying to export???'); header('Content-Type: text/html; charset=utf-8'); header('Content-disposition: attachment; filename=bookmarks_'.$exportWhat.'_'.strval(date('Ymd_His')).'.html'); @@ -1679,8 +1691,8 @@ function importFile() $filename=$_FILES['filetoupload']['name']; $filesize=$_FILES['filetoupload']['size']; $data=file_get_contents($_FILES['filetoupload']['tmp_name']); - $private = (empty($_POST['private']) ? 0 : 1); // Should the links be imported as private ? - $overwrite = !empty($_POST['overwrite']) ; // Should the imported links overwrite existing ones ? + $private = (empty($_POST['private']) ? 0 : 1); // Should the links be imported as private? + $overwrite = !empty($_POST['overwrite']) ; // Should the imported links overwrite existing ones? $import_count=0; // Sniff file type: @@ -1691,7 +1703,7 @@ function importFile() if ($type=='netscape') { // This is a standard Netscape-style bookmark file. - // This format is supported by all browsers (except IE, of course), also delicious, diigo and others. + // This format is supported by all browsers (except IE, of course), also Delicious, Diigo and others. foreach(explode('
',$data) as $html) // explode is very fast { $link = array('linkdate'=>'','title'=>'','url'=>'','description'=>'','tags'=>'','private'=>0); @@ -1725,14 +1737,14 @@ function importFile() // Make sure date/time is not already used by another link. // (Some bookmark files have several different links with the same ADD_DATE) - // We increment date by 1 second until we find a date which is not used in db. + // We increment date by 1 second until we find a date which is not used in DB. // (so that links that have the same date/time are more or less kept grouped by date, but do not conflict.) while (!empty($LINKSDB[date('Ymd_His',$raw_add_date)])) { $raw_add_date++; }// Yes, I know it's ugly. $link['linkdate']=date('Ymd_His',$raw_add_date); $LINKSDB[$link['linkdate']] = $link; $import_count++; } - else // link already present in database. + else // Link already present in database. { if ($overwrite) { // If overwrite is required, we import link data, except date/time. @@ -1747,11 +1759,11 @@ function importFile() } $LINKSDB->savedb(); - echo ''; + echo ''; } else { - echo ''; + echo ''; } } @@ -1783,13 +1795,13 @@ function buildLinkList($PAGE,$LINKSDB) { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); echo '

404 Not found.

Oh crap. The link you are trying to reach does not exist or has been deleted.'; - echo '
You would mind clicking here ?'; + echo '
You would mind clicking here?'; exit; } $search_type='permalink'; } else - $linksToDisplay = $LINKSDB; // otherwise, display without filtering. + $linksToDisplay = $LINKSDB; // Otherwise, display without filtering. // Option: Show only private links if (!empty($_SESSION['privateonly'])) @@ -1803,11 +1815,11 @@ function buildLinkList($PAGE,$LINKSDB) } // ---- Handle paging. - /* Can someone explain to me why you get the following error when using array_keys() on an object which implements the interface ArrayAccess ??? + /* Can someone explain to me why you get the following error when using array_keys() on an object which implements the interface ArrayAccess??? "Warning: array_keys() expects parameter 1 to be array, object given in ... " If my class implements ArrayAccess, why won't array_keys() accept it ? ( $keys=array_keys($linksToDisplay); ) */ - $keys=array(); foreach($linksToDisplay as $key=>$value) { $keys[]=$key; } // Stupid and ugly. Thanks php. + $keys=array(); foreach($linksToDisplay as $key=>$value) { $keys[]=$key; } // Stupid and ugly. Thanks PHP. // If there is only a single link, we change on-the-fly the title of the page. if (count($linksToDisplay)==1) $GLOBALS['pagetitle'] = $linksToDisplay[$keys[0]]['title'].' - '.$GLOBALS['title']; @@ -1854,7 +1866,7 @@ function buildLinkList($PAGE,$LINKSDB) $PAGE->assign('result_count',count($linksToDisplay)); $PAGE->assign('search_type',$search_type); $PAGE->assign('search_crits',$search_crits); - $PAGE->assign('redirector',empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector']); // optional redirector URL + $PAGE->assign('redirector',empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector']); // Optional redirector URL. $PAGE->assign('token',$token); $PAGE->assign('links',$linkDisp); return; @@ -1862,9 +1874,9 @@ function buildLinkList($PAGE,$LINKSDB) // Compute the thumbnail for a link. // -// with a link to the original URL. +// With a link to the original URL. // Understands various services (youtube.com...) -// Input: $url = url for which the thumbnail must be found. +// Input: $url = URL for which the thumbnail must be found. // $href = if provided, this URL will be followed instead of $url // Returns an associative array with thumbnail attributes (src,href,width,height,style,alt) // Some of them may be missing. @@ -1875,19 +1887,19 @@ function computeThumbnail($url,$href=false) if ($href==false) $href=$url; // For most hosts, the URL of the thumbnail can be easily deduced from the URL of the link. - // (eg. http://www.youtube.com/watch?v=spVypYk4kto ---> http://img.youtube.com/vi/spVypYk4kto/default.jpg ) + // (e.g. http://www.youtube.com/watch?v=spVypYk4kto ---> http://img.youtube.com/vi/spVypYk4kto/default.jpg ) // ^^^^^^^^^^^ ^^^^^^^^^^^ $domain = parse_url($url,PHP_URL_HOST); if ($domain=='youtube.com' || $domain=='www.youtube.com') { parse_str(parse_url($url,PHP_URL_QUERY), $params); // Extract video ID and get thumbnail - if (!empty($params['v'])) return array('src'=>'http://img.youtube.com/vi/'.$params['v'].'/default.jpg', + if (!empty($params['v'])) return array('src'=>'https://img.youtube.com/vi/'.$params['v'].'/default.jpg', 'href'=>$href,'width'=>'120','height'=>'90','alt'=>'YouTube thumbnail'); } if ($domain=='youtu.be') // Youtube short links { $path = parse_url($url,PHP_URL_PATH); - return array('src'=>'http://img.youtube.com/vi'.$path.'/default.jpg', + return array('src'=>'https://img.youtube.com/vi'.$path.'/default.jpg', 'href'=>$href,'width'=>'120','height'=>'90','alt'=>'YouTube thumbnail'); } if ($domain=='pix.toile-libre.org') // pix.toile-libre.org image hosting @@ -1901,18 +1913,18 @@ function computeThumbnail($url,$href=false) { $path = parse_url($url,PHP_URL_PATH); if (startsWith($path,'/a/')) return array(); // Thumbnails for albums are not available. - if (startsWith($path,'/r/')) return array('src'=>'http://i.imgur.com/'.basename($path).'s.jpg', + if (startsWith($path,'/r/')) return array('src'=>'https://i.imgur.com/'.basename($path).'s.jpg', 'href'=>$href,'width'=>'90','height'=>'90','alt'=>'imgur.com thumbnail'); - if (startsWith($path,'/gallery/')) return array('src'=>'http://i.imgur.com'.substr($path,8).'s.jpg', + if (startsWith($path,'/gallery/')) return array('src'=>'https://i.imgur.com'.substr($path,8).'s.jpg', 'href'=>$href,'width'=>'90','height'=>'90','alt'=>'imgur.com thumbnail'); - if (substr_count($path,'/')==1) return array('src'=>'http://i.imgur.com/'.substr($path,1).'s.jpg', + if (substr_count($path,'/')==1) return array('src'=>'https://i.imgur.com/'.substr($path,1).'s.jpg', 'href'=>$href,'width'=>'90','height'=>'90','alt'=>'imgur.com thumbnail'); } if ($domain=='i.imgur.com') { $pi = pathinfo(parse_url($url,PHP_URL_PATH)); - if (!empty($pi['filename'])) return array('src'=>'http://i.imgur.com/'.$pi['filename'].'s.jpg', + if (!empty($pi['filename'])) return array('src'=>'https://i.imgur.com/'.$pi['filename'].'s.jpg', 'href'=>$href,'width'=>'90','height'=>'90','alt'=>'imgur.com thumbnail'); } if ($domain=='dailymotion.com' || $domain=='www.dailymotion.com') @@ -1948,17 +1960,17 @@ function computeThumbnail($url,$href=false) ) { if ($domain=='vimeo.com') - { // Make sure this vimeo url points to a video (/xxx... where xxx is numeric) + { // Make sure this vimeo URL points to a video (/xxx... where xxx is numeric) $path = parse_url($url,PHP_URL_PATH); if (!preg_match('!/\d+.+?!',$path)) return array(); // This is not a single video URL. } if ($domain=='xkcd.com' || endsWith($domain,'.xkcd.com')) - { // Make sure this url points to a single comic (/xxx... where xxx is numeric) + { // Make sure this URL points to a single comic (/xxx... where xxx is numeric) $path = parse_url($url,PHP_URL_PATH); if (!preg_match('!/\d+.+?!',$path)) return array(); } if ($domain=='ted.com' || endsWith($domain,'.ted.com')) - { // Make sure this TED url points to a video (/talks/...) + { // Make sure this TED URL points to a video (/talks/...) $path = parse_url($url,PHP_URL_PATH); if ("/talks/" !== substr($path,0,7)) return array(); // This is not a single video URL. } @@ -1985,7 +1997,7 @@ function computeThumbnail($url,$href=false) // Returns the HTML code to display a thumbnail for a link // with a link to the original URL. // Understands various services (youtube.com...) -// Input: $url = url for which the thumbnail must be found. +// Input: $url = URL for which the thumbnail must be found. // $href = if provided, this URL will be followed instead of $url // Returns '' if no thumbnail available. function thumbnail($url,$href=false) @@ -2006,7 +2018,7 @@ function thumbnail($url,$href=false) // Returns the HTML code to display a thumbnail for a link // for the picture wall (using lazy image loading) // Understands various services (youtube.com...) -// Input: $url = url for which the thumbnail must be found. +// Input: $url = URL for which the thumbnail must be found. // $href = if provided, this URL will be followed instead of $url // Returns '' if no thumbnail available. function lazyThumbnail($url,$href=false) @@ -2016,7 +2028,7 @@ function lazyThumbnail($url,$href=false) $html=''; - // Lazy image (only loaded by javascript when in the viewport). + // Lazy image (only loaded by JavaScript when in the viewport). if (!empty($GLOBALS['disablejquery'])) // (except if jQuery is disabled) $html.='Sessions do not seem to work correctly on your server.
'; echo 'Make sure the variable session.save_path is set correctly in your php config, and that you have write access to it.
'; - echo 'It currently points to '.session_save_path().'

Click to try again.'; + echo 'It currently points to '.session_save_path().'
'; + echo 'Check that the hostname used to access Shaarli contains a dot. On some browsers, accessing your server via a hostname like \'localhost\' or any 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.
'; + echo '
Click to try again.'; die; } if (!isset($_SESSION['session_tested'])) @@ -2065,7 +2079,7 @@ function install() header('Location: '.indexUrl().'?test_session'); // Redirect to check stored data. } if (isset($_GET['test_session'])) - { // Step 3: Sessions are ok. Remove test parameter from URL. + { // Step 3: Sessions are OK. Remove test parameter from URL. header('Location: '.indexUrl()); } @@ -2083,7 +2097,7 @@ function install() $GLOBALS['hash'] = sha1($_POST['setpassword'].$GLOBALS['login'].$GLOBALS['salt']); $GLOBALS['title'] = (empty($_POST['title']) ? 'Shared links on '.htmlspecialchars(indexUrl()) : $_POST['title'] ); writeConfig(); - echo ''; + echo ''; exit; } @@ -2098,14 +2112,14 @@ function install() exit; } -// Generates the timezone selection form and javascript. +// Generates the timezone selection form and JavaScript. // Input: (optional) current timezone (can be 'UTC/UTC'). It will be pre-selected. // Output: array(html,js) // Example: list($htmlform,$js) = templateTZform('Europe/Paris'); // Europe/Paris pre-selected. -// Returns array('','') if server does not support timezones list. (eg. php 5.1 on free.fr) +// Returns array('','') if server does not support timezones list. (e.g. PHP 5.1 on free.fr) function templateTZform($ptz=false) { - if (function_exists('timezone_identifiers_list')) // because of old php version (5.1) which can be found on free.fr + if (function_exists('timezone_identifiers_list')) // because of old PHP version (5.1) which can be found on free.fr { // Try to split the provided timezone. if ($ptz==false) { $l=timezone_identifiers_list(); $ptz=$l[0]; } @@ -2114,7 +2128,7 @@ function templateTZform($ptz=false) // Display config form: $timezone_form = ''; $timezone_js = ''; - // The list is in the forme "Europe/Paris", "America/Argentina/Buenos_Aires"... + // The list is in the form "Europe/Paris", "America/Argentina/Buenos_Aires"... // We split the list in continents/cities. $continents = array(); $cities = array(); @@ -2152,9 +2166,9 @@ function templateTZform($ptz=false) function isTZvalid($continent,$city) { $tz = $continent.'/'.$city; - if (function_exists('timezone_identifiers_list')) // because of old php version (5.1) which can be found on free.fr + if (function_exists('timezone_identifiers_list')) // because of old PHP version (5.1) which can be found on free.fr { - if (in_array($tz, timezone_identifiers_list())) // it's a valid timezone ? + if (in_array($tz, timezone_identifiers_list())) // it's a valid timezone? return true; } return false; @@ -2197,7 +2211,7 @@ if (!function_exists('json_encode')) { } // Webservices (for use with jQuery/jQueryUI) -// eg. index.php?ws=tags&term=minecr +// e.g. index.php?ws=tags&term=minecr function processWS() { if (empty($_GET['ws']) || empty($_GET['term'])) return; @@ -2205,7 +2219,7 @@ function processWS() $LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in). header('Content-Type: application/json; charset=utf-8'); - // Search in tags (case insentitive, cumulative search) + // Search in tags (case insensitive, cumulative search) if ($_GET['ws']=='tags') { $tags=explode(' ',str_replace(',',' ',$term)); $last = array_pop($tags); // Get the last term ("a b c d" ==> "a b c", "d") @@ -2221,7 +2235,7 @@ function processWS() exit; } - // Search a single tag (case sentitive, single tag search) + // Search a single tag (case sensitive, single tag search) if ($_GET['ws']=='singletag') { /* To speed up things, we store list of tags in session */ @@ -2237,13 +2251,14 @@ function processWS() // Re-write configuration file according to globals. // Requires some $GLOBALS to be set (login,hash,salt,title). -// If the config file cannot be saved, an error message is dislayed and the user is redirected to "Tools" menu. +// If the config file cannot be saved, an error message is displayed and the user is redirected to "Tools" menu. // (otherwise, the function simply returns.) function writeConfig() { if (is_file($GLOBALS['config']['CONFIG_FILE']) && !isLoggedIn()) die('You are not authorized to alter config.'); // Only logged in user can alter config. $config='Page title: + Title link:
Timezone:{$timezone_form} Redirector
(e.g. http://anonym.to/? will mask the HTTP_REFERER) @@ -18,7 +19,7 @@ Security: Features: - + New link: diff --git a/tpl/import.html b/tpl/import.html index 9e581fc9..259e56ee 100644 --- a/tpl/import.html +++ b/tpl/import.html @@ -5,7 +5,7 @@