diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..050a13869
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+vendor
+composer.phar
+db/poche.sqlite
\ No newline at end of file
diff --git a/CREDITS b/CREDITS
index 77a3f663e..d6874a7bb 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1,17 +1,14 @@
poche is based on :
-* ReadItYourself http://www.memiks.fr/readityourself/
* PHP Readability http://www.keyvan.net/2010/08/php-readability/
* Encoding https://github.com/neitanod/forceutf8
* logo by Brightmix http://www.iconfinder.com/icondetails/43256/128/jeans_monotone_pocket_icon
* icons http://icomoon.io
* PHP Simple HTML DOM Parser (for Pocket import) http://simplehtmldom.sourceforge.net/
* Session https://github.com/tontof/kriss_feed/blob/master/src/class/Session.php
-* RainTPL http://www.raintpl.com/
+* Twig http://twig.sensiolabs.org
+* Flash messages https://github.com/plasticbrain/PHP-Flash-Messages
+* Pagination https://github.com/daveismyname/pagination
poche is developed by Nicolas Lœuillet under the Do What the Fuck You Want to Public License
-Contributors :
-Nicolas Lœuillet aka nico_somb
-Tom.C. aka tmos
-PeaceCopathe
-Gregoire_M
\ No newline at end of file
+Contributors : https://github.com/inthepoche/poche/graphs/contributors
\ No newline at end of file
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 000000000..47208ef05
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,53 @@
+# Installing poche
+
+Get the [latest twig version](https://github.com/inthepoche/poche/archive/twig.zip) of poche on github. Unzip it and upload it on your server.
+
+your datas can be stored on sqlite, postgres or mysql databases.
+
+Edit /inc/poche/config.inc.php :
+
+```php
+define ('STORAGE','sqlite'); # postgres, mysql, sqlite
+define ('STORAGE_SERVER', 'localhost'); # leave blank for sqlite
+define ('STORAGE_DB', 'poche'); # only for postgres & mysql
+define ('STORAGE_SQLITE', './db/poche.sqlite');
+define ('STORAGE_USER', 'user'); # leave blank for sqlite
+define ('STORAGE_PASSWORD', 'pass'); # leave blank for sqlite
+```
+
+poche must have write access on assets, cache and db directories.
+
+[PHP cURL](http://www.php.net/manual/en/book.curl.php) & [tidy_parse_string](http://www.php.net/manual/en/tidy.parsestring.php) are recommended.
+
+## twig
+poche now uses twig for templating. You have to install twig.
+
+Install composer in your project :
+```bash
+curl -s http://getcomposer.org/installer | php
+```
+Install via composer :
+```bash
+php composer.phar install
+```
+
+If you don't want to install twig by yourself, you can download [this file](http://static.inthepoche.com/files/poche-1.0-latest-with-twig.zip).
+
+## storage in sqlite
+You have to install [sqlite for php](http://www.php.net/manual/en/book.sqlite.php) on your server.
+
+Copy /install/poche.sqlite in /db
+
+## storage in mysql
+Execute /install/mysql.sql file in your database.
+
+## storage in postgres
+Execute /install/postgres.sql file in your database.
+
+## upgrading from poche <= 0.3
+With poche <= 0.3, all your datas were stored in a sqlite file. The structure of this file changed.
+
+You have to execute http://yourpoche/install/update_sqlite_from_0_to_1.php before using this new version.
+
+## installing poche
+you can go on your poche http://yourpoche. You have to fill the fields and that's all !
\ No newline at end of file
diff --git a/README.md b/README.md
index b44e7d368..25385da8c 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# poche
-Abandon Pocket, Instapaper and other Readability service : adopt poche. It is the same, but it is open source.
+Abandon Pocket, Instapaper and other Readability service : adopt poche. It is the same, but it is open source. Moreover, you can migrate from Pocket & Readability.
![poche](http://inthepoche.com/img/logo.png)
@@ -11,24 +11,6 @@ To get news from poche, [follow us on twitter](http://twitter.com/getpoche) or [
[![flattr](http://api.flattr.com/button/flattr-badge-large.png)](http://flattr.com/thing/1265480/poche-a-read-it-later-open-source-system)
-## Usage
-You can easily add a "poched" page with the bookmarklet.
-
-poche save the entire content of a poched links : text and pictures are stored on your server.
-
-You can :
-* read a page in a comfortable reading view
-* archive a link
-* put a link in favorite
-* delete a link
-
-## Requirements & installation
-You have to install [sqlite for php](http://www.php.net/manual/en/book.sqlite.php) on your server.
-
-Get the [latest version](https://github.com/inthepoche/poche) of poche on github. Unzip it and upload it on your server. poche must have write access on assets, cache and db directories.
-
-That's all, **poche works** !
-
## Security
You **have** to protect your db/poche.sqlite file. Modify the virtual host of your website to add this condition :
```apache
@@ -46,12 +28,11 @@ location ~ /(db) {
}
```
-## Import from Pocket
-
-If you want to import your Pocket datas, [export them here](https://getpocket.com/export). Put the HTML file in your poche directory, execute import.php file locally by following instructions. Be careful, the script can take a very long time.
+## Usage
+See the documentation on our website : [inthepoche.com](http://inthepoche.com).
## License
-Copyright © 2010-2013 Nicolas Lœuillet
+Copyright © 2010-2013 Nicolas Lœuillet
This work is free. You can redistribute it and/or modify it under the
terms of the Do What The Fuck You Want To Public License, Version 2,
-as published by Sam Hocevar. See the COPYING file for more details.
+as published by Sam Hocevar. See the COPYING file for more details.
\ No newline at end of file
diff --git a/composer.json b/composer.json
new file mode 100644
index 000000000..6c69e48de
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,7 @@
+{
+ "require": {
+ "twig/twig": "1.*",
+ "twig/extensions": "1.0.*",
+ "umpirsky/twig-gettext-extractor": "1.1.*"
+ }
+}
\ No newline at end of file
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 000000000..9e17fca9c
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,744 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
+ ],
+ "hash": "1c8badb14d91f4f3ef1cfae23252a2c4",
+ "packages": [
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v2.3.2",
+ "target-dir": "Symfony/Component/EventDispatcher",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/EventDispatcher.git",
+ "reference": "v2.3.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.2",
+ "reference": "v2.3.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/dependency-injection": "~2.0"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony EventDispatcher Component",
+ "homepage": "http://symfony.com",
+ "time": "2013-05-13 14:36:40"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v2.3.2",
+ "target-dir": "Symfony/Component/Filesystem",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Filesystem.git",
+ "reference": "v2.3.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Filesystem/zipball/v2.3.2",
+ "reference": "v2.3.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Filesystem\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Filesystem Component",
+ "homepage": "http://symfony.com",
+ "time": "2013-06-04 15:02:05"
+ },
+ {
+ "name": "symfony/form",
+ "version": "v2.3.2",
+ "target-dir": "Symfony/Component/Form",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Form.git",
+ "reference": "v2.3.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Form/zipball/v2.3.2",
+ "reference": "v2.3.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/event-dispatcher": "~2.1",
+ "symfony/intl": "~2.3",
+ "symfony/options-resolver": "~2.1",
+ "symfony/property-access": "~2.2"
+ },
+ "require-dev": {
+ "symfony/http-foundation": "~2.2",
+ "symfony/validator": "~2.2"
+ },
+ "suggest": {
+ "symfony/http-foundation": "",
+ "symfony/validator": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Form\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Form Component",
+ "homepage": "http://symfony.com",
+ "time": "2013-07-01 12:24:43"
+ },
+ {
+ "name": "symfony/icu",
+ "version": "v1.0.0",
+ "target-dir": "Symfony/Component/Icu",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Icu.git",
+ "reference": "v1.0.0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Icu/zipball/v1.0.0",
+ "reference": "v1.0.0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/intl": ">=2.3,<3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Icu\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Contains an excerpt of the ICU data and classes to load it.",
+ "homepage": "http://symfony.com",
+ "keywords": [
+ "icu",
+ "intl"
+ ],
+ "time": "2013-06-03 18:32:07"
+ },
+ {
+ "name": "symfony/intl",
+ "version": "v2.3.2",
+ "target-dir": "Symfony/Component/Intl",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Intl.git",
+ "reference": "v2.3.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Intl/zipball/v2.3.2",
+ "reference": "v2.3.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/icu": "~1.0-RC"
+ },
+ "require-dev": {
+ "symfony/filesystem": ">=2.1"
+ },
+ "suggest": {
+ "ext-intl": "to use the component with locales other than \"en\""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Intl\\": ""
+ },
+ "classmap": [
+ "Symfony/Component/Intl/Resources/stubs"
+ ],
+ "files": [
+ "Symfony/Component/Intl/Resources/stubs/functions.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch",
+ "homepage": "http://wiedler.ch/igor/"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ },
+ {
+ "name": "Eriksen Costa",
+ "email": "eriksen.costa@infranology.com.br"
+ }
+ ],
+ "description": "A PHP replacement layer for the C intl extension that includes additional data from the ICU library.",
+ "homepage": "http://symfony.com",
+ "keywords": [
+ "i18n",
+ "icu",
+ "internationalization",
+ "intl",
+ "l10n",
+ "localization"
+ ],
+ "time": "2013-07-08 13:00:35"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v2.3.2",
+ "target-dir": "Symfony/Component/OptionsResolver",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/OptionsResolver.git",
+ "reference": "v2.3.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/OptionsResolver/zipball/v2.3.2",
+ "reference": "v2.3.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony OptionsResolver Component",
+ "homepage": "http://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "time": "2013-04-11 06:50:46"
+ },
+ {
+ "name": "symfony/property-access",
+ "version": "v2.3.2",
+ "target-dir": "Symfony/Component/PropertyAccess",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/PropertyAccess.git",
+ "reference": "v2.3.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/PropertyAccess/zipball/v2.3.2",
+ "reference": "v2.3.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\PropertyAccess\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony PropertyAccess Component",
+ "homepage": "http://symfony.com",
+ "keywords": [
+ "access",
+ "array",
+ "extraction",
+ "index",
+ "injection",
+ "object",
+ "property",
+ "property path",
+ "reflection"
+ ],
+ "time": "2013-07-01 12:24:43"
+ },
+ {
+ "name": "symfony/routing",
+ "version": "v2.3.2",
+ "target-dir": "Symfony/Component/Routing",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Routing.git",
+ "reference": "v2.3.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.3.2",
+ "reference": "v2.3.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "doctrine/common": "~2.2",
+ "psr/log": "~1.0",
+ "symfony/config": "~2.2",
+ "symfony/yaml": "~2.0"
+ },
+ "suggest": {
+ "doctrine/common": "",
+ "symfony/config": "",
+ "symfony/yaml": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Routing\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Routing Component",
+ "homepage": "http://symfony.com",
+ "time": "2013-06-23 08:16:02"
+ },
+ {
+ "name": "symfony/translation",
+ "version": "v2.3.2",
+ "target-dir": "Symfony/Component/Translation",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Translation.git",
+ "reference": "v2.3.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Translation/zipball/v2.3.2",
+ "reference": "v2.3.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/config": "~2.0",
+ "symfony/yaml": "~2.2"
+ },
+ "suggest": {
+ "symfony/config": "",
+ "symfony/yaml": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Translation\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Translation Component",
+ "homepage": "http://symfony.com",
+ "time": "2013-05-13 14:36:40"
+ },
+ {
+ "name": "symfony/twig-bridge",
+ "version": "v2.3.2",
+ "target-dir": "Symfony/Bridge/Twig",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/TwigBridge.git",
+ "reference": "v2.3.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/TwigBridge/zipball/v2.3.2",
+ "reference": "v2.3.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "twig/twig": "~1.11"
+ },
+ "require-dev": {
+ "symfony/form": "2.2.*",
+ "symfony/http-kernel": "~2.2",
+ "symfony/routing": "~2.2",
+ "symfony/security": "~2.0",
+ "symfony/templating": "~2.1",
+ "symfony/translation": "~2.2",
+ "symfony/yaml": "~2.0"
+ },
+ "suggest": {
+ "symfony/form": "",
+ "symfony/http-kernel": "",
+ "symfony/routing": "",
+ "symfony/security": "",
+ "symfony/templating": "",
+ "symfony/translation": "",
+ "symfony/yaml": ""
+ },
+ "type": "symfony-bridge",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Bridge\\Twig\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Twig Bridge",
+ "homepage": "http://symfony.com",
+ "time": "2013-05-16 10:19:58"
+ },
+ {
+ "name": "twig/extensions",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fabpot/Twig-extensions.git",
+ "reference": "v1.0.0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fabpot/Twig-extensions/zipball/v1.0.0",
+ "reference": "v1.0.0",
+ "shasum": ""
+ },
+ "require": {
+ "twig/twig": "1.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Twig_Extensions_": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Common additional features for Twig that do not directly belong in core",
+ "homepage": "https://github.com/fabpot/Twig-extensions",
+ "keywords": [
+ "debug",
+ "i18n",
+ "text"
+ ],
+ "time": "2013-02-28 14:21:30"
+ },
+ {
+ "name": "twig/twig",
+ "version": "v1.13.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fabpot/Twig.git",
+ "reference": "v1.13.2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fabpot/Twig/zipball/v1.13.2",
+ "reference": "v1.13.2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.13-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Twig_": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Armin Ronacher",
+ "email": "armin.ronacher@active-4.com"
+ }
+ ],
+ "description": "Twig, the flexible, fast, and secure template language for PHP",
+ "homepage": "http://twig.sensiolabs.org",
+ "keywords": [
+ "templating"
+ ],
+ "time": "2013-08-03 15:35:31"
+ },
+ {
+ "name": "umpirsky/twig-gettext-extractor",
+ "version": "1.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/umpirsky/Twig-Gettext-Extractor.git",
+ "reference": "1.1.3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/umpirsky/Twig-Gettext-Extractor/zipball/1.1.3",
+ "reference": "1.1.3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/filesystem": ">=2.0,<3.0",
+ "symfony/form": ">=2.0,<3.0",
+ "symfony/routing": ">=2.0,<3.0",
+ "symfony/translation": ">=2.0,<3.0",
+ "symfony/twig-bridge": ">=2.0,<3.0",
+ "twig/extensions": "1.0.*",
+ "twig/twig": ">=1.2.0,<2.0-dev"
+ },
+ "require-dev": {
+ "symfony/config": "2.1.*"
+ },
+ "bin": [
+ "twig-gettext-extractor"
+ ],
+ "type": "application",
+ "autoload": {
+ "psr-0": {
+ "Twig\\Gettext": "."
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Саша Стаменковић",
+ "email": "umpirsky@gmail.com",
+ "homepage": "http://umpirsky.com"
+ }
+ ],
+ "description": "The Twig Gettext Extractor is Poedit friendly tool which extracts translations from twig templates.",
+ "time": "2013-02-14 16:41:48"
+ }
+ ],
+ "packages-dev": [
+
+ ],
+ "aliases": [
+
+ ],
+ "minimum-stability": "stable",
+ "stability-flags": [
+
+ ],
+ "platform": [
+
+ ],
+ "platform-dev": [
+
+ ]
+}
diff --git a/css/style-dark.css b/css/style-dark.css
deleted file mode 100644
index 0fcced246..000000000
--- a/css/style-dark.css
+++ /dev/null
@@ -1,90 +0,0 @@
-/*** GENERAL ***/
-body {
- color: #fff;
- background-color: #0d0d0d;
-}
-
-a, a:hover, a:visited {
- color: #fff;
-}
-
-#main ul#links li a.current {
- background-color: #000;
- color: #fff;
-}
-
-#links a:hover, .backhome a:hover, .support a:hover{
- background-color: #fff;
- color: #000;
-}
-
-input[type=submit].delete {
- background : url('../img/dark/remove.png') no-repeat center center;
- color : transparent;
-}
-
-#main .entrie {
- color: #fff;
- background-color: #000;
- border: 1px solid #fff;
-}
-
-#main .entrie h2 a:hover {
- color: #29B1E3;
-}
-
-a.fav span {
- background: url('../img/dark/star-on.png') no-repeat;
-}
-
-a.fav span:hover {
- background: url('../img/dark/star-off.png') no-repeat;
-}
-
-a.fav-off span {
- background: url('../img/dark/star-off.png') no-repeat;
-}
-
-a.fav-off span:hover {
- background: url('../img/dark/star-on.png') no-repeat;
-}
-
-a.archive span {
- background: url('../img/dark/checkmark-on.png') no-repeat;
-}
-
-a.archive span:hover {
- background: url('../img/dark/checkmark-off.png') no-repeat;
-}
-
-a.archive-off span {
- background: url('../img/dark/checkmark-off.png') no-repeat;
-}
-
-a.archive-off span:hover {
- background: url('../img/dark/checkmark-on.png') no-repeat;
-}
-
-/*** ***/
-/*** ARTICLE PAGE ***/
-
-body.article {
- color: #fff;
- background-color: #0d0d0d;
-}
-
-#article header {
- border-bottom: 1px solid #222222;
-}
-
-#article article {
- border-bottom: 1px solid #222222;
-}
-
-.vieworiginal a {
- color: #888888;
-}
-
-.entrie {
- background-color: #fff;
-}
diff --git a/css/style-light.css b/css/style-light.css
deleted file mode 100644
index c1d98326d..000000000
--- a/css/style-light.css
+++ /dev/null
@@ -1,100 +0,0 @@
-/*** GENERAL ***/
-body {
- color: #222222;
- background-color: #F1F1F1;
-}
-
-a, a:hover, a:visited {
- color: #000;
-}
-
-.bouton {
- background-color: #000;
- color: #fff;
- border: none;
-}
-.bouton:hover {
- background-color: #222222;
- color: #F1F1F1;
-}
-
-#main ul#links li a.current {
- background-color: #000;
- color: #fff;
-}
-
-#links a:hover, .backhome a:hover, .support a:hover{
- background-color: #040707;
- color: #F1F1F1;
-}
-
-input[type=submit].delete {
- background : url('../img/light/remove.png') no-repeat center center;
- color : transparent;
-}
-
-#main .entrie {
- color: #2e2e2e;
- background-color: #ffffff;
- border: 1px solid #000;
-}
-
-#main .entrie h2 a:hover {
- color: #F5BE00;
-}
-
-a.fav span {
- background: url('../img/light/star-on.png') no-repeat;
-}
-
-a.fav span:hover {
- background: url('../img/light/star-off.png') no-repeat;
-}
-
-a.fav-off span {
- background: url('../img/light/star-off.png') no-repeat;
-}
-
-a.fav-off span:hover {
- background: url('../img/light/star-on.png') no-repeat;
-}
-
-a.archive span {
- background: url('../img/light/checkmark-on.png') no-repeat;
-}
-
-a.archive span:hover {
- background: url('../img/light/checkmark-off.png') no-repeat;
-}
-
-a.archive-off span {
- background: url('../img/light/checkmark-off.png') no-repeat;
-}
-
-a.archive-off span:hover {
- background: url('../img/light/checkmark-on.png') no-repeat;
-}
-
-/*** ***/
-/*** ARTICLE PAGE ***/
-
-body.article {
- color: #222222;
- background-color: #F1F1F1;
-}
-
-#article header {
- border-bottom: 1px solid #222222;
-}
-
-#article article {
- border-bottom: 1px solid #222222;
-}
-
-.vieworiginal a {
- color: #888888;
-}
-
-.entrie {
- background-color: #fff;
-}
diff --git a/css/style.css b/css/style.css
deleted file mode 100644
index 28e18b968..000000000
--- a/css/style.css
+++ /dev/null
@@ -1,223 +0,0 @@
-/*** GENERAL ***/
-body {
- font: 20px/1.3em Palatino,Georgia,serif;
- margin: 10px;
-}
-
-header {
- text-align: center;
-}
-
-.bouton {
- border-radius: 2px;
-}
-
-#main ul#links {
- padding: 0;
- list-style-type: none;
- text-align: center;
-}
-
-#main ul#links li {
- display: inline;
-}
-
-#main ul#links li a.current {
- -webkit-border-radius: 2px;
- border-radius: 2px;
-}
-
-#main ul#sort {
- padding: 0;
- list-style-type: none;
- text-align: center;
-}
-
-#main ul#sort li {
- display: inline;
- font-size: 0.9em;
-}
-
-#main ul#sort img:hover {
- cursor: pointer;
-}
-
-#main, #article {
- margin: 0 auto;
-}
-
-#links a, .backhome a, .support a{
- text-decoration: none;
- padding: 5px 10px;
-}
-#links a:hover, .backhome a:hover, .support a:hover{
- -webkit-border-radius: 2px;
- border-radius: 2px;
-}
-
-.support {
- font-size: 14px;
-}
-
-footer {
- text-align: right;
-}
-
-/*** ***/
-/*** LINKS DISPLAY ***/
-
-#main a.tool {
- text-decoration: none;
- cursor: pointer;
-}
-
-input[type=submit].delete {
- width : 16px;
- height :16px;
- border : none;
- cursor: pointer;
- font-size : 0;
-}
-
-#main #content {
- margin-top: 20px;
-}
-
-#main .entrie {
- padding: 15px;
- min-height: 8em;
- border: 1px solid;
-}
-
-#main .entrie h2 a {
- text-decoration: none;
-}
-
-.tools {
- text-align: right;
-}
-
-.tools ul {
- padding: 0; margin: 0;
- list-style-type: none;
-}
-
-.tools ul li {
- line-height: 20px;
-}
-
-.tools a.tool {
- cursor: pointer;
-}
-
-#article .tools {
- position: relative;
- display: inline;
- top: 0px;
- right: 0px;
- width: 100%;
- text-align: left;
-}
-
-#article .tools ul li{
- display: inline;
-}
-
-#main .entrie .tools a.tool span, #article .tools a.tool span {
- display: inline-block;
- width: 16px;
- height: 16px;
-}
-
-#main .entrie .url {
- font-size: 13px;
-}
-
-
-/*** ***/
-/*** ARTICLE PAGE ***/
-
-body.article {
- font: 20px/1.3em Palatino,Georgia,serif;
-}
-
-#article header {
- text-align: left;
-}
-
-#article header a {
- text-decoration: none;
-}
-
-.vieworiginal a {
- text-decoration: none;
-}
-
-.backhome {
- display: inline;
-}
-
-/*** ***/
-
-#main
-{
- max-width: 60em; /* 960 px */
- margin: 0 auto;
-}
-#content
-{
- width: 103.125%; /* 990px */
- overflow: hidden;
- margin-left: -1.562%; /* 15px */
- margin-bottom: -1.875em; /* 30px */
-}
-
-.entrie
-{
- width: 30.303%; /* 300px */
- background-color: #fff;
- float: left;
- margin: 0 1.515% 1.875em; /* 15px 30px */
-}
-
-@media only screen and ( max-width: 40em ) /* 640px */
-{
- .entrie
- {
- width: 46.876%; /* 305px */
- margin-bottom: 0.938em; /* 15px */
- }
-}
-
-@media only screen and ( max-width: 20em ) /* 320px */
-{
- #content
- {
- width: 100%;
- margin-left: 0;
- }
-
- .entrie
- {
- width: 100%;
- margin-left: 0;
- margin-right: 0;
- }
-}
-
-/*** ***/
-/*** MESSAGES ***/
-
-.messages { width: 100%; -moz-border-radius: 4px; border-radius: 4px; display: block; padding: 10px 0; margin: 10px auto 10px; clear: both; }
-.messages a.closeMessage { margin: -14px -8px 0 0; display:none; width: 16px; height: 16px; float: right; background: url(../img/messages/close.png) no-repeat; }
-/*.messages:hover a.closeMessage { visibility:visible; }*/
-.messages p { margin: 3px 0 3px 10px !important; padding: 0 10px 0 23px !important; font-size: 14px; line-height: 16px; }
-.messages.error { border: 1px solid #C42608; color: #c00 !important; background: #FFF0EF; }
-.messages.error p { background: url(../img/messages/cross.png ) no-repeat 0px 50%; color:#c00 !important; }
-.messages.success {background: #E0FBCC; border: 1px solid #6DC70C; }
-.messages.success p { background: url(../img/messages/tick.png) no-repeat 0px 50%; color: #2B6301 !important; }
-.messages.warning { background: #FFFCD3; border: 1px solid #EBCD41; color: #000; }
-.messages.warning p { background: url(../img/messages/warning.png ) no-repeat 0px 50%; color: #5F4E01; }
-.messages.information, .messages.info { background: #DFEBFB; border: 1px solid #82AEE7; }
-.messages.information p, .messages.info p { background: url(../img/messages/help.png ) no-repeat 0px 50%; color: #064393; }
-.messages.information a { text-decoration: underline; }
diff --git a/img/dark/checkmark-off.png b/img/dark/checkmark-off.png
deleted file mode 100644
index efc3439fe..000000000
Binary files a/img/dark/checkmark-off.png and /dev/null differ
diff --git a/img/dark/checkmark-on.png b/img/dark/checkmark-on.png
deleted file mode 100644
index 24391c2ee..000000000
Binary files a/img/dark/checkmark-on.png and /dev/null differ
diff --git a/img/dark/down.png b/img/dark/down.png
deleted file mode 100644
index 41ea9604e..000000000
Binary files a/img/dark/down.png and /dev/null differ
diff --git a/img/dark/logo.png b/img/dark/logo.png
deleted file mode 100644
index 9fba06425..000000000
Binary files a/img/dark/logo.png and /dev/null differ
diff --git a/img/dark/remove.png b/img/dark/remove.png
deleted file mode 100644
index 41786fd71..000000000
Binary files a/img/dark/remove.png and /dev/null differ
diff --git a/img/dark/star-off.png b/img/dark/star-off.png
deleted file mode 100644
index 90651b54a..000000000
Binary files a/img/dark/star-off.png and /dev/null differ
diff --git a/img/dark/star-on.png b/img/dark/star-on.png
deleted file mode 100644
index 7fc144772..000000000
Binary files a/img/dark/star-on.png and /dev/null differ
diff --git a/img/dark/up.png b/img/dark/up.png
deleted file mode 100644
index 1679e18fd..000000000
Binary files a/img/dark/up.png and /dev/null differ
diff --git a/img/logo.png b/img/logo.png
deleted file mode 100644
index f917857fb..000000000
Binary files a/img/logo.png and /dev/null differ
diff --git a/import.php b/import.php
deleted file mode 100644
index 45fe83347..000000000
--- a/import.php
+++ /dev/null
@@ -1,73 +0,0 @@
-
- * @copyright 2013
- * @license http://www.wtfpl.net/ see COPYING file
- */
-
-set_time_limit(0);
-
-include dirname(__FILE__).'/inc/config.php';
-include dirname(__FILE__).'/inc/simple_html_dom.php';
-
-if (!isset($_GET['start'])) {
- echo _('Please execute the import script locally, it can take a very long time.') . ' ' . _('Please choose between Pocket & Readabilty :') . '' . _('Bye bye Pocket, let\'s go !') . ' ' . _('Bye bye Readability, let\'s go !') . ' ';
-}
-else {
- if ($_GET['start'] == 'pocket') {
- $html = new simple_html_dom();
- $html->load_file('ril_export.html');
-
- $read = 0;
- $errors = array();
- foreach($html->find('ul') as $ul)
- {
- foreach($ul->find('li') as $li)
- {
- $a = $li->find('a');
- $url = $a[0]->href;
-
- action_to_do('add', $url);
- if ($read == '1') {
- $last_id = $db->getHandle()->lastInsertId();
- $sql_update = "UPDATE entries SET is_read=~is_read WHERE id=?";
- $params_update = array($last_id);
- $query_update = $db->getHandle()->prepare($sql_update);
- $query_update->execute($params_update);
- }
- }
- # Pocket génère un fichier HTML avec deux
- # Le premier concerne les éléments non lus
- # Le second concerne les éléments archivés
- $read = 1;
- }
-
- echo _('Import from Pocket completed.') . '' . _('Welcome to poche !') .' ';
- logm('import from pocket completed');
- }
- else if ($_GET['start'] == 'readability') {
- $str_data = file_get_contents("readability");
- $data = json_decode($str_data,true);
-
- foreach ($data as $key => $value) {
- $url = '';
- foreach ($value as $key2 => $value2) {
- if ($key2 == 'article__url') {
- $url = $value2;
- }
- }
- if ($url != '')
- action_to_do('add', $url);
- }
-
- echo _('Import from Readability completed.') . '' . _('Welcome to poche !') . ' ';
- logm('import from Readability completed');
- }
- else {
- echo _('Error with the import.') . '' . _('Back to poche'). ' ';
- logm('error with the import');
- }
-}
\ No newline at end of file
diff --git a/inc/Encoding.php b/inc/3rdparty/Encoding.php
similarity index 100%
rename from inc/Encoding.php
rename to inc/3rdparty/Encoding.php
diff --git a/inc/JSLikeHTMLElement.php b/inc/3rdparty/JSLikeHTMLElement.php
similarity index 100%
rename from inc/JSLikeHTMLElement.php
rename to inc/3rdparty/JSLikeHTMLElement.php
diff --git a/inc/Readability.php b/inc/3rdparty/Readability.php
similarity index 100%
rename from inc/Readability.php
rename to inc/3rdparty/Readability.php
diff --git a/inc/Session.class.php b/inc/3rdparty/Session.class.php
similarity index 99%
rename from inc/Session.class.php
rename to inc/3rdparty/Session.class.php
index eff924ccd..3162f5074 100644
--- a/inc/Session.class.php
+++ b/inc/3rdparty/Session.class.php
@@ -93,7 +93,7 @@ class Session
// Force logout
public static function logout()
{
- unset($_SESSION['uid'],$_SESSION['info'],$_SESSION['expires_on'],$_SESSION['tokens'], $_SESSION['login'], $_SESSION['pass']);
+ unset($_SESSION['uid'],$_SESSION['info'],$_SESSION['expires_on'],$_SESSION['tokens'], $_SESSION['login'], $_SESSION['pass'], $_SESSION['poche_user']);
}
// Make sure user is logged in.
diff --git a/inc/class.messages.php b/inc/3rdparty/class.messages.php
old mode 100644
new mode 100755
similarity index 96%
rename from inc/class.messages.php
rename to inc/3rdparty/class.messages.php
index 6d515bf69..e60bd3a19
--- a/inc/class.messages.php
+++ b/inc/3rdparty/class.messages.php
@@ -1,231 +1,231 @@
- \n%s\n";
- var $msgBefore = '';
- var $msgAfter = "
\n";
-
-
- /**
- * Constructor
- * @author Mike Everhart
- */
- public function __construct() {
-
- // Generate a unique ID for this user and session
- $this->msgId = md5(uniqid());
-
- // Create the session array if it doesnt already exist
- if( !array_key_exists('flash_messages', $_SESSION) ) $_SESSION['flash_messages'] = array();
-
- }
-
- /**
- * Add a message to the queue
- *
- * @author Mike Everhart
- *
- * @param string $type The type of message to add
- * @param string $message The message
- * @param string $redirect_to (optional) If set, the user will be redirected to this URL
- * @return bool
- *
- */
- public function add($type, $message, $redirect_to=null) {
-
- if( !isset($_SESSION['flash_messages']) ) return false;
-
- if( !isset($type) || !isset($message[0]) ) return false;
-
- // Replace any shorthand codes with their full version
- if( strlen(trim($type)) == 1 ) {
- $type = str_replace( array('h', 'i', 'w', 'e', 's'), array('help', 'info', 'warning', 'error', 'success'), $type );
-
- // Backwards compatibility...
- } elseif( $type == 'information' ) {
- $type = 'info';
- }
-
- // Make sure it's a valid message type
- if( !in_array($type, $this->msgTypes) ) die('"' . strip_tags($type) . '" is not a valid message type!' );
-
- // If the session array doesn't exist, create it
- if( !array_key_exists( $type, $_SESSION['flash_messages'] ) ) $_SESSION['flash_messages'][$type] = array();
-
- $_SESSION['flash_messages'][$type][] = $message;
-
- if( !is_null($redirect_to) ) {
- header("Location: $redirect_to");
- exit();
- }
-
- return true;
-
- }
-
- //-----------------------------------------------------------------------------------------------
- // display()
- // print queued messages to the screen
- //-----------------------------------------------------------------------------------------------
- /**
- * Display the queued messages
- *
- * @author Mike Everhart
- *
- * @param string $type Which messages to display
- * @param bool $print True = print the messages on the screen
- * @return mixed
- *
- */
- public function display($type='all', $print=true) {
- $messages = '';
- $data = '';
-
- if( !isset($_SESSION['flash_messages']) ) return false;
-
- if( $type == 'g' || $type == 'growl' ) {
- $this->displayGrowlMessages();
- return true;
- }
-
- // Print a certain type of message?
- if( in_array($type, $this->msgTypes) ) {
- foreach( $_SESSION['flash_messages'][$type] as $msg ) {
- $messages .= $this->msgBefore . $msg . $this->msgAfter;
- }
-
- $data .= sprintf($this->msgWrapper, $this->msgClass, $type, $messages);
-
- // Clear the viewed messages
- $this->clear($type);
-
- // Print ALL queued messages
- } elseif( $type == 'all' ) {
- foreach( $_SESSION['flash_messages'] as $type => $msgArray ) {
- $messages = '';
- foreach( $msgArray as $msg ) {
- $messages .= $this->msgBefore . $msg . $this->msgAfter;
- }
- $data .= sprintf($this->msgWrapper, $this->msgClass, $type, $messages);
- }
-
- // Clear ALL of the messages
- $this->clear();
-
- // Invalid Message Type?
- } else {
- return false;
- }
-
- // Print everything to the screen or return the data
- if( $print ) {
- echo $data;
- } else {
- return $data;
- }
- }
-
-
- /**
- * Check to see if there are any queued error messages
- *
- * @author Mike Everhart
- *
- * @return bool true = There ARE error messages
- * false = There are NOT any error messages
- *
- */
- public function hasErrors() {
- return empty($_SESSION['flash_messages']['error']) ? false : true;
- }
-
- /**
- * Check to see if there are any ($type) messages queued
- *
- * @author Mike Everhart
- *
- * @param string $type The type of messages to check for
- * @return bool
- *
- */
- public function hasMessages($type=null) {
- if( !is_null($type) ) {
- if( !empty($_SESSION['flash_messages'][$type]) ) return $_SESSION['flash_messages'][$type];
- } else {
- foreach( $this->msgTypes as $type ) {
- if( !empty($_SESSION['flash_messages']) ) return true;
- }
- }
- return false;
- }
-
- /**
- * Clear messages from the session data
- *
- * @author Mike Everhart
- *
- * @param string $type The type of messages to clear
- * @return bool
- *
- */
- public function clear($type='all') {
- if( $type == 'all' ) {
- unset($_SESSION['flash_messages']);
- } else {
- unset($_SESSION['flash_messages'][$type]);
- }
- return true;
- }
-
- public function __toString() { return $this->hasMessages(); }
-
- public function __destruct() {
- //$this->clear();
- }
-
-
-} // end class
+X \n%s\n";
+ var $msgBefore = '';
+ var $msgAfter = "
\n";
+
+
+ /**
+ * Constructor
+ * @author Mike Everhart
+ */
+ public function __construct() {
+
+ // Generate a unique ID for this user and session
+ $this->msgId = md5(uniqid());
+
+ // Create the session array if it doesnt already exist
+ if( !array_key_exists('flash_messages', $_SESSION) ) $_SESSION['flash_messages'] = array();
+
+ }
+
+ /**
+ * Add a message to the queue
+ *
+ * @author Mike Everhart
+ *
+ * @param string $type The type of message to add
+ * @param string $message The message
+ * @param string $redirect_to (optional) If set, the user will be redirected to this URL
+ * @return bool
+ *
+ */
+ public function add($type, $message, $redirect_to=null) {
+
+ if( !isset($_SESSION['flash_messages']) ) return false;
+
+ if( !isset($type) || !isset($message[0]) ) return false;
+
+ // Replace any shorthand codes with their full version
+ if( strlen(trim($type)) == 1 ) {
+ $type = str_replace( array('h', 'i', 'w', 'e', 's'), array('help', 'info', 'warning', 'error', 'success'), $type );
+
+ // Backwards compatibility...
+ } elseif( $type == 'information' ) {
+ $type = 'info';
+ }
+
+ // Make sure it's a valid message type
+ if( !in_array($type, $this->msgTypes) ) die('"' . strip_tags($type) . '" is not a valid message type!' );
+
+ // If the session array doesn't exist, create it
+ if( !array_key_exists( $type, $_SESSION['flash_messages'] ) ) $_SESSION['flash_messages'][$type] = array();
+
+ $_SESSION['flash_messages'][$type][] = $message;
+
+ if( !is_null($redirect_to) ) {
+ header("Location: $redirect_to");
+ exit();
+ }
+
+ return true;
+
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ // display()
+ // print queued messages to the screen
+ //-----------------------------------------------------------------------------------------------
+ /**
+ * Display the queued messages
+ *
+ * @author Mike Everhart
+ *
+ * @param string $type Which messages to display
+ * @param bool $print True = print the messages on the screen
+ * @return mixed
+ *
+ */
+ public function display($type='all', $print=true) {
+ $messages = '';
+ $data = '';
+
+ if( !isset($_SESSION['flash_messages']) ) return false;
+
+ if( $type == 'g' || $type == 'growl' ) {
+ $this->displayGrowlMessages();
+ return true;
+ }
+
+ // Print a certain type of message?
+ if( in_array($type, $this->msgTypes) ) {
+ foreach( $_SESSION['flash_messages'][$type] as $msg ) {
+ $messages .= $this->msgBefore . $msg . $this->msgAfter;
+ }
+
+ $data .= sprintf($this->msgWrapper, $this->msgClass, $type, $messages);
+
+ // Clear the viewed messages
+ $this->clear($type);
+
+ // Print ALL queued messages
+ } elseif( $type == 'all' ) {
+ foreach( $_SESSION['flash_messages'] as $type => $msgArray ) {
+ $messages = '';
+ foreach( $msgArray as $msg ) {
+ $messages .= $this->msgBefore . $msg . $this->msgAfter;
+ }
+ $data .= sprintf($this->msgWrapper, $this->msgClass, $type, $messages);
+ }
+
+ // Clear ALL of the messages
+ $this->clear();
+
+ // Invalid Message Type?
+ } else {
+ return false;
+ }
+
+ // Print everything to the screen or return the data
+ if( $print ) {
+ echo $data;
+ } else {
+ return $data;
+ }
+ }
+
+
+ /**
+ * Check to see if there are any queued error messages
+ *
+ * @author Mike Everhart
+ *
+ * @return bool true = There ARE error messages
+ * false = There are NOT any error messages
+ *
+ */
+ public function hasErrors() {
+ return empty($_SESSION['flash_messages']['error']) ? false : true;
+ }
+
+ /**
+ * Check to see if there are any ($type) messages queued
+ *
+ * @author Mike Everhart
+ *
+ * @param string $type The type of messages to check for
+ * @return bool
+ *
+ */
+ public function hasMessages($type=null) {
+ if( !is_null($type) ) {
+ if( !empty($_SESSION['flash_messages'][$type]) ) return $_SESSION['flash_messages'][$type];
+ } else {
+ foreach( $this->msgTypes as $type ) {
+ if( !empty($_SESSION['flash_messages']) ) return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Clear messages from the session data
+ *
+ * @author Mike Everhart
+ *
+ * @param string $type The type of messages to clear
+ * @return bool
+ *
+ */
+ public function clear($type='all') {
+ if( $type == 'all' ) {
+ unset($_SESSION['flash_messages']);
+ } else {
+ unset($_SESSION['flash_messages'][$type]);
+ }
+ return true;
+ }
+
+ public function __toString() { return $this->hasMessages(); }
+
+ public function __destruct() {
+ //$this->clear();
+ }
+
+
+} // end class
?>
\ No newline at end of file
diff --git a/inc/3rdparty/paginator.php b/inc/3rdparty/paginator.php
new file mode 100644
index 000000000..306756c0e
--- /dev/null
+++ b/inc/3rdparty/paginator.php
@@ -0,0 +1,202 @@
+_instance = $instance;
+ $this->_perPage = $perPage;
+ $this->set_instance();
+ }
+
+ /**
+ * get_start
+ *
+ * creates the starting point for limiting the dataset
+ * @return numeric
+ */
+ private function get_start(){
+ return ($this->_page * $this->_perPage) - $this->_perPage;
+ }
+
+ /**
+ * set_instance
+ *
+ * sets the instance parameter, if numeric value is 0 then set to 1
+ *
+ * @var numeric
+ */
+ private function set_instance(){
+ $this->_page = (int) (!isset($_GET[$this->_instance]) ? 1 : $_GET[$this->_instance]);
+ $this->_page = ($this->_page == 0 ? 1 : $this->_page);
+ }
+
+ /**
+ * set_total
+ *
+ * collect a numberic value and assigns it to the totalRows
+ *
+ * @var numeric
+ */
+ public function set_total($_totalRows){
+ $this->_totalRows = $_totalRows;
+ }
+
+ /**
+ * get_limit
+ *
+ * returns the limit for the data source, calling the get_start method and passing in the number of items perp page
+ *
+ * @return string
+ */
+ public function get_limit(){
+ if (STORAGE == 'postgres') {
+ return "LIMIT ".$this->_perPage." OFFSET ".$this->get_start();
+ } else {
+ return "LIMIT ".$this->get_start().",".$this->_perPage;
+ }
+ }
+
+ /**
+ * page_links
+ *
+ * create the html links for navigating through the dataset
+ *
+ * @var sting $path optionally set the path for the link
+ * @var sting $ext optionally pass in extra parameters to the GET
+ * @return string returns the html menu
+ */
+ public function page_links($path='?',$ext=null)
+ {
+ $adjacents = "2";
+ $prev = $this->_page - 1;
+ $next = $this->_page + 1;
+ $lastpage = ceil($this->_totalRows/$this->_perPage);
+ $lpm1 = $lastpage - 1;
+
+ $pagination = "";
+ if($lastpage > 1)
+ {
+ $pagination .= "\n";
+ }
+
+
+ return $pagination;
+ }
+}
diff --git a/inc/simple_html_dom.php b/inc/3rdparty/simple_html_dom.php
similarity index 100%
rename from inc/simple_html_dom.php
rename to inc/3rdparty/simple_html_dom.php
diff --git a/inc/MyTool.class.php b/inc/MyTool.class.php
deleted file mode 100644
index b11f18e97..000000000
--- a/inc/MyTool.class.php
+++ /dev/null
@@ -1,265 +0,0 @@
-
- * @copyright 2013
- * @license http://www.wtfpl.net/ see COPYING file
- */
-
-class MyTool
-{
- public static function initPhp()
- {
- define('START_TIME', microtime(true));
-
- if (phpversion() < 5) {
- die(_('Oops, it seems you don\'t have PHP 5.'));
- }
-
- error_reporting(E_ALL);
-
- function stripslashesDeep($value) {
- return is_array($value)
- ? array_map('stripslashesDeep', $value)
- : stripslashes($value);
- }
-
- if (get_magic_quotes_gpc()) {
- $_POST = array_map('stripslashesDeep', $_POST);
- $_GET = array_map('stripslashesDeep', $_GET);
- $_COOKIE = array_map('stripslashesDeep', $_COOKIE);
- }
-
- ob_start();
- register_shutdown_function('ob_end_flush');
- }
-
- public static function isUrl($url)
- {
- // http://neo22s.com/check-if-url-exists-and-is-online-php/
- $pattern='|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i';
-
- return preg_match($pattern, $url);
- }
-
- public static function isEmail($email)
- {
- $pattern = "/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2, 4}$/i";
-
- return (preg_match($pattern, $email));
- }
-
- public static function formatBBCode($text)
- {
- $replace = array(
- '/\[m\](.+?)\[\/m\]/is'
- => '/* moderate */',
- '/\[b\](.+?)\[\/b\]/is'
- => '$1 ',
- '/\[i\](.+?)\[\/i\]/is'
- => '$1 ',
- '/\[s\](.+?)\[\/s\]/is'
- => '$1',
- '/\[u\](.+?)\[\/u\]/is'
- => '$1 ',
- '/\[url\](.+?)\[\/url]/is'
- => '$1 ',
- '/\[url=(\w+:\/\/[^\]]+)\](.+?)\[\/url]/is'
- => '$2 ',
- '/\[quote\](.+?)\[\/quote\]/is'
- => '$1 ',
- '/\[code\](.+?)\[\/code\]/is'
- => '$1
',
- '/\[([^[]+)\|([^[]+)\]/is'
- => '$1 '
- );
- $text = preg_replace(
- array_keys($replace),
- array_values($replace),
- $text
- );
-
- return $text;
- }
-
- public static function formatText($text)
- {
- $text = preg_replace_callback(
- '/(.*?)<\/code_html>/is',
- create_function(
- '$matches',
- 'return htmlspecialchars($matches[1]);'
- ),
- $text
- );
- $text = preg_replace_callback(
- '/(.*?)<\/code_php>/is',
- create_function(
- '$matches',
- 'return highlight_string("", true);'
- ),
- $text
- );
- $text = preg_replace('/ /is', '', $text);
-
- $text = preg_replace(
- '#(^|\s)([a-z]+://([^\s\w/]?[\w/])*)(\s|$)#im',
- '\\1\\2 \\4',
- $text
- );
- $text = preg_replace(
- '#(^|\s)wp:?([a-z]{2}|):([\w]+)#im',
- '\\1\\3 ',
- $text
- );
- $text = str_replace(
- 'http://.wikipedia.org/wiki/',
- 'http://www.wikipedia.org/wiki/',
- $text
- );
- $text = str_replace('\wp:', 'wp:', $text);
- $text = str_replace('\http:', 'http:', $text);
- $text = MyTool::formatBBCode($text);
- $text = nl2br($text);
-
- return $text;
- }
-
- public static function getUrl()
- {
- $https = (!empty($_SERVER['HTTPS'])
- && (strtolower($_SERVER['HTTPS']) == 'on'))
- || (isset($_SERVER["SERVER_PORT"])
- && $_SERVER["SERVER_PORT"] == '443'); // HTTPS detection.
- $serverport = (!isset($_SERVER["SERVER_PORT"])
- || $_SERVER["SERVER_PORT"] == '80'
- || ($https && $_SERVER["SERVER_PORT"] == '443')
- ? ''
- : ':' . $_SERVER["SERVER_PORT"]);
-
- $scriptname = str_replace('/index.php', '/', $_SERVER["SCRIPT_NAME"]);
-
- if (!isset($_SERVER["SERVER_NAME"])) {
- return $scriptname;
- }
-
- return 'http' . ($https ? 's' : '') . '://'
- . $_SERVER["SERVER_NAME"] . $serverport . $scriptname;
- }
-
- public static function rrmdir($dir)
- {
- if (is_dir($dir) && ($d = @opendir($dir))) {
- while (($file = @readdir($d)) !== false) {
- if ( $file == '.' || $file == '..' ) {
- continue;
- } else {
- unlink($dir . '/' . $file);
- }
- }
- }
- }
-
- public static function humanBytes($bytes)
- {
- $siPrefix = array( 'bytes', 'KB', 'MB', 'GB', 'TB', 'EB', 'ZB', 'YB' );
- $base = 1024;
- $class = min((int) log($bytes, $base), count($siPrefix) - 1);
- $val = sprintf('%1.2f', $bytes / pow($base, $class));
-
- return $val . ' ' . $siPrefix[$class];
- }
-
- public static function returnBytes($val)
- {
- $val = trim($val);
- $last = strtolower($val[strlen($val)-1]);
- switch($last)
- {
- case 'g': $val *= 1024;
- case 'm': $val *= 1024;
- case 'k': $val *= 1024;
- }
-
- return $val;
- }
-
- public static function getMaxFileSize()
- {
- $sizePostMax = MyTool::returnBytes(ini_get('post_max_size'));
- $sizeUploadMax = MyTool::returnBytes(ini_get('upload_max_filesize'));
-
- // Return the smaller of two:
- return min($sizePostMax, $sizeUploadMax);
- }
-
- public static function smallHash($text)
- {
- $t = rtrim(base64_encode(hash('crc32', $text, true)), '=');
- // Get rid of characters which need encoding in URLs.
- $t = str_replace('+', '-', $t);
- $t = str_replace('/', '_', $t);
- $t = str_replace('=', '@', $t);
-
- return $t;
- }
-
- public static function renderJson($data)
- {
- header('Cache-Control: no-cache, must-revalidate');
- header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
- header('Content-type: application/json; charset=UTF-8');
-
- echo json_encode($data);
- exit();
- }
-
- public static function grabToLocal($url, $file, $force = false)
- {
- if ((!file_exists($file) || $force) && in_array('curl', get_loaded_extensions())){
- $ch = curl_init ($url);
- curl_setopt($ch, CURLOPT_HEADER, false);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
- $raw = curl_exec($ch);
- if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200) {
- $fp = fopen($file, 'x');
- fwrite($fp, $raw);
- fclose($fp);
- }
- curl_close ($ch);
- }
- }
-
- public static function redirect($rurl = '')
- {
- if ($rurl === '') {
- // if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['SERVER_NAME'])==0)
- $rurl = (empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER']);
- if (isset($_POST['returnurl'])) {
- $rurl = $_POST['returnurl'];
- }
- }
-
- // prevent loop
- if (empty($rurl) || parse_url($rurl, PHP_URL_QUERY) === $_SERVER['QUERY_STRING']) {
- $rurl = MyTool::getUrl();
- }
-
- if (substr($rurl, 0, 1) !== '?') {
- $ref = MyTool::getUrl();
- if (substr($rurl, 0, strlen($ref)) !== $ref) {
- $rurl = $ref;
- }
- }
- header('Location: '.$rurl);
- exit();
- }
-
- public static function silence_errors($num, $str)
- {
-// No-op
- }
-}
\ No newline at end of file
diff --git a/inc/config.php b/inc/config.php
deleted file mode 100644
index 6e3f80b81..000000000
--- a/inc/config.php
+++ /dev/null
@@ -1,73 +0,0 @@
-
- * @copyright 2013
- * @license http://www.wtfpl.net/ see COPYING file
- */
-
-define ('POCHE_VERSION', '0.3');
-
-if (!is_dir('db/')) {
- @mkdir('db/',0705);
-}
-
-define ('MODE_DEMO', FALSE);
-define ('ABS_PATH', 'assets/');
-define ('CONVERT_LINKS_FOOTNOTES', TRUE);
-define ('REVERT_FORCED_PARAGRAPH_ELEMENTS',FALSE);
-define ('DOWNLOAD_PICTURES', TRUE);
-define ('SALT', '464v54gLLw928uz4zUBqkRJeiPY68zCX');
-define ('LANG', 'fr_FR.UTF8');
-
-putenv("LC_ALL=".LANG);
-setlocale(LC_ALL, LANG);
-bindtextdomain(LANG, "./locale");
-textdomain(LANG);
-
-$storage_type = 'sqlite'; # sqlite or file
-
-include 'functions.php';
-require_once 'Readability.php';
-require_once 'Encoding.php';
-require_once 'rain.tpl.class.php';
-require_once 'MyTool.class.php';
-require_once 'Session.class.php';
-require_once 'store/store.class.php';
-require_once 'store/sqlite.class.php';
-require_once 'store/file.class.php';
-require_once 'class.messages.php';
-
-Session::init();
-
-$store = new $storage_type();
-# initialisation de RainTPL
-raintpl::$tpl_dir = './tpl/';
-raintpl::$cache_dir = './cache/';
-raintpl::$base_url = get_poche_url();
-raintpl::configure('path_replace', false);
-raintpl::configure('debug', false);
-$tpl = new raintpl();
-
-if(!$store->isInstalled())
-{
- logm('poche still not installed');
- $tpl->draw('install');
- if (isset($_GET['install'])) {
- if (($_POST['password'] == $_POST['password_repeat'])
- && $_POST['password'] != "" && $_POST['login'] != "") {
- $store->install($_POST['login'], encode_string($_POST['password'] . $_POST['login']));
- Session::logout();
- MyTool::redirect();
- }
- }
- exit();
-}
-
-$_SESSION['login'] = (isset ($_SESSION['login'])) ? $_SESSION['login'] : $store->getLogin();
-$_SESSION['pass'] = (isset ($_SESSION['pass'])) ? $_SESSION['pass'] : $store->getPassword();
-
-$msg = new Messages();
-$tpl->assign('msg', $msg);
\ No newline at end of file
diff --git a/inc/functions.php b/inc/functions.php
deleted file mode 100644
index ee26fbaae..000000000
--- a/inc/functions.php
+++ /dev/null
@@ -1,400 +0,0 @@
-
- * @copyright 2013
- * @license http://www.wtfpl.net/ see COPYING file
- */
-
-/**
- * Permet de générer l'URL de poche pour le bookmarklet
- */
-function get_poche_url()
-{
- $protocol = "http";
- if(isset($_SERVER['HTTPS'])) {
- if($_SERVER['HTTPS'] != "off" && $_SERVER['HTTPS'] != "") {
- $protocol = "https";
- }
- }
-
- return $protocol . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
-}
-
-function encode_string($string)
-{
- return sha1($string . SALT);
-}
-
-// function define to retrieve url content
-function get_external_file($url)
-{
- $timeout = 15;
- // spoofing FireFox 18.0
- $useragent="Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0";
-
- if (in_array ('curl', get_loaded_extensions())) {
- // Fetch feed from URL
- $curl = curl_init();
- curl_setopt($curl, CURLOPT_URL, $url);
- curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($curl, CURLOPT_HEADER, false);
-
- // FOR SSL do not verified certificate
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
- curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE );
-
- // FeedBurner requires a proper USER-AGENT...
- curl_setopt($curl, CURL_HTTP_VERSION_1_1, true);
- curl_setopt($curl, CURLOPT_ENCODING, "gzip, deflate");
- curl_setopt($curl, CURLOPT_USERAGENT, $useragent);
-
- $data = curl_exec($curl);
-
- $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
-
- $httpcodeOK = isset($httpcode) and ($httpcode == 200 or $httpcode == 301);
-
- curl_close($curl);
- } else {
-
- // create http context and add timeout and user-agent
- $context = stream_context_create(array(
- 'http'=>array('timeout' => $timeout,
- 'header'=> "User-Agent: ".$useragent, /*spoot Mozilla Firefox*/
- 'follow_location' => true),
- // FOR SSL do not verified certificate
- 'ssl' => array('verify_peer' => false,
- 'allow_self_signed' => true)
- )
- );
-
- // only download page lesser than 4MB
- $data = @file_get_contents($url, false, $context, -1, 4000000); // We download at most 4 MB from source.
-
- if(isset($http_response_header) and isset($http_response_header[0])) {
- $httpcodeOK = isset($http_response_header) and isset($http_response_header[0]) and ((strpos($http_response_header[0], '200 OK') !== FALSE) or (strpos($http_response_header[0], '301 Moved Permanently') !== FALSE));
- }
- }
-
- // if response is not empty and response is OK
- if (isset($data) and isset($httpcodeOK) and $httpcodeOK ) {
-
- // take charset of page and get it
- preg_match('# #Usi', $data, $meta);
-
- // if meta tag is found
- if (!empty($meta[0])) {
- // retrieve encoding in $enc
- preg_match('#charset="?(.*)"#si', $meta[0], $enc);
-
- // if charset is found set it otherwise, set it to utf-8
- $html_charset = (!empty($enc[1])) ? strtolower($enc[1]) : 'utf-8';
-
- } else {
- $html_charset = 'utf-8';
- $enc[1] = '';
- }
-
- // replace charset of url to charset of page
- $data = str_replace('charset='.$enc[1], 'charset='.$html_charset, $data);
-
- return $data;
- }
- else {
- return FALSE;
- }
-}
-
-/**
- * Préparation de l'URL avec récupération du contenu avant insertion en base
- */
-function prepare_url($url)
-{
- $parametres = array();
- $url = html_entity_decode(trim($url));
-
- // We remove the annoying parameters added by FeedBurner and GoogleFeedProxy (?utm_source=...)
- // from shaarli, by sebsauvage
- $i=strpos($url,'&utm_source='); if ($i!==false) $url=substr($url,0,$i);
- $i=strpos($url,'?utm_source='); if ($i!==false) $url=substr($url,0,$i);
- $i=strpos($url,'#xtor=RSS-'); if ($i!==false) $url=substr($url,0,$i);
-
- $title = $url;
- $html = Encoding::toUTF8(get_external_file($url,15));
- // If get_external_file if not able to retrieve HTTPS content try the same URL with HTTP protocol
- if (!preg_match('!^https?://!i', $url) && (!isset($html) || strlen($html) <= 0)) {
- $url = 'http://' . $url;
- $html = Encoding::toUTF8(get_external_file($url,15));
- }
-
- if (function_exists('tidy_parse_string')) {
- $tidy = tidy_parse_string($html, array(), 'UTF8');
- $tidy->cleanRepair();
- $html = $tidy->value;
- }
-
- if (isset($html) and strlen($html) > 0)
- {
- $r = new Readability($html, $url);
-
- $r->convertLinksToFootnotes = CONVERT_LINKS_FOOTNOTES;
- $r->revertForcedParagraphElements = REVERT_FORCED_PARAGRAPH_ELEMENTS;
-
- if($r->init())
- {
- $content = $r->articleContent->innerHTML;
- $parametres['title'] = $r->articleTitle->innerHTML;
- $parametres['content'] = $content;
- return $parametres;
- }
- }
-
- return FALSE;
-}
-
-/**
- * On modifie les URLS des images dans le corps de l'article
- */
-function filtre_picture($content, $url, $id)
-{
- $matches = array();
- preg_match_all('#<\s*(img)[^>]+src="([^"]*)"[^>]*>#Si', $content, $matches, PREG_SET_ORDER);
- foreach($matches as $i => $link)
- {
- $link[1] = trim($link[1]);
- if (!preg_match('#^(([a-z]+://)|(\#))#', $link[1]) )
- {
- $absolute_path = get_absolute_link($link[2],$url);
- $filename = basename(parse_url($absolute_path, PHP_URL_PATH));
- $directory = create_assets_directory($id);
- $fullpath = $directory . '/' . $filename;
- download_pictures($absolute_path, $fullpath);
- $content = str_replace($matches[$i][2], $fullpath, $content);
- }
-
- }
-
- return $content;
-}
-
-/**
- * Retourne le lien absolu
- */
-function get_absolute_link($relative_link, $url)
-{
- /* return if already absolute URL */
- if (parse_url($relative_link, PHP_URL_SCHEME) != '') return $relative_link;
-
- /* queries and anchors */
- if ($relative_link[0]=='#' || $relative_link[0]=='?') return $url . $relative_link;
-
- /* parse base URL and convert to local variables:
- $scheme, $host, $path */
- extract(parse_url($url));
-
- /* remove non-directory element from path */
- $path = preg_replace('#/[^/]*$#', '', $path);
-
- /* destroy path if relative url points to root */
- if ($relative_link[0] == '/') $path = '';
-
- /* dirty absolute URL */
- $abs = $host . $path . '/' . $relative_link;
-
- /* replace '//' or '/./' or '/foo/../' with '/' */
- $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
- for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}
-
- /* absolute URL is ready! */
- return $scheme.'://'.$abs;
-}
-
-/**
- * Téléchargement des images
- */
-
-function download_pictures($absolute_path, $fullpath)
-{
- $rawdata = get_external_file($absolute_path);
-
- if(file_exists($fullpath)) {
- unlink($fullpath);
- }
- $fp = fopen($fullpath, 'x');
- fwrite($fp, $rawdata);
- fclose($fp);
-}
-
-/**
- * Crée un répertoire de médias pour l'article
- */
-function create_assets_directory($id)
-{
- $assets_path = ABS_PATH;
- if(!is_dir($assets_path)) {
- mkdir($assets_path, 0705);
- }
-
- $article_directory = $assets_path . $id;
- if(!is_dir($article_directory)) {
- mkdir($article_directory, 0705);
- }
-
- return $article_directory;
-}
-
-/**
- * Suppression du répertoire d'images
- */
-function remove_directory($directory)
-{
- if(is_dir($directory)) {
- $files = array_diff(scandir($directory), array('.','..'));
- foreach ($files as $file) {
- (is_dir("$directory/$file")) ? remove_directory("$directory/$file") : unlink("$directory/$file");
- }
- return rmdir($directory);
- }
-}
-
-function display_view($view, $id = 0, $full_head = 'yes')
-{
- global $tpl, $store, $msg;
-
- switch ($view)
- {
- case 'export':
- $entries = $store->retrieveAll();
- $tpl->assign('export', myTool::renderJson($entries));
- $tpl->draw('export');
- logm('export view');
- break;
- case 'config':
- $tpl->assign('load_all_js', 0);
- $tpl->draw('head');
- $tpl->draw('home');
- $tpl->draw('config');
- $tpl->draw('js');
- $tpl->draw('footer');
- logm('config view');
- break;
- case 'view':
- $entry = $store->retrieveOneById($id);
-
- if ($entry != NULL) {
- $tpl->assign('id', $entry['id']);
- $tpl->assign('url', $entry['url']);
- $tpl->assign('title', $entry['title']);
- $content = $entry['content'];
- if (function_exists('tidy_parse_string')) {
- $tidy = tidy_parse_string($content, array('indent'=>true, 'show-body-only' => true), 'UTF8');
- $tidy->cleanRepair();
- $content = $tidy->value;
- }
- $tpl->assign('content', $content);
- $tpl->assign('is_fav', $entry['is_fav']);
- $tpl->assign('is_read', $entry['is_read']);
- $tpl->assign('load_all_js', 0);
- $tpl->draw('view');
- }
- else {
- logm('error in view call : entry is NULL');
- }
-
- logm('view link #' . $id);
- break;
- default: # home view
- $entries = $store->getEntriesByView($view);
-
- $tpl->assign('entries', $entries);
-
- if ($full_head == 'yes') {
- $tpl->assign('load_all_js', 1);
- $tpl->draw('head');
- $tpl->draw('home');
- }
-
- $tpl->draw('entries');
-
- if ($full_head == 'yes') {
- $tpl->draw('js');
- $tpl->draw('footer');
- }
- break;
- }
-}
-
-/**
- * Appel d'une action (mark as fav, archive, delete)
- */
-function action_to_do($action, $url, $id = 0)
-{
- global $store, $msg;
-
- switch ($action)
- {
- case 'add':
- if ($url == '')
- continue;
-
- $url = base64_decode($url);
- error_log(print_r($url, TRUE));
- if (MyTool::isUrl($url)) {
- if($parametres_url = prepare_url($url)) {
- if ($store->add($url, $parametres_url['title'], $parametres_url['content'])) {
- $last_id = $store->getLastId();
- if (DOWNLOAD_PICTURES) {
- $content = filtre_picture($parametres_url['content'], $url, $last_id);
- }
- $msg->add('s', _('the link has been added successfully'));
- }
- else {
- $msg->add('e', _('error during insertion : the link wasn\'t added'));
- }
- }
- else {
- $msg->add('e', _('error during url preparation : the link wasn\'t added'));
- logm('error during url preparation');
- }
- }
- else {
- $msg->add('e', _('error during url preparation : the link is not valid'));
- logm($url . ' is not a valid url');
- }
-
- logm('add link ' . $url);
- break;
- case 'delete':
- if ($store->deleteById($id)) {
- remove_directory(ABS_PATH . $id);
- $msg->add('s', _('the link has been deleted successfully'));
- logm('delete link #' . $id);
- }
- else {
- $msg->add('e', _('the link wasn\'t deleted'));
- logm('error : can\'t delete link #' . $id);
- }
- break;
- case 'toggle_fav' :
- $store->favoriteById($id);
- logm('mark as favorite link #' . $id);
- break;
- case 'toggle_archive' :
- $store->archiveById($id);
- logm('archive link #' . $id);
- break;
- default:
- break;
- }
-}
-
-function logm($message)
-{
- $t = strval(date('Y/m/d_H:i:s')).' - '.$_SERVER["REMOTE_ADDR"].' - '.strval($message)."\n";
- file_put_contents('./log.txt',$t,FILE_APPEND);
-}
diff --git a/inc/poche/Database.class.php b/inc/poche/Database.class.php
new file mode 100644
index 000000000..cd5a9a312
--- /dev/null
+++ b/inc/poche/Database.class.php
@@ -0,0 +1,216 @@
+
+ * @copyright 2013
+ * @license http://www.wtfpl.net/ see COPYING file
+ */
+
+class Database {
+ var $handle;
+
+ function __construct()
+ {
+ switch (STORAGE) {
+ case 'sqlite':
+ $db_path = 'sqlite:' . STORAGE_SQLITE;
+ $this->handle = new PDO($db_path);
+ break;
+ case 'mysql':
+ $db_path = 'mysql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB;
+ $this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
+ break;
+ case 'postgres':
+ $db_path = 'pgsql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB;
+ $this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
+ break;
+ }
+
+ $this->handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ Tools::logm('storage type ' . STORAGE);
+ }
+
+ private function getHandle() {
+ return $this->handle;
+ }
+
+ public function isInstalled() {
+ $sql = "SELECT username FROM users";
+ $query = $this->executeQuery($sql, array());
+ $hasAdmin = count($query->fetchAll());
+
+ if ($hasAdmin == 0)
+ return FALSE;
+
+ return TRUE;
+ }
+
+ public function install($login, $password) {
+ $sql = 'INSERT INTO users ( username, password, name, email) VALUES (?, ?, ?, ?)';
+ $params = array($login, $password, $login, ' ');
+ $query = $this->executeQuery($sql, $params);
+
+ $sequence = '';
+ if (STORAGE == 'postgres') {
+ $sequence = 'users_id_seq';
+ }
+
+ $id_user = intval($this->getLastId($sequence));
+
+ $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
+ $params = array($id_user, 'pager', '10');
+ $query = $this->executeQuery($sql, $params);
+
+ $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
+ $params = array($id_user, 'language', 'en_EN.UTF8');
+ $query = $this->executeQuery($sql, $params);
+
+ return TRUE;
+ }
+
+ private function getConfigUser($id) {
+ $sql = "SELECT * FROM users_config WHERE user_id = ?";
+ $query = $this->executeQuery($sql, array($id));
+ $result = $query->fetchAll();
+ $user_config = array();
+
+ foreach ($result as $key => $value) {
+ $user_config[$value['name']] = $value['value'];
+ }
+
+ return $user_config;
+ }
+
+ public function login($username, $password) {
+ $sql = "SELECT * FROM users WHERE username=? AND password=?";
+ $query = $this->executeQuery($sql, array($username, $password));
+ $login = $query->fetchAll();
+
+ $user = array();
+ if (isset($login[0])) {
+ $user['id'] = $login[0]['id'];
+ $user['username'] = $login[0]['username'];
+ $user['password'] = $login[0]['password'];
+ $user['name'] = $login[0]['name'];
+ $user['email'] = $login[0]['email'];
+ $user['config'] = $this->getConfigUser($login[0]['id']);
+ }
+
+ return $user;
+ }
+
+ public function updatePassword($id, $password)
+ {
+ $sql_update = "UPDATE users SET password=? WHERE id=?";
+ $params_update = array($password, $id);
+ $query = $this->executeQuery($sql_update, $params_update);
+ }
+
+ private function executeQuery($sql, $params) {
+ try
+ {
+ $query = $this->getHandle()->prepare($sql);
+ $query->execute($params);
+ return $query;
+ }
+ catch (Exception $e)
+ {
+ Tools::logm('execute query error : '.$e->getMessage());
+ return FALSE;
+ }
+ }
+
+ public function retrieveAll($user_id) {
+ $sql = "SELECT * FROM entries WHERE user_id=? ORDER BY id";
+ $query = $this->executeQuery($sql, array($user_id));
+ $entries = $query->fetchAll();
+
+ return $entries;
+ }
+
+ public function retrieveOneById($id, $user_id) {
+ $entry = NULL;
+ $sql = "SELECT * FROM entries WHERE id=? AND user_id=?";
+ $params = array(intval($id), $user_id);
+ $query = $this->executeQuery($sql, $params);
+ $entry = $query->fetchAll();
+
+ return $entry[0];
+ }
+
+ public function getEntriesByView($view, $user_id, $limit = '') {
+ switch ($_SESSION['sort'])
+ {
+ case 'ia':
+ $order = 'ORDER BY id';
+ break;
+ case 'id':
+ $order = 'ORDER BY id DESC';
+ break;
+ case 'ta':
+ $order = 'ORDER BY lower(title)';
+ break;
+ case 'td':
+ $order = 'ORDER BY lower(title) DESC';
+ break;
+ default:
+ $order = 'ORDER BY id';
+ break;
+ }
+
+ switch ($view)
+ {
+ case 'archive':
+ $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? " . $order;
+ $params = array($user_id, 1);
+ break;
+ case 'fav' :
+ $sql = "SELECT * FROM entries WHERE user_id=? AND is_fav=? " . $order;
+ $params = array($user_id, 1);
+ break;
+ default:
+ $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? " . $order;
+ $params = array($user_id, 0);
+ break;
+ }
+
+ $sql .= ' ' . $limit;
+
+ $query = $this->executeQuery($sql, $params);
+ $entries = $query->fetchAll();
+
+ return $entries;
+ }
+
+ public function add($url, $title, $content, $user_id) {
+ $sql_action = 'INSERT INTO entries ( url, title, content, user_id ) VALUES (?, ?, ?, ?)';
+ $params_action = array($url, $title, $content, $user_id);
+ $query = $this->executeQuery($sql_action, $params_action);
+ return $query;
+ }
+
+ public function deleteById($id, $user_id) {
+ $sql_action = "DELETE FROM entries WHERE id=? AND user_id=?";
+ $params_action = array($id, $user_id);
+ $query = $this->executeQuery($sql_action, $params_action);
+ return $query;
+ }
+
+ public function favoriteById($id, $user_id) {
+ $sql_action = "UPDATE entries SET is_fav=NOT is_fav WHERE id=? AND user_id=?";
+ $params_action = array($id, $user_id);
+ $query = $this->executeQuery($sql_action, $params_action);
+ }
+
+ public function archiveById($id, $user_id) {
+ $sql_action = "UPDATE entries SET is_read=NOT is_read WHERE id=? AND user_id=?";
+ $params_action = array($id, $user_id);
+ $query = $this->executeQuery($sql_action, $params_action);
+ }
+
+ public function getLastId($column = '') {
+ return $this->getHandle()->lastInsertId($column);
+ }
+}
diff --git a/inc/poche/Poche.class.php b/inc/poche/Poche.class.php
new file mode 100644
index 000000000..38b4a98ea
--- /dev/null
+++ b/inc/poche/Poche.class.php
@@ -0,0 +1,429 @@
+
+ * @copyright 2013
+ * @license http://www.wtfpl.net/ see COPYING file
+ */
+
+class Poche
+{
+ public $user;
+ public $store;
+ public $tpl;
+ public $messages;
+ public $pagination;
+
+ function __construct()
+ {
+ $this->store = new Database();
+ $this->init();
+ $this->messages = new Messages();
+
+ # installation
+ if(!$this->store->isInstalled())
+ {
+ $this->install();
+ }
+ }
+
+ private function init()
+ {
+ Tools::initPhp();
+ Session::init();
+
+ if (isset($_SESSION['poche_user']) && $_SESSION['poche_user'] != array()) {
+ $this->user = $_SESSION['poche_user'];
+ }
+ else {
+ # fake user, just for install & login screens
+ $this->user = new User();
+ $this->user->setConfig($this->getDefaultConfig());
+ }
+
+ # l10n
+ $language = $this->user->getConfigValue('language');
+ putenv('LC_ALL=' . $language);
+ setlocale(LC_ALL, $language);
+ bindtextdomain($language, LOCALE);
+ textdomain($language);
+
+ # template engine
+ $loader = new Twig_Loader_Filesystem(TPL);
+ if (DEBUG_POCHE) {
+ $twig_params = array();
+ }
+ else {
+ $twig_params = array('cache' => CACHE);
+ }
+ $this->tpl = new Twig_Environment($loader, $twig_params);
+ $this->tpl->addExtension(new Twig_Extensions_Extension_I18n());
+ # filter to display domain name of an url
+ $filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain');
+ $this->tpl->addFilter($filter);
+
+ # Pagination
+ $this->pagination = new Paginator($this->user->getConfigValue('pager'), 'p');
+ }
+
+ private function install()
+ {
+ Tools::logm('poche still not installed');
+ echo $this->tpl->render('install.twig', array(
+ 'token' => Session::getToken()
+ ));
+ if (isset($_GET['install'])) {
+ if (($_POST['password'] == $_POST['password_repeat'])
+ && $_POST['password'] != "" && $_POST['login'] != "") {
+ # let's rock, install poche baby !
+ $this->store->install($_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']));
+ Session::logout();
+ Tools::logm('poche is now installed');
+ Tools::redirect();
+ }
+ else {
+ Tools::logm('error during installation');
+ Tools::redirect();
+ }
+ }
+ exit();
+ }
+
+ public function getDefaultConfig()
+ {
+ return array(
+ 'pager' => PAGINATION,
+ 'language' => LANG,
+ );
+ }
+
+ /**
+ * Call action (mark as fav, archive, delete, etc.)
+ */
+ public function action($action, Url $url, $id = 0, $import = FALSE)
+ {
+ switch ($action)
+ {
+ case 'add':
+ if($parametres_url = $url->fetchContent()) {
+ if ($this->store->add($url->getUrl(), $parametres_url['title'], $parametres_url['content'], $this->user->getId())) {
+ Tools::logm('add link ' . $url->getUrl());
+ $sequence = '';
+ if (STORAGE == 'postgres') {
+ $sequence = 'entries_id_seq';
+ }
+ $last_id = $this->store->getLastId($sequence);
+ if (DOWNLOAD_PICTURES) {
+ $content = filtre_picture($parametres_url['content'], $url->getUrl(), $last_id);
+ }
+ if (!$import) {
+ $this->messages->add('s', _('the link has been added successfully'));
+ }
+ }
+ else {
+ if (!$import) {
+ $this->messages->add('e', _('error during insertion : the link wasn\'t added'));
+ Tools::logm('error during insertion : the link wasn\'t added ' . $url->getUrl());
+ }
+ }
+ }
+ else {
+ if (!$import) {
+ $this->messages->add('e', _('error during fetching content : the link wasn\'t added'));
+ Tools::logm('error during content fetch ' . $url->getUrl());
+ }
+ }
+ if (!$import) {
+ Tools::redirect();
+ }
+ break;
+ case 'delete':
+ $msg = 'delete link #' . $id;
+ if ($this->store->deleteById($id, $this->user->getId())) {
+ if (DOWNLOAD_PICTURES) {
+ remove_directory(ABS_PATH . $id);
+ }
+ $this->messages->add('s', _('the link has been deleted successfully'));
+ }
+ else {
+ $this->messages->add('e', _('the link wasn\'t deleted'));
+ $msg = 'error : can\'t delete link #' . $id;
+ }
+ Tools::logm($msg);
+ Tools::redirect('?');
+ break;
+ case 'toggle_fav' :
+ $this->store->favoriteById($id, $this->user->getId());
+ Tools::logm('mark as favorite link #' . $id);
+ if (!$import) {
+ Tools::redirect();
+ }
+ break;
+ case 'toggle_archive' :
+ $this->store->archiveById($id, $this->user->getId());
+ Tools::logm('archive link #' . $id);
+ if (!$import) {
+ Tools::redirect();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ function displayView($view, $id = 0)
+ {
+ $tpl_vars = array();
+
+ switch ($view)
+ {
+ case 'config':
+ $dev = $this->getPocheVersion('dev');
+ $prod = $this->getPocheVersion('prod');
+ $compare_dev = version_compare(POCHE_VERSION, $dev);
+ $compare_prod = version_compare(POCHE_VERSION, $prod);
+ $tpl_vars = array(
+ 'dev' => $dev,
+ 'prod' => $prod,
+ 'compare_dev' => $compare_dev,
+ 'compare_prod' => $compare_prod,
+ );
+ Tools::logm('config view');
+ break;
+ case 'view':
+ $entry = $this->store->retrieveOneById($id, $this->user->getId());
+ if ($entry != NULL) {
+ Tools::logm('view link #' . $id);
+ $content = $entry['content'];
+ if (function_exists('tidy_parse_string')) {
+ $tidy = tidy_parse_string($content, array('indent'=>true, 'show-body-only' => true), 'UTF8');
+ $tidy->cleanRepair();
+ $content = $tidy->value;
+ }
+ $tpl_vars = array(
+ 'entry' => $entry,
+ 'content' => $content,
+ );
+ }
+ else {
+ Tools::logm('error in view call : entry is NULL');
+ }
+ break;
+ default: # home view
+ $entries = $this->store->getEntriesByView($view, $this->user->getId());
+ $this->pagination->set_total(count($entries));
+ $page_links = $this->pagination->page_links('?view=' . $view . '&sort=' . $_SESSION['sort'] . '&');
+ $datas = $this->store->getEntriesByView($view, $this->user->getId(), $this->pagination->get_limit());
+ $tpl_vars = array(
+ 'entries' => $datas,
+ 'page_links' => $page_links,
+ );
+ Tools::logm('display ' . $view . ' view');
+ break;
+ }
+
+ return $tpl_vars;
+ }
+
+ public function updatePassword()
+ {
+ if (MODE_DEMO) {
+ $this->messages->add('i', _('in demo mode, you can\'t update your password'));
+ Tools::logm('in demo mode, you can\'t do this');
+ Tools::redirect('?view=config');
+ }
+ else {
+ if (isset($_POST['password']) && isset($_POST['password_repeat'])) {
+ if ($_POST['password'] == $_POST['password_repeat'] && $_POST['password'] != "") {
+ $this->messages->add('s', _('your password has been updated'));
+ $this->store->updatePassword($this->user->getId(), Tools::encodeString($_POST['password'] . $this->user->getUsername()));
+ Session::logout();
+ Tools::logm('password updated');
+ Tools::redirect();
+ }
+ else {
+ $this->messages->add('e', _('the two fields have to be filled & the password must be the same in the two fields'));
+ Tools::redirect('?view=config');
+ }
+ }
+ }
+ }
+
+ public function login($referer)
+ {
+ if (!empty($_POST['login']) && !empty($_POST['password'])) {
+ $user = $this->store->login($_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']));
+ if ($user != array()) {
+ # Save login into Session
+ Session::login($user['username'], $user['password'], $_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']), array('poche_user' => new User($user)));
+
+ $this->messages->add('s', _('welcome to your poche'));
+ if (!empty($_POST['longlastingsession'])) {
+ $_SESSION['longlastingsession'] = 31536000;
+ $_SESSION['expires_on'] = time() + $_SESSION['longlastingsession'];
+ session_set_cookie_params($_SESSION['longlastingsession']);
+ } else {
+ session_set_cookie_params(0);
+ }
+ session_regenerate_id(true);
+ Tools::logm('login successful');
+ Tools::redirect($referer);
+ }
+ $this->messages->add('e', _('login failed: bad login or password'));
+ Tools::logm('login failed');
+ Tools::redirect();
+ } else {
+ $this->messages->add('e', _('login failed: you have to fill all fields'));
+ Tools::logm('login failed');
+ Tools::redirect();
+ }
+ }
+
+ public function logout()
+ {
+ $this->user = array();
+ Session::logout();
+ $this->messages->add('s', _('see you soon!'));
+ Tools::logm('logout');
+ Tools::redirect();
+ }
+
+ private function importFromInstapaper()
+ {
+ # TODO gestion des articles favs
+ $html = new simple_html_dom();
+ $html->load_file('./instapaper-export.html');
+ Tools::logm('starting import from instapaper');
+
+ $read = 0;
+ $errors = array();
+ foreach($html->find('ol') as $ul)
+ {
+ foreach($ul->find('li') as $li)
+ {
+ $a = $li->find('a');
+ $url = new Url(base64_encode($a[0]->href));
+ $this->action('add', $url, 0, TRUE);
+ if ($read == '1') {
+ $sequence = '';
+ if (STORAGE == 'postgres') {
+ $sequence = 'entries_id_seq';
+ }
+ $last_id = $this->store->getLastId($sequence);
+ $this->action('toggle_archive', $url, $last_id, TRUE);
+ }
+ }
+
+ # the second is for read links
+ $read = 1;
+ }
+ $this->messages->add('s', _('import from instapaper completed'));
+ Tools::logm('import from instapaper completed');
+ Tools::redirect();
+ }
+
+ private function importFromPocket()
+ {
+ # TODO gestion des articles favs
+ $html = new simple_html_dom();
+ $html->load_file('./ril_export.html');
+ Tools::logm('starting import from pocket');
+
+ $read = 0;
+ $errors = array();
+ foreach($html->find('ul') as $ul)
+ {
+ foreach($ul->find('li') as $li)
+ {
+ $a = $li->find('a');
+ $url = new Url(base64_encode($a[0]->href));
+ $this->action('add', $url, 0, TRUE);
+ if ($read == '1') {
+ $sequence = '';
+ if (STORAGE == 'postgres') {
+ $sequence = 'entries_id_seq';
+ }
+ $last_id = $this->store->getLastId($sequence);
+ $this->action('toggle_archive', $url, $last_id, TRUE);
+ }
+ }
+
+ # the second is for read links
+ $read = 1;
+ }
+ $this->messages->add('s', _('import from pocket completed'));
+ Tools::logm('import from pocket completed');
+ Tools::redirect();
+ }
+
+ private function importFromReadability()
+ {
+ # TODO gestion des articles lus / favs
+ $str_data = file_get_contents("./readability");
+ $data = json_decode($str_data,true);
+ Tools::logm('starting import from Readability');
+
+ foreach ($data as $key => $value) {
+ $url = '';
+ foreach ($value as $attr => $attr_value) {
+ if ($attr == 'article__url') {
+ $url = new Url(base64_encode($attr_value));
+ }
+ $sequence = '';
+ if (STORAGE == 'postgres') {
+ $sequence = 'entries_id_seq';
+ }
+ // if ($attr_value == 'favorite' && $attr_value == 'true') {
+ // $last_id = $this->store->getLastId($sequence);
+ // $this->store->favoriteById($last_id);
+ // $this->action('toogle_fav', $url, $last_id, TRUE);
+ // }
+ if ($attr_value == 'archive' && $attr_value == 'true') {
+ $last_id = $this->store->getLastId($sequence);
+ $this->action('toggle_archive', $url, $last_id, TRUE);
+ }
+ }
+ if ($url->isCorrect())
+ $this->action('add', $url, 0, TRUE);
+ }
+ $this->messages->add('s', _('import from Readability completed'));
+ Tools::logm('import from Readability completed');
+ Tools::redirect();
+ }
+
+ public function import($from)
+ {
+ if ($from == 'pocket') {
+ $this->importFromPocket();
+ }
+ else if ($from == 'readability') {
+ $this->importFromReadability();
+ }
+ else if ($from == 'instapaper') {
+ $this->importFromInstapaper();
+ }
+ }
+
+ public function export()
+ {
+ $entries = $this->store->retrieveAll($this->user->getId());
+ echo $this->tpl->render('export.twig', array(
+ 'export' => Tools::renderJson($entries),
+ ));
+ Tools::logm('export view');
+ }
+
+ private function getPocheVersion($which = 'prod')
+ {
+ $cache_file = CACHE . '/' . $which;
+ if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 86400 ))) {
+ $version = file_get_contents($cache_file);
+ } else {
+ $version = file_get_contents('http://static.inthepoche.com/versions/' . $which);
+ file_put_contents($cache_file, $version, LOCK_EX);
+ }
+ return $version;
+ }
+}
\ No newline at end of file
diff --git a/inc/poche/Tools.class.php b/inc/poche/Tools.class.php
new file mode 100644
index 000000000..d0e431663
--- /dev/null
+++ b/inc/poche/Tools.class.php
@@ -0,0 +1,226 @@
+
+ * @copyright 2013
+ * @license http://www.wtfpl.net/ see COPYING file
+ */
+
+class Tools
+{
+ public static function initPhp()
+ {
+ define('START_TIME', microtime(true));
+
+ if (phpversion() < 5) {
+ die(_('Oops, it seems you don\'t have PHP 5.'));
+ }
+
+ error_reporting(E_ALL);
+
+ function stripslashesDeep($value) {
+ return is_array($value)
+ ? array_map('stripslashesDeep', $value)
+ : stripslashes($value);
+ }
+
+ if (get_magic_quotes_gpc()) {
+ $_POST = array_map('stripslashesDeep', $_POST);
+ $_GET = array_map('stripslashesDeep', $_GET);
+ $_COOKIE = array_map('stripslashesDeep', $_COOKIE);
+ }
+
+ ob_start();
+ register_shutdown_function('ob_end_flush');
+ }
+
+ public static function getPocheUrl()
+ {
+ $https = (!empty($_SERVER['HTTPS'])
+ && (strtolower($_SERVER['HTTPS']) == 'on'))
+ || (isset($_SERVER["SERVER_PORT"])
+ && $_SERVER["SERVER_PORT"] == '443'); // HTTPS detection.
+ $serverport = (!isset($_SERVER["SERVER_PORT"])
+ || $_SERVER["SERVER_PORT"] == '80'
+ || ($https && $_SERVER["SERVER_PORT"] == '443')
+ ? '' : ':' . $_SERVER["SERVER_PORT"]);
+
+ $scriptname = str_replace('/index.php', '/', $_SERVER["SCRIPT_NAME"]);
+
+ if (!isset($_SERVER["SERVER_NAME"])) {
+ return $scriptname;
+ }
+
+ return 'http' . ($https ? 's' : '') . '://'
+ . $_SERVER["SERVER_NAME"] . $serverport . $scriptname;
+ }
+
+ public static function redirect($url = '')
+ {
+ if ($url === '') {
+ $url = (empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER']);
+ if (isset($_POST['returnurl'])) {
+ $url = $_POST['returnurl'];
+ }
+ }
+
+ # prevent loop
+ if (empty($url) || parse_url($url, PHP_URL_QUERY) === $_SERVER['QUERY_STRING']) {
+ $url = Tools::getPocheUrl();
+ }
+
+ if (substr($url, 0, 1) !== '?') {
+ $ref = Tools::getPocheUrl();
+ if (substr($url, 0, strlen($ref)) !== $ref) {
+ $url = $ref;
+ }
+ }
+ self::logm('redirect to ' . $url);
+ header('Location: '.$url);
+ exit();
+ }
+
+ public static function getTplFile($view)
+ {
+ $tpl_file = 'home.twig';
+ switch ($view)
+ {
+ case 'install':
+ $tpl_file = 'install.twig';
+ break;
+ case 'import';
+ $tpl_file = 'import.twig';
+ break;
+ case 'export':
+ $tpl_file = 'export.twig';
+ break;
+ case 'config':
+ $tpl_file = 'config.twig';
+ break;
+ case 'view':
+ $tpl_file = 'view.twig';
+ break;
+ default:
+ break;
+ }
+ return $tpl_file;
+ }
+
+ public static function getFile($url)
+ {
+ $timeout = 15;
+ $useragent = "Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0";
+
+ if (in_array ('curl', get_loaded_extensions())) {
+ # Fetch feed from URL
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+
+ # for ssl, do not verified certificate
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
+ curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE );
+
+ # FeedBurner requires a proper USER-AGENT...
+ curl_setopt($curl, CURL_HTTP_VERSION_1_1, true);
+ curl_setopt($curl, CURLOPT_ENCODING, "gzip, deflate");
+ curl_setopt($curl, CURLOPT_USERAGENT, $useragent);
+
+ $data = curl_exec($curl);
+ $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+ $httpcodeOK = isset($httpcode) and ($httpcode == 200 or $httpcode == 301);
+ curl_close($curl);
+ } else {
+ # create http context and add timeout and user-agent
+ $context = stream_context_create(
+ array(
+ 'http' => array(
+ 'timeout' => $timeout,
+ 'header' => "User-Agent: " . $useragent,
+ 'follow_location' => true
+ ),
+ 'ssl' => array(
+ 'verify_peer' => false,
+ 'allow_self_signed' => true
+ )
+ )
+ );
+
+ # only download page lesser than 4MB
+ $data = @file_get_contents($url, false, $context, -1, 4000000);
+
+ if (isset($http_response_header) and isset($http_response_header[0])) {
+ $httpcodeOK = isset($http_response_header) and isset($http_response_header[0]) and ((strpos($http_response_header[0], '200 OK') !== FALSE) or (strpos($http_response_header[0], '301 Moved Permanently') !== FALSE));
+ }
+ }
+
+ # if response is not empty and response is OK
+ if (isset($data) and isset($httpcodeOK) and $httpcodeOK) {
+
+ # take charset of page and get it
+ preg_match('# #Usi', $data, $meta);
+
+ # if meta tag is found
+ if (!empty($meta[0])) {
+ preg_match('#charset="?(.*)"#si', $meta[0], $encoding);
+ # if charset is found set it otherwise, set it to utf-8
+ $html_charset = (!empty($encoding[1])) ? strtolower($encoding[1]) : 'utf-8';
+ } else {
+ $html_charset = 'utf-8';
+ $encoding[1] = '';
+ }
+
+ # replace charset of url to charset of page
+ $data = str_replace('charset=' . $encoding[1], 'charset=' . $html_charset, $data);
+
+ return $data;
+ }
+ else {
+ return FALSE;
+ }
+ }
+
+ public static function renderJson($data)
+ {
+ header('Cache-Control: no-cache, must-revalidate');
+ header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
+ header('Content-type: application/json; charset=UTF-8');
+ echo json_encode($data);
+ exit();
+ }
+
+ public static function logm($message)
+ {
+ if (DEBUG_POCHE) {
+ $t = strval(date('Y/m/d_H:i:s')) . ' - ' . $_SERVER["REMOTE_ADDR"] . ' - ' . strval($message) . "\n";
+ file_put_contents(CACHE . '/log.txt', $t, FILE_APPEND);
+ error_log('DEBUG POCHE : ' . $message);
+ }
+ }
+
+ public static function encodeString($string)
+ {
+ return sha1($string . SALT);
+ }
+
+ public static function checkVar($var, $default = '')
+ {
+ return ((isset ($_REQUEST["$var"])) ? htmlentities($_REQUEST["$var"]) : $default);
+ }
+
+ public static function getDomain($url)
+ {
+ $pieces = parse_url($url);
+ $domain = isset($pieces['host']) ? $pieces['host'] : '';
+ if (preg_match('/(?P[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain, $regs)) {
+ return $regs['domain'];
+ }
+
+ return FALSE;
+ }
+}
\ No newline at end of file
diff --git a/inc/poche/Url.class.php b/inc/poche/Url.class.php
new file mode 100644
index 000000000..f4a8f99e6
--- /dev/null
+++ b/inc/poche/Url.class.php
@@ -0,0 +1,94 @@
+
+ * @copyright 2013
+ * @license http://www.wtfpl.net/ see COPYING file
+ */
+
+class Url
+{
+ public $url;
+
+ function __construct($url)
+ {
+ $this->url = base64_decode($url);
+ }
+
+ public function getUrl() {
+ return $this->url;
+ }
+
+ public function setUrl($url) {
+ $this->url = $url;
+ }
+
+ public function isCorrect()
+ {
+ $pattern = '|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i';
+
+ return preg_match($pattern, $this->url);
+ }
+
+ public function clean()
+ {
+ $url = html_entity_decode(trim($this->url));
+
+ $stuff = strpos($url,'&utm_source=');
+ if ($stuff !== FALSE)
+ $url = substr($url, 0, $stuff);
+ $stuff = strpos($url,'?utm_source=');
+ if ($stuff !== FALSE)
+ $url = substr($url, 0, $stuff);
+ $stuff = strpos($url,'#xtor=RSS-');
+ if ($stuff !== FALSE)
+ $url = substr($url, 0, $stuff);
+
+ $this->url = $url;
+ }
+
+ public function fetchContent()
+ {
+ if ($this->isCorrect()) {
+ $this->clean();
+ $html = Encoding::toUTF8(Tools::getFile($this->getUrl()));
+
+ # if Tools::getFile() if not able to retrieve HTTPS content, try the same URL with HTTP protocol
+ if (!preg_match('!^https?://!i', $this->getUrl()) && (!isset($html) || strlen($html) <= 0)) {
+ $this->setUrl('http://' . $this->getUrl());
+ $html = Encoding::toUTF8(Tools::getFile($this->getUrl()));
+ }
+
+ if (function_exists('tidy_parse_string')) {
+ $tidy = tidy_parse_string($html, array(), 'UTF8');
+ $tidy->cleanRepair();
+ $html = $tidy->value;
+ }
+
+ $parameters = array();
+ if (isset($html) and strlen($html) > 0)
+ {
+ $readability = new Readability($html, $this->getUrl());
+ $readability->convertLinksToFootnotes = CONVERT_LINKS_FOOTNOTES;
+ $readability->revertForcedParagraphElements = REVERT_FORCED_PARAGRAPH_ELEMENTS;
+
+ if($readability->init())
+ {
+ $content = $readability->articleContent->innerHTML;
+ $parameters['title'] = $readability->articleTitle->innerHTML;
+ $parameters['content'] = $content;
+
+ return $parameters;
+ }
+ }
+ }
+ else {
+ #$msg->add('e', _('error during url preparation : the link is not valid'));
+ Tools::logm($this->getUrl() . ' is not a valid url');
+ }
+
+ return FALSE;
+ }
+}
\ No newline at end of file
diff --git a/inc/poche/User.class.php b/inc/poche/User.class.php
new file mode 100644
index 000000000..6dac78397
--- /dev/null
+++ b/inc/poche/User.class.php
@@ -0,0 +1,50 @@
+
+ * @copyright 2013
+ * @license http://www.wtfpl.net/ see COPYING file
+ */
+
+class User
+{
+ public $id;
+ public $username;
+ public $name;
+ public $password;
+ public $email;
+ public $config;
+
+ function __construct($user = array())
+ {
+ if ($user != array()) {
+ $this->id = $user['id'];
+ $this->username = $user['username'];
+ $this->name = $user['name'];
+ $this->password = $user['password'];
+ $this->email = $user['email'];
+ $this->config = $user['config'];
+ }
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getUsername()
+ {
+ return $this->username;
+ }
+
+ public function setConfig($config)
+ {
+ $this->config = $config;
+ }
+
+ public function getConfigValue($name) {
+ return (isset($this->config[$name])) ? $this->config[$name] : FALSE;
+ }
+}
\ No newline at end of file
diff --git a/inc/poche/config.inc.php b/inc/poche/config.inc.php
new file mode 100644
index 000000000..930b31e5f
--- /dev/null
+++ b/inc/poche/config.inc.php
@@ -0,0 +1,61 @@
+
+ * @copyright 2013
+ * @license http://www.wtfpl.net/ see COPYING file
+ */
+
+# storage
+define ('STORAGE','sqlite'); # postgres, mysql, sqlite
+define ('STORAGE_SERVER', 'localhost'); # leave blank for sqlite
+define ('STORAGE_DB', 'poche'); # only for postgres & mysql
+define ('STORAGE_SQLITE', './db/poche.sqlite');
+define ('STORAGE_USER', 'postgres'); # leave blank for sqlite
+define ('STORAGE_PASSWORD', 'postgres'); # leave blank for sqlite
+
+define ('POCHE_VERSION', '1.0-beta');
+define ('MODE_DEMO', FALSE);
+define ('DEBUG_POCHE', FALSE);
+define ('CONVERT_LINKS_FOOTNOTES', FALSE);
+define ('REVERT_FORCED_PARAGRAPH_ELEMENTS', FALSE);
+define ('DOWNLOAD_PICTURES', FALSE);
+define ('SHARE_TWITTER', TRUE);
+define ('SHARE_MAIL', TRUE);
+define ('SALT', '464v54gLLw928uz4zUBqkRJeiPY68zCX');
+define ('ABS_PATH', 'assets/');
+define ('TPL', './tpl');
+define ('LOCALE', './locale');
+define ('CACHE', './cache');
+define ('LANG', 'en_EN.UTF8');
+define ('PAGINATION', '10');
+define ('THEME', 'light');
+
+# /!\ Be careful if you change the lines below /!\
+require_once './inc/poche/User.class.php';
+require_once './inc/poche/Tools.class.php';
+require_once './inc/poche/Url.class.php';
+require_once './inc/3rdparty/class.messages.php';
+require_once './inc/poche/Poche.class.php';
+require_once './inc/3rdparty/Readability.php';
+require_once './inc/3rdparty/Encoding.php';
+require_once './inc/poche/Database.class.php';
+require_once './vendor/autoload.php';
+require_once './inc/3rdparty/simple_html_dom.php';
+require_once './inc/3rdparty/paginator.php';
+require_once './inc/3rdparty/Session.class.php';
+
+if (DOWNLOAD_PICTURES) {
+ require_once './inc/poche/pochePictures.php';
+}
+
+$poche = new Poche();
+#XSRF protection with token
+// if (!empty($_POST)) {
+// if (!Session::isToken($_POST['token'])) {
+// die(_('Wrong token'));
+// }
+// unset($_SESSION['tokens']);
+// }
\ No newline at end of file
diff --git a/inc/poche/pochePictures.php b/inc/poche/pochePictures.php
new file mode 100644
index 000000000..4e4a0b085
--- /dev/null
+++ b/inc/poche/pochePictures.php
@@ -0,0 +1,110 @@
+
+ * @copyright 2013
+ * @license http://www.wtfpl.net/ see COPYING file
+ */
+
+/**
+ * On modifie les URLS des images dans le corps de l'article
+ */
+function filtre_picture($content, $url, $id)
+{
+ $matches = array();
+ preg_match_all('#<\s*(img)[^>]+src="([^"]*)"[^>]*>#Si', $content, $matches, PREG_SET_ORDER);
+ foreach($matches as $i => $link) {
+ $link[1] = trim($link[1]);
+ if (!preg_match('#^(([a-z]+://)|(\#))#', $link[1])) {
+ $absolute_path = get_absolute_link($link[2],$url);
+ $filename = basename(parse_url($absolute_path, PHP_URL_PATH));
+ $directory = create_assets_directory($id);
+ $fullpath = $directory . '/' . $filename;
+ download_pictures($absolute_path, $fullpath);
+ $content = str_replace($matches[$i][2], $fullpath, $content);
+ }
+
+ }
+
+ return $content;
+}
+
+/**
+ * Retourne le lien absolu
+ */
+function get_absolute_link($relative_link, $url) {
+ /* return if already absolute URL */
+ if (parse_url($relative_link, PHP_URL_SCHEME) != '') return $relative_link;
+
+ /* queries and anchors */
+ if ($relative_link[0]=='#' || $relative_link[0]=='?') return $url . $relative_link;
+
+ /* parse base URL and convert to local variables:
+ $scheme, $host, $path */
+ extract(parse_url($url));
+
+ /* remove non-directory element from path */
+ $path = preg_replace('#/[^/]*$#', '', $path);
+
+ /* destroy path if relative url points to root */
+ if ($relative_link[0] == '/') $path = '';
+
+ /* dirty absolute URL */
+ $abs = $host . $path . '/' . $relative_link;
+
+ /* replace '//' or '/./' or '/foo/../' with '/' */
+ $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
+ for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}
+
+ /* absolute URL is ready! */
+ return $scheme.'://'.$abs;
+}
+
+/**
+ * Téléchargement des images
+ */
+function download_pictures($absolute_path, $fullpath)
+{
+ $rawdata = Tools::getFile($absolute_path);
+
+ if(file_exists($fullpath)) {
+ unlink($fullpath);
+ }
+ $fp = fopen($fullpath, 'x');
+ fwrite($fp, $rawdata);
+ fclose($fp);
+}
+
+/**
+ * Crée un répertoire de médias pour l'article
+ */
+function create_assets_directory($id)
+{
+ $assets_path = ABS_PATH;
+ if(!is_dir($assets_path)) {
+ mkdir($assets_path, 0705);
+ }
+
+ $article_directory = $assets_path . $id;
+ if(!is_dir($article_directory)) {
+ mkdir($article_directory, 0705);
+ }
+
+ return $article_directory;
+}
+
+/**
+ * Suppression du répertoire d'images
+ */
+function remove_directory($directory)
+{
+ if(is_dir($directory)) {
+ $files = array_diff(scandir($directory), array('.','..'));
+ foreach ($files as $file) {
+ (is_dir("$directory/$file")) ? remove_directory("$directory/$file") : unlink("$directory/$file");
+ }
+ return rmdir($directory);
+ }
+}
\ No newline at end of file
diff --git a/inc/rain.tpl.class.php b/inc/rain.tpl.class.php
deleted file mode 100644
index 6522c7985..000000000
--- a/inc/rain.tpl.class.php
+++ /dev/null
@@ -1,1043 +0,0 @@
-), stylesheet ( ), script (
\ No newline at end of file
diff --git a/tpl/_footer.twig b/tpl/_footer.twig
new file mode 100644
index 000000000..6891756a3
--- /dev/null
+++ b/tpl/_footer.twig
@@ -0,0 +1,4 @@
+
+ {% trans "powered by" %} poche
+ {% if constant('DEBUG_POCHE') == 1 %}{% trans "debug mode is on so cache is off." %} {% trans "your poche version:" %}{{constant('POCHE_VERSION')}}. {% trans "storage:" %} {{constant('STORAGE')}}
{% endif %}
+
\ No newline at end of file
diff --git a/tpl/_head.twig b/tpl/_head.twig
new file mode 100644
index 000000000..f25f04719
--- /dev/null
+++ b/tpl/_head.twig
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tpl/_menu.twig b/tpl/_menu.twig
new file mode 100644
index 000000000..699d6a0c9
--- /dev/null
+++ b/tpl/_menu.twig
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/tpl/_messages.twig b/tpl/_messages.twig
new file mode 100644
index 000000000..679aa0981
--- /dev/null
+++ b/tpl/_messages.twig
@@ -0,0 +1 @@
+ {{ messages | raw }}
\ No newline at end of file
diff --git a/tpl/_top.twig b/tpl/_top.twig
new file mode 100644
index 000000000..ae01cc3ff
--- /dev/null
+++ b/tpl/_top.twig
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/tpl/config.html b/tpl/config.html
deleted file mode 100644
index 2c7df4f74..000000000
--- a/tpl/config.html
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
Bookmarklet
-
Thanks to the bookmarklet, you will be able to easily add a link to your poche. If you don't know how use a bookmarklet, have a look here .
-
Drag & drop this link to your bookmarks bar and have fun with poche.
-
poche it !
-
-
Password
-
-
Export
-
Click here to export your poche datas.
-
\ No newline at end of file
diff --git a/tpl/config.twig b/tpl/config.twig
new file mode 100644
index 000000000..95d5d8cf0
--- /dev/null
+++ b/tpl/config.twig
@@ -0,0 +1,57 @@
+{% extends "layout.twig" %}
+
+{% block title %}{% trans "config" %}{% endblock %}
+{% block menu %}
+
+{% endblock %}
+{% block content %}
+ {% trans "Bookmarklet" %}
+ {% trans "Thanks to the bookmarklet, you will be able to easily add a link to your poche." %} {% trans "Have a look to this documentation:" %} inthepoche.com .
+ {% trans "Drag & drop this link to your bookmarks bar and have fun with poche." %}
+ {% trans "poche it!" %}
+
+ {% trans "Updating poche" %}
+
+
+
+ {% trans "Change your password" %}
+
+
+ {% trans "Import" %}
+ {% trans "Please execute the import script locally, it can take a very long time." %}
+ {% trans "More infos in the official doc:" %} inthepoche.com
+
+
+ {% trans "Export your poche datas" %}
+ {% trans "Click here" %} {% trans "to export your poche datas." %}
+{% endblock %}
\ No newline at end of file
diff --git a/css/knacss.css b/tpl/css/knacss.css
similarity index 100%
rename from css/knacss.css
rename to tpl/css/knacss.css
diff --git a/tpl/css/messages.css b/tpl/css/messages.css
new file mode 100755
index 000000000..9222bb88b
--- /dev/null
+++ b/tpl/css/messages.css
@@ -0,0 +1,13 @@
+.messages { width: 400px; -moz-border-radius: 4px; border-radius: 4px; display: block; padding: 10px 0; margin: 10px auto 10px; clear: both; }
+.messages a.closeMessage { margin: -14px -8px 0 0; display:none; width: 16px; height: 16px; float: right; background: url(../img/messages/close.png) no-repeat; }
+/*.messages:hover a.closeMessage { visibility:visible; }*/
+.messages p { margin: 3px 0 3px 10px !important; padding: 0 10px 0 23px !important; font-size: 14px; line-height: 16px; }
+.messages.error { border: 1px solid #C42608; color: #c00 !important; background: #FFF0EF; }
+.messages.error p { background: url(../img/messages/cross.png ) no-repeat 0px 50%; color:#c00 !important; }
+.messages.success {background: #E0FBCC; border: 1px solid #6DC70C; }
+.messages.success p { background: url(../img/messages/tick.png) no-repeat 0px 50%; color: #2B6301 !important; }
+.messages.warning { background: #FFFCD3; border: 1px solid #EBCD41; color: #000; }
+.messages.warning p { background: url(../img/messages/warning.png ) no-repeat 0px 50%; color: #5F4E01; }
+.messages.information, .messages.info { background: #DFEBFB; border: 1px solid #82AEE7; }
+.messages.information p, .messages.info p { background: url(../img/messages/help.png ) no-repeat 0px 50%; color: #064393; }
+.messages.information a { text-decoration: underline; }
\ No newline at end of file
diff --git a/tpl/css/style-light.css b/tpl/css/style-light.css
new file mode 100644
index 000000000..9ea7955a5
--- /dev/null
+++ b/tpl/css/style-light.css
@@ -0,0 +1,53 @@
+
+a.back span {
+ background: url('../img/light/left.png') no-repeat;
+}
+
+a.top span {
+ background: url('../img/light/top.png') no-repeat;
+}
+
+
+a.fav span {
+ background: url('../img/light/star-on.png') no-repeat;
+}
+
+a.fav span:hover {
+ background: url('../img/light/star-off.png') no-repeat;
+}
+
+a.fav-off span {
+ background: url('../img/light/star-off.png') no-repeat;
+}
+
+a.fav-off span:hover {
+ background: url('../img/light/star-on.png') no-repeat;
+}
+
+a.archive span {
+ background: url('../img/light/checkmark-on.png') no-repeat;
+}
+
+a.archive span:hover {
+ background: url('../img/light/checkmark-off.png') no-repeat;
+}
+
+a.archive-off span {
+ background: url('../img/light/checkmark-off.png') no-repeat;
+}
+
+a.archive-off span:hover {
+ background: url('../img/light/checkmark-on.png') no-repeat;
+}
+
+a.twitter span {
+ background: url('../img/light/twitter.png') no-repeat;
+}
+
+a.email span {
+ background: url('../img/light/envelop.png') no-repeat;
+}
+
+a.delete span {
+ background: url('../img/light/remove.png') no-repeat;
+}
\ No newline at end of file
diff --git a/tpl/css/style.css b/tpl/css/style.css
new file mode 100644
index 000000000..d23c18964
--- /dev/null
+++ b/tpl/css/style.css
@@ -0,0 +1,244 @@
+body {
+ font-size: 16px;
+ font-family: 'Roboto', sans-serif;
+ margin: 10px;
+}
+
+header {
+ text-align: center;
+}
+
+header h1 {
+ font-size: 1.3em;
+}
+
+.bouton {
+ border-radius: 2px;
+}
+
+#main {
+ margin: 0 auto;
+}
+
+#main ul#links {
+ padding: 0;
+ list-style-type: none;
+ text-align: center;
+ font-size: 0.9em;
+}
+
+#main ul#links li {
+ display: inline;
+}
+
+#main ul#links li a.current {
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+}
+
+#main ul#sort {
+ padding: 0;
+ list-style-type: none;
+ text-align: center;
+ opacity: 0.5;
+}
+
+#main ul#sort li {
+ display: inline;
+ font-size: 0.9em;
+}
+
+#main ul#sort img:hover {
+ cursor: pointer;
+}
+
+
+#links a{
+ text-decoration: none;
+ padding: 5px 10px;
+}
+#links a:hover{
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+}
+
+/*** ***/
+/*** LINKS DISPLAY ***/
+
+#main a.tool {
+ text-decoration: none;
+ cursor: pointer;
+}
+
+#main #content {
+ margin-top: 20px;
+}
+
+#main #content h2 {
+ font-size: 1.3em;
+ text-decoration: none;
+}
+
+#main #content .entrie {
+ border-bottom: 1px dashed #222222;
+}
+
+#main .entrie ul.tools {
+ list-style-type: none;
+}
+
+#main .entrie ul.tools li {
+ /*display: inline;*/
+}
+
+.tools {
+ float: right;
+ text-align: right;
+ opacity: 0.5;
+}
+
+.tools p {
+ font-size: 0.8em;}
+
+/*
+.tools ul {
+ padding: 0; margin: 0;
+ list-style-type: none;
+}
+
+.tools ul li {
+ line-height: 20px;
+}
+
+.tools a.tool {
+ cursor: pointer;
+}*/
+
+#main .entrie .tools a.tool span, #article .tools a.tool span {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+}
+
+#main .entrie .url {
+ font-size: 13px;
+}
+
+
+/*** ***/
+/*** ARTICLE PAGE ***/
+
+#article {
+ margin: 0 auto;
+}
+#article header {
+ text-align: left;
+}
+
+#article header a {
+ text-decoration: none;
+}
+
+.vieworiginal a, .vieworiginal a:hover, .vieworiginal a:visited {
+ text-decoration: none;
+ color: #888888;
+}
+
+.backhome {
+ display: inline;
+}
+
+#article .tools {
+ position: relative;
+ display: inline;
+ top: 0px;
+ right: 0px;
+ width: 100%;
+}
+
+#article .tools ul li{
+ display: inline;
+}
+
+
+/*** GENERAL ***/
+body {
+ color: #000;
+}
+
+a, a:hover, a:visited {
+ color: #000;
+}
+
+.bouton {
+ background-color: #000;
+ color: #fff;
+ border: none;
+}
+.bouton:hover {
+ background-color: #222222;
+ color: #F1F1F1;
+}
+
+#main ul#links li a.current {
+ background-color: #000;
+ color: #fff;
+}
+
+#links a:hover{
+ background-color: #040707;
+ color: #F1F1F1;
+}
+
+
+/*** ***/
+/*** ARTICLE PAGE ***/
+
+#article header, #article article {
+ border-bottom: 1px solid #222222;
+}
+
+
+/* Pagination */
+.pagination {
+ clear: both;
+ padding-bottom: 20px;
+ padding-top: 10px;
+ text-align: right;
+}
+.pagination a {
+ border: 1px solid #D5D5D5;
+ color: #333;
+ font-size: 11px;
+ font-weight: bold;
+ height: 25px;
+ padding: 4px 8px;
+ text-decoration: none;
+ margin:2px;
+}
+.pagination a:hover, .pagination a:active {
+ background:#efefef;
+}
+.pagination span.current {
+ background-color: #ccc;
+ border: 1px solid #D5D5D5;
+ color: #000;
+ font-size: 11px;
+ font-weight: bold;
+ height: 25px;
+ padding: 4px 8px;
+ text-decoration: none;
+ margin:2px;
+}
+.pagination span.disabled {
+ border: 1px solid #EEEEEE;
+ color: #DDDDDD;
+ margin:2px;
+ padding: 4px 8px;
+ font-size: 11px;
+ font-weight: bold;
+}
+
+footer {
+ clear: both;
+}
\ No newline at end of file
diff --git a/tpl/entries.html b/tpl/entries.html
deleted file mode 100644
index 83e58c741..000000000
--- a/tpl/entries.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
- {loop="entries"}
-
- {/loop}
-
\ No newline at end of file
diff --git a/tpl/export.html b/tpl/export.html
deleted file mode 100644
index d22d05fc9..000000000
--- a/tpl/export.html
+++ /dev/null
@@ -1 +0,0 @@
-export {$export}
\ No newline at end of file
diff --git a/tpl/export.twig b/tpl/export.twig
new file mode 100644
index 000000000..4adb95402
--- /dev/null
+++ b/tpl/export.twig
@@ -0,0 +1 @@
+{{ export }}
\ No newline at end of file
diff --git a/tpl/footer.html b/tpl/footer.html
deleted file mode 100644
index b8bd755c8..000000000
--- a/tpl/footer.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-