aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CREDITS.md3
-rw-r--r--composer.json23
-rw-r--r--inc/3rdparty/libraries/MOBIClass/MOBI.php4
-rw-r--r--inc/3rdparty/libraries/MOBIClass/readability/JSLikeHTMLElement.php110
-rw-r--r--inc/3rdparty/libraries/MOBIClass/readability/Readability.php1069
-rwxr-xr-xinc/3rdparty/libraries/readability/Readability.php5
-rw-r--r--inc/3rdparty/libraries/tcpdf/tcpdf.php10
-rwxr-xr-xinc/3rdparty/makefulltextfeed.php2
-rwxr-xr-xinc/poche/Poche.class.php94
-rwxr-xr-xinc/poche/Routing.class.php5
-rwxr-xr-xinc/poche/Tools.class.php5
-rw-r--r--inc/poche/WallabagEBooks.class.php41
-rwxr-xr-xinstall/index.php643
-rw-r--r--install/wallabag_compatibility_test.php425
-rw-r--r--locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.mobin10620 -> 16993 bytes
-rw-r--r--locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.po741
-rw-r--r--locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.mobin21037 -> 21037 bytes
-rw-r--r--locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.po2
-rwxr-xr-xthemes/baggy/home.twig6
-rwxr-xr-xthemes/courgette/config.twig127
-rwxr-xr-xthemes/default/home.twig8
21 files changed, 1069 insertions, 2254 deletions
diff --git a/CREDITS.md b/CREDITS.md
index f1e9d7af..e76c580d 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -8,9 +8,10 @@ wallabag is based on :
8* Twig http://twig.sensiolabs.org 8* Twig http://twig.sensiolabs.org
9* Flash messages https://github.com/plasticbrain/PHP-Flash-Messages 9* Flash messages https://github.com/plasticbrain/PHP-Flash-Messages
10* Pagination https://github.com/daveismyname/pagination 10* Pagination https://github.com/daveismyname/pagination
11* PHPePub https://github.com/Grandt/PHPePub/
11 12
12wallabag is mainly developed by Nicolas LÅ“uillet under the MIT License 13wallabag is mainly developed by Nicolas LÅ“uillet under the MIT License
13 14
14Thank you so much to @tcitworld and @mariroz. 15Thank you so much to @tcitworld and @mariroz.
15 16
16Contributors : https://github.com/wallabag/wallabag/graphs/contributors \ No newline at end of file 17Contributors : https://github.com/wallabag/wallabag/graphs/contributors
diff --git a/composer.json b/composer.json
index 6c69e48d..a63f2893 100644
--- a/composer.json
+++ b/composer.json
@@ -1,4 +1,27 @@
1{ 1{
2 "name": "wallabag/wallabag",
3 "type": "project",
4 "description": "open source self hostable read-it-later web application",
5 "keywords": ["read-it-later","read it later"],
6 "homepage": "https://github.com/wallabag/wallabag",
7 "license": "MIT",
8 "authors": [
9 {
10 "name": "Nicolas LÅ“uillet",
11 "email": "nicolas@loeuillet.org",
12 "homepage": "http://www.cdetc.fr",
13 "role": "Developer"
14 },
15 {
16 "name": "Thomas Citharel",
17 "homepage": "http://tcit.fr",
18 "role": "Developer"
19 }
20 ],
21 "support": {
22 "email": "hello@wallabag.org",
23 "issues": "https://github.com/wallabag/wallabag/issues"
24 },
2 "require": { 25 "require": {
3 "twig/twig": "1.*", 26 "twig/twig": "1.*",
4 "twig/extensions": "1.0.*", 27 "twig/extensions": "1.0.*",
diff --git a/inc/3rdparty/libraries/MOBIClass/MOBI.php b/inc/3rdparty/libraries/MOBIClass/MOBI.php
index 17e718c1..df4826b0 100644
--- a/inc/3rdparty/libraries/MOBIClass/MOBI.php
+++ b/inc/3rdparty/libraries/MOBIClass/MOBI.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2require_once(dirname(__FILE__)."/readability/Readability.php"); 2require_once(dirname(__FILE__)."/../readability/Readability.php");
3require_once(dirname(__FILE__).'/CharacterEntities.php'); 3require_once(dirname(__FILE__).'/CharacterEntities.php');
4require_once(dirname(__FILE__).'/constants.php'); 4require_once(dirname(__FILE__).'/constants.php');
5require_once(dirname(__FILE__).'/ContentProvider.php'); 5require_once(dirname(__FILE__).'/ContentProvider.php');
@@ -189,4 +189,4 @@ class MOBI {
189 } 189 }
190 190
191} 191}
192?> \ No newline at end of file 192?>
diff --git a/inc/3rdparty/libraries/MOBIClass/readability/JSLikeHTMLElement.php b/inc/3rdparty/libraries/MOBIClass/readability/JSLikeHTMLElement.php
deleted file mode 100644
index 1a8ec88c..00000000
--- a/inc/3rdparty/libraries/MOBIClass/readability/JSLikeHTMLElement.php
+++ /dev/null
@@ -1,110 +0,0 @@
1<?php
2/**
3* JavaScript-like HTML DOM Element
4*
5* This class extends PHP's DOMElement to allow
6* users to get and set the innerHTML property of
7* HTML elements in the same way it's done in
8* JavaScript.
9*
10* Example usage:
11* @code
12* require_once 'JSLikeHTMLElement.php';
13* header('Content-Type: text/plain');
14* $doc = new DOMDocument();
15* $doc->registerNodeClass('DOMElement', 'JSLikeHTMLElement');
16* $doc->loadHTML('<div><p>Para 1</p><p>Para 2</p></div>');
17* $elem = $doc->getElementsByTagName('div')->item(0);
18*
19* // print innerHTML
20* echo $elem->innerHTML; // prints '<p>Para 1</p><p>Para 2</p>'
21* echo "\n\n";
22*
23* // set innerHTML
24* $elem->innerHTML = '<a href="http://fivefilters.org">FiveFilters.org</a>';
25* echo $elem->innerHTML; // prints '<a href="http://fivefilters.org">FiveFilters.org</a>'
26* echo "\n\n";
27*
28* // print document (with our changes)
29* echo $doc->saveXML();
30* @endcode
31*
32* @author Keyvan Minoukadeh - http://www.keyvan.net - keyvan@keyvan.net
33* @see http://fivefilters.org (the project this was written for)
34*/
35class JSLikeHTMLElement extends DOMElement
36{
37 /**
38 * Used for setting innerHTML like it's done in JavaScript:
39 * @code
40 * $div->innerHTML = '<h2>Chapter 2</h2><p>The story begins...</p>';
41 * @endcode
42 */
43 public function __set($name, $value) {
44 if ($name == 'innerHTML') {
45 // first, empty the element
46 for ($x=$this->childNodes->length-1; $x>=0; $x--) {
47 $this->removeChild($this->childNodes->item($x));
48 }
49 // $value holds our new inner HTML
50 if ($value != '') {
51 $f = $this->ownerDocument->createDocumentFragment();
52 // appendXML() expects well-formed markup (XHTML)
53 $result = @$f->appendXML($value); // @ to suppress PHP warnings
54 if ($result) {
55 if ($f->hasChildNodes()) $this->appendChild($f);
56 } else {
57 // $value is probably ill-formed
58 $f = new DOMDocument();
59 $value = mb_convert_encoding($value, 'HTML-ENTITIES', 'UTF-8');
60 // Using <htmlfragment> will generate a warning, but so will bad HTML
61 // (and by this point, bad HTML is what we've got).
62 // We use it (and suppress the warning) because an HTML fragment will
63 // be wrapped around <html><body> tags which we don't really want to keep.
64 // Note: despite the warning, if loadHTML succeeds it will return true.
65 $result = @$f->loadHTML('<htmlfragment>'.$value.'</htmlfragment>');
66 if ($result) {
67 $import = $f->getElementsByTagName('htmlfragment')->item(0);
68 foreach ($import->childNodes as $child) {
69 $importedNode = $this->ownerDocument->importNode($child, true);
70 $this->appendChild($importedNode);
71 }
72 } else {
73 // oh well, we tried, we really did. :(
74 // this element is now empty
75 }
76 }
77 }
78 } else {
79 $trace = debug_backtrace();
80 trigger_error('Undefined property via __set(): '.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE);
81 }
82 }
83
84 /**
85 * Used for getting innerHTML like it's done in JavaScript:
86 * @code
87 * $string = $div->innerHTML;
88 * @endcode
89 */
90 public function __get($name)
91 {
92 if ($name == 'innerHTML') {
93 $inner = '';
94 foreach ($this->childNodes as $child) {
95 $inner .= $this->ownerDocument->saveXML($child);
96 }
97 return $inner;
98 }
99
100 $trace = debug_backtrace();
101 trigger_error('Undefined property via __get(): '.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE);
102 return null;
103 }
104
105 public function __toString()
106 {
107 return '['.$this->tagName.']';
108 }
109}
110?> \ No newline at end of file
diff --git a/inc/3rdparty/libraries/MOBIClass/readability/Readability.php b/inc/3rdparty/libraries/MOBIClass/readability/Readability.php
deleted file mode 100644
index 91554243..00000000
--- a/inc/3rdparty/libraries/MOBIClass/readability/Readability.php
+++ /dev/null
@@ -1,1069 +0,0 @@
1<?php
2/**
3* Arc90's Readability ported to PHP for FiveFilters.org
4* Based on readability.js version 1.7.1 (without multi-page support)
5* ------------------------------------------------------
6* Original URL: http://lab.arc90.com/experiments/readability/js/readability.js
7* Arc90's project URL: http://lab.arc90.com/experiments/readability/
8* JS Source: http://code.google.com/p/arc90labs-readability
9* Ported by: Keyvan Minoukadeh, http://www.keyvan.net
10* More information: http://fivefilters.org/content-only/
11* License: Apache License, Version 2.0
12* Requires: PHP5
13* Date: 2010-10-29
14*
15* Differences between the PHP port and the original
16* ------------------------------------------------------
17* Arc90's Readability is designed to run in the browser. It works on the DOM
18* tree (the parsed HTML) after the page's CSS styles have been applied and
19* Javascript code executed. This PHP port does not run inside a browser.
20* We use PHP's ability to parse HTML to build our DOM tree, but we cannot
21* rely on CSS or Javascript support. As such, the results will not always
22* match Arc90's Readability. (For example, if a web page contains CSS style
23* rules or Javascript code which hide certain HTML elements from display,
24* Arc90's Readability will dismiss those from consideration but our PHP port,
25* unable to understand CSS or Javascript, will not know any better.)
26*
27* Another significant difference is that the aim of Arc90's Readability is
28* to re-present the main content block of a given web page so users can
29* read it more easily in their browsers. Correct identification, clean up,
30* and separation of the content block is only a part of this process.
31* This PHP port is only concerned with this part, it does not include code
32* that relates to presentation in the browser - Arc90 already do
33* that extremely well, and for PDF output there's FiveFilters.org's
34* PDF Newspaper: http://fivefilters.org/pdf-newspaper/.
35*
36* Finally, this class contains methods that might be useful for developers
37* working on HTML document fragments. So without deviating too much from
38* the original code (which I don't want to do because it makes debugging
39* and updating more difficult), I've tried to make it a little more
40* developer friendly. You should be able to use the methods here on
41* existing DOMElement objects without passing an entire HTML document to
42* be parsed.
43*/
44
45// This class allows us to do JavaScript like assignements to innerHTML
46require_once(dirname(__FILE__).'/JSLikeHTMLElement.php');
47
48// Alternative usage (for testing only!)
49// uncomment the lins below and call Readability.php in your browser
50// passing it the URL of the page you'd like content from, e.g.:
51// Readability.php?url=http://medialens.org/alerts/09/090615_the_guardian_climate.php
52
53/*
54if (!isset($_GET['url']) || $_GET['url'] == '') {
55 die('Please pass a URL to the script. E.g. Readability.php?url=bla.com/story.html');
56}
57$url = $_GET['url'];
58if (!preg_match('!^https?://!i', $url)) $url = 'http://'.$url;
59$html = file_get_contents($url);
60$r = new Readability($html, $url);
61$r->init();
62echo $r->articleContent->innerHTML;
63*/
64
65class Readability
66{
67 public $version = '1.7.1-without-multi-page';
68 public $convertLinksToFootnotes = false;
69 public $revertForcedParagraphElements = true;
70 public $articleTitle;
71 public $articleContent;
72 public $dom;
73 public $url = null; // optional - URL where HTML was retrieved
74 public $debug = false;
75 protected $body = null; //
76 protected $bodyCache = null; // Cache the body HTML in case we need to re-use it later
77 protected $flags = 7; // 1 | 2 | 4; // Start with all flags set.
78 protected $success = false; // indicates whether we were able to extract or not
79
80 /**
81 * All of the regular expressions in use within readability.
82 * Defined up here so we don't instantiate them repeatedly in loops.
83 **/
84 public $regexps = array(
85 'unlikelyCandidates' => '/combx|comment|community|disqus|extra|foot|header|menu|remark|rss|shoutbox|sidebar|sponsor|ad-break|agegate|pagination|pager|popup|tweet|twitter/i',
86 'okMaybeItsACandidate' => '/and|article|body|column|main|shadow/i',
87 'positive' => '/article|body|content|entry|hentry|main|page|pagination|post|text|blog|story/i',
88 'negative' => '/combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|shoutbox|sidebar|sponsor|shopping|tags|tool|widget/i',
89 'divToPElements' => '/<(a|blockquote|dl|div|img|ol|p|pre|table|ul)/i',
90 'replaceBrs' => '/(<br[^>]*>[ \n\r\t]*){2,}/i',
91 'replaceFonts' => '/<(\/?)font[^>]*>/i',
92 // 'trimRe' => '/^\s+|\s+$/g', // PHP has trim()
93 'normalize' => '/\s{2,}/',
94 'killBreaks' => '/(<br\s*\/?>(\s|&nbsp;?)*){1,}/',
95 'video' => '/http:\/\/(www\.)?(youtube|vimeo)\.com/i',
96 'skipFootnoteLink' => '/^\s*(\[?[a-z0-9]{1,2}\]?|^|edit|citation needed)\s*$/i'
97 );
98
99 /* constants */
100 const FLAG_STRIP_UNLIKELYS = 1;
101 const FLAG_WEIGHT_CLASSES = 2;
102 const FLAG_CLEAN_CONDITIONALLY = 4;
103
104 /**
105 * Create instance of Readability
106 * @param string UTF-8 encoded string
107 * @param string (optional) URL associated with HTML (used for footnotes)
108 */
109 function __construct($html, $url=null)
110 {
111 /* Turn all double br's into p's */
112 /* Note, this is pretty costly as far as processing goes. Maybe optimize later. */
113 $html = preg_replace($this->regexps['replaceBrs'], '</p><p>', $html);
114 $html = preg_replace($this->regexps['replaceFonts'], '<$1span>', $html);
115 $html = mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8");
116 $this->dom = new DOMDocument();
117 $this->dom->preserveWhiteSpace = false;
118 $this->dom->registerNodeClass('DOMElement', 'JSLikeHTMLElement');
119 @$this->dom->loadHTML($html);
120 $this->url = $url;
121 }
122
123 /**
124 * Get article title element
125 * @return DOMElement
126 */
127 public function getTitle() {
128 return $this->articleTitle;
129 }
130
131 /**
132 * Get article content element
133 * @return DOMElement
134 */
135 public function getContent() {
136 return $this->articleContent;
137 }
138
139 /**
140 * Runs readability.
141 *
142 * Workflow:
143 * 1. Prep the document by removing script tags, css, etc.
144 * 2. Build readability's DOM tree.
145 * 3. Grab the article content from the current dom tree.
146 * 4. Replace the current DOM tree with the new one.
147 * 5. Read peacefully.
148 *
149 * @return boolean true if we found content, false otherwise
150 **/
151 public function init()
152 {
153 $this->removeScripts($this->dom);
154
155 // Assume successful outcome
156 $this->success = true;
157
158 $bodyElems = $this->dom->getElementsByTagName('body');
159 if ($bodyElems->length > 0) {
160 if ($this->bodyCache == null) {
161 $this->bodyCache = $bodyElems->item(0)->innerHTML;
162 }
163 if ($this->body == null) {
164 $this->body = $bodyElems->item(0);
165 }
166 }
167
168 $this->prepDocument();
169
170 //die($this->dom->documentElement->parentNode->nodeType);
171 //$this->setInnerHTML($this->dom->documentElement, $this->getInnerHTML($this->dom->documentElement));
172 //die($this->getInnerHTML($this->dom->documentElement));
173
174 /* Build readability's DOM tree */
175 $overlay = $this->dom->createElement('div');
176 $innerDiv = $this->dom->createElement('div');
177 $articleTitle = $this->getArticleTitle();
178 $articleContent = $this->grabArticle();
179
180 if (!$articleContent) {
181 $this->success = false;
182 $articleContent = $this->dom->createElement('div');
183 $articleContent->setAttribute('id', 'readability-content');
184 $articleContent->innerHTML = '<p>Sorry, Readability was unable to parse this page for content.</p>';
185 }
186
187 $overlay->setAttribute('id', 'readOverlay');
188 $innerDiv->setAttribute('id', 'readInner');
189
190 /* Glue the structure of our document together. */
191 $innerDiv->appendChild($articleTitle);
192 $innerDiv->appendChild($articleContent);
193 $overlay->appendChild($innerDiv);
194
195 /* Clear the old HTML, insert the new content. */
196 $this->body->innerHTML = '';
197 $this->body->appendChild($overlay);
198 //document.body.insertBefore(overlay, document.body.firstChild);
199 $this->body->removeAttribute('style');
200
201 $this->postProcessContent($articleContent);
202
203 // Set title and content instance variables
204 $this->articleTitle = $articleTitle;
205 $this->articleContent = $articleContent;
206
207 return $this->success;
208 }
209
210 /**
211 * Debug
212 */
213 protected function dbg($msg) {
214 if ($this->debug) echo '* ',$msg, '<br />', "\n";
215 }
216
217 /**
218 * Run any post-process modifications to article content as necessary.
219 *
220 * @param DOMElement
221 * @return void
222 */
223 public function postProcessContent($articleContent) {
224 if ($this->convertLinksToFootnotes && !preg_match('/wikipedia\.org/', @$this->url)) {
225 $this->addFootnotes($articleContent);
226 }
227 }
228
229 /**
230 * Get the article title as an H1.
231 *
232 * @return DOMElement
233 */
234 protected function getArticleTitle() {
235 $curTitle = '';
236 $origTitle = '';
237
238 try {
239 $curTitle = $origTitle = $this->getInnerText($this->dom->getElementsByTagName('title')->item(0));
240 } catch(Exception $e) {}
241
242 if (preg_match('/ [\|\-] /', $curTitle))
243 {
244 $curTitle = preg_replace('/(.*)[\|\-] .*/i', '$1', $origTitle);
245
246 if (count(explode(' ', $curTitle)) < 3) {
247 $curTitle = preg_replace('/[^\|\-]*[\|\-](.*)/i', '$1', $origTitle);
248 }
249 }
250 else if (strpos($curTitle, ': ') !== false)
251 {
252 $curTitle = preg_replace('/.*:(.*)/i', '$1', $origTitle);
253
254 if (count(explode(' ', $curTitle)) < 3) {
255 $curTitle = preg_replace('/[^:]*[:](.*)/i','$1', $origTitle);
256 }
257 }
258 else if(strlen($curTitle) > 150 || strlen($curTitle) < 15)
259 {
260 $hOnes = $this->dom->getElementsByTagName('h1');
261 if($hOnes->length == 1)
262 {
263 $curTitle = $this->getInnerText($hOnes->item(0));
264 }
265 }
266
267 $curTitle = trim($curTitle);
268
269 if (count(explode(' ', $curTitle)) <= 4) {
270 $curTitle = $origTitle;
271 }
272
273 $articleTitle = $this->dom->createElement('h1');
274 $articleTitle->innerHTML = $curTitle;
275
276 return $articleTitle;
277 }
278
279 /**
280 * Prepare the HTML document for readability to scrape it.
281 * This includes things like stripping javascript, CSS, and handling terrible markup.
282 *
283 * @return void
284 **/
285 protected function prepDocument() {
286 /**
287 * In some cases a body element can't be found (if the HTML is totally hosed for example)
288 * so we create a new body node and append it to the document.
289 */
290 if($this->dom->documentElement == null){
291 throw new Exception("No document element");
292 }
293 if ($this->body == null)
294 {
295 $this->body = $this->dom->createElement('body');
296 $this->dom->documentElement->appendChild($this->body);
297 }
298
299 $this->body->setAttribute('id', 'readabilityBody');
300
301 /* Remove all style tags in head */
302 $styleTags = $this->dom->getElementsByTagName('style');
303 for ($i = $styleTags->length-1; $i >= 0; $i--)
304 {
305 $styleTags->item($i)->parentNode->removeChild($styleTags->item($i));
306 }
307
308 /* Turn all double br's into p's */
309 /* Note, this is pretty costly as far as processing goes. Maybe optimize later. */
310 //document.body.innerHTML = document.body.innerHTML.replace(readability.regexps.replaceBrs, '</p><p>').replace(readability.regexps.replaceFonts, '<$1span>');
311 // We do this in the constructor for PHP as that's when we have raw HTML - before parsing it into a DOM tree.
312 // Manipulating innerHTML as it's done in JS is not possible in PHP.
313 }
314
315 /**
316 * For easier reading, convert this document to have footnotes at the bottom rather than inline links.
317 * @see http://www.roughtype.com/archives/2010/05/experiments_in.php
318 *
319 * @return void
320 **/
321 public function addFootnotes($articleContent) {
322 $footnotesWrapper = $this->dom->createElement('div');
323 $footnotesWrapper->setAttribute('id', 'readability-footnotes');
324 $footnotesWrapper->innerHTML = '<h3>References</h3>';
325
326 $articleFootnotes = $this->dom->createElement('ol');
327 $articleFootnotes->setAttribute('id', 'readability-footnotes-list');
328 $footnotesWrapper->appendChild($articleFootnotes);
329
330 $articleLinks = $articleContent->getElementsByTagName('a');
331
332 $linkCount = 0;
333 for ($i = 0; $i < $articleLinks->length; $i++)
334 {
335 $articleLink = $articleLinks->item($i);
336 $footnoteLink = $articleLink->cloneNode(true);
337 $refLink = $this->dom->createElement('a');
338 $footnote = $this->dom->createElement('li');
339 $linkDomain = @parse_url($footnoteLink->getAttribute('href'), PHP_URL_HOST);
340 if (!$linkDomain && isset($this->url)) $linkDomain = @parse_url($this->url, PHP_URL_HOST);
341 //linkDomain = footnoteLink.host ? footnoteLink.host : document.location.host,
342 $linkText = $this->getInnerText($articleLink);
343
344 if ((strpos($articleLink->getAttribute('class'), 'readability-DoNotFootnote') !== false) || preg_match($this->regexps['skipFootnoteLink'], $linkText)) {
345 continue;
346 }
347
348 $linkCount++;
349
350 /** Add a superscript reference after the article link */
351 $refLink->setAttribute('href', '#readabilityFootnoteLink-' . $linkCount);
352 $refLink->innerHTML = '<small><sup>[' . $linkCount . ']</sup></small>';
353 $refLink->setAttribute('class', 'readability-DoNotFootnote');
354 $refLink->setAttribute('style', 'color: inherit;');
355
356 //TODO: does this work or should we use DOMNode.isSameNode()?
357 if ($articleLink->parentNode->lastChild == $articleLink) {
358 $articleLink->parentNode->appendChild($refLink);
359 } else {
360 $articleLink->parentNode->insertBefore($refLink, $articleLink->nextSibling);
361 }
362
363 $articleLink->setAttribute('style', 'color: inherit; text-decoration: none;');
364 $articleLink->setAttribute('name', 'readabilityLink-' . $linkCount);
365
366 $footnote->innerHTML = '<small><sup><a href="#readabilityLink-' . $linkCount . '" title="Jump to Link in Article">^</a></sup></small> ';
367
368 $footnoteLink->innerHTML = ($footnoteLink->getAttribute('title') != '' ? $footnoteLink->getAttribute('title') : $linkText);
369 $footnoteLink->setAttribute('name', 'readabilityFootnoteLink-' . $linkCount);
370
371 $footnote->appendChild($footnoteLink);
372 if ($linkDomain) $footnote->innerHTML = $footnote->innerHTML . '<small> (' . $linkDomain . ')</small>';
373
374 $articleFootnotes->appendChild($footnote);
375 }
376
377 if ($linkCount > 0) {
378 $articleContent->appendChild($footnotesWrapper);
379 }
380 }
381
382 /**
383 * Reverts P elements with class 'readability-styled'
384 * to text nodes - which is what they were before.
385 *
386 * @param DOMElement
387 * @return void
388 */
389 function revertReadabilityStyledElements($articleContent) {
390 $xpath = new DOMXPath($articleContent->ownerDocument);
391 $elems = $xpath->query('.//p[@class="readability-styled"]', $articleContent);
392 //$elems = $articleContent->getElementsByTagName('p');
393 for ($i = $elems->length-1; $i >= 0; $i--) {
394 $e = $elems->item($i);
395 $e->parentNode->replaceChild($articleContent->ownerDocument->createTextNode($e->textContent), $e);
396 //if ($e->hasAttribute('class') && $e->getAttribute('class') == 'readability-styled') {
397 // $e->parentNode->replaceChild($this->dom->createTextNode($e->textContent), $e);
398 //}
399 }
400 }
401
402 /**
403 * Prepare the article node for display. Clean out any inline styles,
404 * iframes, forms, strip extraneous <p> tags, etc.
405 *
406 * @param DOMElement
407 * @return void
408 */
409 function prepArticle($articleContent) {
410 $this->cleanStyles($articleContent);
411 $this->killBreaks($articleContent);
412 if ($this->revertForcedParagraphElements) {
413 $this->revertReadabilityStyledElements($articleContent);
414 }
415
416 /* Clean out junk from the article content */
417 $this->cleanConditionally($articleContent, 'form');
418 $this->clean($articleContent, 'object');
419 $this->clean($articleContent, 'h1');
420
421 /**
422 * If there is only one h2, they are probably using it
423 * as a header and not a subheader, so remove it since we already have a header.
424 ***/
425 if ($articleContent->getElementsByTagName('h2')->length == 1) {
426 $this->clean($articleContent, 'h2');
427 }
428 $this->clean($articleContent, 'iframe');
429
430 $this->cleanHeaders($articleContent);
431
432 /* Do these last as the previous stuff may have removed junk that will affect these */
433 $this->cleanConditionally($articleContent, 'table');
434 $this->cleanConditionally($articleContent, 'ul');
435 $this->cleanConditionally($articleContent, 'div');
436
437 /* Remove extra paragraphs */
438 $articleParagraphs = $articleContent->getElementsByTagName('p');
439 for ($i = $articleParagraphs->length-1; $i >= 0; $i--)
440 {
441 $imgCount = $articleParagraphs->item($i)->getElementsByTagName('img')->length;
442 $embedCount = $articleParagraphs->item($i)->getElementsByTagName('embed')->length;
443 $objectCount = $articleParagraphs->item($i)->getElementsByTagName('object')->length;
444
445 if ($imgCount === 0 && $embedCount === 0 && $objectCount === 0 && $this->getInnerText($articleParagraphs->item($i), false) == '')
446 {
447 $articleParagraphs->item($i)->parentNode->removeChild($articleParagraphs->item($i));
448 }
449 }
450
451 try {
452 $articleContent->innerHTML = preg_replace('/<br[^>]*>\s*<p/i', '<p', $articleContent->innerHTML);
453 //articleContent.innerHTML = articleContent.innerHTML.replace(/<br[^>]*>\s*<p/gi, '<p');
454 }
455 catch (Exception $e) {
456 $this->dbg("Cleaning innerHTML of breaks failed. This is an IE strict-block-elements bug. Ignoring.: " . $e);
457 }
458 }
459
460 /**
461 * Initialize a node with the readability object. Also checks the
462 * className/id for special names to add to its score.
463 *
464 * @param Element
465 * @return void
466 **/
467 protected function initializeNode($node) {
468 $readability = $this->dom->createAttribute('readability');
469 $readability->value = 0; // this is our contentScore
470 $node->setAttributeNode($readability);
471
472 switch (strtoupper($node->tagName)) { // unsure if strtoupper is needed, but using it just in case
473 case 'DIV':
474 $readability->value += 5;
475 break;
476
477 case 'PRE':
478 case 'TD':
479 case 'BLOCKQUOTE':
480 $readability->value += 3;
481 break;
482
483 case 'ADDRESS':
484 case 'OL':
485 case 'UL':
486 case 'DL':
487 case 'DD':
488 case 'DT':
489 case 'LI':
490 case 'FORM':
491 $readability->value -= 3;
492 break;
493
494 case 'H1':
495 case 'H2':
496 case 'H3':
497 case 'H4':
498 case 'H5':
499 case 'H6':
500 case 'TH':
501 $readability->value -= 5;
502 break;
503 }
504 $readability->value += $this->getClassWeight($node);
505 }
506
507 /***
508 * grabArticle - Using a variety of metrics (content score, classname, element types), find the content that is
509 * most likely to be the stuff a user wants to read. Then return it wrapped up in a div.
510 *
511 * @return DOMElement
512 **/
513 protected function grabArticle($page=null) {
514 $stripUnlikelyCandidates = $this->flagIsActive(self::FLAG_STRIP_UNLIKELYS);
515 if (!$page) $page = $this->dom;
516 $allElements = $page->getElementsByTagName('*');
517 /**
518 * First, node prepping. Trash nodes that look cruddy (like ones with the class name "comment", etc), and turn divs
519 * into P tags where they have been used inappropriately (as in, where they contain no other block level elements.)
520 *
521 * Note: Assignment from index for performance. See http://www.peachpit.com/articles/article.aspx?p=31567&seqNum=5
522 * TODO: Shouldn't this be a reverse traversal?
523 **/
524 $node = null;
525 $nodesToScore = array();
526 for ($nodeIndex = 0; ($node = $allElements->item($nodeIndex)); $nodeIndex++) {
527 //for ($nodeIndex=$targetList->length-1; $nodeIndex >= 0; $nodeIndex--) {
528 //$node = $targetList->item($nodeIndex);
529 $tagName = strtoupper($node->tagName);
530 /* Remove unlikely candidates */
531 if ($stripUnlikelyCandidates) {
532 $unlikelyMatchString = $node->getAttribute('class') . $node->getAttribute('id');
533 if (
534 preg_match($this->regexps['unlikelyCandidates'], $unlikelyMatchString) &&
535 !preg_match($this->regexps['okMaybeItsACandidate'], $unlikelyMatchString) &&
536 $tagName != 'BODY'
537 )
538 {
539 $this->dbg('Removing unlikely candidate - ' . $unlikelyMatchString);
540 //$nodesToRemove[] = $node;
541 $node->parentNode->removeChild($node);
542 $nodeIndex--;
543 continue;
544 }
545 }
546
547 if ($tagName == 'P' || $tagName == 'TD' || $tagName == 'PRE') {
548 $nodesToScore[] = $node;
549 }
550
551 /* Turn all divs that don't have children block level elements into p's */
552 if ($tagName == 'DIV') {
553 if (!preg_match($this->regexps['divToPElements'], $node->innerHTML)) {
554 //$this->dbg('Altering div to p');
555 $newNode = $this->dom->createElement('p');
556 try {
557 $newNode->innerHTML = $node->innerHTML;
558 //$nodesToReplace[] = array('new'=>$newNode, 'old'=>$node);
559 $node->parentNode->replaceChild($newNode, $node);
560 $nodeIndex--;
561 $nodesToScore[] = $node; // or $newNode?
562 }
563 catch(Exception $e) {
564 $this->dbg('Could not alter div to p, reverting back to div.: ' . $e);
565 }
566 }
567 else
568 {
569 /* EXPERIMENTAL */
570 // TODO: change these p elements back to text nodes after processing
571 for ($i = 0, $il = $node->childNodes->length; $i < $il; $i++) {
572 $childNode = $node->childNodes->item($i);
573 if ($childNode->nodeType == 3) { // XML_TEXT_NODE
574 //$this->dbg('replacing text node with a p tag with the same content.');
575 $p = $this->dom->createElement('p');
576 $p->innerHTML = $childNode->nodeValue;
577 $p->setAttribute('style', 'display: inline;');
578 $p->setAttribute('class', 'readability-styled');
579 $childNode->parentNode->replaceChild($p, $childNode);
580 }
581 }
582 }
583 }
584 }
585
586 /**
587 * Loop through all paragraphs, and assign a score to them based on how content-y they look.
588 * Then add their score to their parent node.
589 *
590 * A score is determined by things like number of commas, class names, etc. Maybe eventually link density.
591 **/
592 $candidates = array();
593 for ($pt=0; $pt < count($nodesToScore); $pt++) {
594 $parentNode = $nodesToScore[$pt]->parentNode;
595 // $grandParentNode = $parentNode ? $parentNode->parentNode : null;
596 $grandParentNode = !$parentNode ? null : (($parentNode->parentNode instanceof DOMElement) ? $parentNode->parentNode : null);
597 $innerText = $this->getInnerText($nodesToScore[$pt]);
598
599 if (!$parentNode || !isset($parentNode->tagName)) {
600 continue;
601 }
602
603 /* If this paragraph is less than 25 characters, don't even count it. */
604 if(strlen($innerText) < 25) {
605 continue;
606 }
607
608 /* Initialize readability data for the parent. */
609 if (!$parentNode->hasAttribute('readability'))
610 {
611 $this->initializeNode($parentNode);
612 $candidates[] = $parentNode;
613 }
614
615 /* Initialize readability data for the grandparent. */
616 if ($grandParentNode && !$grandParentNode->hasAttribute('readability') && isset($grandParentNode->tagName))
617 {
618 $this->initializeNode($grandParentNode);
619 $candidates[] = $grandParentNode;
620 }
621
622 $contentScore = 0;
623
624 /* Add a point for the paragraph itself as a base. */
625 $contentScore++;
626
627 /* Add points for any commas within this paragraph */
628 $contentScore += count(explode(',', $innerText));
629
630 /* For every 100 characters in this paragraph, add another point. Up to 3 points. */
631 $contentScore += min(floor(strlen($innerText) / 100), 3);
632
633 /* Add the score to the parent. The grandparent gets half. */
634 $parentNode->getAttributeNode('readability')->value += $contentScore;
635
636 if ($grandParentNode) {
637 $grandParentNode->getAttributeNode('readability')->value += $contentScore/2;
638 }
639 }
640
641 /**
642 * After we've calculated scores, loop through all of the possible candidate nodes we found
643 * and find the one with the highest score.
644 **/
645 $topCandidate = null;
646 for ($c=0, $cl=count($candidates); $c < $cl; $c++)
647 {
648 /**
649 * Scale the final candidates score based on link density. Good content should have a
650 * relatively small link density (5% or less) and be mostly unaffected by this operation.
651 **/
652 $readability = $candidates[$c]->getAttributeNode('readability');
653 $readability->value = $readability->value * (1-$this->getLinkDensity($candidates[$c]));
654
655 $this->dbg('Candidate: ' . $candidates[$c]->tagName . ' (' . $candidates[$c]->getAttribute('class') . ':' . $candidates[$c]->getAttribute('id') . ') with score ' . $readability->value);
656
657 if (!$topCandidate || $readability->value > (int)$topCandidate->getAttribute('readability')) {
658 $topCandidate = $candidates[$c];
659 }
660 }
661
662 /**
663 * If we still have no top candidate, just use the body as a last resort.
664 * We also have to copy the body node so it is something we can modify.
665 **/
666 if ($topCandidate === null || strtoupper($topCandidate->tagName) == 'BODY')
667 {
668 $topCandidate = $this->dom->createElement('div');
669 $topCandidate->innerHTML = ($page instanceof DOMDocument) ? $page->saveXML($page->documentElement) : $page->innerHTML;
670 $page->innerHTML = '';
671 $page->appendChild($topCandidate);
672 $this->initializeNode($topCandidate);
673 }
674
675 /**
676 * Now that we have the top candidate, look through its siblings for content that might also be related.
677 * Things like preambles, content split by ads that we removed, etc.
678 **/
679 $articleContent = $this->dom->createElement('div');
680 $articleContent->setAttribute('id', 'readability-content');
681 $siblingScoreThreshold = max(10, ((int)$topCandidate->getAttribute('readability')) * 0.2);
682 $siblingNodes = $topCandidate->parentNode->childNodes;
683
684 for ($s=0, $sl=$siblingNodes->length; $s < $sl; $s++)
685 {
686 $siblingNode = $siblingNodes->item($s);
687 $append = false;
688
689 $this->dbg('Looking at sibling node: ' . $siblingNode->nodeName . (($siblingNode->nodeType === XML_ELEMENT_NODE && $siblingNode->hasAttribute('readability')) ? (' with score ' . $siblingNode->getAttribute('readability')) : ''));
690
691 //dbg('Sibling has score ' . ($siblingNode->readability ? siblingNode.readability.contentScore : 'Unknown'));
692
693 if ($siblingNode === $topCandidate)
694 // or if ($siblingNode->isSameNode($topCandidate))
695 {
696 $append = true;
697 }
698
699 $contentBonus = 0;
700 /* Give a bonus if sibling nodes and top candidates have the example same classname */
701 if ($siblingNode->nodeType === XML_ELEMENT_NODE && $siblingNode->getAttribute('class') == $topCandidate->getAttribute('class') && $topCandidate->getAttribute('class') != '') {
702 $contentBonus += ((int)$topCandidate->getAttribute('readability')) * 0.2;
703 }
704
705 if ($siblingNode->nodeType === XML_ELEMENT_NODE && $siblingNode->hasAttribute('readability') && (((int)$siblingNode->getAttribute('readability')) + $contentBonus) >= $siblingScoreThreshold)
706 {
707 $append = true;
708 }
709
710 if (strtoupper($siblingNode->nodeName) == 'P') {
711 $linkDensity = $this->getLinkDensity($siblingNode);
712 $nodeContent = $this->getInnerText($siblingNode);
713 $nodeLength = strlen($nodeContent);
714
715 if ($nodeLength > 80 && $linkDensity < 0.25)
716 {
717 $append = true;
718 }
719 else if ($nodeLength < 80 && $linkDensity === 0 && preg_match('/\.( |$)/', $nodeContent))
720 {
721 $append = true;
722 }
723 }
724
725 if ($append)
726 {
727 $this->dbg('Appending node: ' . $siblingNode->nodeName);
728
729 $nodeToAppend = null;
730 $sibNodeName = strtoupper($siblingNode->nodeName);
731 if ($sibNodeName != 'DIV' && $sibNodeName != 'P') {
732 /* We have a node that isn't a common block level element, like a form or td tag. Turn it into a div so it doesn't get filtered out later by accident. */
733
734 $this->dbg('Altering siblingNode of ' . $sibNodeName . ' to div.');
735 $nodeToAppend = $this->dom->createElement('div');
736 try {
737 $nodeToAppend->setAttribute('id', $siblingNode->getAttribute('id'));
738 $nodeToAppend->innerHTML = $siblingNode->innerHTML;
739 }
740 catch(Exception $e)
741 {
742 $this->dbg('Could not alter siblingNode to div, reverting back to original.');
743 $nodeToAppend = $siblingNode;
744 $s--;
745 $sl--;
746 }
747 } else {
748 $nodeToAppend = $siblingNode;
749 $s--;
750 $sl--;
751 }
752
753 /* To ensure a node does not interfere with readability styles, remove its classnames */
754 $nodeToAppend->removeAttribute('class');
755
756 /* Append sibling and subtract from our list because it removes the node when you append to another node */
757 $articleContent->appendChild($nodeToAppend);
758 }
759 }
760
761 /**
762 * So we have all of the content that we need. Now we clean it up for presentation.
763 **/
764 $this->prepArticle($articleContent);
765
766 /**
767 * Now that we've gone through the full algorithm, check to see if we got any meaningful content.
768 * If we didn't, we may need to re-run grabArticle with different flags set. This gives us a higher
769 * likelihood of finding the content, and the sieve approach gives us a higher likelihood of
770 * finding the -right- content.
771 **/
772 if (strlen($this->getInnerText($articleContent, false)) < 250)
773 {
774 $this->body->innerHTML = $this->bodyCache;
775
776 if ($this->flagIsActive(self::FLAG_STRIP_UNLIKELYS)) {
777 $this->removeFlag(self::FLAG_STRIP_UNLIKELYS);
778 return $this->grabArticle($this->body);
779 }
780 else if ($this->flagIsActive(self::FLAG_WEIGHT_CLASSES)) {
781 $this->removeFlag(self::FLAG_WEIGHT_CLASSES);
782 return $this->grabArticle($this->body);
783 }
784 else if ($this->flagIsActive(self::FLAG_CLEAN_CONDITIONALLY)) {
785 $this->removeFlag(self::FLAG_CLEAN_CONDITIONALLY);
786 return $this->grabArticle($this->body);
787 }
788 else {
789 return false;
790 }
791 }
792 return $articleContent;
793 }
794
795 /**
796 * Remove script tags from document
797 *
798 * @param DOMElement
799 * @return void
800 */
801 public function removeScripts($doc) {
802 $scripts = $doc->getElementsByTagName('script');
803 for($i = $scripts->length-1; $i >= 0; $i--)
804 {
805 $scripts->item($i)->parentNode->removeChild($scripts->item($i));
806 }
807 }
808
809 /**
810 * Get the inner text of a node.
811 * This also strips out any excess whitespace to be found.
812 *
813 * @param DOMElement $
814 * @param boolean $normalizeSpaces (default: true)
815 * @return string
816 **/
817 public function getInnerText($e, $normalizeSpaces=true) {
818 $textContent = '';
819
820 if (!isset($e->textContent) || $e->textContent == '') {
821 return '';
822 }
823
824 $textContent = trim($e->textContent);
825
826 if ($normalizeSpaces) {
827 return preg_replace($this->regexps['normalize'], ' ', $textContent);
828 } else {
829 return $textContent;
830 }
831 }
832
833 /**
834 * Get the number of times a string $s appears in the node $e.
835 *
836 * @param DOMElement $e
837 * @param string - what to count. Default is ","
838 * @return number (integer)
839 **/
840 public function getCharCount($e, $s=',') {
841 return substr_count($this->getInnerText($e), $s);
842 }
843
844 /**
845 * Remove the style attribute on every $e and under.
846 *
847 * @param DOMElement $e
848 * @return void
849 */
850 public function cleanStyles($e) {
851 $elems = $e->getElementsByTagName('*');
852 foreach ($elems as $elem) {
853 $elem->removeAttribute('style');
854 }
855 }
856
857 /**
858 * Get the density of links as a percentage of the content
859 * This is the amount of text that is inside a link divided by the total text in the node.
860 *
861 * @param DOMElement $e
862 * @return number (float)
863 */
864 public function getLinkDensity($e) {
865 $links = $e->getElementsByTagName('a');
866 $textLength = strlen($this->getInnerText($e));
867 $linkLength = 0;
868 for ($i=0, $il=$links->length; $i < $il; $i++)
869 {
870 $linkLength += strlen($this->getInnerText($links->item($i)));
871 }
872 if ($textLength > 0) {
873 return $linkLength / $textLength;
874 } else {
875 return 0;
876 }
877 }
878
879 /**
880 * Get an elements class/id weight. Uses regular expressions to tell if this
881 * element looks good or bad.
882 *
883 * @param DOMElement $e
884 * @return number (Integer)
885 */
886 public function getClassWeight($e) {
887 if(!$this->flagIsActive(self::FLAG_WEIGHT_CLASSES)) {
888 return 0;
889 }
890
891 $weight = 0;
892
893 /* Look for a special classname */
894 if ($e->hasAttribute('class') && $e->getAttribute('class') != '')
895 {
896 if (preg_match($this->regexps['negative'], $e->getAttribute('class'))) {
897 $weight -= 25;
898 }
899 if (preg_match($this->regexps['positive'], $e->getAttribute('class'))) {
900 $weight += 25;
901 }
902 }
903
904 /* Look for a special ID */
905 if ($e->hasAttribute('id') && $e->getAttribute('id') != '')
906 {
907 if (preg_match($this->regexps['negative'], $e->getAttribute('id'))) {
908 $weight -= 25;
909 }
910 if (preg_match($this->regexps['positive'], $e->getAttribute('id'))) {
911 $weight += 25;
912 }
913 }
914 return $weight;
915 }
916
917 /**
918 * Remove extraneous break tags from a node.
919 *
920 * @param DOMElement $node
921 * @return void
922 */
923 public function killBreaks($node) {
924 $html = $node->innerHTML;
925 $html = preg_replace($this->regexps['killBreaks'], '<br />', $html);
926 $node->innerHTML = $html;
927 }
928
929 /**
930 * Clean a node of all elements of type "tag".
931 * (Unless it's a youtube/vimeo video. People love movies.)
932 *
933 * @param DOMElement $e
934 * @param string $tag
935 * @return void
936 */
937 public function clean($e, $tag) {
938 $targetList = $e->getElementsByTagName($tag);
939 $isEmbed = ($tag == 'object' || $tag == 'embed');
940
941 for ($y=$targetList->length-1; $y >= 0; $y--) {
942 /* Allow youtube and vimeo videos through as people usually want to see those. */
943 if ($isEmbed) {
944 $attributeValues = '';
945 for ($i=0, $il=$targetList->item($y)->attributes->length; $i < $il; $i++) {
946 $attributeValues .= $targetList->item($y)->attributes->item($i)->value . '|'; // DOMAttr? (TODO: test)
947 }
948
949 /* First, check the elements attributes to see if any of them contain youtube or vimeo */
950 if (preg_match($this->regexps['video'], $attributeValues)) {
951 continue;
952 }
953
954 /* Then check the elements inside this element for the same. */
955 if (preg_match($this->regexps['video'], $targetList->item($y)->innerHTML)) {
956 continue;
957 }
958 }
959 $targetList->item($y)->parentNode->removeChild($targetList->item($y));
960 }
961 }
962
963 /**
964 * Clean an element of all tags of type "tag" if they look fishy.
965 * "Fishy" is an algorithm based on content length, classnames,
966 * link density, number of images & embeds, etc.
967 *
968 * @param DOMElement $e
969 * @param string $tag
970 * @return void
971 */
972 public function cleanConditionally($e, $tag) {
973 if (!$this->flagIsActive(self::FLAG_CLEAN_CONDITIONALLY)) {
974 return;
975 }
976
977 $tagsList = $e->getElementsByTagName($tag);
978 $curTagsLength = $tagsList->length;
979
980 /**
981 * Gather counts for other typical elements embedded within.
982 * Traverse backwards so we can remove nodes at the same time without effecting the traversal.
983 *
984 * TODO: Consider taking into account original contentScore here.
985 */
986 for ($i=$curTagsLength-1; $i >= 0; $i--) {
987 $weight = $this->getClassWeight($tagsList->item($i));
988 $contentScore = ($tagsList->item($i)->hasAttribute('readability')) ? (int)$tagsList->item($i)->getAttribute('readability') : 0;
989
990 $this->dbg('Cleaning Conditionally ' . $tagsList->item($i)->tagName . ' (' . $tagsList->item($i)->getAttribute('class') . ':' . $tagsList->item($i)->getAttribute('id') . ')' . (($tagsList->item($i)->hasAttribute('readability')) ? (' with score ' . $tagsList->item($i)->getAttribute('readability')) : ''));
991
992 if ($weight + $contentScore < 0) {
993 $tagsList->item($i)->parentNode->removeChild($tagsList->item($i));
994 }
995 else if ( $this->getCharCount($tagsList->item($i), ',') < 10) {
996 /**
997 * If there are not very many commas, and the number of
998 * non-paragraph elements is more than paragraphs or other ominous signs, remove the element.
999 **/
1000 $p = $tagsList->item($i)->getElementsByTagName('p')->length;
1001 $img = $tagsList->item($i)->getElementsByTagName('img')->length;
1002 $li = $tagsList->item($i)->getElementsByTagName('li')->length-100;
1003 $input = $tagsList->item($i)->getElementsByTagName('input')->length;
1004
1005 $embedCount = 0;
1006 $embeds = $tagsList->item($i)->getElementsByTagName('embed');
1007 for ($ei=0, $il=$embeds->length; $ei < $il; $ei++) {
1008 if (preg_match($this->regexps['video'], $embeds->item($ei)->getAttribute('src'))) {
1009 $embedCount++;
1010 }
1011 }
1012
1013 $linkDensity = $this->getLinkDensity($tagsList->item($i));
1014 $contentLength = strlen($this->getInnerText($tagsList->item($i)));
1015 $toRemove = false;
1016
1017 if ( $img > $p ) {
1018 $toRemove = true;
1019 } else if ($li > $p && $tag != 'ul' && $tag != 'ol') {
1020 $toRemove = true;
1021 } else if ( $input > floor($p/3) ) {
1022 $toRemove = true;
1023 } else if ($contentLength < 25 && ($img === 0 || $img > 2) ) {
1024 $toRemove = true;
1025 } else if($weight < 25 && $linkDensity > 0.2) {
1026 $toRemove = true;
1027 } else if($weight >= 25 && $linkDensity > 0.5) {
1028 $toRemove = true;
1029 } else if(($embedCount == 1 && $contentLength < 75) || $embedCount > 1) {
1030 $toRemove = true;
1031 }
1032
1033 if ($toRemove) {
1034 $tagsList->item($i)->parentNode->removeChild($tagsList->item($i));
1035 }
1036 }
1037 }
1038 }
1039
1040 /**
1041 * Clean out spurious headers from an Element. Checks things like classnames and link density.
1042 *
1043 * @param DOMElement $e
1044 * @return void
1045 */
1046 public function cleanHeaders($e) {
1047 for ($headerIndex = 1; $headerIndex < 3; $headerIndex++) {
1048 $headers = $e->getElementsByTagName('h' . $headerIndex);
1049 for ($i=$headers->length-1; $i >=0; $i--) {
1050 if ($this->getClassWeight($headers->item($i)) < 0 || $this->getLinkDensity($headers->item($i)) > 0.33) {
1051 $headers->item($i)->parentNode->removeChild($headers->item($i));
1052 }
1053 }
1054 }
1055 }
1056
1057 public function flagIsActive($flag) {
1058 return ($this->flags & $flag) > 0;
1059 }
1060
1061 public function addFlag($flag) {
1062 $this->flags = $this->flags | $flag;
1063 }
1064
1065 public function removeFlag($flag) {
1066 $this->flags = $this->flags & ~$flag;
1067 }
1068}
1069?> \ No newline at end of file
diff --git a/inc/3rdparty/libraries/readability/Readability.php b/inc/3rdparty/libraries/readability/Readability.php
index 4fa3ba63..a30012ce 100755
--- a/inc/3rdparty/libraries/readability/Readability.php
+++ b/inc/3rdparty/libraries/readability/Readability.php
@@ -46,6 +46,7 @@
46 46
47// This class allows us to do JavaScript like assignements to innerHTML 47// This class allows us to do JavaScript like assignements to innerHTML
48require_once(dirname(__FILE__).'/JSLikeHTMLElement.php'); 48require_once(dirname(__FILE__).'/JSLikeHTMLElement.php');
49libxml_use_internal_errors(true);
49 50
50// Alternative usage (for testing only!) 51// Alternative usage (for testing only!)
51// uncomment the lines below and call Readability.php in your browser 52// uncomment the lines below and call Readability.php in your browser
@@ -697,7 +698,7 @@ class Readability
697 $articleContent = $this->dom->createElement('div'); 698 $articleContent = $this->dom->createElement('div');
698 $articleContent->setAttribute('id', 'readability-content'); 699 $articleContent->setAttribute('id', 'readability-content');
699 $siblingScoreThreshold = max(10, ((int)$topCandidate->getAttribute('readability')) * 0.2); 700 $siblingScoreThreshold = max(10, ((int)$topCandidate->getAttribute('readability')) * 0.2);
700 $siblingNodes = $topCandidate->parentNode->childNodes; 701 $siblingNodes = @$topCandidate->parentNode->childNodes;
701 if (!isset($siblingNodes)) { 702 if (!isset($siblingNodes)) {
702 $siblingNodes = new stdClass; 703 $siblingNodes = new stdClass;
703 $siblingNodes->length = 0; 704 $siblingNodes->length = 0;
@@ -1148,4 +1149,4 @@ class Readability
1148 } 1149 }
1149 1150
1150} 1151}
1151?> \ No newline at end of file 1152?>
diff --git a/inc/3rdparty/libraries/tcpdf/tcpdf.php b/inc/3rdparty/libraries/tcpdf/tcpdf.php
index 78694a0e..70c1747a 100644
--- a/inc/3rdparty/libraries/tcpdf/tcpdf.php
+++ b/inc/3rdparty/libraries/tcpdf/tcpdf.php
@@ -2927,11 +2927,17 @@ class TCPDF {
2927 public function Error($msg) { 2927 public function Error($msg) {
2928 // unset all class variables 2928 // unset all class variables
2929 $this->_destroy(true); 2929 $this->_destroy(true);
2930 throw new Exception('TCPDF ERROR: '.$msg);
2931 /*
2932
2933 I had problems with the constants for some reason, so here we force
2934
2935 $this->_destroy(true);
2930 if (defined('K_TCPDF_THROW_EXCEPTION_ERROR') AND !K_TCPDF_THROW_EXCEPTION_ERROR) { 2936 if (defined('K_TCPDF_THROW_EXCEPTION_ERROR') AND !K_TCPDF_THROW_EXCEPTION_ERROR) {
2931 die('<strong>TCPDF ERROR: </strong>'.$msg); 2937 die('<strong>TCPDF ERROR: </strong>'.$msg);
2932 } else { 2938 } else {
2933 throw new Exception('TCPDF ERROR: '.$msg); 2939 throw new Exception('TCPDF ERROR: '.$msg);
2934 } 2940 }*/
2935 } 2941 }
2936 2942
2937 /** 2943 /**
@@ -6915,7 +6921,7 @@ class TCPDF {
6915 $ph = $this->getHTMLUnitToUnits($h, 0, $this->pdfunit, true) * $this->imgscale * $this->k; 6921 $ph = $this->getHTMLUnitToUnits($h, 0, $this->pdfunit, true) * $this->imgscale * $this->k;
6916 $imsize = array($pw, $ph); 6922 $imsize = array($pw, $ph);
6917 } else { 6923 } else {
6918 $this->Error('[Image] Unable to get the size of the image: '.$file); 6924 $this->Error('[Image] Unable to fetch image: '.$file);
6919 } 6925 }
6920 } 6926 }
6921 // file hash 6927 // file hash
diff --git a/inc/3rdparty/makefulltextfeed.php b/inc/3rdparty/makefulltextfeed.php
index a081f88b..27a62d73 100755
--- a/inc/3rdparty/makefulltextfeed.php
+++ b/inc/3rdparty/makefulltextfeed.php
@@ -31,6 +31,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
31//error_reporting(E_ALL ^ E_NOTICE); 31//error_reporting(E_ALL ^ E_NOTICE);
32ini_set("display_errors", 1); 32ini_set("display_errors", 1);
33@set_time_limit(120); 33@set_time_limit(120);
34libxml_use_internal_errors(true);
35
34 36
35// Deal with magic quotes 37// Deal with magic quotes
36if (get_magic_quotes_gpc()) { 38if (get_magic_quotes_gpc()) {
diff --git a/inc/poche/Poche.class.php b/inc/poche/Poche.class.php
index 3c7a2c5a..5b8e235f 100755
--- a/inc/poche/Poche.class.php
+++ b/inc/poche/Poche.class.php
@@ -180,6 +180,13 @@ class Poche
180 } 180 }
181 } 181 }
182 182
183 // if there are tags, add them to the new article
184 if (isset($_GET['tags'])) {
185 $_POST['value'] = $_GET['tags'];
186 $_POST['entry_id'] = $last_id;
187 $this->action('add_tag', $url);
188 }
189
183 $this->messages->add('s', _('the link has been added successfully')); 190 $this->messages->add('s', _('the link has been added successfully'));
184 } 191 }
185 else { 192 else {
@@ -192,20 +199,34 @@ class Poche
192 } else { 199 } else {
193 Tools::redirect('?view=home&closewin=true'); 200 Tools::redirect('?view=home&closewin=true');
194 } 201 }
202 return $last_id;
195 break; 203 break;
196 case 'delete': 204 case 'delete':
197 $msg = 'delete link #' . $id; 205 if (isset($_GET['search'])) {
198 if ($this->store->deleteById($id, $this->user->getId())) { 206 //when we want to apply a delete to a search
199 if (DOWNLOAD_PICTURES) { 207 $tags = array($_GET['search']);
200 Picture::removeDirectory(ABS_PATH . $id); 208 $allentry_ids = $this->store->search($tags[0], $this->user->getId());
209 $entry_ids = array();
210 foreach ($allentry_ids as $eachentry) {
211 $entry_ids[] = $eachentry[0];
201 } 212 }
202 $this->messages->add('s', _('the link has been deleted successfully')); 213 } else { // delete a single article
214 $entry_ids = array($id);
203 } 215 }
204 else { 216 foreach($entry_ids as $id) {
205 $this->messages->add('e', _('the link wasn\'t deleted')); 217 $msg = 'delete link #' . $id;
206 $msg = 'error : can\'t delete link #' . $id; 218 if ($this->store->deleteById($id, $this->user->getId())) {
219 if (DOWNLOAD_PICTURES) {
220 Picture::removeDirectory(ABS_PATH . $id);
221 }
222 $this->messages->add('s', _('the link has been deleted successfully'));
223 }
224 else {
225 $this->messages->add('e', _('the link wasn\'t deleted'));
226 $msg = 'error : can\'t delete link #' . $id;
227 }
228 Tools::logm($msg);
207 } 229 }
208 Tools::logm($msg);
209 Tools::redirect('?'); 230 Tools::redirect('?');
210 break; 231 break;
211 case 'toggle_fav' : 232 case 'toggle_fav' :
@@ -220,8 +241,21 @@ class Poche
220 } 241 }
221 break; 242 break;
222 case 'toggle_archive' : 243 case 'toggle_archive' :
223 $this->store->archiveById($id, $this->user->getId()); 244 if (isset($_GET['tag_id'])) {
224 Tools::logm('archive link #' . $id); 245 //when we want to archive a whole tag
246 $tag_id = $_GET['tag_id'];
247 $allentry_ids = $this->store->retrieveEntriesByTag($tag_id, $this->user->getId());
248 $entry_ids = array();
249 foreach ($allentry_ids as $eachentry) {
250 $entry_ids[] = $eachentry[0];
251 }
252 } else { //archive a single article
253 $entry_ids = array($id);
254 }
255 foreach($entry_ids as $id) {
256 $this->store->archiveById($id, $this->user->getId());
257 Tools::logm('archive link #' . $id);
258 }
225 if ( Tools::isAjaxRequest() ) { 259 if ( Tools::isAjaxRequest() ) {
226 echo 1; 260 echo 1;
227 exit; 261 exit;
@@ -413,9 +447,12 @@ class Poche
413 } 447 }
414 448
415 # flattr checking 449 # flattr checking
416 $flattr = new FlattrItem(); 450 $flattr = NULL;
417 $flattr->checkItem($entry['url'], $entry['id']); 451 if (FLATTR) {
418 452 $flattr = new FlattrItem();
453 $flattr->checkItem($entry['url'], $entry['id']);
454 }
455
419 # tags 456 # tags
420 $tags = $this->store->retrieveTagsByEntry($entry['id']); 457 $tags = $this->store->retrieveTagsByEntry($entry['id']);
421 458
@@ -548,6 +585,8 @@ class Poche
548 Tools::redirect($referer); 585 Tools::redirect($referer);
549 } 586 }
550 $this->messages->add('e', _('login failed: bad login or password')); 587 $this->messages->add('e', _('login failed: bad login or password'));
588 // log login failure in web server log to allow fail2ban usage
589 error_log('user '.$login.' authentication failure');
551 Tools::logm('login failed'); 590 Tools::logm('login failed');
552 Tools::redirect(); 591 Tools::redirect();
553 } 592 }
@@ -633,7 +672,18 @@ class Poche
633 $urlsInserted[] = $url; //add 672 $urlsInserted[] = $url; //add
634 if (isset($record['tags']) && trim($record['tags'])) { 673 if (isset($record['tags']) && trim($record['tags'])) {
635 674
636 // @TODO: set tags 675 $tags = explode(',', $record['tags']);
676 foreach($tags as $tag) {
677 $entry_id = $id;
678 $tag_id = $this->store->retrieveTagByValue($tag);
679 if ($tag_id) {
680 $this->store->setTagToEntry($tag_id['id'], $entry_id);
681 } else {
682 $this->store->createTag($tag);
683 $tag_id = $this->store->retrieveTagByValue($tag);
684 $this->store->setTagToEntry($tag_id['id'], $entry_id);
685 }
686 }
637 687
638 } 688 }
639 } 689 }
@@ -756,10 +806,11 @@ class Poche
756 * 806 *
757 * @param $token 807 * @param $token
758 * @param $user_id 808 * @param $user_id
759 * @param $tag_id 809 * @param $tag_id if $type is 'tag', the id of the tag to generate feed for
760 * @param string $type 810 * @param string $type the type of feed to generate
811 * @param int $limit the maximum number of items (0 means all)
761 */ 812 */
762 public function generateFeeds($token, $user_id, $tag_id, $type = 'home') 813 public function generateFeeds($token, $user_id, $tag_id, $type = 'home', $limit = 0)
763 { 814 {
764 $allowed_types = array('home', 'fav', 'archive', 'tag'); 815 $allowed_types = array('home', 'fav', 'archive', 'tag');
765 $config = $this->store->getConfigUser($user_id); 816 $config = $this->store->getConfigUser($user_id);
@@ -786,8 +837,13 @@ class Poche
786 $entries = $this->store->getEntriesByView($type, $user_id); 837 $entries = $this->store->getEntriesByView($type, $user_id);
787 } 838 }
788 839
840 // if $limit is set to zero, use all entries
841 if (0 == $limit) {
842 $limit = count($entries);
843 }
789 if (count($entries) > 0) { 844 if (count($entries) > 0) {
790 foreach ($entries as $entry) { 845 for ($i = 0; $i < min(count($entries), $limit); $i++) {
846 $entry = $entries[$i];
791 $newItem = $feed->createNewItem(); 847 $newItem = $feed->createNewItem();
792 $newItem->setTitle($entry['title']); 848 $newItem->setTitle($entry['title']);
793 $newItem->setSource(Tools::getPocheUrl() . '?view=view&amp;id=' . $entry['id']); 849 $newItem->setSource(Tools::getPocheUrl() . '?view=view&amp;id=' . $entry['id']);
diff --git a/inc/poche/Routing.class.php b/inc/poche/Routing.class.php
index 5acd08ba..a8d00b89 100755
--- a/inc/poche/Routing.class.php
+++ b/inc/poche/Routing.class.php
@@ -102,7 +102,8 @@ class Routing
102 $this->wallabag->login($this->referer); 102 $this->wallabag->login($this->referer);
103 } elseif (isset($_GET['feed']) && isset($_GET['user_id'])) { 103 } elseif (isset($_GET['feed']) && isset($_GET['user_id'])) {
104 $tag_id = (isset($_GET['tag_id']) ? intval($_GET['tag_id']) : 0); 104 $tag_id = (isset($_GET['tag_id']) ? intval($_GET['tag_id']) : 0);
105 $this->wallabag->generateFeeds($_GET['token'], filter_var($_GET['user_id'],FILTER_SANITIZE_NUMBER_INT), $tag_id, $_GET['type']); 105 $limit = (isset($_GET['limit']) ? intval($_GET['limit']) : 0);
106 $this->wallabag->generateFeeds($_GET['token'], filter_var($_GET['user_id'],FILTER_SANITIZE_NUMBER_INT), $tag_id, $_GET['type'], $limit);
106 } 107 }
107 108
108 //allowed ONLY to logged in user 109 //allowed ONLY to logged in user
@@ -115,7 +116,7 @@ class Routing
115 // update password 116 // update password
116 $this->wallabag->updatePassword($_POST['password'], $_POST['password_repeat']); 117 $this->wallabag->updatePassword($_POST['password'], $_POST['password_repeat']);
117 } elseif (isset($_GET['newuser'])) { 118 } elseif (isset($_GET['newuser'])) {
118 $this->wallabag->createNewUser($_POST['newusername'], $_POST['password4newuser']); 119 $this->wallabag->createNewUser($_POST['newusername'], $_POST['password4newuser'], $_POST['newuseremail']);
119 } elseif (isset($_GET['deluser'])) { 120 } elseif (isset($_GET['deluser'])) {
120 $this->wallabag->deleteUser($_POST['password4deletinguser']); 121 $this->wallabag->deleteUser($_POST['password4deletinguser']);
121 } elseif (isset($_GET['epub'])) { 122 } elseif (isset($_GET['epub'])) {
diff --git a/inc/poche/Tools.class.php b/inc/poche/Tools.class.php
index f803e3b5..7ccfc069 100755
--- a/inc/poche/Tools.class.php
+++ b/inc/poche/Tools.class.php
@@ -342,7 +342,10 @@ final class Tools
342 return $json; 342 return $json;
343 }; 343 };
344 344
345 $json = $scope("inc/3rdparty/makefulltextfeed.php", array("url" => $url)); 345 // Silence $scope function to avoid
346 // issues with FTRSS when error_reporting is to high
347 // FTRSS generates PHP warnings which break output
348 $json = @$scope("inc/3rdparty/makefulltextfeed.php", array("url" => $url));
346 349
347 // Clearing and restoring context 350 // Clearing and restoring context
348 foreach ($GLOBALS as $key => $value) { 351 foreach ($GLOBALS as $key => $value) {
diff --git a/inc/poche/WallabagEBooks.class.php b/inc/poche/WallabagEBooks.class.php
index bc40990b..55831571 100644
--- a/inc/poche/WallabagEBooks.class.php
+++ b/inc/poche/WallabagEBooks.class.php
@@ -33,7 +33,7 @@ class WallabagEBooks
33 $entry = $this->wallabag->store->retrieveOneById($entryID, $this->wallabag->user->getId()); 33 $entry = $this->wallabag->store->retrieveOneById($entryID, $this->wallabag->user->getId());
34 $this->entries = array($entry); 34 $this->entries = array($entry);
35 $this->bookTitle = $entry['title']; 35 $this->bookTitle = $entry['title'];
36 $this->bookFileName = substr($this->bookTitle, 0, 200); 36 $this->bookFileName = str_replace('/', '_', substr($this->bookTitle, 0, 200));
37 $this->author = preg_replace('#^w{3}.#', '', Tools::getdomain($entry["url"])); # if only one article, set author to domain name (we strip the eventual www part) 37 $this->author = preg_replace('#^w{3}.#', '', Tools::getdomain($entry["url"])); # if only one article, set author to domain name (we strip the eventual www part)
38 Tools::logm('Producing ebook from article ' . $this->bookTitle); 38 Tools::logm('Producing ebook from article ' . $this->bookTitle);
39 break; 39 break;
@@ -81,6 +81,9 @@ class WallabagEpub extends WallabagEBooks
81 public function produceEpub() 81 public function produceEpub()
82 { 82 {
83 Tools::logm('Starting to produce ePub 3 file'); 83 Tools::logm('Starting to produce ePub 3 file');
84
85 try {
86
84 $content_start = 87 $content_start =
85 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 88 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
86 . "<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n" 89 . "<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n"
@@ -155,6 +158,11 @@ class WallabagEpub extends WallabagEBooks
155 $book->finalize(); 158 $book->finalize();
156 $zipData = $book->sendBook($this->bookFileName); 159 $zipData = $book->sendBook($this->bookFileName);
157 Tools::logm('Ebook produced'); 160 Tools::logm('Ebook produced');
161 }
162 catch (Exception $e) {
163 Tools::logm('PHPePub has encountered an error : '.$e->getMessage());
164 $this->wallabag->messages->add('e', $e->getMessage());
165 }
158 } 166 }
159} 167}
160 168
@@ -167,7 +175,7 @@ class WallabagMobi extends WallabagEBooks
167 175
168 public function produceMobi() 176 public function produceMobi()
169 { 177 {
170 178 try {
171 Tools::logm('Starting to produce Mobi file'); 179 Tools::logm('Starting to produce Mobi file');
172 $mobi = new MOBI(); 180 $mobi = new MOBI();
173 $content = new MOBIFile(); 181 $content = new MOBIFile();
@@ -194,9 +202,17 @@ class WallabagMobi extends WallabagEBooks
194 } 202 }
195 $mobi->setContentProvider($content); 203 $mobi->setContentProvider($content);
196 204
205 // the browser inside Kindle Devices doesn't likes special caracters either, we limit to A-z/0-9
206 $this->bookFileName = preg_replace('/[^A-Za-z0-9\-]/', '', $this->bookFileName);
207
197 // we offer file to download 208 // we offer file to download
198 $mobi->download($this->bookFileName.'.mobi'); 209 $mobi->download($this->bookFileName.'.mobi');
199 Tools::logm('Mobi file produced'); 210 Tools::logm('Mobi file produced');
211 }
212 catch (Exception $e) {
213 Tools::logm('PHPMobi has encountered an error : '.$e->getMessage());
214 $this->wallabag->messages->add('e', $e->getMessage());
215 }
200 } 216 }
201} 217}
202 218
@@ -206,15 +222,16 @@ class WallabagPDF extends WallabagEbooks
206 { 222 {
207 223
208 Tools::logm('Starting to produce PDF file'); 224 Tools::logm('Starting to produce PDF file');
209 225 @define ('K_TCPDF_THROW_EXCEPTION_ERROR', TRUE);
226 try {
210 $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); 227 $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
211 228
212 Tools::logm('Filling metadata for PDF...'); 229 Tools::logm('Filling metadata for PDF...');
213 $pdf->SetCreator(PDF_CREATOR); 230 $pdf->SetCreator(PDF_CREATOR);
214 $pdf->SetAuthor(''); 231 $pdf->SetAuthor('wallabag');
215 $pdf->SetTitle($this->bookTitle); 232 $pdf->SetTitle($this->bookTitle);
216 $pdf->SetSubject('TCPDF Tutorial'); 233 $pdf->SetSubject('Articles via wallabag');
217 $pdf->SetKeywords('TCPDF, PDF, example, test, guide'); 234 $pdf->SetKeywords('wallabag');
218 235
219 Tools::logm('Adding introduction...'); 236 Tools::logm('Adding introduction...');
220 $pdf->AddPage(); 237 $pdf->AddPage();
@@ -229,18 +246,26 @@ class WallabagPDF extends WallabagEbooks
229 $i = 1; 246 $i = 1;
230 Tools::logm('Adding actual content...'); 247 Tools::logm('Adding actual content...');
231 foreach ($this->entries as $item) { 248 foreach ($this->entries as $item) {
249 $tags = $this->wallabag->store->retrieveTagsByEntry($entry['id']);
250 foreach ($tags as $tag) {
251 $pdf->SetKeywords($tag['value']);
252 }
232 $pdf->AddPage(); 253 $pdf->AddPage();
233 $html = '<h1>' . $item['title'] . '</h1>'; 254 $html = '<h1>' . $item['title'] . '</h1>';
234 $html .= $item['content']; 255 $html .= $item['content'];
235 $pdf->writeHTMLCell(0, 0, '', '', $html, 0, 1, 0, true, '', true); 256 $pdf->writeHTMLCell(0, 0, '', '', $html, 0, 1, 0, true, '', true);
236 $i = $i+1;
237 } 257 }
238 258
239 // set image scale factor 259 // set image scale factor
240 $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); 260 $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
241 261
242 262
243 $pdf->Output($this->bookFileName . '.pdf', 'FD'); 263 $pdf->Output($this->bookFileName . '.pdf', 'FD');
264 }
265 catch (Exception $e) {
266 Tools::logm('TCPDF has encountered an error : '.$e->getMessage());
267 $this->wallabag->messages->add('e', $e->getMessage());
268 }
244 269
245 } 270 }
246} 271}
diff --git a/install/index.php b/install/index.php
index ec504160..892af241 100755
--- a/install/index.php
+++ b/install/index.php
@@ -11,18 +11,7 @@
11$errors = array(); 11$errors = array();
12$successes = array(); 12$successes = array();
13 13
14/* Function taken from at http://php.net/manual/en/function.rmdir.php#110489 14require_once('wallabag_compatibility_test.php');
15 * Idea : nbari at dalmp dot com
16 * Rights unknown
17 * Here in case of .gitignore files
18 */
19function delTree($dir) {
20 $files = array_diff(scandir($dir), array('.','..'));
21 foreach ($files as $file) {
22 (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
23 }
24 return rmdir($dir);
25 }
26 15
27if (isset($_GET['clean'])) { 16if (isset($_GET['clean'])) {
28 if (is_dir('install')){ 17 if (is_dir('install')){
@@ -58,136 +47,109 @@ if (isset($_POST['download'])) {
58else if (isset($_POST['install'])) { 47else if (isset($_POST['install'])) {
59 if (!is_dir('vendor')) { 48 if (!is_dir('vendor')) {
60 $errors[] = 'You must install twig before.'; 49 $errors[] = 'You must install twig before.';
61 } 50 } else {
62 else {
63 $continue = true; 51 $continue = true;
64 // Create config.inc.php 52 $salt = generate_salt();
65 if (!copy('inc/poche/config.inc.default.php', 'inc/poche/config.inc.php')) { 53 $content = file_get_contents('inc/poche/config.inc.default.php');
66 $errors[] = 'Installation aborted, impossible to create inc/poche/config.inc.php file. Maybe you don\'t have write access to create it.';
67 $continue = false;
68 }
69 else {
70 function generate_salt() {
71 mt_srand(microtime(true)*100000 + memory_get_usage(true));
72 return md5(uniqid(mt_rand(), true));
73 }
74 54
75 $content = file_get_contents('inc/poche/config.inc.php'); 55 // User informations
76 $salt = generate_salt(); 56 $username = trim($_POST['username']);
77 $content = str_replace("define ('SALT', '');", "define ('SALT', '".$salt."');", $content); 57 $password = trim($_POST['password']);
78 file_put_contents('inc/poche/config.inc.php', $content); 58 $salted_password = sha1($password . $username . $salt);
79 }
80 59
81 if ($continue) { 60 // Database informations
82 61 $moreQueries = array();
83 // User informations 62
84 $username = trim($_POST['username']); 63 if ($_POST['db_engine'] == 'sqlite') {
85 $password = trim($_POST['password']); 64 if (!copy('install/poche.sqlite', 'db/poche.sqlite')) {
86 $salted_password = sha1($password . $username . $salt); 65 $errors[] = 'Impossible to create the SQLite database file.';
87
88 // Database informations
89 $moreQueries = array();
90 if ($_POST['db_engine'] == 'sqlite') {
91 if (!copy('install/poche.sqlite', 'db/poche.sqlite')) {
92 $errors[] = 'Impossible to create inc/poche/config.inc.php file.';
93 $continue = false;
94 }
95 else {
96 $db_path = 'sqlite:' . realpath('') . '/db/poche.sqlite';
97 $handle = new PDO($db_path);
98 $sql_structure = "";
99 }
100 } 66 }
101 else { 67 else {
102 $content = file_get_contents('inc/poche/config.inc.php'); 68 $db_path = 'sqlite:' . realpath('') . '/db/poche.sqlite';
103 69 $handle = new PDO($db_path);
104 if ($_POST['db_engine'] == 'mysql') { 70 $handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
105 $db_path = 'mysql:host=' . $_POST['mysql_server'] . ';dbname=' . $_POST['mysql_database'] . ';charset=utf8mb4'; 71 $sql_structure = "";
106 $content = str_replace("define ('STORAGE_SERVER', 'localhost');", "define ('STORAGE_SERVER', '".$_POST['mysql_server']."');", $content); 72 }
107 $content = str_replace("define ('STORAGE_DB', 'poche');", "define ('STORAGE_DB', '".$_POST['mysql_database']."');", $content); 73 } else {
108 $content = str_replace("define ('STORAGE_USER', 'poche');", "define ('STORAGE_USER', '".$_POST['mysql_user']."');", $content); 74 // MySQL and Postgre
109 $content = str_replace("define ('STORAGE_PASSWORD', 'poche');", "define ('STORAGE_PASSWORD', '".$_POST['mysql_password']."');", $content); 75 try {
110 $handle = new PDO($db_path, $_POST['mysql_user'], $_POST['mysql_password'], array( 76
111 PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4', 77 if ($_POST['db_engine'] == 'mysql') {
112 )); 78 $db_path = 'mysql:host=' . $_POST['mysql_server'] . ';dbname=' . $_POST['mysql_database'] . ';charset=utf8mb4';
113 79 $content = str_replace("define ('STORAGE_SERVER', 'localhost');", "define ('STORAGE_SERVER', '".$_POST['mysql_server']."');", $content);
114 $moreQueries[] = "INSERT INTO `entries` (`id`, `title`, `url`, `is_read`, `is_fav`, `content`, `user_id`) VALUES 80 $content = str_replace("define ('STORAGE_DB', 'poche');", "define ('STORAGE_DB', '".$_POST['mysql_database']."');", $content);
81 $content = str_replace("define ('STORAGE_USER', 'poche');", "define ('STORAGE_USER', '".$_POST['mysql_user']."');", $content);
82 $content = str_replace("define ('STORAGE_PASSWORD', 'poche');", "define ('STORAGE_PASSWORD', '".$_POST['mysql_password']."');", $content);
83 $handle = new PDO($db_path, $_POST['mysql_user'], $_POST['mysql_password'], array(
84 PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4',
85 ));
86
87 $moreQueries[] = "INSERT INTO `entries` (`id`, `title`, `url`, `is_read`, `is_fav`, `content`, `user_id`) VALUES
115(1, 'Framabag, un nouveau service libre et gratuit', 'http://www.framablog.org/index.php/post/2014/02/05/Framabag-service-libre-gratuit-interview-developpeur', 0, 0, 0x0a3c68323e556e6520696e74657276696577206465204e69636f6c61732c20736f6e2064c3a976656c6f70706575722e3c2f68323e0a3c703e3c656d3e496c206e6520766f757320612073c3bb72656d656e742070617320c3a96368617070c3a920717565206e6f74726520636f6e736f6d6d6174696f6e20646520636f6e74656e75732064752057656220657374207465727269626c656d656e74206368726f6e6f706861676520657420706172746963756c69c3a872656d656e7420667275737472616e746520746f757420c3a0206c6120666f6973c2a03a206e6f6e207365756c656d656e74206e6f757320706173736f6e732062656175636f7570202874726f70c2a03f292064652074656d707320656e206c69676e6520c3a0206578706c6f726572206c6573206d696e6573206175726966c3a8726573206465206c6120746f696c652c20792064c3a974656374616e742070c3a970697465732065742066696c6f6e732c206d616973206e6f757320736f6d6d657320737572746f757420636f6e7374616d6d656e7420656e206d616e7175652e204dc3aa6d65207369206e6f7573206e6520736f6d6d6573207061732064616e73206c65207a617070696e67206672c3a96ec3a9746971756520736920666163696c656d656e742064c3a96e6f6e63c3a920706172206c657320646f637465732070737963686f6c6f677565732071756920706f6e74696669656e7420737572206c65732064616e67657273206475206e756dc3a9726971756520706f7572206c6573206a65756e65732063657276656c6c65732c20696c206e6f7573207669656e7420736f7576656e74206c6520676fc3bb7420616d6572206465206ce28099696e6163686576c3a9c2a03a20706173206c652074656d707320646520746f7574206c69726520283c6120687265663d22687474703a2f2f66722e77696b74696f6e6172792e6f72672f77696b692f544c4452223e544c3b44523c2f613e2065737420646576656e75206c6520636c696e2064e28099c593696c206d692d6669677565206d692d72616973696e2064e28099756e652067c3a96ec3a9726174696f6e206465206c65637465757273207072657373c3a973292c207061732074726f70206c652074656d70732064652072c3a9666cc3a963686972206e6f6e20706c75732068c3a96c61732c20706173206c652074656d707320646520737569767265206c6120726962616d62656c6c65206465206c69656e73206173736f6369c3a97320c3a020756e2061727469636c65e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e506f7572206e6f757320646f6e6e657220626f6e6e6520636f6e736369656e63652c206e6f75732072616e67656f6e73207363727570756c657573656d656e7420756e206d61727175652d7061676520646520706c75732064616e7320756e20736f75732d646f73736965722071756920656e20636f6d706f7274652064c3a96ac3a0203235362c206e6f7573206e6f746f6e7320756e20c3a96cc3a96d656e7420646520706c75732064616e73206c6120746f756a6f757273207269646963756c656d656e74206c6f6e67756520746f75646f756c697374652c2062726566206e6f75732072656d6574746f6e7320c3a020706c757320746172642c2063e280996573742dc3a02d64697265206c6520706c757320736f7576656e742061757820696e74726f757661626c65732063616c656e6465732067726563717565732c206c6520736f696e206465206c69726520767261696d656e7420756e2061727469636c65206a7567c3a920696e74c3a972657373616e742c20646520726567617264657220756e6520766964c3a96f207369676e616cc3a96520706172206c65732072c3a97a6f73736f63696f732c206465206c69726520756e20636861706974726520656e746965722064e28099756e206f75767261676520646973706f6e69626c6520656e206c69676e65e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e416c6f7273206269656e2073c3bb722c20c3a02064c3a966617574206465206e6f757320646f6e6e657220746f7574206c652074656d70732071756920736572616974206ec3a963657373616972652c2064657320736f6c7574696f6e73206578697374656e7420706f7572206e6f7573207065726d657474726520646520c2abc2a06c69726520706c75732074617264c2a0c2bb20656e20736175766567617264616e74206c65207072c3a9636965757820706f6c6c656e206465206e6f7320627574696e61676573206465207369746520656e20736974652c2065742064e28099656e20666169726520756c74c3a97269657572656d656e7420766f747265206d69656cc2a03b2063e280996573742062656c20657420626f6e206d616973206c65732072756368657320736f6e7420756e207065752064697374616e7465732c20c3a7612073e28099617070656c6c65206c6520636c6f756420286e6f7320616d69732074656368696573206de280996f6e74206269656e206578706c697175c3a9206d616973206ae280996169207365756c656d656e7420636f6d70726973207175652064657320747275637320c3a0206d6f6920736f6e742073757220646573206d616368696e6573206c6f696e7461696e65732c20c3a761206e65206d652072617373757265207061732074726f702920657420656c6c657320736f6e7420736f7576656e742070726f707269c3a97461697265732c206e65206c61697373616e7420656e7472657220717565206c6573203c733e7574696c69736174657572733c2f733e20636f6e736f6d6d61746575727320706179616e74732065742071756920636f6e73656e74656e7420c3a0206c6575727320636f6e646974696f6e732e2053616e7320636f6d70746572207175652064652067726f7320626f7572646f6e73207669656e6e656e742070726f666974657220706c7573206f75206d6f696e73206469736372c3a874656d656e7420646520746f757465732063657320747261636573206465206e6f75732d6dc3aa6d657320717569207065726d657474656e74206465206d6f6ec3a97469736572206e6f7472652070726f66696cc2a03a207369206a6520636f6c6c65637465207375722063657320736572766963657320286e65206c6573206e6f6d6d6f6e73207061732c206a757374656d656e742920756e652073c3a97269652064e2809961727469636c657320737572206ce280996964c3a965206465204e6174757265206368657a2044696465726f742c206a6520726563657672616920646976657273657320736f6c6c696369746174696f6e7320706f757220646576656e697220636c69656e74206465206c6120626f757469717565204e61747572652026616d703b2044c3a9636f75766572746520647520626f756c65766172642044696465726f742e2045742073692064e280996176656e74757265206c65732070726f6772616d6d6573206465206c61204e5341206d6f756c696e656e7420737572206c6520736572766963652c206a6520736572616920706575742dc3aa74726520756e206a6f75722064616e7320756e65206c6973746520646573206d696c6974616e7473206e61747572697374657320696e64c3a973697261626c657320737572206c657320766f6c73206465206c612050616e416d20286a65206e65207361697320706c75732074726f70207369206a6520706c616973616e7465206cc3a02c2066696e616c656d656e74e280a6293c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4c6120626f6e6e65206964c3a965c2a03a20c2abc2a0736520636f6e7374697475657220756e2072c3a9736572766f697220646520646f63756d656e74732073c3a96c656374696f6e6ec3a97320c3a020706172636f7572697220706c75732074617264c2a0c2bb20617070656c61697420646f6e6320756e6520617574726520626f6e6e65206964c3a9652c2063656c6c652064e2809961766f6972206c6520636f6e7472c3b46c652064652063652072c3a9736572766f69722c206465206e6f74726520636f6c6c656374696f6e20706572736f6e6e656c6c652e2043e28099657374204e69636f6c6173204cc59375696c6c65742c2063692d646573736f757320696e74657276696577c3a92c207175692073e28099792065737420636f6c6cc3a9206176656320756e652062656c6c65206170706c69636174696f6e20617070656cc3a96520657568e280a6206f75692c20617070656cc3a9652057616c6c616261672e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4672616d61736f667420736f757469656e742064e28099617574616e7420706c757320736f6e20696e6974696174697665207175e280993c6120687265663d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f696e6465782e7068702f706f73742f323031342f30312f33312f4765656b74696f6e6e6572642d57616c6c61626167223e6f6e206c7569206120636865726368c3a920646573206d6973c3a872657320706f757220756e6520686973746f697265206465206e6f6d3c2f613e206574207175e28099696c2065737420706f737369626c652064e28099696e7374616c6c657220736f692d6dc3aa6d6520756e6520636f7069652064652057616c6c616261672073757220736f6e2070726f70726520736974652e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4c6520706574697420706c7573206465204672616d61736f66742c2072c3a97365617520746f756a6f7572732064c3a973697265757820646520766f75732070726f706f7365722064657320616c7465726e617469766573206c6962c3a972617472696365732c2063e2809965737420646520766f75732070726f706f736572202873757220696e736372697074696f6e207072c3a9616c61626c652920756e20616363c3a873206175204672616d616261672c2061757472656d656e742064697420766f7472652057616c6c616261672073757220756e2073657276657572204672616d612a2061766563206e6f74726520676172616e74696520646520636f6e666964656e7469616c6974c3a92e20436f6d6d6520706f7572206c65204672616d616e6577732c206e6f757320766f7573206163637565696c6c6f6e7320766f6c6f6e74696572732064616e73206c61206c696d697465206465206e6f732063617061636974c3a9732c20656e20766f757320696e766974616e7420c3a020766f7573206c616e6365722064616e7320766f747265206175746f2d68c3a962657267656d656e742064652057616c6c616261672e3c6272202f3e4365742061727469636c65206573742074726f70206c6f6e67c2a03f204d657474657a2d6c652064616e73203c6120687265663d22687474703a2f2f7777772e6672616d616261672e6f72672f696e6465782e706870223e766f747265204672616d616261673c2f613e20657420686f702e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4672616d61626c6f67c2a03a2053616c7574204e69636f6c6173e280a62054752070657578207465207072c3a973656e74657220627269c3a876656d656e74c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e53616c7574c2a0212044c3a976656c6f70706575722050485020646570756973207175656c7175657320616e6ec3a96573206d61696e74656e616e742028313020616e73292c206ae28099616920766f756c75206d652072656d657474726520c3a0206e697665617520746563686e697175656d656e74207061726c616e742028646570756973203320616e732c206ae28099616920706173206d616c206cc3a26368c3a9206c6520636c6176696572292e20506f7572206d6573206265736f696e7320706572736f732c206ae28099616920646f6e63206372c3a9c3a920756e2070657469742070726f6a657420706f75722072656d706c6163657220756e6520736f6c7574696f6e2070726f707269c3a97461697265206578697374616e74652e2053616e7320617563756e65207072c3a974656e74696f6e2c206ae2809961692068c3a962657267c3a92063652070726f6a6574207375722047697468756220657420636f6d6d652063e28099657374206c61207365756c6520736f6c7574696f6e203c656d3e6f70656e20736f757263653c2f656d3e20646520636520747970652c206c65206e6f6d62726520646520706572736f6e6e657320696e74c3a972657373c3a965732061206175676d656e74c3a920e280a63c2f703e0a3c703e3c656d3e4c6573207574696c6973617465757273206465207365727669636573204672616d61736f6674206e65206c6520736176656e742070617320666f7263c3a96d656e742c206d6169732074752061732064c3a96ac3a020706173206d616c207061727469636970c3a920c3a0206c61204672616d6147616c617869652c206e6f6ec2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e456e2065666665742e204ae28099616920636f6d6d656e63c3a920756e20706c7567696e20706f7572204672616d616e6577732c203c6120687265663d2268747470733a2f2f6769746875622e636f6d2f6e69636f736f6d622f74747273732d70757267652d6163636f756e7473223e74747273732d70757267652d6163636f756e74733c2f613e2c20717569207065726d6574206465206e6574746f796572206c61206261736520646520646f6e6ec3a9657320646520636f6d7074657320706c7573207574696c6973c3a9732e204d616973206365203c656d3e706c7567696e3c2f656d3e2061206265736f696e2064e28099c3aa747265207465726d696ec3a920c3a0203130302520706f757220c3aa74726520696e74c3a96772c3a9206175207365696e206465204672616d616e6577732028657420646f6e632064652054696e792054696e7920525353292c207369207175656c7175e28099756e20736f756861697465206de2809961696465722c20696c206ee2809979206120617563756e20736f7563692e3c6272202f3e4ae28099616920617573736920666169742031206f7520322061707061726974696f6e732064616e73206465732074726164756374696f6e7320706f7572204672616d61626c6f672e205269656e2064e2809965787472616f7264696e616972652c206a65206e652073756973207061732062696c696e6775652c20c3a761206d65207065726d6574206465206de28099656e747261c3ae6e65722e3c2f703e0a3c703e3c656d3e5061726c6f6e73206465207375697465206465206365207175692066c3a2636865c2a03a20746f6e206170706c69636174696f6e2057616c6c616261672c20656c6c652073e28099617070656c6c6169742070617320e2809c506f636865e2809d2c206176616e74c2a03f205475206e6f7573207261636f6e746573206ce28099686973746f697265c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e45756820656e20656666657420e280a62044c3a96ac3a02c20706f757271756f69203c656d3e706f6368653c2f656d3ec2a03f20506172636520717565206ce28099756e206465732074726f697320c2abc2a074c3a96e6f7273c2a0c2bb20737572206c65206d61726368c3a92073e28099617070656c6c65203c656d3e506f636b65743c2f656d3e2e20436f6d6d65206d6f6e206170706c69206ee28099c3a9746169742064657374696ec3a965207175e28099c3a0206d6f6e20757361676520706572736f6e6e656c2061752064c3a9706172742c206a65206e65206d6520737569732070617320746f72747572c3a9206269656e206c6f6e6774656d70732e3c2f703e0a3c703e43657420c3a974c3a92c206f6e2061206661696c6c69206368616e676572206465206e6f6d2c207175616e6420696c2079206120657520646520706c757320656e20706c75732064e280997574696c69736174657572732e2045742070756973206f6e2073e28099657374206469742071756520706f6368652c2063e28099c3a97461697420706173206d616c2c20c3a76120736f6e6e616974206269656e206672616ec3a761697320657420707569732061766563206c6573207175656c717565732064697a61696e65732064e280997574696c69736174657572732c206f6e206e652067c3aa6e657261697420706572736f6e6e652e3c2f703e0a3c703e43e280996573742073616e7320636f6d707465722061766563206c657320736f6369c3a974c3a97320616dc3a972696361696e6573206574206c6575722066c3a2636865757365206d616e696520646520766f756c6f697220656e766f796572206c657572732061766f6361747320c3a020746f757420626f7574206465206368616d702e204c65203233206a616e766965722c206ae280996169207265c3a77520756e20656d61696c206465206c61207061727420647520636162696e65742064e2809961766f6361747320646520506f636b6574206d652064656d616e64616e74206465206368616e676572206c65206e6f6d2c206c65206c6f676f2c206465206e6520706c7573207574696c69736572206c65207465726d6520e2809c726561642d69742d6c61746572e2809d2028c2abc2a06c6973657a206c6520706c75732074617264c2a0c2bb29206574206465206e6520706c757320646972652071756520506f636b6574206ee280996573742070617320677261747569742028746f7574206573742070617274692064e280993c6120687265663d2268747470733a2f2f747769747465722e636f6d2f77616c6c616261676170702f7374617475732f343233373836333635393434323235373932223e756e2074776565743c2f613e206fc3b9206a65207175616c6966696520506f636b657420646520c2abc2a06e6f6e2066726565c2a0c2bb20c3a0207361766f6972206e6f6e206c69627265292e20427265662c206dc3aa6d65207369206a652073656d626c6169732064616e73206d6f6e2064726f69742c206ae280996169207175616e64206dc3aa6d652070726973206c612064c3a9636973696f6e206465206368616e676572206465206e6f6d2065742057616c6c6162616720657374206ec3a92c20737569746520617578203c6120687265663d22687474703a2f2f6672616d61646174652e6f72672f73747564732e7068703f736f6e646167653d6c6c6370366f6a70796339706b6c6861223e64697a61696e65732064652070726f706f736974696f6e73206465206e6f6d207265c3a77565733c2f613e2e2043e2809965737420756e206dc3a96c616e676520656e747265206c652077616c6c61627920286465206c612066616d696c6c6520646573206b616e676f75726f75732c207175692073746f636b656e742064616e73206c65757220706f63686520636520717569206c65757220657374206368657229206574203c656d3e6261673c2f656d3e20286c6573207465726d657320736163202f207361636f636865202f2062657361636520736f6e7420c3a96e6f726dc3a96d656e7420726576656e7573292e204d616973206d61696e74656e616e742c206f6e207661206465206ce280996176616e742c20706c75732064652074656d707320c3a020706572647265206176656320c3a7612c206f6e2061206475207061696e20737572206c6120706c616e6368652e3c6272202f3e3c696d67207372633d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f7075626c69632f5f696d672f6672616d61626c6f672f77616c6c6162795f626162792e6a70672220616c743d2277616c6c61627920617665632062c3a962c3a92064616e7320736120706f6368652220636c6173733d22633122207469746c653d2277616c6c61627920617665632062c3a962c3a92064616e7320736120706f63686522202f3e206372c3a96469742070686f746f203c6120687265663d22687474703a2f2f7777772e666c69636b722e636f6d2f70686f746f732f3236373832383634404e30302f353032373230323233342f696e2f70686f746f6c6973742d3845654a35412d6831544c36762d4e454c38312d636e4e6b536f2d39594d3174762d374b636736622d387a70416f612d61315a4c4d4e2d39594d3339722d3768355341442d38456548664c2d3845654677752d647456776e4d2d38756f4d45312d4a457a58652d47713471792d3932564a50522d43786531762d38483344324a2d61315a464e732d395937324b362d38456547784c2d354c353346782d354e6b454e732d3555384354592d354e6b7373682d6e6b6176462d3943726777502d3773644341612d647566324b682d685a65707a792d685a645531652d685a656f66462d685a656b44672d685a656741592d685a654d5a6e2d6a61486741662d3850383744322d354e677152762d6154343851422d685a645634592d685a654336342d45526770732d3556594747642d3556594a42312d354e6b72466b2d364a786837682d3768395075512d4552664d782d6831553169682d683155534278223e57696c6c69616d2057617262793c2f613e20717569206175746f72697365206578706c69636974656d656e7420746f7574652072c3a97574696c69736174696f6e2e3c2f703e0a3c703e3c656d3e426f6e2c20616c6f7273206578706c697175652d6d6f6920636520717565206a65207661697320706f75766f69722066616972652061766563204672616d61626167e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e416c6f7273204672616d616261672c20c3a761207465207065726d6574206465207465206372c3a9657220756e20636f6d7074652067726174756974656d656e74206574206c696272656d656e7420706f757220706f75766f6972207574696c697365722057616c6c616261672e205365756c6520746f6e206164726573736520656d61696c20657374206ec3a963657373616972652c206f6e207365206368617267652064e28099696e7374616c6c6572206574206465206d657474726520c3a0206a6f75722057616c6c6162616720706f757220746f692e20547520706575782064e2809961696c6c657572732070726f6669746572203c6120687265663d22687474703a2f2f7777772e6672616d61736f66742e6e65742f23746f705067436c6f7564223e64e280996175747265732073657276696365732070726f706f73c3a97320706172204672616d61736f6674206963693c2f613e2e3c2f703e0a3c703ec380206365206a6f75722c20696c207920612038333420636f6d70746573206372c3a9c3a97320737572204672616d616261672e3c2f703e0a3c703e3c656d3e566f7573206176657a20767261696d656e7420636f6ec3a7752063652073657276696365206166696e207175e280996f6e20707569737365206ce280997574696c69736572206176656320756e206d6178696d756d2064e280996f7574696c732c206e6f6ec2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4175746f7572206465206ce280996170706c69636174696f6e207765622c20696c206578697374652064c3a96ac3a020646573206170706c69636174696f6e7320706f757220736d61727470686f6e65732028416e64726f69642065742057696e646f77732050686f6e65292c2064657320657874656e73696f6e732046697265666f7820657420476f6f676c65204368726f6d652e3c2f703e0a3c703e436f6d6d652057616c6c6162616720706f7373c3a864652064657320666c7578205253532c2063e2809965737420666163696c65206465206c697265206c65732061727469636c657320736175766567617264c3a97320737572207361206c697365757365202873692063656c6c652d6369207065726d6574206465206c6972652064657320666c757820525353292e2043616c696272652028c2abc2a06c6f67696369656c206465206c6563747572652c2064652067657374696f6e206465206269626c696f7468c3a87175657320657420646520636f6e76657273696f6e206465206669636869657273206e756dc3a972697175657320646520747970652065626f6f6b206f75206c6976726520c3a96c656374726f6e69717565c2a0c2bb2c6e6f757320646974207562756e74752d66722e6f72672920696e74c3a867726520646570756973207175656c717565732073656d61696e6573206d61696e74656e616e74206c6120706f73736962696c6974c3a92064652072c3a9637570c3a9726572206c65732061727469636c6573206e6f6e206c75732c20707261746971756520706f757220666169726520756e20666963686965722065507562c2a0213c2f703e0a3c703e44e28099617574726573206170706c69636174696f6e7320776562207065726d657474656e74206ce28099696e74c3a967726174696f6e20617665632057616c6c61626167202846726573685253532c204c6565642065742054696e792054696e792052535320706f7572206c657320616772c3a96761746575727320646520666c7578292e204ce2809941504920717569207365726120646973706f6e69626c652064616e73206c612070726f636861696e652076657273696f6e2064652057616c6c61626167207065726d657474726120656e636f726520706c75732064e28099696e74657261637469766974c3a92e3c2f703e0a3c703e3c656d3e5920612d742d696c20756e206d6f6465206465206c65637475726520686f7273206c69676e65206f75206573742d6365207175652063e28099657374207072c3a9767520706f7572206c65732070726f636861696e65732076657273696f6e73c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e496c2079206120756e2070736575646f206d6f646520686f7273206c69676e652c20646973706f6e69626c652061766563206ce280996170706c69636174696f6e20416e64726f69642e204f6e20706575742072c3a9637570c3a9726572202876696120756e20666c75782052535329206c65732061727469636c6573206e6f6e206c757320717565206ce280996f6e206120736175766567617264c3a9732e20556e6520666f69732064c3a9636f6e6e656374c3a92c206f6e207065757420636f6e74696e75657220c3a0206c6972652073757220736f6e20736d61727470686f6e65206f75207361207461626c65747465206c65732061727469636c65732e2050617220636f6e7472652c20696c206d616e7175652064657320666f6e6374696f6e6e616c6974c3a973c2a03a207175616e64207475206d61727175657320756e2061727469636c6520636f6d6d65206c752c206365206ee28099657374207061732073796e6368726f6e6973c3a92061766563206c612076657273696f6e207765622064652057616c6c616261672e204ae28099657370c3a8726520717565206a652073756973207072657371756520636c6169722064616e73206d6573206578706c69636174696f6e732e3c2f703e0a3c703e506f7572206c612076322c20717569206573742064c3a96ac3a020656e20636f7572732064652064c3a976656c6f7070656d656e742c206fc3b9206a652073756973206269656e20616964c3a9207061722056696e63656e74204a6f757373652c206f6e2061757261206c6120706f73736962696c6974c3a92064e2809961766f697220756e2076726169206d6f646520686f7273206c69676e652e3c2f703e0a3c703e3c656d3e416c6f7273207369206f6e2076657574206169646572202f2070617274696369706572202f20747269666f75696c6c6572206c6520636f6465202f20766f757320656e766f79657220646573207265746f7572732c206f6e206661697420636f6d6d656e74c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4f6e207065757420616964657220646520706c75736965757273206661c3a76f6e73c2a03a3c2f703e0a3c756c3e3c6c693e7574696c697365722077616c6c61626167206574206e6f75732072656d6f6e746572206c65732070726f626cc3a86d65732072656e636f6e7472c3a973c2a03b3c2f6c693e0a3c6c693e706172746963697065722061752064c3a976656c6f7070656d656e74206465206ce280996170706c69636174696f6e2068747470733a2f2f6769746875622e636f6d2f77616c6c616261672f77616c6c616261672053692053696c6578202f2053796d666f6e7932202f2048544d4c35202f206574632e207465207061726c656e742c206ee2809968c3a97369746520706173c2a0213c2f6c693e0a3c6c693e636f6d6d6520746f75742070726f6a65742c206c652067726f7320706f696e74206e6f697220657374206c65206d616e71756520646520646f63756d656e746174696f6e2e203c6120687265663d22687474703a2f2f646f632e77616c6c616261672e6f7267223e456c6c652065737420646973706f206963693c2f613e206d61697320696c206d616e71756520706c65696e2064652063686f73657320657420746f7574206ee280996573742070617320c3a0206a6f7572c2a03b3c2f6c693e0a3c6c693e7061726c65722064652057616c6c61626167206175746f757220646520766f7573c2a03b3c2f6c693e0a3c6c693e696c20657869737465203c6120687265663d2268747470733a2f2f666c617474722e636f6d2f7468696e672f313236353438302f706f6368652d612d726561642d69742d6c617465722d6f70656e2d736f757263652d73797374656d223e756e20636f6d70746520466c617474723c2f613e2e3c2f6c693e0a3c2f756c3e3c703e3c656d3e4c65206d6f74206465206c612066696ee280a63f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4d6572636920c3a0204672616d61736f66742064e280996163637565696c6c697220657420646520736f7574656e69722057616c6c61626167c2a0213c2f703e0a3c703e4c6120726f7574652065737420656e636f7265206269656e206c6f6e67756520706f7572206e6520706c7573207574696c6973657220646520736f6c7574696f6e732070726f707269c3a97461697265732c206d616973206f6e2064657672616974207920617272697665722c206e6f6ec2a03f3c2f703e0a3c703e3c696d67207372633d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f7075626c69632f5f696d672f6672616d61626c6f672f706c65696e4c6573506f636865732e706e672220616c743d226672616d61736f667420706c65696e206c657320706f636865732220636c6173733d22633122207469746c653d226672616d61736f667420706c65696e206c657320706f6368657322202f3e3c6272202f3e3c6120687265663d22687474703a2f2f6672616d616c61622e6f72672f676b6e642d63726561746f722f223e6861636b657a2047c3a967c3a9c2a0213c2f613e3c2f703e0a, 1), 88(1, 'Framabag, un nouveau service libre et gratuit', 'http://www.framablog.org/index.php/post/2014/02/05/Framabag-service-libre-gratuit-interview-developpeur', 0, 0, 0x0a3c68323e556e6520696e74657276696577206465204e69636f6c61732c20736f6e2064c3a976656c6f70706575722e3c2f68323e0a3c703e3c656d3e496c206e6520766f757320612073c3bb72656d656e742070617320c3a96368617070c3a920717565206e6f74726520636f6e736f6d6d6174696f6e20646520636f6e74656e75732064752057656220657374207465727269626c656d656e74206368726f6e6f706861676520657420706172746963756c69c3a872656d656e7420667275737472616e746520746f757420c3a0206c6120666f6973c2a03a206e6f6e207365756c656d656e74206e6f757320706173736f6e732062656175636f7570202874726f70c2a03f292064652074656d707320656e206c69676e6520c3a0206578706c6f726572206c6573206d696e6573206175726966c3a8726573206465206c6120746f696c652c20792064c3a974656374616e742070c3a970697465732065742066696c6f6e732c206d616973206e6f757320736f6d6d657320737572746f757420636f6e7374616d6d656e7420656e206d616e7175652e204dc3aa6d65207369206e6f7573206e6520736f6d6d6573207061732064616e73206c65207a617070696e67206672c3a96ec3a9746971756520736920666163696c656d656e742064c3a96e6f6e63c3a920706172206c657320646f637465732070737963686f6c6f677565732071756920706f6e74696669656e7420737572206c65732064616e67657273206475206e756dc3a9726971756520706f7572206c6573206a65756e65732063657276656c6c65732c20696c206e6f7573207669656e7420736f7576656e74206c6520676fc3bb7420616d6572206465206ce28099696e6163686576c3a9c2a03a20706173206c652074656d707320646520746f7574206c69726520283c6120687265663d22687474703a2f2f66722e77696b74696f6e6172792e6f72672f77696b692f544c4452223e544c3b44523c2f613e2065737420646576656e75206c6520636c696e2064e28099c593696c206d692d6669677565206d692d72616973696e2064e28099756e652067c3a96ec3a9726174696f6e206465206c65637465757273207072657373c3a973292c207061732074726f70206c652074656d70732064652072c3a9666cc3a963686972206e6f6e20706c75732068c3a96c61732c20706173206c652074656d707320646520737569767265206c6120726962616d62656c6c65206465206c69656e73206173736f6369c3a97320c3a020756e2061727469636c65e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e506f7572206e6f757320646f6e6e657220626f6e6e6520636f6e736369656e63652c206e6f75732072616e67656f6e73207363727570756c657573656d656e7420756e206d61727175652d7061676520646520706c75732064616e7320756e20736f75732d646f73736965722071756920656e20636f6d706f7274652064c3a96ac3a0203235362c206e6f7573206e6f746f6e7320756e20c3a96cc3a96d656e7420646520706c75732064616e73206c6120746f756a6f757273207269646963756c656d656e74206c6f6e67756520746f75646f756c697374652c2062726566206e6f75732072656d6574746f6e7320c3a020706c757320746172642c2063e280996573742dc3a02d64697265206c6520706c757320736f7576656e742061757820696e74726f757661626c65732063616c656e6465732067726563717565732c206c6520736f696e206465206c69726520767261696d656e7420756e2061727469636c65206a7567c3a920696e74c3a972657373616e742c20646520726567617264657220756e6520766964c3a96f207369676e616cc3a96520706172206c65732072c3a97a6f73736f63696f732c206465206c69726520756e20636861706974726520656e746965722064e28099756e206f75767261676520646973706f6e69626c6520656e206c69676e65e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e416c6f7273206269656e2073c3bb722c20c3a02064c3a966617574206465206e6f757320646f6e6e657220746f7574206c652074656d70732071756920736572616974206ec3a963657373616972652c2064657320736f6c7574696f6e73206578697374656e7420706f7572206e6f7573207065726d657474726520646520c2abc2a06c69726520706c75732074617264c2a0c2bb20656e20736175766567617264616e74206c65207072c3a9636965757820706f6c6c656e206465206e6f7320627574696e61676573206465207369746520656e20736974652c2065742064e28099656e20666169726520756c74c3a97269657572656d656e7420766f747265206d69656cc2a03b2063e280996573742062656c20657420626f6e206d616973206c65732072756368657320736f6e7420756e207065752064697374616e7465732c20c3a7612073e28099617070656c6c65206c6520636c6f756420286e6f7320616d69732074656368696573206de280996f6e74206269656e206578706c697175c3a9206d616973206ae280996169207365756c656d656e7420636f6d70726973207175652064657320747275637320c3a0206d6f6920736f6e742073757220646573206d616368696e6573206c6f696e7461696e65732c20c3a761206e65206d652072617373757265207061732074726f702920657420656c6c657320736f6e7420736f7576656e742070726f707269c3a97461697265732c206e65206c61697373616e7420656e7472657220717565206c6573203c733e7574696c69736174657572733c2f733e20636f6e736f6d6d61746575727320706179616e74732065742071756920636f6e73656e74656e7420c3a0206c6575727320636f6e646974696f6e732e2053616e7320636f6d70746572207175652064652067726f7320626f7572646f6e73207669656e6e656e742070726f666974657220706c7573206f75206d6f696e73206469736372c3a874656d656e7420646520746f757465732063657320747261636573206465206e6f75732d6dc3aa6d657320717569207065726d657474656e74206465206d6f6ec3a97469736572206e6f7472652070726f66696cc2a03a207369206a6520636f6c6c65637465207375722063657320736572766963657320286e65206c6573206e6f6d6d6f6e73207061732c206a757374656d656e742920756e652073c3a97269652064e2809961727469636c657320737572206ce280996964c3a965206465204e6174757265206368657a2044696465726f742c206a6520726563657672616920646976657273657320736f6c6c696369746174696f6e7320706f757220646576656e697220636c69656e74206465206c6120626f757469717565204e61747572652026616d703b2044c3a9636f75766572746520647520626f756c65766172642044696465726f742e2045742073692064e280996176656e74757265206c65732070726f6772616d6d6573206465206c61204e5341206d6f756c696e656e7420737572206c6520736572766963652c206a6520736572616920706575742dc3aa74726520756e206a6f75722064616e7320756e65206c6973746520646573206d696c6974616e7473206e61747572697374657320696e64c3a973697261626c657320737572206c657320766f6c73206465206c612050616e416d20286a65206e65207361697320706c75732074726f70207369206a6520706c616973616e7465206cc3a02c2066696e616c656d656e74e280a6293c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4c6120626f6e6e65206964c3a965c2a03a20c2abc2a0736520636f6e7374697475657220756e2072c3a9736572766f697220646520646f63756d656e74732073c3a96c656374696f6e6ec3a97320c3a020706172636f7572697220706c75732074617264c2a0c2bb20617070656c61697420646f6e6320756e6520617574726520626f6e6e65206964c3a9652c2063656c6c652064e2809961766f6972206c6520636f6e7472c3b46c652064652063652072c3a9736572766f69722c206465206e6f74726520636f6c6c656374696f6e20706572736f6e6e656c6c652e2043e28099657374204e69636f6c6173204cc59375696c6c65742c2063692d646573736f757320696e74657276696577c3a92c207175692073e28099792065737420636f6c6cc3a9206176656320756e652062656c6c65206170706c69636174696f6e20617070656cc3a96520657568e280a6206f75692c20617070656cc3a9652057616c6c616261672e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4672616d61736f667420736f757469656e742064e28099617574616e7420706c757320736f6e20696e6974696174697665207175e280993c6120687265663d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f696e6465782e7068702f706f73742f323031342f30312f33312f4765656b74696f6e6e6572642d57616c6c61626167223e6f6e206c7569206120636865726368c3a920646573206d6973c3a872657320706f757220756e6520686973746f697265206465206e6f6d3c2f613e206574207175e28099696c2065737420706f737369626c652064e28099696e7374616c6c657220736f692d6dc3aa6d6520756e6520636f7069652064652057616c6c616261672073757220736f6e2070726f70726520736974652e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4c6520706574697420706c7573206465204672616d61736f66742c2072c3a97365617520746f756a6f7572732064c3a973697265757820646520766f75732070726f706f7365722064657320616c7465726e617469766573206c6962c3a972617472696365732c2063e2809965737420646520766f75732070726f706f736572202873757220696e736372697074696f6e207072c3a9616c61626c652920756e20616363c3a873206175204672616d616261672c2061757472656d656e742064697420766f7472652057616c6c616261672073757220756e2073657276657572204672616d612a2061766563206e6f74726520676172616e74696520646520636f6e666964656e7469616c6974c3a92e20436f6d6d6520706f7572206c65204672616d616e6577732c206e6f757320766f7573206163637565696c6c6f6e7320766f6c6f6e74696572732064616e73206c61206c696d697465206465206e6f732063617061636974c3a9732c20656e20766f757320696e766974616e7420c3a020766f7573206c616e6365722064616e7320766f747265206175746f2d68c3a962657267656d656e742064652057616c6c616261672e3c6272202f3e4365742061727469636c65206573742074726f70206c6f6e67c2a03f204d657474657a2d6c652064616e73203c6120687265663d22687474703a2f2f7777772e6672616d616261672e6f72672f696e6465782e706870223e766f747265204672616d616261673c2f613e20657420686f702e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4672616d61626c6f67c2a03a2053616c7574204e69636f6c6173e280a62054752070657578207465207072c3a973656e74657220627269c3a876656d656e74c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e53616c7574c2a0212044c3a976656c6f70706575722050485020646570756973207175656c7175657320616e6ec3a96573206d61696e74656e616e742028313020616e73292c206ae28099616920766f756c75206d652072656d657474726520c3a0206e697665617520746563686e697175656d656e74207061726c616e742028646570756973203320616e732c206ae28099616920706173206d616c206cc3a26368c3a9206c6520636c6176696572292e20506f7572206d6573206265736f696e7320706572736f732c206ae28099616920646f6e63206372c3a9c3a920756e2070657469742070726f6a657420706f75722072656d706c6163657220756e6520736f6c7574696f6e2070726f707269c3a97461697265206578697374616e74652e2053616e7320617563756e65207072c3a974656e74696f6e2c206ae2809961692068c3a962657267c3a92063652070726f6a6574207375722047697468756220657420636f6d6d652063e28099657374206c61207365756c6520736f6c7574696f6e203c656d3e6f70656e20736f757263653c2f656d3e20646520636520747970652c206c65206e6f6d62726520646520706572736f6e6e657320696e74c3a972657373c3a965732061206175676d656e74c3a920e280a63c2f703e0a3c703e3c656d3e4c6573207574696c6973617465757273206465207365727669636573204672616d61736f6674206e65206c6520736176656e742070617320666f7263c3a96d656e742c206d6169732074752061732064c3a96ac3a020706173206d616c207061727469636970c3a920c3a0206c61204672616d6147616c617869652c206e6f6ec2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e456e2065666665742e204ae28099616920636f6d6d656e63c3a920756e20706c7567696e20706f7572204672616d616e6577732c203c6120687265663d2268747470733a2f2f6769746875622e636f6d2f6e69636f736f6d622f74747273732d70757267652d6163636f756e7473223e74747273732d70757267652d6163636f756e74733c2f613e2c20717569207065726d6574206465206e6574746f796572206c61206261736520646520646f6e6ec3a9657320646520636f6d7074657320706c7573207574696c6973c3a9732e204d616973206365203c656d3e706c7567696e3c2f656d3e2061206265736f696e2064e28099c3aa747265207465726d696ec3a920c3a0203130302520706f757220c3aa74726520696e74c3a96772c3a9206175207365696e206465204672616d616e6577732028657420646f6e632064652054696e792054696e7920525353292c207369207175656c7175e28099756e20736f756861697465206de2809961696465722c20696c206ee2809979206120617563756e20736f7563692e3c6272202f3e4ae28099616920617573736920666169742031206f7520322061707061726974696f6e732064616e73206465732074726164756374696f6e7320706f7572204672616d61626c6f672e205269656e2064e2809965787472616f7264696e616972652c206a65206e652073756973207061732062696c696e6775652c20c3a761206d65207065726d6574206465206de28099656e747261c3ae6e65722e3c2f703e0a3c703e3c656d3e5061726c6f6e73206465207375697465206465206365207175692066c3a2636865c2a03a20746f6e206170706c69636174696f6e2057616c6c616261672c20656c6c652073e28099617070656c6c6169742070617320e2809c506f636865e2809d2c206176616e74c2a03f205475206e6f7573207261636f6e746573206ce28099686973746f697265c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e45756820656e20656666657420e280a62044c3a96ac3a02c20706f757271756f69203c656d3e706f6368653c2f656d3ec2a03f20506172636520717565206ce28099756e206465732074726f697320c2abc2a074c3a96e6f7273c2a0c2bb20737572206c65206d61726368c3a92073e28099617070656c6c65203c656d3e506f636b65743c2f656d3e2e20436f6d6d65206d6f6e206170706c69206ee28099c3a9746169742064657374696ec3a965207175e28099c3a0206d6f6e20757361676520706572736f6e6e656c2061752064c3a9706172742c206a65206e65206d6520737569732070617320746f72747572c3a9206269656e206c6f6e6774656d70732e3c2f703e0a3c703e43657420c3a974c3a92c206f6e2061206661696c6c69206368616e676572206465206e6f6d2c207175616e6420696c2079206120657520646520706c757320656e20706c75732064e280997574696c69736174657572732e2045742070756973206f6e2073e28099657374206469742071756520706f6368652c2063e28099c3a97461697420706173206d616c2c20c3a76120736f6e6e616974206269656e206672616ec3a761697320657420707569732061766563206c6573207175656c717565732064697a61696e65732064e280997574696c69736174657572732c206f6e206e652067c3aa6e657261697420706572736f6e6e652e3c2f703e0a3c703e43e280996573742073616e7320636f6d707465722061766563206c657320736f6369c3a974c3a97320616dc3a972696361696e6573206574206c6575722066c3a2636865757365206d616e696520646520766f756c6f697220656e766f796572206c657572732061766f6361747320c3a020746f757420626f7574206465206368616d702e204c65203233206a616e766965722c206ae280996169207265c3a77520756e20656d61696c206465206c61207061727420647520636162696e65742064e2809961766f6361747320646520506f636b6574206d652064656d616e64616e74206465206368616e676572206c65206e6f6d2c206c65206c6f676f2c206465206e6520706c7573207574696c69736572206c65207465726d6520e2809c726561642d69742d6c61746572e2809d2028c2abc2a06c6973657a206c6520706c75732074617264c2a0c2bb29206574206465206e6520706c757320646972652071756520506f636b6574206ee280996573742070617320677261747569742028746f7574206573742070617274692064e280993c6120687265663d2268747470733a2f2f747769747465722e636f6d2f77616c6c616261676170702f7374617475732f343233373836333635393434323235373932223e756e2074776565743c2f613e206fc3b9206a65207175616c6966696520506f636b657420646520c2abc2a06e6f6e2066726565c2a0c2bb20c3a0207361766f6972206e6f6e206c69627265292e20427265662c206dc3aa6d65207369206a652073656d626c6169732064616e73206d6f6e2064726f69742c206ae280996169207175616e64206dc3aa6d652070726973206c612064c3a9636973696f6e206465206368616e676572206465206e6f6d2065742057616c6c6162616720657374206ec3a92c20737569746520617578203c6120687265663d22687474703a2f2f6672616d61646174652e6f72672f73747564732e7068703f736f6e646167653d6c6c6370366f6a70796339706b6c6861223e64697a61696e65732064652070726f706f736974696f6e73206465206e6f6d207265c3a77565733c2f613e2e2043e2809965737420756e206dc3a96c616e676520656e747265206c652077616c6c61627920286465206c612066616d696c6c6520646573206b616e676f75726f75732c207175692073746f636b656e742064616e73206c65757220706f63686520636520717569206c65757220657374206368657229206574203c656d3e6261673c2f656d3e20286c6573207465726d657320736163202f207361636f636865202f2062657361636520736f6e7420c3a96e6f726dc3a96d656e7420726576656e7573292e204d616973206d61696e74656e616e742c206f6e207661206465206ce280996176616e742c20706c75732064652074656d707320c3a020706572647265206176656320c3a7612c206f6e2061206475207061696e20737572206c6120706c616e6368652e3c6272202f3e3c696d67207372633d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f7075626c69632f5f696d672f6672616d61626c6f672f77616c6c6162795f626162792e6a70672220616c743d2277616c6c61627920617665632062c3a962c3a92064616e7320736120706f6368652220636c6173733d22633122207469746c653d2277616c6c61627920617665632062c3a962c3a92064616e7320736120706f63686522202f3e206372c3a96469742070686f746f203c6120687265663d22687474703a2f2f7777772e666c69636b722e636f6d2f70686f746f732f3236373832383634404e30302f353032373230323233342f696e2f70686f746f6c6973742d3845654a35412d6831544c36762d4e454c38312d636e4e6b536f2d39594d3174762d374b636736622d387a70416f612d61315a4c4d4e2d39594d3339722d3768355341442d38456548664c2d3845654677752d647456776e4d2d38756f4d45312d4a457a58652d47713471792d3932564a50522d43786531762d38483344324a2d61315a464e732d395937324b362d38456547784c2d354c353346782d354e6b454e732d3555384354592d354e6b7373682d6e6b6176462d3943726777502d3773644341612d647566324b682d685a65707a792d685a645531652d685a656f66462d685a656b44672d685a656741592d685a654d5a6e2d6a61486741662d3850383744322d354e677152762d6154343851422d685a645634592d685a654336342d45526770732d3556594747642d3556594a42312d354e6b72466b2d364a786837682d3768395075512d4552664d782d6831553169682d683155534278223e57696c6c69616d2057617262793c2f613e20717569206175746f72697365206578706c69636974656d656e7420746f7574652072c3a97574696c69736174696f6e2e3c2f703e0a3c703e3c656d3e426f6e2c20616c6f7273206578706c697175652d6d6f6920636520717565206a65207661697320706f75766f69722066616972652061766563204672616d61626167e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e416c6f7273204672616d616261672c20c3a761207465207065726d6574206465207465206372c3a9657220756e20636f6d7074652067726174756974656d656e74206574206c696272656d656e7420706f757220706f75766f6972207574696c697365722057616c6c616261672e205365756c6520746f6e206164726573736520656d61696c20657374206ec3a963657373616972652c206f6e207365206368617267652064e28099696e7374616c6c6572206574206465206d657474726520c3a0206a6f75722057616c6c6162616720706f757220746f692e20547520706575782064e2809961696c6c657572732070726f6669746572203c6120687265663d22687474703a2f2f7777772e6672616d61736f66742e6e65742f23746f705067436c6f7564223e64e280996175747265732073657276696365732070726f706f73c3a97320706172204672616d61736f6674206963693c2f613e2e3c2f703e0a3c703ec380206365206a6f75722c20696c207920612038333420636f6d70746573206372c3a9c3a97320737572204672616d616261672e3c2f703e0a3c703e3c656d3e566f7573206176657a20767261696d656e7420636f6ec3a7752063652073657276696365206166696e207175e280996f6e20707569737365206ce280997574696c69736572206176656320756e206d6178696d756d2064e280996f7574696c732c206e6f6ec2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4175746f7572206465206ce280996170706c69636174696f6e207765622c20696c206578697374652064c3a96ac3a020646573206170706c69636174696f6e7320706f757220736d61727470686f6e65732028416e64726f69642065742057696e646f77732050686f6e65292c2064657320657874656e73696f6e732046697265666f7820657420476f6f676c65204368726f6d652e3c2f703e0a3c703e436f6d6d652057616c6c6162616720706f7373c3a864652064657320666c7578205253532c2063e2809965737420666163696c65206465206c697265206c65732061727469636c657320736175766567617264c3a97320737572207361206c697365757365202873692063656c6c652d6369207065726d6574206465206c6972652064657320666c757820525353292e2043616c696272652028c2abc2a06c6f67696369656c206465206c6563747572652c2064652067657374696f6e206465206269626c696f7468c3a87175657320657420646520636f6e76657273696f6e206465206669636869657273206e756dc3a972697175657320646520747970652065626f6f6b206f75206c6976726520c3a96c656374726f6e69717565c2a0c2bb2c6e6f757320646974207562756e74752d66722e6f72672920696e74c3a867726520646570756973207175656c717565732073656d61696e6573206d61696e74656e616e74206c6120706f73736962696c6974c3a92064652072c3a9637570c3a9726572206c65732061727469636c6573206e6f6e206c75732c20707261746971756520706f757220666169726520756e20666963686965722065507562c2a0213c2f703e0a3c703e44e28099617574726573206170706c69636174696f6e7320776562207065726d657474656e74206ce28099696e74c3a967726174696f6e20617665632057616c6c61626167202846726573685253532c204c6565642065742054696e792054696e792052535320706f7572206c657320616772c3a96761746575727320646520666c7578292e204ce2809941504920717569207365726120646973706f6e69626c652064616e73206c612070726f636861696e652076657273696f6e2064652057616c6c61626167207065726d657474726120656e636f726520706c75732064e28099696e74657261637469766974c3a92e3c2f703e0a3c703e3c656d3e5920612d742d696c20756e206d6f6465206465206c65637475726520686f7273206c69676e65206f75206573742d6365207175652063e28099657374207072c3a9767520706f7572206c65732070726f636861696e65732076657273696f6e73c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e496c2079206120756e2070736575646f206d6f646520686f7273206c69676e652c20646973706f6e69626c652061766563206ce280996170706c69636174696f6e20416e64726f69642e204f6e20706575742072c3a9637570c3a9726572202876696120756e20666c75782052535329206c65732061727469636c6573206e6f6e206c757320717565206ce280996f6e206120736175766567617264c3a9732e20556e6520666f69732064c3a9636f6e6e656374c3a92c206f6e207065757420636f6e74696e75657220c3a0206c6972652073757220736f6e20736d61727470686f6e65206f75207361207461626c65747465206c65732061727469636c65732e2050617220636f6e7472652c20696c206d616e7175652064657320666f6e6374696f6e6e616c6974c3a973c2a03a207175616e64207475206d61727175657320756e2061727469636c6520636f6d6d65206c752c206365206ee28099657374207061732073796e6368726f6e6973c3a92061766563206c612076657273696f6e207765622064652057616c6c616261672e204ae28099657370c3a8726520717565206a652073756973207072657371756520636c6169722064616e73206d6573206578706c69636174696f6e732e3c2f703e0a3c703e506f7572206c612076322c20717569206573742064c3a96ac3a020656e20636f7572732064652064c3a976656c6f7070656d656e742c206fc3b9206a652073756973206269656e20616964c3a9207061722056696e63656e74204a6f757373652c206f6e2061757261206c6120706f73736962696c6974c3a92064e2809961766f697220756e2076726169206d6f646520686f7273206c69676e652e3c2f703e0a3c703e3c656d3e416c6f7273207369206f6e2076657574206169646572202f2070617274696369706572202f20747269666f75696c6c6572206c6520636f6465202f20766f757320656e766f79657220646573207265746f7572732c206f6e206661697420636f6d6d656e74c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4f6e207065757420616964657220646520706c75736965757273206661c3a76f6e73c2a03a3c2f703e0a3c756c3e3c6c693e7574696c697365722077616c6c61626167206574206e6f75732072656d6f6e746572206c65732070726f626cc3a86d65732072656e636f6e7472c3a973c2a03b3c2f6c693e0a3c6c693e706172746963697065722061752064c3a976656c6f7070656d656e74206465206ce280996170706c69636174696f6e2068747470733a2f2f6769746875622e636f6d2f77616c6c616261672f77616c6c616261672053692053696c6578202f2053796d666f6e7932202f2048544d4c35202f206574632e207465207061726c656e742c206ee2809968c3a97369746520706173c2a0213c2f6c693e0a3c6c693e636f6d6d6520746f75742070726f6a65742c206c652067726f7320706f696e74206e6f697220657374206c65206d616e71756520646520646f63756d656e746174696f6e2e203c6120687265663d22687474703a2f2f646f632e77616c6c616261672e6f7267223e456c6c652065737420646973706f206963693c2f613e206d61697320696c206d616e71756520706c65696e2064652063686f73657320657420746f7574206ee280996573742070617320c3a0206a6f7572c2a03b3c2f6c693e0a3c6c693e7061726c65722064652057616c6c61626167206175746f757220646520766f7573c2a03b3c2f6c693e0a3c6c693e696c20657869737465203c6120687265663d2268747470733a2f2f666c617474722e636f6d2f7468696e672f313236353438302f706f6368652d612d726561642d69742d6c617465722d6f70656e2d736f757263652d73797374656d223e756e20636f6d70746520466c617474723c2f613e2e3c2f6c693e0a3c2f756c3e3c703e3c656d3e4c65206d6f74206465206c612066696ee280a63f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4d6572636920c3a0204672616d61736f66742064e280996163637565696c6c697220657420646520736f7574656e69722057616c6c61626167c2a0213c2f703e0a3c703e4c6120726f7574652065737420656e636f7265206269656e206c6f6e67756520706f7572206e6520706c7573207574696c6973657220646520736f6c7574696f6e732070726f707269c3a97461697265732c206d616973206f6e2064657672616974207920617272697665722c206e6f6ec2a03f3c2f703e0a3c703e3c696d67207372633d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f7075626c69632f5f696d672f6672616d61626c6f672f706c65696e4c6573506f636865732e706e672220616c743d226672616d61736f667420706c65696e206c657320706f636865732220636c6173733d22633122207469746c653d226672616d61736f667420706c65696e206c657320706f6368657322202f3e3c6272202f3e3c6120687265663d22687474703a2f2f6672616d616c61622e6f72672f676b6e642d63726561746f722f223e6861636b657a2047c3a967c3a9c2a0213c2f613e3c2f703e0a, 1),
116(2, 'wallabag/wallabag', 'https://github.com/wallabag/wallabag', 0, 0, 0x3c7370616e20636c6173733d226e616d65223e524541444d452e6d643c2f7370616e3e3c703e77616c6c6162616720697320612073656c6620686f737461626c65206170706c69636174696f6e20616c6c6f77696e6720796f7520746f206e6f74206d69737320616e7920636f6e74656e7420616e796d6f72652e20436c69636b2c20736176652c2072656164206974207768656e20796f752063616e2e20497420657874726163747320636f6e74656e7420736f207468617420796f752063616e2072656164206974207768656e20796f7520686176652074696d652e3c2f703e0a3c703e4d6f726520696e666f726d6174696f6e73206f6e206f757220776562736974653a203c6120687265663d22687474703a2f2f77616c6c616261672e6f7267223e77616c6c616261672e6f72673c2f613e3c2f703e0a3c68323e3c6120636c6173733d22616e63686f722220687265663d2268747470733a2f2f6769746875622e636f6d2f77616c6c616261672f77616c6c61626167236c6963656e7365223e3c2f613e4c6963656e73653c2f68323e0a3c703e436f7079726967687420c2a920323031302d32303134204e69636f6c6173204cc59375696c6c6574203c6120687265663d226d61696c746f3a6e69636f6c6173406c6f6575696c6c65742e6f7267223e6e69636f6c6173406c6f6575696c6c65742e6f72673c2f613e205468697320776f726b20697320667265652e20596f752063616e2072656469737472696275746520697420616e642f6f72206d6f6469667920697420756e64657220746865207465726d73206f662074686520446f205768617420546865204675636b20596f752057616e7420546f205075626c6963204c6963656e73652c2056657273696f6e20322c206173207075626c69736865642062792053616d20486f63657661722e205365652074686520434f5059494e472066696c6520666f72206d6f72652064657461696c732e3c2f703e0a, 1), 89(2, 'wallabag/wallabag', 'https://github.com/wallabag/wallabag', 0, 0, 0x3c7370616e20636c6173733d226e616d65223e524541444d452e6d643c2f7370616e3e3c703e77616c6c6162616720697320612073656c6620686f737461626c65206170706c69636174696f6e20616c6c6f77696e6720796f7520746f206e6f74206d69737320616e7920636f6e74656e7420616e796d6f72652e20436c69636b2c20736176652c2072656164206974207768656e20796f752063616e2e20497420657874726163747320636f6e74656e7420736f207468617420796f752063616e2072656164206974207768656e20796f7520686176652074696d652e3c2f703e0a3c703e4d6f726520696e666f726d6174696f6e73206f6e206f757220776562736974653a203c6120687265663d22687474703a2f2f77616c6c616261672e6f7267223e77616c6c616261672e6f72673c2f613e3c2f703e0a3c68323e3c6120636c6173733d22616e63686f722220687265663d2268747470733a2f2f6769746875622e636f6d2f77616c6c616261672f77616c6c61626167236c6963656e7365223e3c2f613e4c6963656e73653c2f68323e0a3c703e436f7079726967687420c2a920323031302d32303134204e69636f6c6173204cc59375696c6c6574203c6120687265663d226d61696c746f3a6e69636f6c6173406c6f6575696c6c65742e6f7267223e6e69636f6c6173406c6f6575696c6c65742e6f72673c2f613e205468697320776f726b20697320667265652e20596f752063616e2072656469737472696275746520697420616e642f6f72206d6f6469667920697420756e64657220746865207465726d73206f662074686520446f205768617420546865204675636b20596f752057616e7420546f205075626c6963204c6963656e73652c2056657273696f6e20322c206173207075626c69736865642062792053616d20486f63657661722e205365652074686520434f5059494e472066696c6520666f72206d6f72652064657461696c732e3c2f703e0a, 1),
117(3, 'a self hostable application for saving web pages | wallabag', 'https://www.wallabag.org/', 0, 1, 0x0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3820636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c703e77616c6c616261672028666f726d65726c7920706f636865292069732061203c7374726f6e673e73656c6620686f737461626c65206170706c69636174696f6e20666f7220736176696e67207765622070616765733c2f7374726f6e673e2e20556e6c696b65206f746865722073657276696365732cc2a077616c6c6162616720697320667265652028617320696e2066726565646f6d2920616e64206f70656e20736f757263652e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3820636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c703e576974682074686973206170706c69636174696f6e20796f752077696c6c206e6f74206d69737320636f6e74656e7420616e796d6f72652e203c7374726f6e673e436c69636b2c20736176652c2072656164206974207768656e20796f752077616e743c2f7374726f6e673e2e2049742073617665732074686520636f6e74656e7420796f752073656c65637420736f207468617420796f752063616e2072656164206974207768656e20796f7520686176652074696d652e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3620636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c68323e486f7720697420776f726b733c2f68323e0a3c703e5468616e6b7320746f2074686520626f6f6b6d61726b6c6574206f72203c61207469746c653d22446f776e6c6f6164732220687265663d22687474703a2f2f7777772e77616c6c616261672e6f72672f646f776e6c6f6164732f223e74686972642d7061727479206170706c69636174696f6e733c2f613e2c20796f75207361766520616e2061727469636c6520696e20796f7572c2a077616c6c6162616720746f2072656164206974206c617465722e205468656e2c207768656e20796f75206f70656e20796f75722077616c6c616261672c203c7374726f6e673e796f752063616e20636f6d666f727461626c79207265616420796f75722061727469636c65733c2f7374726f6e673e2e3c2f703e0a3c68323e486f7720746f207573652077616c6c616261673c2f68323e0a3c703e5468657265206172652074776f207761797320746f207573652077616c6c616261673a20796f752063616e203c6120687265663d22687474703a2f2f7777772e77616c6c616261672e6f72672f6672657175656e746c792d61736b65642d7175657374696f6e732f23486f775f63616e5f495f696e7374616c6c5f77616c6c616261675f616e645f776861745f6172655f7468655f726571756972656d656e7473223e696e7374616c6c2069743c2f613ec2a06f6e20796f75722077656220736572766572206f7220796f752063616ec2a03c6120687265663d22687474703a2f2f6170702e696e746865706f6368652e636f6d223e63726561746520616e206163636f756e743c2f613ec2a06174204672616d616261672028776520696e7374616c6c20616e642075706772616465c2a077616c6c6162616720666f7220796f75292e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a, 1);"; 90(3, 'a self hostable application for saving web pages | wallabag', 'https://www.wallabag.org/', 0, 1, 0x0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3820636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c703e77616c6c616261672028666f726d65726c7920706f636865292069732061203c7374726f6e673e73656c6620686f737461626c65206170706c69636174696f6e20666f7220736176696e67207765622070616765733c2f7374726f6e673e2e20556e6c696b65206f746865722073657276696365732cc2a077616c6c6162616720697320667265652028617320696e2066726565646f6d2920616e64206f70656e20736f757263652e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3820636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c703e576974682074686973206170706c69636174696f6e20796f752077696c6c206e6f74206d69737320636f6e74656e7420616e796d6f72652e203c7374726f6e673e436c69636b2c20736176652c2072656164206974207768656e20796f752077616e743c2f7374726f6e673e2e2049742073617665732074686520636f6e74656e7420796f752073656c65637420736f207468617420796f752063616e2072656164206974207768656e20796f7520686176652074696d652e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3620636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c68323e486f7720697420776f726b733c2f68323e0a3c703e5468616e6b7320746f2074686520626f6f6b6d61726b6c6574206f72203c61207469746c653d22446f776e6c6f6164732220687265663d22687474703a2f2f7777772e77616c6c616261672e6f72672f646f776e6c6f6164732f223e74686972642d7061727479206170706c69636174696f6e733c2f613e2c20796f75207361766520616e2061727469636c6520696e20796f7572c2a077616c6c6162616720746f2072656164206974206c617465722e205468656e2c207768656e20796f75206f70656e20796f75722077616c6c616261672c203c7374726f6e673e796f752063616e20636f6d666f727461626c79207265616420796f75722061727469636c65733c2f7374726f6e673e2e3c2f703e0a3c68323e486f7720746f207573652077616c6c616261673c2f68323e0a3c703e5468657265206172652074776f207761797320746f207573652077616c6c616261673a20796f752063616e203c6120687265663d22687474703a2f2f7777772e77616c6c616261672e6f72672f6672657175656e746c792d61736b65642d7175657374696f6e732f23486f775f63616e5f495f696e7374616c6c5f77616c6c616261675f616e645f776861745f6172655f7468655f726571756972656d656e7473223e696e7374616c6c2069743c2f613ec2a06f6e20796f75722077656220736572766572206f7220796f752063616ec2a03c6120687265663d22687474703a2f2f6170702e696e746865706f6368652e636f6d223e63726561746520616e206163636f756e743c2f613ec2a06174204672616d616261672028776520696e7374616c6c20616e642075706772616465c2a077616c6c6162616720666f7220796f75292e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a, 1);";
118 $moreQueries[] = "INSERT INTO `tags` (`id`, `value`) VALUES (1, 'opensource');"; 91 $moreQueries[] = "INSERT INTO `tags` (`id`, `value`) VALUES (1, 'opensource');";
119 $moreQueries[] = "INSERT INTO `tags_entries` (`id`, `entry_id`, `tag_id`) VALUES (1, 2, 1);"; 92 $moreQueries[] = "INSERT INTO `tags_entries` (`id`, `entry_id`, `tag_id`) VALUES (1, 2, 1);";
120 93
121 $sql_structure = file_get_contents('install/mysql.sql'); 94 $sql_structure = file_get_contents('install/mysql.sql');
122 } 95 }
123 else if ($_POST['db_engine'] == 'postgres') { 96 else if ($_POST['db_engine'] == 'postgres') {
124 $db_path = 'pgsql:host=' . $_POST['pg_server'] . ';dbname=' . $_POST['pg_database']; 97 $db_path = 'pgsql:host=' . $_POST['pg_server'] . ';dbname=' . $_POST['pg_database'];
125 $content = str_replace("define ('STORAGE_SERVER', 'localhost');", "define ('STORAGE_SERVER', '".$_POST['pg_server']."');", $content); 98 $content = str_replace("define ('STORAGE_SERVER', 'localhost');", "define ('STORAGE_SERVER', '".$_POST['pg_server']."');", $content);
126 $content = str_replace("define ('STORAGE_DB', 'poche');", "define ('STORAGE_DB', '".$_POST['pg_database']."');", $content); 99 $content = str_replace("define ('STORAGE_DB', 'poche');", "define ('STORAGE_DB', '".$_POST['pg_database']."');", $content);
127 $content = str_replace("define ('STORAGE_USER', 'poche');", "define ('STORAGE_USER', '".$_POST['pg_user']."');", $content); 100 $content = str_replace("define ('STORAGE_USER', 'poche');", "define ('STORAGE_USER', '".$_POST['pg_user']."');", $content);
128 $content = str_replace("define ('STORAGE_PASSWORD', 'poche');", "define ('STORAGE_PASSWORD', '".$_POST['pg_password']."');", $content); 101 $content = str_replace("define ('STORAGE_PASSWORD', 'poche');", "define ('STORAGE_PASSWORD', '".$_POST['pg_password']."');", $content);
129 $handle = new PDO($db_path, $_POST['pg_user'], $_POST['pg_password']); 102 $handle = new PDO($db_path, $_POST['pg_user'], $_POST['pg_password']);
130 103
131 $moreQueries[] = "INSERT INTO entries (title, url, is_read, is_fav, content, user_id) VALUES 104 $moreQueries[] = "INSERT INTO entries (title, url, is_read, is_fav, content, user_id) VALUES
132('Framabag, un nouveau service libre et gratuit', 'http://www.framablog.org/index.php/post/2014/02/05/Framabag-service-libre-gratuit-interview-developpeur', false, false, convert_from(decode('3c68323e556e6520696e74657276696577206465204e69636f6c61732c20736f6e2064c3a976656c6f70706575722e3c2f68323e0a3c703e3c656d3e496c206e6520766f757320612073c3bb72656d656e742070617320c3a96368617070c3a920717565206e6f74726520636f6e736f6d6d6174696f6e20646520636f6e74656e75732064752057656220657374207465727269626c656d656e74206368726f6e6f706861676520657420706172746963756c69c3a872656d656e7420667275737472616e746520746f757420c3a0206c6120666f6973c2a03a206e6f6e207365756c656d656e74206e6f757320706173736f6e732062656175636f7570202874726f70c2a03f292064652074656d707320656e206c69676e6520c3a0206578706c6f726572206c6573206d696e6573206175726966c3a8726573206465206c6120746f696c652c20792064c3a974656374616e742070c3a970697465732065742066696c6f6e732c206d616973206e6f757320736f6d6d657320737572746f757420636f6e7374616d6d656e7420656e206d616e7175652e204dc3aa6d65207369206e6f7573206e6520736f6d6d6573207061732064616e73206c65207a617070696e67206672c3a96ec3a9746971756520736920666163696c656d656e742064c3a96e6f6e63c3a920706172206c657320646f637465732070737963686f6c6f677565732071756920706f6e74696669656e7420737572206c65732064616e67657273206475206e756dc3a9726971756520706f7572206c6573206a65756e65732063657276656c6c65732c20696c206e6f7573207669656e7420736f7576656e74206c6520676fc3bb7420616d6572206465206ce28099696e6163686576c3a9c2a03a20706173206c652074656d707320646520746f7574206c69726520283c6120687265663d22687474703a2f2f66722e77696b74696f6e6172792e6f72672f77696b692f544c4452223e544c3b44523c2f613e2065737420646576656e75206c6520636c696e2064e28099c593696c206d692d6669677565206d692d72616973696e2064e28099756e652067c3a96ec3a9726174696f6e206465206c65637465757273207072657373c3a973292c207061732074726f70206c652074656d70732064652072c3a9666cc3a963686972206e6f6e20706c75732068c3a96c61732c20706173206c652074656d707320646520737569767265206c6120726962616d62656c6c65206465206c69656e73206173736f6369c3a97320c3a020756e2061727469636c65e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e506f7572206e6f757320646f6e6e657220626f6e6e6520636f6e736369656e63652c206e6f75732072616e67656f6e73207363727570756c657573656d656e7420756e206d61727175652d7061676520646520706c75732064616e7320756e20736f75732d646f73736965722071756920656e20636f6d706f7274652064c3a96ac3a0203235362c206e6f7573206e6f746f6e7320756e20c3a96cc3a96d656e7420646520706c75732064616e73206c6120746f756a6f757273207269646963756c656d656e74206c6f6e67756520746f75646f756c697374652c2062726566206e6f75732072656d6574746f6e7320c3a020706c757320746172642c2063e280996573742dc3a02d64697265206c6520706c757320736f7576656e742061757820696e74726f757661626c65732063616c656e6465732067726563717565732c206c6520736f696e206465206c69726520767261696d656e7420756e2061727469636c65206a7567c3a920696e74c3a972657373616e742c20646520726567617264657220756e6520766964c3a96f207369676e616cc3a96520706172206c65732072c3a97a6f73736f63696f732c206465206c69726520756e20636861706974726520656e746965722064e28099756e206f75767261676520646973706f6e69626c6520656e206c69676e65e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e416c6f7273206269656e2073c3bb722c20c3a02064c3a966617574206465206e6f757320646f6e6e657220746f7574206c652074656d70732071756920736572616974206ec3a963657373616972652c2064657320736f6c7574696f6e73206578697374656e7420706f7572206e6f7573207065726d657474726520646520c2abc2a06c69726520706c75732074617264c2a0c2bb20656e20736175766567617264616e74206c65207072c3a9636965757820706f6c6c656e206465206e6f7320627574696e61676573206465207369746520656e20736974652c2065742064e28099656e20666169726520756c74c3a97269657572656d656e7420766f747265206d69656cc2a03b2063e280996573742062656c20657420626f6e206d616973206c65732072756368657320736f6e7420756e207065752064697374616e7465732c20c3a7612073e28099617070656c6c65206c6520636c6f756420286e6f7320616d69732074656368696573206de280996f6e74206269656e206578706c697175c3a9206d616973206ae280996169207365756c656d656e7420636f6d70726973207175652064657320747275637320c3a0206d6f6920736f6e742073757220646573206d616368696e6573206c6f696e7461696e65732c20c3a761206e65206d652072617373757265207061732074726f702920657420656c6c657320736f6e7420736f7576656e742070726f707269c3a97461697265732c206e65206c61697373616e7420656e7472657220717565206c6573203c733e7574696c69736174657572733c2f733e20636f6e736f6d6d61746575727320706179616e74732065742071756920636f6e73656e74656e7420c3a0206c6575727320636f6e646974696f6e732e2053616e7320636f6d70746572207175652064652067726f7320626f7572646f6e73207669656e6e656e742070726f666974657220706c7573206f75206d6f696e73206469736372c3a874656d656e7420646520746f757465732063657320747261636573206465206e6f75732d6dc3aa6d657320717569207065726d657474656e74206465206d6f6ec3a97469736572206e6f7472652070726f66696cc2a03a207369206a6520636f6c6c65637465207375722063657320736572766963657320286e65206c6573206e6f6d6d6f6e73207061732c206a757374656d656e742920756e652073c3a97269652064e2809961727469636c657320737572206ce280996964c3a965206465204e6174757265206368657a2044696465726f742c206a6520726563657672616920646976657273657320736f6c6c696369746174696f6e7320706f757220646576656e697220636c69656e74206465206c6120626f757469717565204e61747572652026616d703b2044c3a9636f75766572746520647520626f756c65766172642044696465726f742e2045742073692064e280996176656e74757265206c65732070726f6772616d6d6573206465206c61204e5341206d6f756c696e656e7420737572206c6520736572766963652c206a6520736572616920706575742dc3aa74726520756e206a6f75722064616e7320756e65206c6973746520646573206d696c6974616e7473206e61747572697374657320696e64c3a973697261626c657320737572206c657320766f6c73206465206c612050616e416d20286a65206e65207361697320706c75732074726f70207369206a6520706c616973616e7465206cc3a02c2066696e616c656d656e74e280a6293c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4c6120626f6e6e65206964c3a965c2a03a20c2abc2a0736520636f6e7374697475657220756e2072c3a9736572766f697220646520646f63756d656e74732073c3a96c656374696f6e6ec3a97320c3a020706172636f7572697220706c75732074617264c2a0c2bb20617070656c61697420646f6e6320756e6520617574726520626f6e6e65206964c3a9652c2063656c6c652064e2809961766f6972206c6520636f6e7472c3b46c652064652063652072c3a9736572766f69722c206465206e6f74726520636f6c6c656374696f6e20706572736f6e6e656c6c652e2043e28099657374204e69636f6c6173204cc59375696c6c65742c2063692d646573736f757320696e74657276696577c3a92c207175692073e28099792065737420636f6c6cc3a9206176656320756e652062656c6c65206170706c69636174696f6e20617070656cc3a96520657568e280a6206f75692c20617070656cc3a9652057616c6c616261672e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4672616d61736f667420736f757469656e742064e28099617574616e7420706c757320736f6e20696e6974696174697665207175e280993c6120687265663d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f696e6465782e7068702f706f73742f323031342f30312f33312f4765656b74696f6e6e6572642d57616c6c61626167223e6f6e206c7569206120636865726368c3a920646573206d6973c3a872657320706f757220756e6520686973746f697265206465206e6f6d3c2f613e206574207175e28099696c2065737420706f737369626c652064e28099696e7374616c6c657220736f692d6dc3aa6d6520756e6520636f7069652064652057616c6c616261672073757220736f6e2070726f70726520736974652e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4c6520706574697420706c7573206465204672616d61736f66742c2072c3a97365617520746f756a6f7572732064c3a973697265757820646520766f75732070726f706f7365722064657320616c7465726e617469766573206c6962c3a972617472696365732c2063e2809965737420646520766f75732070726f706f736572202873757220696e736372697074696f6e207072c3a9616c61626c652920756e20616363c3a873206175204672616d616261672c2061757472656d656e742064697420766f7472652057616c6c616261672073757220756e2073657276657572204672616d612a2061766563206e6f74726520676172616e74696520646520636f6e666964656e7469616c6974c3a92e20436f6d6d6520706f7572206c65204672616d616e6577732c206e6f757320766f7573206163637565696c6c6f6e7320766f6c6f6e74696572732064616e73206c61206c696d697465206465206e6f732063617061636974c3a9732c20656e20766f757320696e766974616e7420c3a020766f7573206c616e6365722064616e7320766f747265206175746f2d68c3a962657267656d656e742064652057616c6c616261672e3c6272202f3e4365742061727469636c65206573742074726f70206c6f6e67c2a03f204d657474657a2d6c652064616e73203c6120687265663d22687474703a2f2f7777772e6672616d616261672e6f72672f696e6465782e706870223e766f747265204672616d616261673c2f613e20657420686f702e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4672616d61626c6f67c2a03a2053616c7574204e69636f6c6173e280a62054752070657578207465207072c3a973656e74657220627269c3a876656d656e74c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e53616c7574c2a0212044c3a976656c6f70706575722050485020646570756973207175656c7175657320616e6ec3a96573206d61696e74656e616e742028313020616e73292c206ae28099616920766f756c75206d652072656d657474726520c3a0206e697665617520746563686e697175656d656e74207061726c616e742028646570756973203320616e732c206ae28099616920706173206d616c206cc3a26368c3a9206c6520636c6176696572292e20506f7572206d6573206265736f696e7320706572736f732c206ae28099616920646f6e63206372c3a9c3a920756e2070657469742070726f6a657420706f75722072656d706c6163657220756e6520736f6c7574696f6e2070726f707269c3a97461697265206578697374616e74652e2053616e7320617563756e65207072c3a974656e74696f6e2c206ae2809961692068c3a962657267c3a92063652070726f6a6574207375722047697468756220657420636f6d6d652063e28099657374206c61207365756c6520736f6c7574696f6e203c656d3e6f70656e20736f757263653c2f656d3e20646520636520747970652c206c65206e6f6d62726520646520706572736f6e6e657320696e74c3a972657373c3a965732061206175676d656e74c3a920e280a63c2f703e0a3c703e3c656d3e4c6573207574696c6973617465757273206465207365727669636573204672616d61736f6674206e65206c6520736176656e742070617320666f7263c3a96d656e742c206d6169732074752061732064c3a96ac3a020706173206d616c207061727469636970c3a920c3a0206c61204672616d6147616c617869652c206e6f6ec2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e456e2065666665742e204ae28099616920636f6d6d656e63c3a920756e20706c7567696e20706f7572204672616d616e6577732c203c6120687265663d2268747470733a2f2f6769746875622e636f6d2f6e69636f736f6d622f74747273732d70757267652d6163636f756e7473223e74747273732d70757267652d6163636f756e74733c2f613e2c20717569207065726d6574206465206e6574746f796572206c61206261736520646520646f6e6ec3a9657320646520636f6d7074657320706c7573207574696c6973c3a9732e204d616973206365203c656d3e706c7567696e3c2f656d3e2061206265736f696e2064e28099c3aa747265207465726d696ec3a920c3a0203130302520706f757220c3aa74726520696e74c3a96772c3a9206175207365696e206465204672616d616e6577732028657420646f6e632064652054696e792054696e7920525353292c207369207175656c7175e28099756e20736f756861697465206de2809961696465722c20696c206ee2809979206120617563756e20736f7563692e3c6272202f3e4ae28099616920617573736920666169742031206f7520322061707061726974696f6e732064616e73206465732074726164756374696f6e7320706f7572204672616d61626c6f672e205269656e2064e2809965787472616f7264696e616972652c206a65206e652073756973207061732062696c696e6775652c20c3a761206d65207065726d6574206465206de28099656e747261c3ae6e65722e3c2f703e0a3c703e3c656d3e5061726c6f6e73206465207375697465206465206365207175692066c3a2636865c2a03a20746f6e206170706c69636174696f6e2057616c6c616261672c20656c6c652073e28099617070656c6c6169742070617320e2809c506f636865e2809d2c206176616e74c2a03f205475206e6f7573207261636f6e746573206ce28099686973746f697265c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e45756820656e20656666657420e280a62044c3a96ac3a02c20706f757271756f69203c656d3e706f6368653c2f656d3ec2a03f20506172636520717565206ce28099756e206465732074726f697320c2abc2a074c3a96e6f7273c2a0c2bb20737572206c65206d61726368c3a92073e28099617070656c6c65203c656d3e506f636b65743c2f656d3e2e20436f6d6d65206d6f6e206170706c69206ee28099c3a9746169742064657374696ec3a965207175e28099c3a0206d6f6e20757361676520706572736f6e6e656c2061752064c3a9706172742c206a65206e65206d6520737569732070617320746f72747572c3a9206269656e206c6f6e6774656d70732e3c2f703e0a3c703e43657420c3a974c3a92c206f6e2061206661696c6c69206368616e676572206465206e6f6d2c207175616e6420696c2079206120657520646520706c757320656e20706c75732064e280997574696c69736174657572732e2045742070756973206f6e2073e28099657374206469742071756520706f6368652c2063e28099c3a97461697420706173206d616c2c20c3a76120736f6e6e616974206269656e206672616ec3a761697320657420707569732061766563206c6573207175656c717565732064697a61696e65732064e280997574696c69736174657572732c206f6e206e652067c3aa6e657261697420706572736f6e6e652e3c2f703e0a3c703e43e280996573742073616e7320636f6d707465722061766563206c657320736f6369c3a974c3a97320616dc3a972696361696e6573206574206c6575722066c3a2636865757365206d616e696520646520766f756c6f697220656e766f796572206c657572732061766f6361747320c3a020746f757420626f7574206465206368616d702e204c65203233206a616e766965722c206ae280996169207265c3a77520756e20656d61696c206465206c61207061727420647520636162696e65742064e2809961766f6361747320646520506f636b6574206d652064656d616e64616e74206465206368616e676572206c65206e6f6d2c206c65206c6f676f2c206465206e6520706c7573207574696c69736572206c65207465726d6520e2809c726561642d69742d6c61746572e2809d2028c2abc2a06c6973657a206c6520706c75732074617264c2a0c2bb29206574206465206e6520706c757320646972652071756520506f636b6574206ee280996573742070617320677261747569742028746f7574206573742070617274692064e280993c6120687265663d2268747470733a2f2f747769747465722e636f6d2f77616c6c616261676170702f7374617475732f343233373836333635393434323235373932223e756e2074776565743c2f613e206fc3b9206a65207175616c6966696520506f636b657420646520c2abc2a06e6f6e2066726565c2a0c2bb20c3a0207361766f6972206e6f6e206c69627265292e20427265662c206dc3aa6d65207369206a652073656d626c6169732064616e73206d6f6e2064726f69742c206ae280996169207175616e64206dc3aa6d652070726973206c612064c3a9636973696f6e206465206368616e676572206465206e6f6d2065742057616c6c6162616720657374206ec3a92c20737569746520617578203c6120687265663d22687474703a2f2f6672616d61646174652e6f72672f73747564732e7068703f736f6e646167653d6c6c6370366f6a70796339706b6c6861223e64697a61696e65732064652070726f706f736974696f6e73206465206e6f6d207265c3a77565733c2f613e2e2043e2809965737420756e206dc3a96c616e676520656e747265206c652077616c6c61627920286465206c612066616d696c6c6520646573206b616e676f75726f75732c207175692073746f636b656e742064616e73206c65757220706f63686520636520717569206c65757220657374206368657229206574203c656d3e6261673c2f656d3e20286c6573207465726d657320736163202f207361636f636865202f2062657361636520736f6e7420c3a96e6f726dc3a96d656e7420726576656e7573292e204d616973206d61696e74656e616e742c206f6e207661206465206ce280996176616e742c20706c75732064652074656d707320c3a020706572647265206176656320c3a7612c206f6e2061206475207061696e20737572206c6120706c616e6368652e3c6272202f3e3c696d67207372633d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f7075626c69632f5f696d672f6672616d61626c6f672f77616c6c6162795f626162792e6a70672220616c743d2277616c6c61627920617665632062c3a962c3a92064616e7320736120706f6368652220636c6173733d22633122207469746c653d2277616c6c61627920617665632062c3a962c3a92064616e7320736120706f63686522202f3e206372c3a96469742070686f746f203c6120687265663d22687474703a2f2f7777772e666c69636b722e636f6d2f70686f746f732f3236373832383634404e30302f353032373230323233342f696e2f70686f746f6c6973742d3845654a35412d6831544c36762d4e454c38312d636e4e6b536f2d39594d3174762d374b636736622d387a70416f612d61315a4c4d4e2d39594d3339722d3768355341442d38456548664c2d3845654677752d647456776e4d2d38756f4d45312d4a457a58652d47713471792d3932564a50522d43786531762d38483344324a2d61315a464e732d395937324b362d38456547784c2d354c353346782d354e6b454e732d3555384354592d354e6b7373682d6e6b6176462d3943726777502d3773644341612d647566324b682d685a65707a792d685a645531652d685a656f66462d685a656b44672d685a656741592d685a654d5a6e2d6a61486741662d3850383744322d354e677152762d6154343851422d685a645634592d685a654336342d45526770732d3556594747642d3556594a42312d354e6b72466b2d364a786837682d3768395075512d4552664d782d6831553169682d683155534278223e57696c6c69616d2057617262793c2f613e20717569206175746f72697365206578706c69636974656d656e7420746f7574652072c3a97574696c69736174696f6e2e3c2f703e0a3c703e3c656d3e426f6e2c20616c6f7273206578706c697175652d6d6f6920636520717565206a65207661697320706f75766f69722066616972652061766563204672616d61626167e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e416c6f7273204672616d616261672c20c3a761207465207065726d6574206465207465206372c3a9657220756e20636f6d7074652067726174756974656d656e74206574206c696272656d656e7420706f757220706f75766f6972207574696c697365722057616c6c616261672e205365756c6520746f6e206164726573736520656d61696c20657374206ec3a963657373616972652c206f6e207365206368617267652064e28099696e7374616c6c6572206574206465206d657474726520c3a0206a6f75722057616c6c6162616720706f757220746f692e20547520706575782064e2809961696c6c657572732070726f6669746572203c6120687265663d22687474703a2f2f7777772e6672616d61736f66742e6e65742f23746f705067436c6f7564223e64e280996175747265732073657276696365732070726f706f73c3a97320706172204672616d61736f6674206963693c2f613e2e3c2f703e0a3c703ec380206365206a6f75722c20696c207920612038333420636f6d70746573206372c3a9c3a97320737572204672616d616261672e3c2f703e0a3c703e3c656d3e566f7573206176657a20767261696d656e7420636f6ec3a7752063652073657276696365206166696e207175e280996f6e20707569737365206ce280997574696c69736572206176656320756e206d6178696d756d2064e280996f7574696c732c206e6f6ec2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4175746f7572206465206ce280996170706c69636174696f6e207765622c20696c206578697374652064c3a96ac3a020646573206170706c69636174696f6e7320706f757220736d61727470686f6e65732028416e64726f69642065742057696e646f77732050686f6e65292c2064657320657874656e73696f6e732046697265666f7820657420476f6f676c65204368726f6d652e3c2f703e0a3c703e436f6d6d652057616c6c6162616720706f7373c3a864652064657320666c7578205253532c2063e2809965737420666163696c65206465206c697265206c65732061727469636c657320736175766567617264c3a97320737572207361206c697365757365202873692063656c6c652d6369207065726d6574206465206c6972652064657320666c757820525353292e2043616c696272652028c2abc2a06c6f67696369656c206465206c6563747572652c2064652067657374696f6e206465206269626c696f7468c3a87175657320657420646520636f6e76657273696f6e206465206669636869657273206e756dc3a972697175657320646520747970652065626f6f6b206f75206c6976726520c3a96c656374726f6e69717565c2a0c2bb2c6e6f757320646974207562756e74752d66722e6f72672920696e74c3a867726520646570756973207175656c717565732073656d61696e6573206d61696e74656e616e74206c6120706f73736962696c6974c3a92064652072c3a9637570c3a9726572206c65732061727469636c6573206e6f6e206c75732c20707261746971756520706f757220666169726520756e20666963686965722065507562c2a0213c2f703e0a3c703e44e28099617574726573206170706c69636174696f6e7320776562207065726d657474656e74206ce28099696e74c3a967726174696f6e20617665632057616c6c61626167202846726573685253532c204c6565642065742054696e792054696e792052535320706f7572206c657320616772c3a96761746575727320646520666c7578292e204ce2809941504920717569207365726120646973706f6e69626c652064616e73206c612070726f636861696e652076657273696f6e2064652057616c6c61626167207065726d657474726120656e636f726520706c75732064e28099696e74657261637469766974c3a92e3c2f703e0a3c703e3c656d3e5920612d742d696c20756e206d6f6465206465206c65637475726520686f7273206c69676e65206f75206573742d6365207175652063e28099657374207072c3a9767520706f7572206c65732070726f636861696e65732076657273696f6e73c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e496c2079206120756e2070736575646f206d6f646520686f7273206c69676e652c20646973706f6e69626c652061766563206ce280996170706c69636174696f6e20416e64726f69642e204f6e20706575742072c3a9637570c3a9726572202876696120756e20666c75782052535329206c65732061727469636c6573206e6f6e206c757320717565206ce280996f6e206120736175766567617264c3a9732e20556e6520666f69732064c3a9636f6e6e656374c3a92c206f6e207065757420636f6e74696e75657220c3a0206c6972652073757220736f6e20736d61727470686f6e65206f75207361207461626c65747465206c65732061727469636c65732e2050617220636f6e7472652c20696c206d616e7175652064657320666f6e6374696f6e6e616c6974c3a973c2a03a207175616e64207475206d61727175657320756e2061727469636c6520636f6d6d65206c752c206365206ee28099657374207061732073796e6368726f6e6973c3a92061766563206c612076657273696f6e207765622064652057616c6c616261672e204ae28099657370c3a8726520717565206a652073756973207072657371756520636c6169722064616e73206d6573206578706c69636174696f6e732e3c2f703e0a3c703e506f7572206c612076322c20717569206573742064c3a96ac3a020656e20636f7572732064652064c3a976656c6f7070656d656e742c206fc3b9206a652073756973206269656e20616964c3a9207061722056696e63656e74204a6f757373652c206f6e2061757261206c6120706f73736962696c6974c3a92064e2809961766f697220756e2076726169206d6f646520686f7273206c69676e652e3c2f703e0a3c703e3c656d3e416c6f7273207369206f6e2076657574206169646572202f2070617274696369706572202f20747269666f75696c6c6572206c6520636f6465202f20766f757320656e766f79657220646573207265746f7572732c206f6e206661697420636f6d6d656e74c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4f6e207065757420616964657220646520706c75736965757273206661c3a76f6e73c2a03a3c2f703e0a3c756c3e3c6c693e7574696c697365722077616c6c61626167206574206e6f75732072656d6f6e746572206c65732070726f626cc3a86d65732072656e636f6e7472c3a973c2a03b3c2f6c693e0a3c6c693e706172746963697065722061752064c3a976656c6f7070656d656e74206465206ce280996170706c69636174696f6e2068747470733a2f2f6769746875622e636f6d2f77616c6c616261672f77616c6c616261672053692053696c6578202f2053796d666f6e7932202f2048544d4c35202f206574632e207465207061726c656e742c206ee2809968c3a97369746520706173c2a0213c2f6c693e0a3c6c693e636f6d6d6520746f75742070726f6a65742c206c652067726f7320706f696e74206e6f697220657374206c65206d616e71756520646520646f63756d656e746174696f6e2e203c6120687265663d22687474703a2f2f646f632e77616c6c616261672e6f7267223e456c6c652065737420646973706f206963693c2f613e206d61697320696c206d616e71756520706c65696e2064652063686f73657320657420746f7574206ee280996573742070617320c3a0206a6f7572c2a03b3c2f6c693e0a3c6c693e7061726c65722064652057616c6c61626167206175746f757220646520766f7573c2a03b3c2f6c693e0a3c6c693e696c20657869737465203c6120687265663d2268747470733a2f2f666c617474722e636f6d2f7468696e672f313236353438302f706f6368652d612d726561642d69742d6c617465722d6f70656e2d736f757263652d73797374656d223e756e20636f6d70746520466c617474723c2f613e2e3c2f6c693e0a3c2f756c3e3c703e3c656d3e4c65206d6f74206465206c612066696ee280a63f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4d6572636920c3a0204672616d61736f66742064e280996163637565696c6c697220657420646520736f7574656e69722057616c6c61626167c2a0213c2f703e0a3c703e4c6120726f7574652065737420656e636f7265206269656e206c6f6e67756520706f7572206e6520706c7573207574696c6973657220646520736f6c7574696f6e732070726f707269c3a97461697265732c206d616973206f6e2064657672616974207920617272697665722c206e6f6ec2a03f3c2f703e0a3c703e3c696d67207372633d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f7075626c69632f5f696d672f6672616d61626c6f672f706c65696e4c6573506f636865732e706e672220616c743d226672616d61736f667420706c65696e206c657320706f636865732220636c6173733d22633122207469746c653d226672616d61736f667420706c65696e206c657320706f6368657322202f3e3c6272202f3e3c6120687265663d22687474703a2f2f6672616d616c61622e6f72672f676b6e642d63726561746f722f223e6861636b657a2047c3a967c3a9c2a0213c2f613e3c2f703e0a', 'hex'), 'UTF8'), 1), 105('Framabag, un nouveau service libre et gratuit', 'http://www.framablog.org/index.php/post/2014/02/05/Framabag-service-libre-gratuit-interview-developpeur', false, false, convert_from(decode('3c68323e556e6520696e74657276696577206465204e69636f6c61732c20736f6e2064c3a976656c6f70706575722e3c2f68323e0a3c703e3c656d3e496c206e6520766f757320612073c3bb72656d656e742070617320c3a96368617070c3a920717565206e6f74726520636f6e736f6d6d6174696f6e20646520636f6e74656e75732064752057656220657374207465727269626c656d656e74206368726f6e6f706861676520657420706172746963756c69c3a872656d656e7420667275737472616e746520746f757420c3a0206c6120666f6973c2a03a206e6f6e207365756c656d656e74206e6f757320706173736f6e732062656175636f7570202874726f70c2a03f292064652074656d707320656e206c69676e6520c3a0206578706c6f726572206c6573206d696e6573206175726966c3a8726573206465206c6120746f696c652c20792064c3a974656374616e742070c3a970697465732065742066696c6f6e732c206d616973206e6f757320736f6d6d657320737572746f757420636f6e7374616d6d656e7420656e206d616e7175652e204dc3aa6d65207369206e6f7573206e6520736f6d6d6573207061732064616e73206c65207a617070696e67206672c3a96ec3a9746971756520736920666163696c656d656e742064c3a96e6f6e63c3a920706172206c657320646f637465732070737963686f6c6f677565732071756920706f6e74696669656e7420737572206c65732064616e67657273206475206e756dc3a9726971756520706f7572206c6573206a65756e65732063657276656c6c65732c20696c206e6f7573207669656e7420736f7576656e74206c6520676fc3bb7420616d6572206465206ce28099696e6163686576c3a9c2a03a20706173206c652074656d707320646520746f7574206c69726520283c6120687265663d22687474703a2f2f66722e77696b74696f6e6172792e6f72672f77696b692f544c4452223e544c3b44523c2f613e2065737420646576656e75206c6520636c696e2064e28099c593696c206d692d6669677565206d692d72616973696e2064e28099756e652067c3a96ec3a9726174696f6e206465206c65637465757273207072657373c3a973292c207061732074726f70206c652074656d70732064652072c3a9666cc3a963686972206e6f6e20706c75732068c3a96c61732c20706173206c652074656d707320646520737569767265206c6120726962616d62656c6c65206465206c69656e73206173736f6369c3a97320c3a020756e2061727469636c65e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e506f7572206e6f757320646f6e6e657220626f6e6e6520636f6e736369656e63652c206e6f75732072616e67656f6e73207363727570756c657573656d656e7420756e206d61727175652d7061676520646520706c75732064616e7320756e20736f75732d646f73736965722071756920656e20636f6d706f7274652064c3a96ac3a0203235362c206e6f7573206e6f746f6e7320756e20c3a96cc3a96d656e7420646520706c75732064616e73206c6120746f756a6f757273207269646963756c656d656e74206c6f6e67756520746f75646f756c697374652c2062726566206e6f75732072656d6574746f6e7320c3a020706c757320746172642c2063e280996573742dc3a02d64697265206c6520706c757320736f7576656e742061757820696e74726f757661626c65732063616c656e6465732067726563717565732c206c6520736f696e206465206c69726520767261696d656e7420756e2061727469636c65206a7567c3a920696e74c3a972657373616e742c20646520726567617264657220756e6520766964c3a96f207369676e616cc3a96520706172206c65732072c3a97a6f73736f63696f732c206465206c69726520756e20636861706974726520656e746965722064e28099756e206f75767261676520646973706f6e69626c6520656e206c69676e65e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e416c6f7273206269656e2073c3bb722c20c3a02064c3a966617574206465206e6f757320646f6e6e657220746f7574206c652074656d70732071756920736572616974206ec3a963657373616972652c2064657320736f6c7574696f6e73206578697374656e7420706f7572206e6f7573207065726d657474726520646520c2abc2a06c69726520706c75732074617264c2a0c2bb20656e20736175766567617264616e74206c65207072c3a9636965757820706f6c6c656e206465206e6f7320627574696e61676573206465207369746520656e20736974652c2065742064e28099656e20666169726520756c74c3a97269657572656d656e7420766f747265206d69656cc2a03b2063e280996573742062656c20657420626f6e206d616973206c65732072756368657320736f6e7420756e207065752064697374616e7465732c20c3a7612073e28099617070656c6c65206c6520636c6f756420286e6f7320616d69732074656368696573206de280996f6e74206269656e206578706c697175c3a9206d616973206ae280996169207365756c656d656e7420636f6d70726973207175652064657320747275637320c3a0206d6f6920736f6e742073757220646573206d616368696e6573206c6f696e7461696e65732c20c3a761206e65206d652072617373757265207061732074726f702920657420656c6c657320736f6e7420736f7576656e742070726f707269c3a97461697265732c206e65206c61697373616e7420656e7472657220717565206c6573203c733e7574696c69736174657572733c2f733e20636f6e736f6d6d61746575727320706179616e74732065742071756920636f6e73656e74656e7420c3a0206c6575727320636f6e646974696f6e732e2053616e7320636f6d70746572207175652064652067726f7320626f7572646f6e73207669656e6e656e742070726f666974657220706c7573206f75206d6f696e73206469736372c3a874656d656e7420646520746f757465732063657320747261636573206465206e6f75732d6dc3aa6d657320717569207065726d657474656e74206465206d6f6ec3a97469736572206e6f7472652070726f66696cc2a03a207369206a6520636f6c6c65637465207375722063657320736572766963657320286e65206c6573206e6f6d6d6f6e73207061732c206a757374656d656e742920756e652073c3a97269652064e2809961727469636c657320737572206ce280996964c3a965206465204e6174757265206368657a2044696465726f742c206a6520726563657672616920646976657273657320736f6c6c696369746174696f6e7320706f757220646576656e697220636c69656e74206465206c6120626f757469717565204e61747572652026616d703b2044c3a9636f75766572746520647520626f756c65766172642044696465726f742e2045742073692064e280996176656e74757265206c65732070726f6772616d6d6573206465206c61204e5341206d6f756c696e656e7420737572206c6520736572766963652c206a6520736572616920706575742dc3aa74726520756e206a6f75722064616e7320756e65206c6973746520646573206d696c6974616e7473206e61747572697374657320696e64c3a973697261626c657320737572206c657320766f6c73206465206c612050616e416d20286a65206e65207361697320706c75732074726f70207369206a6520706c616973616e7465206cc3a02c2066696e616c656d656e74e280a6293c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4c6120626f6e6e65206964c3a965c2a03a20c2abc2a0736520636f6e7374697475657220756e2072c3a9736572766f697220646520646f63756d656e74732073c3a96c656374696f6e6ec3a97320c3a020706172636f7572697220706c75732074617264c2a0c2bb20617070656c61697420646f6e6320756e6520617574726520626f6e6e65206964c3a9652c2063656c6c652064e2809961766f6972206c6520636f6e7472c3b46c652064652063652072c3a9736572766f69722c206465206e6f74726520636f6c6c656374696f6e20706572736f6e6e656c6c652e2043e28099657374204e69636f6c6173204cc59375696c6c65742c2063692d646573736f757320696e74657276696577c3a92c207175692073e28099792065737420636f6c6cc3a9206176656320756e652062656c6c65206170706c69636174696f6e20617070656cc3a96520657568e280a6206f75692c20617070656cc3a9652057616c6c616261672e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4672616d61736f667420736f757469656e742064e28099617574616e7420706c757320736f6e20696e6974696174697665207175e280993c6120687265663d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f696e6465782e7068702f706f73742f323031342f30312f33312f4765656b74696f6e6e6572642d57616c6c61626167223e6f6e206c7569206120636865726368c3a920646573206d6973c3a872657320706f757220756e6520686973746f697265206465206e6f6d3c2f613e206574207175e28099696c2065737420706f737369626c652064e28099696e7374616c6c657220736f692d6dc3aa6d6520756e6520636f7069652064652057616c6c616261672073757220736f6e2070726f70726520736974652e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4c6520706574697420706c7573206465204672616d61736f66742c2072c3a97365617520746f756a6f7572732064c3a973697265757820646520766f75732070726f706f7365722064657320616c7465726e617469766573206c6962c3a972617472696365732c2063e2809965737420646520766f75732070726f706f736572202873757220696e736372697074696f6e207072c3a9616c61626c652920756e20616363c3a873206175204672616d616261672c2061757472656d656e742064697420766f7472652057616c6c616261672073757220756e2073657276657572204672616d612a2061766563206e6f74726520676172616e74696520646520636f6e666964656e7469616c6974c3a92e20436f6d6d6520706f7572206c65204672616d616e6577732c206e6f757320766f7573206163637565696c6c6f6e7320766f6c6f6e74696572732064616e73206c61206c696d697465206465206e6f732063617061636974c3a9732c20656e20766f757320696e766974616e7420c3a020766f7573206c616e6365722064616e7320766f747265206175746f2d68c3a962657267656d656e742064652057616c6c616261672e3c6272202f3e4365742061727469636c65206573742074726f70206c6f6e67c2a03f204d657474657a2d6c652064616e73203c6120687265663d22687474703a2f2f7777772e6672616d616261672e6f72672f696e6465782e706870223e766f747265204672616d616261673c2f613e20657420686f702e3c6272202f3e3c2f656d3e3c2f703e0a3c703e3c656d3e4672616d61626c6f67c2a03a2053616c7574204e69636f6c6173e280a62054752070657578207465207072c3a973656e74657220627269c3a876656d656e74c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e53616c7574c2a0212044c3a976656c6f70706575722050485020646570756973207175656c7175657320616e6ec3a96573206d61696e74656e616e742028313020616e73292c206ae28099616920766f756c75206d652072656d657474726520c3a0206e697665617520746563686e697175656d656e74207061726c616e742028646570756973203320616e732c206ae28099616920706173206d616c206cc3a26368c3a9206c6520636c6176696572292e20506f7572206d6573206265736f696e7320706572736f732c206ae28099616920646f6e63206372c3a9c3a920756e2070657469742070726f6a657420706f75722072656d706c6163657220756e6520736f6c7574696f6e2070726f707269c3a97461697265206578697374616e74652e2053616e7320617563756e65207072c3a974656e74696f6e2c206ae2809961692068c3a962657267c3a92063652070726f6a6574207375722047697468756220657420636f6d6d652063e28099657374206c61207365756c6520736f6c7574696f6e203c656d3e6f70656e20736f757263653c2f656d3e20646520636520747970652c206c65206e6f6d62726520646520706572736f6e6e657320696e74c3a972657373c3a965732061206175676d656e74c3a920e280a63c2f703e0a3c703e3c656d3e4c6573207574696c6973617465757273206465207365727669636573204672616d61736f6674206e65206c6520736176656e742070617320666f7263c3a96d656e742c206d6169732074752061732064c3a96ac3a020706173206d616c207061727469636970c3a920c3a0206c61204672616d6147616c617869652c206e6f6ec2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e456e2065666665742e204ae28099616920636f6d6d656e63c3a920756e20706c7567696e20706f7572204672616d616e6577732c203c6120687265663d2268747470733a2f2f6769746875622e636f6d2f6e69636f736f6d622f74747273732d70757267652d6163636f756e7473223e74747273732d70757267652d6163636f756e74733c2f613e2c20717569207065726d6574206465206e6574746f796572206c61206261736520646520646f6e6ec3a9657320646520636f6d7074657320706c7573207574696c6973c3a9732e204d616973206365203c656d3e706c7567696e3c2f656d3e2061206265736f696e2064e28099c3aa747265207465726d696ec3a920c3a0203130302520706f757220c3aa74726520696e74c3a96772c3a9206175207365696e206465204672616d616e6577732028657420646f6e632064652054696e792054696e7920525353292c207369207175656c7175e28099756e20736f756861697465206de2809961696465722c20696c206ee2809979206120617563756e20736f7563692e3c6272202f3e4ae28099616920617573736920666169742031206f7520322061707061726974696f6e732064616e73206465732074726164756374696f6e7320706f7572204672616d61626c6f672e205269656e2064e2809965787472616f7264696e616972652c206a65206e652073756973207061732062696c696e6775652c20c3a761206d65207065726d6574206465206de28099656e747261c3ae6e65722e3c2f703e0a3c703e3c656d3e5061726c6f6e73206465207375697465206465206365207175692066c3a2636865c2a03a20746f6e206170706c69636174696f6e2057616c6c616261672c20656c6c652073e28099617070656c6c6169742070617320e2809c506f636865e2809d2c206176616e74c2a03f205475206e6f7573207261636f6e746573206ce28099686973746f697265c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e45756820656e20656666657420e280a62044c3a96ac3a02c20706f757271756f69203c656d3e706f6368653c2f656d3ec2a03f20506172636520717565206ce28099756e206465732074726f697320c2abc2a074c3a96e6f7273c2a0c2bb20737572206c65206d61726368c3a92073e28099617070656c6c65203c656d3e506f636b65743c2f656d3e2e20436f6d6d65206d6f6e206170706c69206ee28099c3a9746169742064657374696ec3a965207175e28099c3a0206d6f6e20757361676520706572736f6e6e656c2061752064c3a9706172742c206a65206e65206d6520737569732070617320746f72747572c3a9206269656e206c6f6e6774656d70732e3c2f703e0a3c703e43657420c3a974c3a92c206f6e2061206661696c6c69206368616e676572206465206e6f6d2c207175616e6420696c2079206120657520646520706c757320656e20706c75732064e280997574696c69736174657572732e2045742070756973206f6e2073e28099657374206469742071756520706f6368652c2063e28099c3a97461697420706173206d616c2c20c3a76120736f6e6e616974206269656e206672616ec3a761697320657420707569732061766563206c6573207175656c717565732064697a61696e65732064e280997574696c69736174657572732c206f6e206e652067c3aa6e657261697420706572736f6e6e652e3c2f703e0a3c703e43e280996573742073616e7320636f6d707465722061766563206c657320736f6369c3a974c3a97320616dc3a972696361696e6573206574206c6575722066c3a2636865757365206d616e696520646520766f756c6f697220656e766f796572206c657572732061766f6361747320c3a020746f757420626f7574206465206368616d702e204c65203233206a616e766965722c206ae280996169207265c3a77520756e20656d61696c206465206c61207061727420647520636162696e65742064e2809961766f6361747320646520506f636b6574206d652064656d616e64616e74206465206368616e676572206c65206e6f6d2c206c65206c6f676f2c206465206e6520706c7573207574696c69736572206c65207465726d6520e2809c726561642d69742d6c61746572e2809d2028c2abc2a06c6973657a206c6520706c75732074617264c2a0c2bb29206574206465206e6520706c757320646972652071756520506f636b6574206ee280996573742070617320677261747569742028746f7574206573742070617274692064e280993c6120687265663d2268747470733a2f2f747769747465722e636f6d2f77616c6c616261676170702f7374617475732f343233373836333635393434323235373932223e756e2074776565743c2f613e206fc3b9206a65207175616c6966696520506f636b657420646520c2abc2a06e6f6e2066726565c2a0c2bb20c3a0207361766f6972206e6f6e206c69627265292e20427265662c206dc3aa6d65207369206a652073656d626c6169732064616e73206d6f6e2064726f69742c206ae280996169207175616e64206dc3aa6d652070726973206c612064c3a9636973696f6e206465206368616e676572206465206e6f6d2065742057616c6c6162616720657374206ec3a92c20737569746520617578203c6120687265663d22687474703a2f2f6672616d61646174652e6f72672f73747564732e7068703f736f6e646167653d6c6c6370366f6a70796339706b6c6861223e64697a61696e65732064652070726f706f736974696f6e73206465206e6f6d207265c3a77565733c2f613e2e2043e2809965737420756e206dc3a96c616e676520656e747265206c652077616c6c61627920286465206c612066616d696c6c6520646573206b616e676f75726f75732c207175692073746f636b656e742064616e73206c65757220706f63686520636520717569206c65757220657374206368657229206574203c656d3e6261673c2f656d3e20286c6573207465726d657320736163202f207361636f636865202f2062657361636520736f6e7420c3a96e6f726dc3a96d656e7420726576656e7573292e204d616973206d61696e74656e616e742c206f6e207661206465206ce280996176616e742c20706c75732064652074656d707320c3a020706572647265206176656320c3a7612c206f6e2061206475207061696e20737572206c6120706c616e6368652e3c6272202f3e3c696d67207372633d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f7075626c69632f5f696d672f6672616d61626c6f672f77616c6c6162795f626162792e6a70672220616c743d2277616c6c61627920617665632062c3a962c3a92064616e7320736120706f6368652220636c6173733d22633122207469746c653d2277616c6c61627920617665632062c3a962c3a92064616e7320736120706f63686522202f3e206372c3a96469742070686f746f203c6120687265663d22687474703a2f2f7777772e666c69636b722e636f6d2f70686f746f732f3236373832383634404e30302f353032373230323233342f696e2f70686f746f6c6973742d3845654a35412d6831544c36762d4e454c38312d636e4e6b536f2d39594d3174762d374b636736622d387a70416f612d61315a4c4d4e2d39594d3339722d3768355341442d38456548664c2d3845654677752d647456776e4d2d38756f4d45312d4a457a58652d47713471792d3932564a50522d43786531762d38483344324a2d61315a464e732d395937324b362d38456547784c2d354c353346782d354e6b454e732d3555384354592d354e6b7373682d6e6b6176462d3943726777502d3773644341612d647566324b682d685a65707a792d685a645531652d685a656f66462d685a656b44672d685a656741592d685a654d5a6e2d6a61486741662d3850383744322d354e677152762d6154343851422d685a645634592d685a654336342d45526770732d3556594747642d3556594a42312d354e6b72466b2d364a786837682d3768395075512d4552664d782d6831553169682d683155534278223e57696c6c69616d2057617262793c2f613e20717569206175746f72697365206578706c69636974656d656e7420746f7574652072c3a97574696c69736174696f6e2e3c2f703e0a3c703e3c656d3e426f6e2c20616c6f7273206578706c697175652d6d6f6920636520717565206a65207661697320706f75766f69722066616972652061766563204672616d61626167e280a63c6272202f3e3c2f656d3e3c2f703e0a3c703e416c6f7273204672616d616261672c20c3a761207465207065726d6574206465207465206372c3a9657220756e20636f6d7074652067726174756974656d656e74206574206c696272656d656e7420706f757220706f75766f6972207574696c697365722057616c6c616261672e205365756c6520746f6e206164726573736520656d61696c20657374206ec3a963657373616972652c206f6e207365206368617267652064e28099696e7374616c6c6572206574206465206d657474726520c3a0206a6f75722057616c6c6162616720706f757220746f692e20547520706575782064e2809961696c6c657572732070726f6669746572203c6120687265663d22687474703a2f2f7777772e6672616d61736f66742e6e65742f23746f705067436c6f7564223e64e280996175747265732073657276696365732070726f706f73c3a97320706172204672616d61736f6674206963693c2f613e2e3c2f703e0a3c703ec380206365206a6f75722c20696c207920612038333420636f6d70746573206372c3a9c3a97320737572204672616d616261672e3c2f703e0a3c703e3c656d3e566f7573206176657a20767261696d656e7420636f6ec3a7752063652073657276696365206166696e207175e280996f6e20707569737365206ce280997574696c69736572206176656320756e206d6178696d756d2064e280996f7574696c732c206e6f6ec2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4175746f7572206465206ce280996170706c69636174696f6e207765622c20696c206578697374652064c3a96ac3a020646573206170706c69636174696f6e7320706f757220736d61727470686f6e65732028416e64726f69642065742057696e646f77732050686f6e65292c2064657320657874656e73696f6e732046697265666f7820657420476f6f676c65204368726f6d652e3c2f703e0a3c703e436f6d6d652057616c6c6162616720706f7373c3a864652064657320666c7578205253532c2063e2809965737420666163696c65206465206c697265206c65732061727469636c657320736175766567617264c3a97320737572207361206c697365757365202873692063656c6c652d6369207065726d6574206465206c6972652064657320666c757820525353292e2043616c696272652028c2abc2a06c6f67696369656c206465206c6563747572652c2064652067657374696f6e206465206269626c696f7468c3a87175657320657420646520636f6e76657273696f6e206465206669636869657273206e756dc3a972697175657320646520747970652065626f6f6b206f75206c6976726520c3a96c656374726f6e69717565c2a0c2bb2c6e6f757320646974207562756e74752d66722e6f72672920696e74c3a867726520646570756973207175656c717565732073656d61696e6573206d61696e74656e616e74206c6120706f73736962696c6974c3a92064652072c3a9637570c3a9726572206c65732061727469636c6573206e6f6e206c75732c20707261746971756520706f757220666169726520756e20666963686965722065507562c2a0213c2f703e0a3c703e44e28099617574726573206170706c69636174696f6e7320776562207065726d657474656e74206ce28099696e74c3a967726174696f6e20617665632057616c6c61626167202846726573685253532c204c6565642065742054696e792054696e792052535320706f7572206c657320616772c3a96761746575727320646520666c7578292e204ce2809941504920717569207365726120646973706f6e69626c652064616e73206c612070726f636861696e652076657273696f6e2064652057616c6c61626167207065726d657474726120656e636f726520706c75732064e28099696e74657261637469766974c3a92e3c2f703e0a3c703e3c656d3e5920612d742d696c20756e206d6f6465206465206c65637475726520686f7273206c69676e65206f75206573742d6365207175652063e28099657374207072c3a9767520706f7572206c65732070726f636861696e65732076657273696f6e73c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e496c2079206120756e2070736575646f206d6f646520686f7273206c69676e652c20646973706f6e69626c652061766563206ce280996170706c69636174696f6e20416e64726f69642e204f6e20706575742072c3a9637570c3a9726572202876696120756e20666c75782052535329206c65732061727469636c6573206e6f6e206c757320717565206ce280996f6e206120736175766567617264c3a9732e20556e6520666f69732064c3a9636f6e6e656374c3a92c206f6e207065757420636f6e74696e75657220c3a0206c6972652073757220736f6e20736d61727470686f6e65206f75207361207461626c65747465206c65732061727469636c65732e2050617220636f6e7472652c20696c206d616e7175652064657320666f6e6374696f6e6e616c6974c3a973c2a03a207175616e64207475206d61727175657320756e2061727469636c6520636f6d6d65206c752c206365206ee28099657374207061732073796e6368726f6e6973c3a92061766563206c612076657273696f6e207765622064652057616c6c616261672e204ae28099657370c3a8726520717565206a652073756973207072657371756520636c6169722064616e73206d6573206578706c69636174696f6e732e3c2f703e0a3c703e506f7572206c612076322c20717569206573742064c3a96ac3a020656e20636f7572732064652064c3a976656c6f7070656d656e742c206fc3b9206a652073756973206269656e20616964c3a9207061722056696e63656e74204a6f757373652c206f6e2061757261206c6120706f73736962696c6974c3a92064e2809961766f697220756e2076726169206d6f646520686f7273206c69676e652e3c2f703e0a3c703e3c656d3e416c6f7273207369206f6e2076657574206169646572202f2070617274696369706572202f20747269666f75696c6c6572206c6520636f6465202f20766f757320656e766f79657220646573207265746f7572732c206f6e206661697420636f6d6d656e74c2a03f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4f6e207065757420616964657220646520706c75736965757273206661c3a76f6e73c2a03a3c2f703e0a3c756c3e3c6c693e7574696c697365722077616c6c61626167206574206e6f75732072656d6f6e746572206c65732070726f626cc3a86d65732072656e636f6e7472c3a973c2a03b3c2f6c693e0a3c6c693e706172746963697065722061752064c3a976656c6f7070656d656e74206465206ce280996170706c69636174696f6e2068747470733a2f2f6769746875622e636f6d2f77616c6c616261672f77616c6c616261672053692053696c6578202f2053796d666f6e7932202f2048544d4c35202f206574632e207465207061726c656e742c206ee2809968c3a97369746520706173c2a0213c2f6c693e0a3c6c693e636f6d6d6520746f75742070726f6a65742c206c652067726f7320706f696e74206e6f697220657374206c65206d616e71756520646520646f63756d656e746174696f6e2e203c6120687265663d22687474703a2f2f646f632e77616c6c616261672e6f7267223e456c6c652065737420646973706f206963693c2f613e206d61697320696c206d616e71756520706c65696e2064652063686f73657320657420746f7574206ee280996573742070617320c3a0206a6f7572c2a03b3c2f6c693e0a3c6c693e7061726c65722064652057616c6c61626167206175746f757220646520766f7573c2a03b3c2f6c693e0a3c6c693e696c20657869737465203c6120687265663d2268747470733a2f2f666c617474722e636f6d2f7468696e672f313236353438302f706f6368652d612d726561642d69742d6c617465722d6f70656e2d736f757263652d73797374656d223e756e20636f6d70746520466c617474723c2f613e2e3c2f6c693e0a3c2f756c3e3c703e3c656d3e4c65206d6f74206465206c612066696ee280a63f3c6272202f3e3c2f656d3e3c2f703e0a3c703e4d6572636920c3a0204672616d61736f66742064e280996163637565696c6c697220657420646520736f7574656e69722057616c6c61626167c2a0213c2f703e0a3c703e4c6120726f7574652065737420656e636f7265206269656e206c6f6e67756520706f7572206e6520706c7573207574696c6973657220646520736f6c7574696f6e732070726f707269c3a97461697265732c206d616973206f6e2064657672616974207920617272697665722c206e6f6ec2a03f3c2f703e0a3c703e3c696d67207372633d22687474703a2f2f7777772e6672616d61626c6f672e6f72672f7075626c69632f5f696d672f6672616d61626c6f672f706c65696e4c6573506f636865732e706e672220616c743d226672616d61736f667420706c65696e206c657320706f636865732220636c6173733d22633122207469746c653d226672616d61736f667420706c65696e206c657320706f6368657322202f3e3c6272202f3e3c6120687265663d22687474703a2f2f6672616d616c61622e6f72672f676b6e642d63726561746f722f223e6861636b657a2047c3a967c3a9c2a0213c2f613e3c2f703e0a', 'hex'), 'UTF8'), 1),
133('wallabag/wallabag', 'https://github.com/wallabag/wallabag', false, false, convert_from(decode('3c7370616e20636c6173733d226e616d65223e524541444d452e6d643c2f7370616e3e3c703e77616c6c6162616720697320612073656c6620686f737461626c65206170706c69636174696f6e20616c6c6f77696e6720796f7520746f206e6f74206d69737320616e7920636f6e74656e7420616e796d6f72652e20436c69636b2c20736176652c2072656164206974207768656e20796f752063616e2e20497420657874726163747320636f6e74656e7420736f207468617420796f752063616e2072656164206974207768656e20796f7520686176652074696d652e3c2f703e0a3c703e4d6f726520696e666f726d6174696f6e73206f6e206f757220776562736974653a203c6120687265663d22687474703a2f2f77616c6c616261672e6f7267223e77616c6c616261672e6f72673c2f613e3c2f703e0a3c68323e3c6120636c6173733d22616e63686f722220687265663d2268747470733a2f2f6769746875622e636f6d2f77616c6c616261672f77616c6c61626167236c6963656e7365223e3c2f613e4c6963656e73653c2f68323e0a3c703e436f7079726967687420c2a920323031302d32303134204e69636f6c6173204cc59375696c6c6574203c6120687265663d226d61696c746f3a6e69636f6c6173406c6f6575696c6c65742e6f7267223e6e69636f6c6173406c6f6575696c6c65742e6f72673c2f613e205468697320776f726b20697320667265652e20596f752063616e2072656469737472696275746520697420616e642f6f72206d6f6469667920697420756e64657220746865207465726d73206f662074686520446f205768617420546865204675636b20596f752057616e7420546f205075626c6963204c6963656e73652c2056657273696f6e20322c206173207075626c69736865642062792053616d20486f63657661722e205365652074686520434f5059494e472066696c6520666f72206d6f72652064657461696c732e3c2f703e0a', 'hex'), 'UTF8'), 1), 106('wallabag/wallabag', 'https://github.com/wallabag/wallabag', false, false, convert_from(decode('3c7370616e20636c6173733d226e616d65223e524541444d452e6d643c2f7370616e3e3c703e77616c6c6162616720697320612073656c6620686f737461626c65206170706c69636174696f6e20616c6c6f77696e6720796f7520746f206e6f74206d69737320616e7920636f6e74656e7420616e796d6f72652e20436c69636b2c20736176652c2072656164206974207768656e20796f752063616e2e20497420657874726163747320636f6e74656e7420736f207468617420796f752063616e2072656164206974207768656e20796f7520686176652074696d652e3c2f703e0a3c703e4d6f726520696e666f726d6174696f6e73206f6e206f757220776562736974653a203c6120687265663d22687474703a2f2f77616c6c616261672e6f7267223e77616c6c616261672e6f72673c2f613e3c2f703e0a3c68323e3c6120636c6173733d22616e63686f722220687265663d2268747470733a2f2f6769746875622e636f6d2f77616c6c616261672f77616c6c61626167236c6963656e7365223e3c2f613e4c6963656e73653c2f68323e0a3c703e436f7079726967687420c2a920323031302d32303134204e69636f6c6173204cc59375696c6c6574203c6120687265663d226d61696c746f3a6e69636f6c6173406c6f6575696c6c65742e6f7267223e6e69636f6c6173406c6f6575696c6c65742e6f72673c2f613e205468697320776f726b20697320667265652e20596f752063616e2072656469737472696275746520697420616e642f6f72206d6f6469667920697420756e64657220746865207465726d73206f662074686520446f205768617420546865204675636b20596f752057616e7420546f205075626c6963204c6963656e73652c2056657273696f6e20322c206173207075626c69736865642062792053616d20486f63657661722e205365652074686520434f5059494e472066696c6520666f72206d6f72652064657461696c732e3c2f703e0a', 'hex'), 'UTF8'), 1),
134('a self hostable application for saving web pages | wallabag', 'https://www.wallabag.org/', false, true, convert_from(decode('3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3820636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c703e77616c6c616261672028666f726d65726c7920706f636865292069732061203c7374726f6e673e73656c6620686f737461626c65206170706c69636174696f6e20666f7220736176696e67207765622070616765733c2f7374726f6e673e2e20556e6c696b65206f746865722073657276696365732cc2a077616c6c6162616720697320667265652028617320696e2066726565646f6d2920616e64206f70656e20736f757263652e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3820636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c703e576974682074686973206170706c69636174696f6e20796f752077696c6c206e6f74206d69737320636f6e74656e7420616e796d6f72652e203c7374726f6e673e436c69636b2c20736176652c2072656164206974207768656e20796f752077616e743c2f7374726f6e673e2e2049742073617665732074686520636f6e74656e7420796f752073656c65637420736f207468617420796f752063616e2072656164206974207768656e20796f7520686176652074696d652e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3620636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c68323e486f7720697420776f726b733c2f68323e0a3c703e5468616e6b7320746f2074686520626f6f6b6d61726b6c6574206f72203c61207469746c653d22446f776e6c6f6164732220687265663d22687474703a2f2f7777772e77616c6c616261672e6f72672f646f776e6c6f6164732f223e74686972642d7061727479206170706c69636174696f6e733c2f613e2c20796f75207361766520616e2061727469636c6520696e20796f7572c2a077616c6c6162616720746f2072656164206974206c617465722e205468656e2c207768656e20796f75206f70656e20796f75722077616c6c616261672c203c7374726f6e673e796f752063616e20636f6d666f727461626c79207265616420796f75722061727469636c65733c2f7374726f6e673e2e3c2f703e0a3c68323e486f7720746f207573652077616c6c616261673c2f68323e0a3c703e5468657265206172652074776f207761797320746f207573652077616c6c616261673a20796f752063616e203c6120687265663d22687474703a2f2f7777772e77616c6c616261672e6f72672f6672657175656e746c792d61736b65642d7175657374696f6e732f23486f775f63616e5f495f696e7374616c6c5f77616c6c616261675f616e645f776861745f6172655f7468655f726571756972656d656e7473223e696e7374616c6c2069743c2f613ec2a06f6e20796f75722077656220736572766572206f7220796f752063616ec2a03c6120687265663d22687474703a2f2f6170702e696e746865706f6368652e636f6d223e63726561746520616e206163636f756e743c2f613ec2a06174204672616d616261672028776520696e7374616c6c20616e642075706772616465c2a077616c6c6162616720666f7220796f75292e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a', 'hex'), 'UTF8'), 1)"; 107('a self hostable application for saving web pages | wallabag', 'https://www.wallabag.org/', false, true, convert_from(decode('3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3820636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c703e77616c6c616261672028666f726d65726c7920706f636865292069732061203c7374726f6e673e73656c6620686f737461626c65206170706c69636174696f6e20666f7220736176696e67207765622070616765733c2f7374726f6e673e2e20556e6c696b65206f746865722073657276696365732cc2a077616c6c6162616720697320667265652028617320696e2066726565646f6d2920616e64206f70656e20736f757263652e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3820636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c703e576974682074686973206170706c69636174696f6e20796f752077696c6c206e6f74206d69737320636f6e74656e7420616e796d6f72652e203c7374726f6e673e436c69636b2c20736176652c2072656164206974207768656e20796f752077616e743c2f7374726f6e673e2e2049742073617665732074686520636f6e74656e7420796f752073656c65637420736f207468617420796f752063616e2072656164206974207768656e20796f7520686176652074696d652e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a3c64697620636c6173733d22726f77223e0a3c64697620636c6173733d22636f6c2d6c672d3620636f6c2d6d642d313220636f6c2d78732d313220636f6c2d736d2d3132223e0a3c68323e486f7720697420776f726b733c2f68323e0a3c703e5468616e6b7320746f2074686520626f6f6b6d61726b6c6574206f72203c61207469746c653d22446f776e6c6f6164732220687265663d22687474703a2f2f7777772e77616c6c616261672e6f72672f646f776e6c6f6164732f223e74686972642d7061727479206170706c69636174696f6e733c2f613e2c20796f75207361766520616e2061727469636c6520696e20796f7572c2a077616c6c6162616720746f2072656164206974206c617465722e205468656e2c207768656e20796f75206f70656e20796f75722077616c6c616261672c203c7374726f6e673e796f752063616e20636f6d666f727461626c79207265616420796f75722061727469636c65733c2f7374726f6e673e2e3c2f703e0a3c68323e486f7720746f207573652077616c6c616261673c2f68323e0a3c703e5468657265206172652074776f207761797320746f207573652077616c6c616261673a20796f752063616e203c6120687265663d22687474703a2f2f7777772e77616c6c616261672e6f72672f6672657175656e746c792d61736b65642d7175657374696f6e732f23486f775f63616e5f495f696e7374616c6c5f77616c6c616261675f616e645f776861745f6172655f7468655f726571756972656d656e7473223e696e7374616c6c2069743c2f613ec2a06f6e20796f75722077656220736572766572206f7220796f752063616ec2a03c6120687265663d22687474703a2f2f6170702e696e746865706f6368652e636f6d223e63726561746520616e206163636f756e743c2f613ec2a06174204672616d616261672028776520696e7374616c6c20616e642075706772616465c2a077616c6c6162616720666f7220796f75292e3c2f703e0a3c2f6469763e0a0a3c2f6469763e0a', 'hex'), 'UTF8'), 1)";
135 $moreQueries[] = "INSERT INTO tags (value) VALUES ('opensource')"; 108 $moreQueries[] = "INSERT INTO tags (value) VALUES ('opensource')";
136 $moreQueries[] = "INSERT INTO tags_entries (entry_id, tag_id) VALUES (2, 1)"; 109 $moreQueries[] = "INSERT INTO tags_entries (entry_id, tag_id) VALUES (2, 1)";
137
138 $sql_structure = file_get_contents('install/postgres.sql');
139 }
140 110
141 $content = str_replace("define ('STORAGE', 'sqlite');", "define ('STORAGE', '".$_POST['db_engine']."');", $content); 111 $sql_structure = file_get_contents('install/postgres.sql');
142 file_put_contents('inc/poche/config.inc.php', $content);
143 } 112 }
113 // create database structure
114 $query = $handle->exec($sql_structure);
115 } catch (PDOException $e) {
116 $errors[] = $e->getMessage();
117 $continue = false;
118 }
119 }
120 }
121 if ($continue) {
122 $sql = "INSERT INTO users (username, password, name, email) VALUES (?, ?, ?, '')";
123 $params = array($username, $salted_password, $username);
124 $query = executeQuery($handle, $sql, $params);
144 125
145 if ($continue) { 126 $id_user = (int)$handle->lastInsertId('users_id_seq');
146
147 function executeQuery($handle, $sql, $params) {
148 try
149 {
150 $query = $handle->prepare($sql);
151 $query->execute($params);
152 return $query->fetchAll();
153 }
154 catch (Exception $e)
155 {
156 return FALSE;
157 }
158 }
159
160 if ($_POST['db_engine'] != "sqlite") {
161 // create database structure
162 $query = $handle->exec($sql_structure);
163 }
164
165 // Create user
166 $handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
167
168 $sql = "INSERT INTO users (username, password, name, email) VALUES (?, ?, ?, '')";
169 $params = array($username, $salted_password, $username);
170 $query = executeQuery($handle, $sql, $params);
171
172 $id_user = (int)$handle->lastInsertId('users_id_seq');
173 127
174 $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)'; 128 $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
175 $params = array($id_user, 'pager', '10'); 129 $params = array($id_user, 'pager', '10');
176 $query = executeQuery($handle, $sql, $params); 130 $query = executeQuery($handle, $sql, $params);
177 131
178 $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)'; 132 $sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
179 $params = array($id_user, 'language', 'en_EN.UTF8'); 133 $params = array($id_user, 'language', 'en_EN.UTF8');
180 $query = executeQuery($handle, $sql, $params); 134 $query = executeQuery($handle, $sql, $params);
181 135
182 foreach ($moreQueries as $query) { 136 foreach ($moreQueries as $query) {
183 executeQuery($handle, $query, array()); 137 executeQuery($handle, $query, array());
184 } 138 }
139 $successes[] = 'wallabag is now installed. You can now <a href="index.php?clean=0">access it !</a>';
185 140
186 $successes[] = 'wallabag is now installed. You can now <a href="index.php?clean=0">access it !</a>'; 141 if (!copy('inc/poche/config.inc.default.php', 'inc/poche/config.inc.php')) {
187 } 142 $errors[] = 'Installation aborted, impossible to create inc/poche/config.inc.php file. Maybe you don\'t have write access to create it.';
143 } else {
144 if ($_POST['db_engine'] != 'sqlite') {
145 $content = str_replace("define ('STORAGE', 'sqlite');", "define ('STORAGE', '".$_POST['db_engine']."');", $content);
146 file_put_contents('inc/poche/config.inc.php', $content);
188 } 147 }
148 $content = str_replace("define ('SALT', '');", "define ('SALT', '".$salt."');", $content);
149 file_put_contents('inc/poche/config.inc.php', $content);
189 } 150 }
190} 151}
152}
191?> 153?>
192<!DOCTYPE html> 154<!DOCTYPE html>
193<html> 155<html>
@@ -210,6 +172,160 @@ else if (isset($_POST['install'])) {
210 <link rel="stylesheet" href="themes/baggy/css/print.css" media="print"> 172 <link rel="stylesheet" href="themes/baggy/css/print.css" media="print">
211 <script src="themes/_global/js/jquery-2.0.3.min.js"></script> 173 <script src="themes/_global/js/jquery-2.0.3.min.js"></script>
212 <script src="themes/baggy/js/init.js"></script> 174 <script src="themes/baggy/js/init.js"></script>
175
176
177 <style type="text/css">
178a {
179color:#000;
180text-decoration:underline;
181padding:0 1px;
182}
183a:hover {
184color:#fff;
185background-color:#333;
186text-decoration:none;
187padding:0 1px;
188}
189p {
190margin:0;
191padding:5px 0;
192}
193em {
194font-style:normal;
195background-color:#ffc;
196padding: 0.1em 0;
197}
198ul, ol {
199margin:10px 0 10px 20px;
200padding:0 0 0 15px;
201}
202ul li, ol li {
203margin:0 0 7px 0;
204padding:0 0 0 3px;
205}
206h2 {
207font-size:18px;
208padding:0;
209}
210h3 {
211font-size:16px;
212padding:0;
213margin:20px 0 5px 0;
214}
215h4 {
216font-size:14px;
217padding:0;
218margin:15px 0 5px 0;
219}
220code {
221font-size:1.1em;
222background-color:#f3f3ff;
223color:#000;
224}
225em strong {
226text-transform: uppercase;
227}
228table#chart {
229border-collapse:collapse;
230}
231table#chart th {
232background-color:#eee;
233padding:2px 3px;
234border:1px solid #fff;
235}
236table#chart td {
237text-align:center;
238padding:2px 3px;
239border:1px solid #eee;
240}
241table#chart tr.enabled td {
242/* Leave this alone */
243}
244table#chart tr.disabled td,
245table#chart tr.disabled td a {
246}
247table#chart tr.disabled td a {
248text-decoration:underline;
249}
250div.chunk {
251margin:20px 0 0 0;
252padding:0 0 10px 0;
253border-bottom:1px solid #ccc;
254}
255.footnote,
256.footnote a {
257font:10px/12px verdana, sans-serif;
258color:#aaa;
259}
260.footnote em {
261background-color:transparent;
262font-style:italic;
263}
264.good{
265background-color:#52CC5B;
266}
267.bad{
268background-color:#F74343;
269font-style:italic;
270font-weight: bold;
271}
272.pass{
273background-color:#FF9500;
274}
275.detail {
276cursor: pointer;
277}
278.descriptions {
279 margin-left: 10%;
280 position: relative;
281 top: 50%;
282}
283.database_inputs {
284 float: left;
285 width: 50%
286}
287.database_info {
288 width: 100%;
289 overflow: auto;
290}
291.compatibity_result {
292 margin: auto;
293 max-width: 300px;
294 min-height: 50px;
295 line-height: 50px;
296 text-align: center;
297 margin-bottom: 30px;
298 border-radius: 3px;
299}
300
301h2, legend {
302 font-size: 30px;
303 text-transform: uppercase;
304 font-family: "PT Sans",sans-serif;
305}
306
307legend:after {
308 content: "";
309 height: 4px;
310 width: 70px;
311 background-color: #000;
312 display: block;
313}
314#reloadpage {
315cursor: pointer;
316background-color: #000;
317color: #FFF;
318padding: 0.5em 1em;
319display: inline-block;
320border: 1px solid #000;
321}
322#reloadpage:hover {
323 background-color: #FFF;
324 color: #000;
325}
326
327</style>
328
213 </head> 329 </head>
214 <body> 330 <body>
215 <header class="w600p center mbm"> 331 <header class="w600p center mbm">
@@ -259,24 +375,192 @@ else if (isset($_POST['install'])) {
259 <?php endif; ?> 375 <?php endif; ?>
260 <p>To install wallabag, you just have to fill the following fields. That's all.</p> 376 <p>To install wallabag, you just have to fill the following fields. That's all.</p>
261 <p>If you need help, you can read the doc: <a href="docs/" target="_blank">offline documentation</a> and <a href="http://doc.wallabag.org" target="_blank">online one</a> (already up-to-date).</p> 377 <p>If you need help, you can read the doc: <a href="docs/" target="_blank">offline documentation</a> and <a href="http://doc.wallabag.org" target="_blank">online one</a> (already up-to-date).</p>
262 <p>Don't forget to check your server compatibility <a href="install/wallabag_compatibility_test.php?from=install">here</a>.</p> 378
263 <form method="post"> 379 <div>
264 <fieldset> 380 <h2>Server compatibility test</h2>
265 <legend><strong>Technical settings</strong></legend> 381 <?php if (isOkay()) { ?>
266 <?php if (!is_dir('vendor')) : ?> 382 <div class="compatibity_result detail good">All good</div>
267 <div class='messages notice install'>wallabag needs twig, a template engine (<a href="http://twig.sensiolabs.org/">?</a>). Two ways to install it:<br /> 383 <?php } elseif (isPassing()) { ?>
268 <ul> 384 <div class="compatibity_result detail pass">Some problems, but it's OK !</div>
269 <li>automatically download and extract vendor.zip into your wallabag folder. 385 <?php } else { ?>
270 <p><input type="submit" name="download" value="Download vendor.zip" /></p> 386 <div class="compatibity_result detail bad">Bad news : you can't run wallabag</div>
271 <?php if (!extension_loaded('zip')) : ?> 387 <?php } $status = status(); ?>
272 <b>Be careful, zip extension is not enabled in your PHP configuration. You'll have to unzip vendor.zip manually.</b> 388 </div>
273 <?php endif; ?> 389
274 <em>This method is mainly recommended if you don't have a dedicated server.</em></li> 390 <div class="details">
275 <li>use <a href="http://getcomposer.org/">Composer</a> :<pre><code>curl -s http://getcomposer.org/installer | php 391 <div>
276php composer.phar install</code></pre></li> 392 <hr>
277 </ul> 393 <h2 style="text-align:center;"><?php echo $status['app_name']; ?>: Compatibility Test</h2>
278 </div> 394 <table cellpadding="0" cellspacing="0" border="0" width="100%" id="chart">
279 <?php endif; ?> 395 <thead>
396 <tr>
397 <th>Test</th>
398 <th>Should Be</th>
399 <th>What You Have</th>
400 <th>What it means</th>
401 </tr>
402 </thead>
403 <tbody>
404 <tr class="<?php echo ($status['php']) ? 'enabled' : 'disabled'; ?>">
405 <td>PHP</td>
406 <td>5.3.3 or higher</td>
407 <td class="<?php echo ($status['php']) ? 'good' : 'disabled'; ?>"><?php echo phpversion(); ?></td>
408 <td><?php echo ($status['php']) ? '<strong>PHP:</strong> You are running a supported version of PHP.' : '<strong>PHP:</strong> You are running an unsupported version of PHP. <strong>' . $status['app_name'] . ' will not work here.</strong>' ;?></td>
409 </tr>
410 <tr class="<?php echo ($status['pdo']) ? 'enabled' : 'disabled'; ?>">
411 <td><a href="http://php.net/manual/en/book.pdo.php">PDO</a></td>
412 <td>Enabled</td>
413 <?php echo ($status['pdo']) ? '<td class="good">Enabled</span>' : '<td class="bad">Disabled'; ?></td>
414 <td><?php echo ($status['pdo']) ? '<strong>PDO:</strong> You have PDO support enabled.' : '<strong>PDO:</strong> Your PHP installation doesn\'t support PHP PDO. <strong>' . $status['app_name'] . ' will not work here.</strong>' ?></td>
415 </tr>
416 <tr class="<?php echo ($status['pdo_drivers_passing']) ? 'enabled' : 'disabled'; ?>">
417 <td>PDO Drivers</td>
418 <td>One of the PDO drivers must be installed</td>
419 <?php echo ($status['pdo_drivers_passing']) ? '<td class="good">One driver is enabled</span>' : '<td class="bad">No driver available'; ?></td>
420 <td><?php echo ($status['pdo_drivers_passing']) ? '<strong>PDO:</strong> You have at least one PDO driver installed.' : '<strong>PDO Drivers:</strong> Your PHP installation doesn\'t have any PDO driver installed. <strong>' . $status['app_name'] . ' will not work here.</strong>' ?></td>
421 </tr>
422 <tr class="<?php echo ($status['xml']) ? 'enabled' : 'disabled'; ?>">
423 <td><a href="http://php.net/xml">XML</a></td>
424 <td>Enabled</td>
425 <?php echo ($status['xml']) ? '<td class="good">Enabled, and sane</span>' : '<td class="bad">Disabled, or broken'; ?></td>
426 <td><?php echo ($status['xml']) ? '<strong>XML:</strong> You have XMLReader support or a version of XML support that isn\'t broken installed.' : '<strong>XML:</strong> Your PHP installation doesn\'t support XML parsing. <strong>' . $status['app_name'] . ' will not work here.</strong>' ?></td>
427 </tr>
428 <tr class="<?php echo ($status['pcre']) ? 'enabled' : 'disabled'; ?>">
429 <td><a href="http://php.net/pcre">PCRE</a></td>
430 <td>Enabled</td>
431 <?php echo ($status['pcre']) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
432 <td><?php echo ($status['pcre']) ? '<strong>PCRE:</strong> You have PCRE support installed.' : '<strong>PCRE:</strong> Your PHP installation doesn\'t support Perl-Compatible Regular Expressions. <strong>' . $status['app_name'] .' will not work here.</strong>' ?></td>
433 </tr>
434 <tr class="<?php echo ($status['zlib']) ? 'enabled' : 'disabled'; ?>">
435 <td><a href="http://php.net/zlib">Zlib</a></td>
436 <td>Enabled</td>
437 <?php echo ($status['zlib']) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
438 <td><?php echo ($status['zlib']) ? '<strong>Zlib:</strong> You have <code>Zlib</code> enabled. This allows SimplePie to support GZIP-encoded pages.' : '<strong>Zlib:</strong> The <code>Zlib</code> extension is not available. SimplePie will ignore any GZIP-encoding, and instead handle pages as uncompressed text.' ?></td>
439 </tr>
440 <tr class="<?php echo ($status['mbstring']) ? 'enabled' : 'disabled'; ?>">
441 <td><a href="http://php.net/mbstring">mbstring</a></td>
442 <td>Enabled</td>
443 <?php echo ($status['mbstring']) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
444 <td rowspan="2"><?php if(($status['mbstring']) && ($status['iconv'])) { ?><strong>mbstring and iconv:</strong> You have both <code>mbstring</code> and <code>iconv</code> installed! This will allow <?php echo $status['app_name']; ?> to handle the greatest number of languages.
445 <?php } elseif ($status['mbstring']) { ?><strong>mbstring:</strong> <code>mbstring</code> is installed, but <code>iconv</code> is not.
446 <?php } elseif ($status['iconv']) { ?><strong>iconv:</strong> <code>iconv</code> is installed, but <code>mbstring</code> is not.
447 <?php } else { ?><strong>mbstring and iconv:</strong> <em>You do not have either of the extensions installed.</em> This will significantly impair your ability to read non-English pages, as well as even some English ones.
448 <?php } ?>
449 </td>
450 </tr>
451 <tr class="<?php echo ($status['iconv']) ? 'enabled' : 'disabled'; ?>">
452 <td><a href="http://php.net/iconv">iconv</a></td>
453 <td>Enabled</td>
454 <?php echo ($status['iconv']) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
455 </tr>
456 <tr class="<?php echo ($status['dom']) ? 'enabled' : 'disabled'; ?>">
457 <td><a href="http://php.net/manual/en/book.dom.php">DOM / XML extension</a></td>
458 <td>Enabled</td>
459 <?php echo ($status['dom']) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
460 <td><?php echo ($status['dom']) ? '<strong>DOM/XML:</strong> You can parse <em>ini</em> files.' : '<strong>DOM/XML:</strong> Your PHP configuration isn\'t standard, you\'re missing PHP-DOM. You may try to install a package or recompile PHP. <strong>' . $status['app_name'] . ' will not work here.</strong>'; ?></td>
461 </tr>
462 <tr class="<?php echo ($status['filter']) ? 'enabled' : 'disabled'; ?>">
463 <td><a href="http://uk.php.net/manual/en/book.filter.php">Data filtering</a></td>
464 <td>Enabled</td>
465 <?php echo ($status['filter']) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
466 <td><?php echo ($status['filter']) ? '<strong>Data filtering:</strong> You can use the PHP build-in DOM to operate on XML documents.' : '<strong>Data filtering:</strong> Your PHP configuration has the filter extension disabled. <strong>' . $status['app_name'] . ' will not work here.</strong>' ?></td>
467 </tr>
468 <tr class="<?php echo ($status['gd']) ? 'enabled' : 'disabled'; ?>">
469 <td><a href="http://php.net/manual/en/book.image.php">GD</a></td>
470 <td>Enabled</td>
471 <?php echo ($status['gd']) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
472 <td><?php echo($status['gd']) ? '<strong>GD:</strong> You have <code>GD</code> support installed.' : '<strong>GD:</strong> The <code>GD</code> extension is not available. ' . $status['app_name'] . ' will not be able to download pictures locally on your server.' ?></td>
473 </tr>
474 <tr class="<?php echo ($status['tidy']) ? 'enabled' : 'disabled'; ?>">
475 <td><a href="http://php.net/tidy">Tidy</a></td>
476 <td>Enabled</td>
477 <?php echo ($status['tidy']) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
478 <td><?php echo ($status['tidy']) ? '<strong>Tidy:</strong> You have <code>Tidy</code> support installed.' : '<strong>Tidy:</strong> The <code>Tidy</code> extension is not available.' . $status['app_name'] . ' should still work with most pages, but you may experience problems with some. You can install it with <code>sudo apt-get install php5-tidy</code> and then reload Apache <code>sudo service apache2 reload</code>.' ; ?></td>
479 </tr>
480 <tr class="<?php echo ($status['curl']) ? 'enabled' : 'disabled'; ?>">
481 <td><a href="http://php.net/curl">cURL</a></td>
482 <td>Enabled</td>
483 <?php echo (extension_loaded('curl')) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
484 <td><?php echo ($status['curl']) ? '<strong>cURL:</strong> You have <code>cURL</code> support installed.' : '<strong>cURL:</strong> The <code>cURL</code> extension is not available. SimplePie will use <code>fsockopen()</code> instead.' ?></td>
485 </tr>
486 <tr class="<?php echo ($status['parse_ini']) ? 'enabled' : 'disabled'; ?>">
487 <td><a href="http://uk.php.net/manual/en/function.parse-ini-file.php">Parse ini file</td>
488 <td>Enabled</td>
489 <?php echo ($status['parse_ini']) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
490 <td><?php echo ($status['parse_ini']) ? '<strong>Parse ini:</strong> You can parse <em>ini</em> files.' : '<strong>Parse ini files function :</strong> Bad luck : your webhost has decided to block the use of the <em>parse_ini_file</em> function. <strong>' . $status['app_name'] . ' will not work here.' ?></td>
491 </tr>
492 <tr class="<?php echo ($status['parallel']) ? 'enabled' : 'disabled'; ?>">
493 <td>Parallel URL fetching</td>
494 <td>Enabled</td>
495 <?php echo ($status['parallel']) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
496 <td><?php echo ($status['parallel']) ? '<strong>Parallel URL fetching:</strong> You have <code>HttpRequestPool</code> or <code>curl_multi</code> support installed.' : '<strong>Parallel URL fetching:</strong> <code>HttpRequestPool</code> or <code>curl_multi</code> support is not available. ' . $status['app_name'] . ' will use <code>file_get_contents()</code> instead to fetch URLs sequentially rather than in parallel.' ?></td>
497 </tr>
498 <tr class="<?php echo ($status['allow_url_fopen']) ? 'enabled' : 'disabled'; ?>">
499 <td><a href="http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen">allow_url_fopen</a></td>
500 <td>Enabled</td>
501 <?php echo ($status['allow_url_fopen']) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
502 <td><?php echo ($status['allow_url_fopen']) ? '<strong>allow_url_fopen:</strong> You have allow_url_fopen enabled.' : '<strong>allow_url_fopen:</strong> Your PHP configuration has allow_url_fopen disabled. <strong>' . $status['app_name'] . ' will not work here.</strong>' ?></td>
503 </tr>
504 <tr class="<?php echo ($status['gettext']) ? 'enabled' : 'disabled'; ?>">
505 <td><a href="http://php.net/manual/en/book.gettext.php">gettext</a></td>
506 <td>Enabled</td>
507 <?php echo ($status['gettext']) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
508 <td><?php echo ($status['gettext']) ? '<strong>Gettext:</strong> You have <code>gettext</code> enabled.</em>' : '<strong>GetText:</strong> The <code>gettext</code> extension is not available. The system we use to display wallabag in various languages is not available. <strong>' . $status['app_name'] .' will not work here.</strong>' ?></td>
509 </tr>
510 </tbody>
511 </table>
512 <hr>
513 </div>
514 <div class="details">
515 <?php //if ($status['php'] && $status['xml'] && $status['pcre'] && $status['mbstring'] && $status['iconv'] && $status['filter'] && $status['allow_url_fopen']) { ?>
516 <?php if (isOkay()) { ?>
517 <h3>Bottom Line: Yes, you can run <?php echo $status['app_name']; ?> !</h3>
518 <p><em>Your webhost has its act together!</em></p>
519 <p><strong>Note</strong>: Passing this test does not guarantee that <?php echo $status['app_name']; ?> will run on your webhost &mdash; it only ensures that the basic requirements have been addressed. If you experience any problems, please let us know.</p>
520 <?php //} else if ($status['php'] && $status['xml'] && $status['pcre'] && $status['mbstring'] && $status['allow_url_fopen'] && $status['filter']) { ?>
521 <?php } else if (!isOkay() && isPassing()) { ?>
522 <h3>Bottom Line: Yes, you can run <?php echo $status['app_name']; ?> !</h3>
523 <p><em>For most pages, it'll run with no problems.</em> There are certain languages that you might have a hard time with though.</p>
524 <p><strong>Note</strong>: Passing this test does not guarantee that <?php echo $status['app_name']; ?> will run on your webhost &mdash; it only ensures that the basic requirements have been addressed. If you experience any problems, please let us know.</p>
525 <?php } else { ?>
526 <h3>Bottom Line: We're sorry…</h3>
527 <p><em>Your webhost does not support the minimum requirements for <?php echo $status['app_name']; ?>.</em> It may be a good idea to contact your webhost and point them to the results of this test. They may be able to enable/install the required components.</p>
528 <p>If this is your own server and you think you have all the requirements installed, please get in touch with us.</p>
529 <?php } ?>
530 </div>
531
532 <div class="chunk">
533 <p class="footnote">This compatibility test has been borrowed (and slightly adapted by <a href="http://fivefilters.org/content-only/">fivefilters.org</a>) from the one supplied by <a href="http://simplepie.org/">SimplePie.org</a>.</a></p>
534 </div>
535 </div>
536 <form method="post" class="technical">
537 <hr>
538 <div class='twig'>
539 <h2>Twig installation</h2>
540 <?php if (!is_dir('vendor')) : ?>
541
542 <p>wallabag needs twig, a template engine (<a href="http://twig.sensiolabs.org/">?</a>). Two ways to install it:</p>
543 <ul>
544 <li>automatically download and extract vendor.zip into your wallabag folder.
545 <p><input type="submit" name="download" value="Download vendor.zip" /></p>
546 <?php if (!extension_loaded('zip')) : ?>
547 <b>Be careful, zip extension is not enabled in your PHP configuration. You'll have to unzip vendor.zip manually.</b>
548 <?php endif; ?>
549 <em>This method is mainly recommended if you don't have a dedicated server.</em></li>
550 <li>use <a href="http://getcomposer.org/">Composer</a> in your wallabag folder :<pre><code>curl -s http://getcomposer.org/installer | php
551php composer.phar install</code></pre>
552 <span id="reloadpage">Reload to check</span>
553 </li>
554 </ul>
555
556 <?php else : ?>
557 Twig is properly installed.
558 <?php endif; ?>
559 </div>
560 <div class="database_info">
561 <hr>
562 <fieldset class="database_inputs">
563 <legend><strong>Database settings</strong></legend>
280 <p> 564 <p>
281 Database engine: 565 Database engine:
282 <ul> 566 <ul>
@@ -287,6 +571,9 @@ php composer.phar install</code></pre></li>
287 </li> 571 </li>
288 <li> 572 <li>
289 <label for="mysql">MySQL</label> <input name="db_engine" type="radio" id="mysql" value="mysql" /> 573 <label for="mysql">MySQL</label> <input name="db_engine" type="radio" id="mysql" value="mysql" />
574 <div id="pdo_mysql" class='messages notice install'>
575 <p>All fields have to be filled.</p>
576 </div>
290 <ul id="mysql_infos"> 577 <ul id="mysql_infos">
291 <li><label for="mysql_server">Server</label> <input type="text" placeholder="localhost" id="mysql_server" name="mysql_server" /></li> 578 <li><label for="mysql_server">Server</label> <input type="text" placeholder="localhost" id="mysql_server" name="mysql_server" /></li>
292 <li><label for="mysql_database">Database</label> <input type="text" placeholder="wallabag" id="mysql_database" name="mysql_database" /></li> 579 <li><label for="mysql_database">Database</label> <input type="text" placeholder="wallabag" id="mysql_database" name="mysql_database" /></li>
@@ -296,6 +583,9 @@ php composer.phar install</code></pre></li>
296 </li> 583 </li>
297 <li> 584 <li>
298 <label for="postgres">PostgreSQL</label> <input name="db_engine" type="radio" id="postgres" value="postgres" /> 585 <label for="postgres">PostgreSQL</label> <input name="db_engine" type="radio" id="postgres" value="postgres" />
586 <div id="pdo_postgres" class='messages notice install'>
587 <p>All fields have to be filled.</p>
588 </div>
299 <ul id="pg_infos"> 589 <ul id="pg_infos">
300 <li><label for="pg_server">Server</label> <input type="text" placeholder="localhost" id="pg_server" name="pg_server" /></li> 590 <li><label for="pg_server">Server</label> <input type="text" placeholder="localhost" id="pg_server" name="pg_server" /></li>
301 <li><label for="pg_database">Database</label> <input type="text" placeholder="wallabag" id="pg_database" name="pg_database" /></li> 591 <li><label for="pg_database">Database</label> <input type="text" placeholder="wallabag" id="pg_database" name="pg_database" /></li>
@@ -306,8 +596,21 @@ php composer.phar install</code></pre></li>
306 </ul> 596 </ul>
307 </p> 597 </p>
308 </fieldset> 598 </fieldset>
309 599 <div class="descriptions">
310 <fieldset> 600 <div id="sqlite_description">
601 SQLite is the most simple database system of all three. It is therefore recommended for people who don't want or know how to configure other database systems.
602 </div>
603 <div id="mysql_description">
604 MySQL is one of the most popular database systems. It comes with most shared hosting plans.
605 </div>
606 <div id="postgres_description">
607 PostgreSQL. Because some people prefer it to MySQL.
608 </div>
609 </div>
610 </div>
611 <hr>
612 <div class="usersettings">
613 <fieldset style="clear: both">
311 <legend><strong>User settings</strong></legend> 614 <legend><strong>User settings</strong></legend>
312 <p> 615 <p>
313 <label for="username">Username</label> 616 <label for="username">Username</label>
@@ -323,13 +626,42 @@ php composer.phar install</code></pre></li>
323 <input type="email" id="email" name="email" /> 626 <input type="email" id="email" name="email" />
324 </p> 627 </p>
325 </fieldset> 628 </fieldset>
326
327 <input type="submit" id="install_button" value="Install wallabag" name="install" /> 629 <input type="submit" id="install_button" value="Install wallabag" name="install" />
630 </div>
328 </form> 631 </form>
329 </div> 632 </div>
330 <script> 633 <script>
634 <?php if (!is_dir('vendor')) : ?>
635 $(".database_info").hide();
636 $(".usersettings").hide();
637 <?php endif ?>
638 /*
639 * Database showing/hiding
640 */
331 $("#mysql_infos").hide(); 641 $("#mysql_infos").hide();
642 $("#mysql_description").hide();
332 $("#pg_infos").hide(); 643 $("#pg_infos").hide();
644 $("#postgres_description").hide();
645 $("#sqlite_description").show();
646 $("#pdo_postgres").hide();
647 $("#pdo_mysql").hide();
648
649 /*
650 * Details hiding
651 */
652
653 $(".details").hide();
654
655 <?php
656 if (!isPassing()) : ?>
657 $('.technical').hide();
658 <?php
659 else :
660 ?>
661 $('.technical').show();
662 <?php
663 endif;
664 ?>
333 665
334 <?php 666 <?php
335 if (!extension_loaded('pdo_sqlite')) : ?> 667 if (!extension_loaded('pdo_sqlite')) : ?>
@@ -346,20 +678,35 @@ php composer.phar install</code></pre></li>
346 { 678 {
347 if ( $("#mysql").prop('checked')) { 679 if ( $("#mysql").prop('checked')) {
348 $("#mysql_infos").show(); 680 $("#mysql_infos").show();
681 $("#pdo_mysql").show();
349 $("#pg_infos").hide(); 682 $("#pg_infos").hide();
683 $("#pdo_postgres").hide();
350 $("#pdo_sqlite").hide(); 684 $("#pdo_sqlite").hide();
351 $("#install_button").show(); 685 $("#sqlite_description").hide();
686 $("#postgres_description").hide();
687 $("#mysql_description").show();
688 $("#install_button").show();
352 } 689 }
353 else { 690 else {
354 if ( $("#postgres").prop('checked')) { 691 if ( $("#postgres").prop('checked')) {
355 $("#mysql_infos").hide(); 692 $("#mysql_infos").hide();
693 $("#pdo_mysql").hide();
356 $("#pg_infos").show(); 694 $("#pg_infos").show();
695 $("#pdo_postgres").show();
357 $("#pdo_sqlite").hide(); 696 $("#pdo_sqlite").hide();
697 $("#sqlite_description").hide();
698 $("#mysql_description").hide();
699 $("#postgres_description").show();
358 $("#install_button").show(); 700 $("#install_button").show();
359 } 701 }
360 else { 702 else {
361 $("#mysql_infos").hide(); 703 $("#mysql_infos").hide();
362 $("#pg_infos").hide(); 704 $("#pg_infos").hide();
705 $("#pdo_postgres").hide();
706 $("#pdo_mysql").hide();
707 $("#sqlite_description").show();
708 $("#mysql_description").hide();
709 $("#postgres_description").hide();
363 <?php 710 <?php
364 if (!extension_loaded('pdo_sqlite')) : ?> 711 if (!extension_loaded('pdo_sqlite')) : ?>
365 $("#pdo_sqlite").show(); 712 $("#pdo_sqlite").show();
@@ -370,6 +717,16 @@ php composer.phar install</code></pre></li>
370 } 717 }
371 } 718 }
372 }); 719 });
720
721 $(".detail").click(function()
722 {
723 $('.details').toggle();
724 });
725 $("#reloadpage").click(function()
726 {
727 location.reload();
728 });
729
373 </script> 730 </script>
374 </body> 731 </body>
375</html> 732</html>
diff --git a/install/wallabag_compatibility_test.php b/install/wallabag_compatibility_test.php
index 61a8e99f..3b465851 100644
--- a/install/wallabag_compatibility_test.php
+++ b/install/wallabag_compatibility_test.php
@@ -8,9 +8,11 @@
8 * @license http://opensource.org/licenses/MIT see COPYING file 8 * @license http://opensource.org/licenses/MIT see COPYING file
9 */ 9 */
10 10
11function status() {
11$app_name = 'wallabag'; 12$app_name = 'wallabag';
12 13
13$php_ok = (function_exists('version_compare') && version_compare(phpversion(), '5.3.3', '>=')); 14$php_ok = (function_exists('version_compare') && version_compare(phpversion(), '5.3.3', '>='));
15$pdo_ok = class_exists('PDO');
14$pcre_ok = extension_loaded('pcre'); 16$pcre_ok = extension_loaded('pcre');
15$zlib_ok = extension_loaded('zlib'); 17$zlib_ok = extension_loaded('zlib');
16$mbstring_ok = extension_loaded('mbstring'); 18$mbstring_ok = extension_loaded('mbstring');
@@ -24,7 +26,7 @@ $allow_url_fopen_ok = (bool)ini_get('allow_url_fopen');
24$filter_ok = extension_loaded('filter'); 26$filter_ok = extension_loaded('filter');
25$gettext_ok = function_exists("gettext"); 27$gettext_ok = function_exists("gettext");
26$gd_ok = extension_loaded('gd'); 28$gd_ok = extension_loaded('gd');
27 29$pdo_drivers_passing = extension_loaded('pdo_sqlite') || extension_loaded('pdo_mysql') || extension_loaded('pdo_pgsql');
28 30
29if (extension_loaded('xmlreader')) { 31if (extension_loaded('xmlreader')) {
30 $xml_ok = true; 32 $xml_ok = true;
@@ -37,391 +39,50 @@ if (extension_loaded('xmlreader')) {
37 $xml_ok = false; 39 $xml_ok = false;
38} 40}
39 41
40header('Content-type: text/html; charset=UTF-8'); 42$status = array('app_name' => $app_name, 'php' => $php_ok, 'pdo' => $pdo_ok, 'pdo_drivers_passing' => $pdo_drivers_passing, 'xml' => $xml_ok, 'pcre' => $pcre_ok, 'zlib' => $zlib_ok, 'mbstring' => $mbstring_ok, 'dom' => $dom_ok, 'iconv' => $iconv_ok, 'tidy' => $tidy_ok, 'curl' => $curl_ok, 'parse_ini' => $parse_ini_ok, 'parallel' => $parallel_ok, 'allow_url_fopen' => $allow_url_fopen_ok, 'filter' => $filter_ok, 'gettext' => $gettext_ok, 'gd' => $gd_ok);
41
42?><!DOCTYPE html>
43
44<html lang="en">
45<head>
46<title><?php echo $app_name; ?>: Server Compatibility Test</title>
47
48<style type="text/css">
49body {
50 font:14px/1.4em "Lucida Grande", Verdana, Arial, Helvetica, Clean, Sans, sans-serif;
51 letter-spacing:0px;
52 color:#333;
53 margin:0;
54 padding:0;
55 background:#fff;
56}
57
58div#site {
59 width:550px;
60 margin:20px auto 0 auto;
61}
62
63a {
64 color:#000;
65 text-decoration:underline;
66 padding:0 1px;
67}
68
69a:hover {
70 color:#fff;
71 background-color:#333;
72 text-decoration:none;
73 padding:0 1px;
74}
75
76p {
77 margin:0;
78 padding:5px 0;
79}
80
81em {
82 font-style:normal;
83 background-color:#ffc;
84 padding: 0.1em 0;
85}
86
87ul, ol {
88 margin:10px 0 10px 20px;
89 padding:0 0 0 15px;
90}
91
92ul li, ol li {
93 margin:0 0 7px 0;
94 padding:0 0 0 3px;
95}
96
97h2 {
98 font-size:18px;
99 padding:0;
100 margin:30px 0 20px 0;
101}
102
103h3 {
104 font-size:16px;
105 padding:0;
106 margin:20px 0 5px 0;
107}
108
109h4 {
110 font-size:14px;
111 padding:0;
112 margin:15px 0 5px 0;
113}
114
115code {
116 font-size:1.1em;
117 background-color:#f3f3ff;
118 color:#000;
119}
120
121em strong {
122 text-transform: uppercase;
123}
124
125table#chart {
126 border-collapse:collapse;
127}
128
129table#chart th {
130 background-color:#eee;
131 padding:2px 3px;
132 border:1px solid #fff;
133}
134
135table#chart td {
136 text-align:center;
137 padding:2px 3px;
138 border:1px solid #eee;
139}
140
141table#chart tr.enabled td {
142 /* Leave this alone */
143}
144
145table#chart tr.disabled td,
146table#chart tr.disabled td a {
147}
148
149table#chart tr.disabled td a {
150 text-decoration:underline;
151}
152
153div.chunk {
154 margin:20px 0 0 0;
155 padding:0 0 10px 0;
156 border-bottom:1px solid #ccc;
157}
158 43
159.footnote, 44return $status;
160.footnote a {
161 font:10px/12px verdana, sans-serif;
162 color:#aaa;
163} 45}
164 46function isOkay() {
165.footnote em { 47 return !in_array(false, status());
166 background-color:transparent;
167 font-style:italic;
168} 48}
169 49
170.good{ 50function isPassing() {
171background-color:#52CC5B; 51 $status = status();
172} 52 unset($status['curl'], $status['parallel'], $status['tidy'], $status['gd'], $status['filter']);
173.bad{ 53 return !in_array(false, $status);
174background-color:#F74343;
175font-style:italic;
176font-weight: bold;
177} 54}
178.pass{
179background-color:#FF9500;
180}
181
182</style>
183 55
184</head> 56/* Function taken from at http://php.net/manual/en/function.rmdir.php#110489
185 57 * Idea : nbari at dalmp dot com
186<body> 58 * Rights unknown
187<?php 59 * Here in case of .gitignore files
188$frominstall = false; 60 */
189if (isset($_GET['from'])){
190 if ($_GET['from'] == 'install'){
191 $frominstall = true;
192 }}
193?>
194<div id="site">
195 <div id="content">
196
197 <div class="chunk">
198 <h2 style="text-align:center;"><?php echo $app_name; ?>: Compatibility Test</h2>
199 <table cellpadding="0" cellspacing="0" border="0" width="100%" id="chart">
200 <thead>
201 <tr>
202 <th>Test</th>
203 <th>Should Be</th>
204 <th>What You Have</th>
205 </tr>
206 </thead>
207 <tbody>
208 <tr class="<?php echo ($php_ok) ? 'enabled' : 'disabled'; ?>">
209 <td>PHP</td>
210 <td>5.3.3 or higher</td>
211 <td class="<?php echo ($php_ok) ? 'good' : 'disabled'; ?>"><?php echo phpversion(); ?></td>
212 </tr>
213 <tr class="<?php echo ($xml_ok) ? 'enabled' : 'disabled'; ?>">
214 <td><a href="http://php.net/xml">XML</a></td>
215 <td>Enabled</td>
216 <?php echo ($xml_ok) ? '<td class="good">Enabled, and sane</span>' : '<td class="bad">Disabled, or broken'; ?></td>
217 </tr>
218 <tr class="<?php echo ($pcre_ok) ? 'enabled' : 'disabled'; ?>">
219 <td><a href="http://php.net/pcre">PCRE</a></td>
220 <td>Enabled</td>
221 <?php echo ($pcre_ok) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
222 </tr>
223<!-- <tr class="<?php echo ($zlib_ok) ? 'enabled' : 'disabled'; ?>">
224 <td><a href="http://php.net/zlib">Zlib</a></td>
225 <td>Enabled</td>
226 <?php echo ($zlib_ok) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
227 </tr> -->
228<!-- <tr class="<?php echo ($mbstring_ok) ? 'enabled' : 'disabled'; ?>">
229 <td><a href="http://php.net/mbstring">mbstring</a></td>
230 <td>Enabled</td>
231 <?php echo ($mbstring_ok) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
232 </tr> -->
233<!-- <tr class="<?php echo ($iconv_ok) ? 'enabled' : 'disabled'; ?>">
234 <td><a href="http://php.net/iconv">iconv</a></td>
235 <td>Enabled</td>
236 <?php echo ($iconv_ok) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
237 </tr> -->
238 <tr class="<?php echo ($dom_ok) ? 'enabled' : 'disabled'; ?>">
239 <td><a href="http://php.net/manual/en/book.dom.php">DOM / XML extension</a></td>
240 <td>Enabled</td>
241 <?php echo ($dom_ok) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
242 </tr>
243 <tr class="<?php echo ($filter_ok) ? 'enabled' : 'disabled'; ?>">
244 <td><a href="http://uk.php.net/manual/en/book.filter.php">Data filtering</a></td>
245 <td>Enabled</td>
246 <?php echo ($filter_ok) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
247 </tr>
248 <tr class="<?php echo ($gd_ok) ? 'enabled' : 'disabled'; ?>">
249 <td><a href="http://php.net/manual/en/book.image.php">GD</a></td>
250 <td>Enabled</td>
251 <?php echo ($gd_ok) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
252 </tr>
253 <tr class="<?php echo ($tidy_ok) ? 'enabled' : 'disabled'; ?>">
254 <td><a href="http://php.net/tidy">Tidy</a></td>
255 <td>Enabled</td>
256 <?php echo ($tidy_ok) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
257 </tr>
258 <tr class="<?php echo ($curl_ok) ? 'enabled' : 'disabled'; ?>">
259 <td><a href="http://php.net/curl">cURL</a></td>
260 <td>Enabled</td>
261 <?php echo (extension_loaded('curl')) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
262 </tr>
263 <tr class="<?php echo ($parse_ini_ok) ? 'enabled' : 'disabled'; ?>">
264 <td><a href="http://uk.php.net/manual/en/function.parse-ini-file.php">Parse ini file</td>
265 <td>Enabled</td>
266 <?php echo ($parse_ini_ok) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
267 </tr>
268 <tr class="<?php echo ($parallel_ok) ? 'enabled' : 'disabled'; ?>">
269 <td>Parallel URL fetching</td>
270 <td>Enabled</td>
271 <?php echo ($parallel_ok) ? '<td class="good">Enabled' : '<td class="pass">Disabled'; ?></td>
272 </tr>
273 <tr class="<?php echo ($allow_url_fopen_ok) ? 'enabled' : 'disabled'; ?>">
274 <td><a href="http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen">allow_url_fopen</a></td>
275 <td>Enabled</td>
276 <?php echo ($allow_url_fopen_ok) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
277 </tr>
278 <tr class="<?php echo ($gettext_ok) ? 'enabled' : 'disabled'; ?>">
279 <td><a href="http://php.net/manual/en/book.gettext.php">gettext</a></td>
280 <td>Enabled</td>
281 <?php echo ($gettext_ok) ? '<td class="good">Enabled' : '<td class="bad">Disabled'; ?></td>
282 </tr>
283 </tbody>
284 </table>
285 </div>
286
287 <div class="chunk">
288 <h3>What does this mean?</h3>
289 <ol>
290 <?php //if ($php_ok && $xml_ok && $pcre_ok && $mbstring_ok && $iconv_ok && $filter_ok && $zlib_ok && $tidy_ok && $curl_ok && $parallel_ok && $allow_url_fopen_ok): ?>
291 <?php if ($php_ok && $xml_ok && $pcre_ok && $dom_ok && $filter_ok && $gd_ok && $tidy_ok && $curl_ok && $parallel_ok && $allow_url_fopen_ok && $gettext_ok && $parse_ini_ok): ?>
292 <li><em>You have everything you need to run <?php echo $app_name; ?> properly! Congratulations!</em></li>
293 <?php else: ?>
294 <?php if ($php_ok): ?>
295 <li><strong>PHP:</strong> You are running a supported version of PHP. <em>No problems here.</em></li>
296 <?php if ($xml_ok): ?>
297 <li><strong>XML:</strong> You have XMLReader support or a version of XML support that isn't broken installed. <em>No problems here.</em></li>
298 <?php if ($pcre_ok): ?>
299 <li><strong>PCRE:</strong> You have PCRE support installed. <em>No problems here.</em></li>
300
301 <?php if ($allow_url_fopen_ok): ?>
302 <li><strong>allow_url_fopen:</strong> You have allow_url_fopen enabled. <em>No problems here.</em></li>
303
304 <?php if ($gettext_ok): ?>
305 <li><strong>Gettext:</strong> You have <code>gettext</code> enabled. <em>No problems here.</em></li>
306
307 <?php if ($parse_ini_ok): ?>
308 <li><strong>Parse ini:</strong> You can parse <em>ini</em> files. <em>No problems here.</em></li>
309
310 <?php if ($dom_ok): ?>
311 <li><strong>DOM/XML:</strong> You can parse <em>ini</em> files. <em>No problems here.</em></li>
312
313 <?php if ($filter_ok): ?>
314 <li><strong>Data filtering:</strong> You can use the PHP build-in DOM to operate on XML documents. <em>No problems here.</em></li>
315
316 <?php if ($zlib_ok): ?>
317 <li><strong>Zlib:</strong> You have <code>Zlib</code> enabled. This allows SimplePie to support GZIP-encoded feeds. <em>No problems here.</em></li>
318 <?php else: ?>
319 <li><strong>Zlib:</strong> The <code>Zlib</code> extension is not available. SimplePie will ignore any GZIP-encoding, and instead handle feeds as uncompressed text.</li>
320 <?php endif; ?>
321
322 <?php if ($mbstring_ok && $iconv_ok): ?>
323 <li><strong>mbstring and iconv:</strong> You have both <code>mbstring</code> and <code>iconv</code> installed! This will allow <?php echo $app_name; ?> to handle the greatest number of languages. <em>No problems here.</em></li>
324 <?php elseif ($mbstring_ok): ?>
325 <li><strong>mbstring:</strong> <code>mbstring</code> is installed, but <code>iconv</code> is not.</li>
326 <?php elseif ($iconv_ok): ?>
327 <li><strong>iconv:</strong> <code>iconv</code> is installed, but <code>mbstring</code> is not.</li>
328 <?php else: ?>
329 <li><strong>mbstring and iconv:</strong> <em>You do not have either of the extensions installed.</em> This will significantly impair your ability to read non-English feeds, as well as even some English ones.</li>
330 <?php endif; ?>
331
332 <?php if ($gd_ok): ?>
333 <li><strong>GD:</strong> You have <code>GD</code> support installed. <em>No problems here.</em></li>
334 <?php else: ?>
335 <li><strong>GD:</strong> The <code>GD</code> extension is not available. <?php echo $app_name; ?> will not be able to download pictures locally on your server.</li>
336 <?php endif; ?>
337
338 <?php if ($tidy_ok): ?>
339 <li><strong>Tidy:</strong> You have <code>Tidy</code> support installed. <em>No problems here.</em></li>
340 <?php else: ?>
341 <li><strong>Tidy:</strong> The <code>Tidy</code> extension is not available. <?php echo $app_name; ?> should still work with most feeds, but you may experience problems with some. You can install it with <code>sudo apt-get install php5-tidy</code> and then reload Apache <code>sudo service apache2 reload</code>.</li>
342 <?php endif; ?>
343
344 <?php if ($curl_ok): ?>
345 <li><strong>cURL:</strong> You have <code>cURL</code> support installed. <em>No problems here.</em></li>
346 <?php else: ?>
347 <li><strong>cURL:</strong> The <code>cURL</code> extension is not available. SimplePie will use <code>fsockopen()</code> instead.</li>
348 <?php endif; ?>
349
350 <?php if ($parallel_ok): ?>
351 <li><strong>Parallel URL fetching:</strong> You have <code>HttpRequestPool</code> or <code>curl_multi</code> support installed. <em>No problems here.</em></li>
352 <?php else: ?>
353 <li><strong>Parallel URL fetching:</strong> <code>HttpRequestPool</code> or <code>curl_multi</code> support is not available. <?php echo $app_name; ?> will use <code>file_get_contents()</code> instead to fetch URLs sequentially rather than in parallel.</li>
354 <?php endif; ?>
355
356 <?php else: ?>
357 <li><strong>Data filtering:</strong> Your PHP configuration has the filter extension disabled. <strong><?php echo $app_name; ?> will not work here.</strong></li>
358 <?php endif; ?>
359
360 <?php else: ?>
361 <li><strong>DOM/XML:</strong> Your PHP configuration isn't standard, you're missing PHP-DOM. You may try to install a package or recompile PHP. <strong><?php echo $app_name; ?> will not work here.</strong></li>
362 <?php endif; ?>
363
364 <?php else : ?>
365 <li><strong>Parse ini files function :</strong> Bad luck : your webhost has decided to block the use of the <em>parse_ini_file</em> function. <strong><?php echo $app_name; ?> will not work here.</strong>
366 <?php endif; ?>
367
368 <?php else: ?>
369 <li><strong>GetText:</strong> The <code>gettext</code> extension is not available. The system we use to display wallabag in various languages is not available. <strong><?php echo $app_name; ?> will not work here.</strong></li>
370 <?php endif; ?>
371
372 <?php else: ?>
373 <li><strong>allow_url_fopen:</strong> Your PHP configuration has allow_url_fopen disabled. <strong><?php echo $app_name; ?> will not work here.</strong></li>
374 <?php endif; ?>
375
376 <?php else: ?>
377 <li><strong>PCRE:</strong> Your PHP installation doesn't support Perl-Compatible Regular Expressions. <strong><?php echo $app_name; ?> will not work here.</strong></li>
378 <?php endif; ?>
379 <?php else: ?>
380 <li><strong>XML:</strong> Your PHP installation doesn't support XML parsing. <strong><?php echo $app_name; ?> will not work here.</strong></li>
381 <?php endif; ?>
382 <?php else: ?>
383 <li><strong>PHP:</strong> You are running an unsupported version of PHP. <strong><?php echo $app_name; ?> will not work here.</strong></li>
384 <?php endif; ?>
385 <?php endif; ?>
386 </ol>
387 </div>
388
389 <div class="chunk">
390 <?php //if ($php_ok && $xml_ok && $pcre_ok && $mbstring_ok && $iconv_ok && $filter_ok && $allow_url_fopen_ok) { ?>
391 <?php if ($php_ok && $xml_ok && $pcre_ok && $filter_ok && $allow_url_fopen_ok && $gettext_ok && $parse_ini_ok) { ?>
392 <h3>Bottom Line: Yes, you can!</h3>
393 <p><em>Your webhost has its act together!</em></p>
394 <?php if (!$frominstall) { ?>
395 <p>You can download the latest version of <?php echo $app_name; ?> from <a href="http://wallabag.org/download">wallabag.org</a>.</p>
396 <p>If you already have done that, you should access <a href="index.php">the index.php file</a> of your installation to configure and/or start using wallabag</p>
397 <?php } else { ?>
398 <p>You can now <a href="../index.php">return to the installation section</a>.</p>
399 <?php } ?>
400 <p><strong>Note</strong>: Passing this test does not guarantee that <?php echo $app_name; ?> will run on your webhost &mdash; it only ensures that the basic requirements have been addressed. If you experience any problems, please let us know.</p>
401 <?php //} else if ($php_ok && $xml_ok && $pcre_ok && $mbstring_ok && $allow_url_fopen_ok && $filter_ok) { ?>
402 <?php } else if ($php_ok && $xml_ok && $pcre_ok && $allow_url_fopen_ok && $filter_ok && $gettext_ok && $parse_ini_ok) { ?>
403 <h3>Bottom Line: Yes, you can!</h3>
404 <p><em>For most feeds, it'll run with no problems.</em> There are certain languages that you might have a hard time with though.</p>
405 <?php if (!$frominstall) { ?>
406 <p>You can download the latest version of <?php echo $app_name; ?> from <a href="http://wallabag.org/download">wallabag.org</a>.</p>
407 <p>If you already have done that, you should access <a href="index.php">the index.php file</a> of your installation to configure and/or start using wallabag</p>
408 <?php } else { ?>
409 <p>You can now <a href="../index.php">return to the installation section</a>.</p>
410 <?php } ?>
411 <p><strong>Note</strong>: Passing this test does not guarantee that <?php echo $app_name; ?> will run on your webhost &mdash; it only ensures that the basic requirements have been addressed. If you experience any problems, please let us know.</p>
412 <?php } else { ?>
413 <h3>Bottom Line: We're sorry…</h3>
414 <p><em>Your webhost does not support the minimum requirements for <?php echo $app_name; ?>.</em> It may be a good idea to contact your webhost and point them to the results of this test. They may be able to enable/install the required components.</p>
415 <?php } ?>
416 </div>
417
418 <div class="chunk">
419 <p class="footnote">This compatibility test has been borrowed (and slightly adapted by <a href="http://fivefilters.org/content-only/">fivefilters.org</a>) from the one supplied by <a href="http://simplepie.org/">SimplePie.org</a>.</a></p>
420 </div>
421
422 </div>
423
424</div>
425 61
426</body> 62function delTree($dir) {
427</html> 63 $files = array_diff(scandir($dir), array('.','..'));
64 foreach ($files as $file) {
65 (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
66 }
67 return rmdir($dir);
68 }
69
70function generate_salt() {
71 mt_srand(microtime(true)*100000 + memory_get_usage(true));
72 return md5(uniqid(mt_rand(), true));
73}
74
75function executeQuery($handle, $sql, $params) {
76 try
77 {
78 $query = $handle->prepare($sql);
79 $query->execute($params);
80 return $query->fetchAll();
81 }
82 catch (Exception $e)
83 {
84 return FALSE;
85 }
86}
87
88?> \ No newline at end of file
diff --git a/locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.mo b/locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.mo
index bd18817f..3add116c 100644
--- a/locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.mo
+++ b/locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.mo
Binary files differ
diff --git a/locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.po b/locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.po
index 8b82721d..47801007 100644
--- a/locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.po
+++ b/locale/de_DE.utf8/LC_MESSAGES/de_DE.utf8.po
@@ -1,18 +1,26 @@
1msgid "" 1msgid ""
2msgstr "" 2msgstr ""
3"Project-Id-Version: Wallabag\n" 3"Project-Id-Version: wallabag\n"
4"Report-Msgid-Bugs-To: \n" 4"Report-Msgid-Bugs-To: \n"
5"POT-Creation-Date: 2014-03-27 13:41+0100\n" 5"POT-Creation-Date: 2014-02-25 15:17+0300\n"
6"PO-Revision-Date: \n" 6"PO-Revision-Date: \n"
7"Last-Translator: Kevin Meyer <wallabag@kevin-meyer.de>\n" 7"Last-Translator: Julian Oster <wallabag@jlnostr.de>\n"
8"Language-Team: \n" 8"Language-Team: \n"
9"Language: de\n" 9"Language: de_DE\n"
10"MIME-Version: 1.0\n" 10"MIME-Version: 1.0\n"
11"Content-Type: text/plain; charset=UTF-8\n" 11"Content-Type: text/plain; charset=UTF-8\n"
12"Content-Transfer-Encoding: 8bit\n" 12"Content-Transfer-Encoding: 8bit\n"
13"X-Generator: Poedit 1.6.4\n" 13"X-Generator: Poedit 1.7.3\n"
14"X-Poedit-Basepath: .\n" 14"X-Poedit-Basepath: .\n"
15"X-Poedit-SearchPath-0: /Users/kevinmeyer/Dropbox/dev_web/wallabag-dev\n" 15
16msgid "wallabag, a read it later open source system"
17msgstr "wallabag, ein \"Read-it-later\"-Open-Source-System"
18
19msgid "login failed: user doesn't exist"
20msgstr "Anmeldung fehlgeschlagen: Benutzer existiert nicht"
21
22msgid "return home"
23msgstr "Auf Startseite zurückkehren"
16 24
17msgid "config" 25msgid "config"
18msgstr "Konfiguration" 26msgstr "Konfiguration"
@@ -21,13 +29,19 @@ msgid "Saving articles"
21msgstr "Artikel speichern" 29msgstr "Artikel speichern"
22 30
23msgid "There are several ways to save an article:" 31msgid "There are several ways to save an article:"
24msgstr "Es gibt viele Methoden um Artikel zu speichern:" 32msgstr "Es gibt mehrere Wege, um einen Artikel zu speichern:"
25 33
26msgid "read the documentation" 34msgid "read the documentation"
27msgstr "Die Dokumentation lesen" 35msgstr "Dokumentation lesen"
28 36
29msgid "download the extension" 37msgid "download the extension"
30msgstr "installiere die Erweiterung" 38msgstr "Erweiterung herunterladen"
39
40msgid "Firefox Add-On"
41msgstr "Firefox-Addon"
42
43msgid "Chrome Extension"
44msgstr "Chrome-Erweiterung"
31 45
32msgid "via F-Droid" 46msgid "via F-Droid"
33msgstr "via F-Droid" 47msgstr "via F-Droid"
@@ -39,16 +53,16 @@ msgid "via Google Play"
39msgstr "via Google Play" 53msgstr "via Google Play"
40 54
41msgid "download the application" 55msgid "download the application"
42msgstr "lade die App" 56msgstr "App herunterladen"
43 57
44msgid "By filling this field" 58msgid "By filling this field"
45msgstr "Durch Ausfüllen dieses Feldes" 59msgstr "Durch das Ausfüllen dieses Feldes"
46 60
47msgid "bag it!" 61msgid "bag it!"
48msgstr "bag it!" 62msgstr "bag it!"
49 63
50msgid "Bookmarklet: drag & drop this link to your bookmarks bar" 64msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
51msgstr "Bookmarklet: Ziehe diesen Link in deine Lesezeichen-Leiste" 65msgstr "Bookmarklet: Ziehe diesen Link in deine Lesezeichen"
52 66
53msgid "Upgrading wallabag" 67msgid "Upgrading wallabag"
54msgstr "wallabag aktualisieren" 68msgstr "wallabag aktualisieren"
@@ -57,58 +71,46 @@ msgid "Installed version"
57msgstr "Installierte Version" 71msgstr "Installierte Version"
58 72
59msgid "Latest stable version" 73msgid "Latest stable version"
60msgstr "Neuste stabile Version" 74msgstr "Letzte stabile Version"
61 75
62msgid "A more recent stable version is available." 76msgid "A more recent stable version is available."
63msgstr "Eine neuere stabile Version ist verfügbar." 77msgstr "Eine neuere Version ist verfügbar."
64 78
65msgid "You are up to date." 79msgid "You are up to date."
66msgstr "Du bist auf den neuesten Stand." 80msgstr "Du bist auf dem aktuellsten Stand."
67
68msgid "Last check:"
69msgstr "Zuletzt geprüft:"
70 81
71msgid "Latest dev version" 82msgid "Latest dev version"
72msgstr "Neuste Entwicklungsversion" 83msgstr "Letzte Entwickler-Version"
73 84
74msgid "A more recent development version is available." 85msgid "A more recent development version is available."
75msgstr "Eine neuere Entwicklungsversion ist verfügbar." 86msgstr "Eine neuere Entwickler-Version ist verfügbar."
76 87
77msgid "You can clear cache to check the latest release." 88msgid "You can clear cache to check the latest release."
78msgstr "Leere den Cache um die neueste Version zu prüfen." 89msgstr "Du kannst den <a href=\"#cache\">Cache leeren</a>, um nach neueren Versionen zu suchen."
79 90
80msgid "Feeds" 91msgid "Feeds"
81msgstr "Feeds" 92msgstr "Feeds"
82 93
83msgid "" 94msgid "Your feed token is currently empty and must first be generated to enable feeds. Click <a href='?feed&amp;action=generate'>here to generate it</a>."
84"Your feed token is currently empty and must first be generated to enable " 95msgstr "Dein Feed-Token ist momentan leer und muss generiert werden, um die Feeds zu aktivieren. Klicke <a href='?feed&amp;action=generate'>hier, um ihn zu erstellen</a>."
85"feeds. Click <a href='?feed&amp;action=generate'>here to generate it</a>."
86msgstr ""
87"Dein Feed Token ist noch nicht vorhanden und muss zunächst generiert werden, "
88"um deine Feeds zu aktivieren. Klicke <a href='?feed&amp;"
89"action=generate'>hier um ihn zu generieren</a>."
90 96
91msgid "Unread feed" 97msgid "Unread feed"
92msgstr "Ungelesen Feed" 98msgstr "Feed für Ungelesenes"
93 99
94msgid "Favorites feed" 100msgid "Favorites feed"
95msgstr "Favoriten Feed" 101msgstr "Feed für Favoriten"
96 102
97msgid "Archive feed" 103msgid "Archive feed"
98msgstr "Archiv Feed" 104msgstr "Archiv-Feed"
99 105
100msgid "Your token:" 106msgid "Your token:"
101msgstr "Dein Token:" 107msgstr "Dein Token:"
102 108
103msgid "Your user id:" 109msgid "Your user id:"
104msgstr "Deine User ID:" 110msgstr "Deine Benutzer-ID:"
105 111
106msgid "" 112msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
107"You can regenerate your token: <a href='?feed&amp;action=generate'>generate!" 113msgstr "Du kannst deinen Token regenerieren: <a href='?feed&amp;action=generate'>generieren!</a>."
108"</a>."
109msgstr ""
110"Hier kannst du dein Token erzeugen: <a href='?feed&amp;"
111"action=generate'>Generieren!</a>."
112 114
113msgid "Change your theme" 115msgid "Change your theme"
114msgstr "Theme ändern" 116msgstr "Theme ändern"
@@ -138,76 +140,58 @@ msgid "Repeat your new password:"
138msgstr "Neues Passwort wiederholen:" 140msgstr "Neues Passwort wiederholen:"
139 141
140msgid "Import" 142msgid "Import"
141msgstr "Import" 143msgstr "Importieren"
142 144
143msgid "" 145msgid "You can import your Pocket, Readability, Instapaper, Wallabag or any data in appropriate json or html format."
144"Importing from other services can be quite long, and webservers default " 146msgstr "Du kannst aus Pocket, Readability, Instapaper, wallabag oder einer beliebigen Datei in angebrachtem JSON- oder HTML-Format importieren."
145"configuration often prevents long scripts execution time, so it must be done " 147
146"in multiple parts." 148msgid "Please execute the import script locally as it can take a very long time."
147msgstr "" 149msgstr "Führe das Import-Skript lokal aus, da der Import sehr lange dauern kann."
148"Der Import von anderen Diensten kann sehr lange dauern. Deswegen bricht der "
149"Webserver diesen in vielen Konfigurationen ab. Daher muss der Import in "
150"mehrere Teile aufgeteilt werden."
151 150
152msgid "First, select the export file on your computer and upload it." 151msgid "Please select export file on your computer and press \"Import\" button below. Wallabag will parse your file, insert all URLs and start fetching of articles if required."
153msgstr "Wähle eine Datei von deinem Computer aus und lade sie hoch." 152msgstr ""
153"Wähle die Export-Datei auf deinem Computer aus und drücke den \"Import\"-Button unten. Wallabag wird deine Datei durchsuchen, alle URLs in der Datenbank speichern und die Artikel "
154"herunterladen, sofern dies erforderlich ist."
154 155
155msgid "File:" 156msgid "You can click here to fetch content for articles with no content."
156msgstr "Datei:" 157msgstr "Du kannst hier klicken, um den Inhalt für Artikel ohne Inhalt herunterzuladen."
157 158
158msgid "Upload" 159msgid "More info in the official documentation:"
159msgstr "Hochladen" 160msgstr "Mehr Infos in der offiziellen Dokumentation:"
160 161
161msgid "Then, click on the right link below." 162msgid "(<a href=\"http://doc.wallabag.org/en/User_documentation/Save_your_first_article\" target=\"_blank\" title=\"Documentation\">?</a>)"
162msgstr "Klicke dann unten auf den entsprechenden Link." 163msgstr "(<a href=\"http://doc.wallabag.org/de/Anwender/Den_ersten_Artikel_speichern\" target=\"_blank\" title=\"Dokumentation\">?</a>)"
163 164
164msgid "Import from Pocket" 165msgid "Import from Pocket"
165msgstr "Import aus Pocket" 166msgstr "Aus Pocket importieren"
166 167
167#, php-format 168#, php-format
168msgid "(after uploaded %s file)" 169msgid "(you must have a %s file on your server)"
169msgstr "(nach Upload der Datei %s)" 170msgstr "(du solltest eine %s Datei auf deinem Server haben)"
170 171
171msgid "Import from Readability" 172msgid "Import from Readability"
172msgstr "Import aus Readability" 173msgstr "Aus Readability importieren"
173 174
174msgid "Import from Instapaper" 175msgid "Import from Instapaper"
175msgstr "Import aus Instapaper" 176msgstr "Aus Instapaper importieren"
176 177
177msgid "Import from wallabag" 178msgid "Import from wallabag"
178msgstr "Import aus Readability" 179msgstr "Aus wallabag importieren"
179 180
180msgid "" 181msgid "Export your wallabag data"
181"3. Your feed token is currently empty and must first be generated to fetch " 182msgstr "Deine wallabag-Daten exportieren"
182"content. Click <a href='?feed&amp;action=generate'>here to generate it</a>."
183msgstr ""
184"3. Dein Feed Token ist noch nicht vorhanden und muss zunächst generiert "
185"werden, um Inhalt abrufen zu können. Klicke <a href='?feed&amp;"
186"action=generate'>hier um ihn zu generieren</a>."
187
188msgid "Finally, you have to fetch content for imported items."
189msgstr "Jetzt musst du den Inhalt der importierten Artikel abrufen."
190 183
191msgid "Click here" 184msgid "Click here"
192msgstr "Klicke hier" 185msgstr "Hier klicken, "
193
194msgid "to fetch content for 10 articles"
195msgstr "um den Inhalt von 10 Artikeln abzurufen"
196
197msgid ""
198"If you have console access to your server, you can also create a cron task:"
199msgstr ""
200"Wenn du Konsolenzugang zu deinem Server hast kannst du auch einen cron "
201"erstellen:"
202
203msgid "Export your wallabag data"
204msgstr "Exportieren deine wallabag Daten"
205 186
206msgid "to download your database." 187msgid "to download your database."
207msgstr "um deine Datenbank herunterzuladen" 188msgstr "um die Datenbank herunterzuladen."
208 189
209msgid "to export your wallabag data." 190msgid "to export your wallabag data."
210msgstr "um deine Daten aus wallabag zu exportieren." 191msgstr "um die wallabag-Daten zu exportieren."
192
193msgid "Export JSON"
194msgstr "JSON exportieren"
211 195
212msgid "Cache" 196msgid "Cache"
213msgstr "Cache" 197msgstr "Cache"
@@ -215,444 +199,437 @@ msgstr "Cache"
215msgid "to delete cache." 199msgid "to delete cache."
216msgstr "um den Cache zu löschen." 200msgstr "um den Cache zu löschen."
217 201
218msgid "Tags" 202msgid "Delete Cache"
219msgstr "Tags" 203msgstr "Cache löschen, "
204
205msgid "You can enter multiple tags, separated by commas."
206msgstr "Du kannst mehrere Schlagworte, getrennt von einem Komma, hinzufügen."
207
208msgid "Add tags:"
209msgstr "Schlagworte hinzufügen:"
210
211msgid "no tags"
212msgstr "keine schlagworte"
213
214msgid "The tag has been applied successfully"
215msgstr "Das Schlagwort wurde erfolgreich übernommen."
216
217msgid "interview"
218msgstr "interview"
219
220msgid "editorial"
221msgstr "editorial"
222
223msgid "video"
224msgstr "video"
225
226msgid "return to article"
227msgstr "zum artikel zurückkehren"
228
229msgid "plop"
230msgstr "plop"
231
232msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
233msgstr "Du kannst deine <a href='wallabag_compatibility_test.php'>Konfiguration hier überprüfen</a>."
234
235msgid "favoris"
236msgstr "Favoriten"
237
238msgid "archive"
239msgstr "archiv"
240
241msgid "unread"
242msgstr "ungelesen"
220 243
221msgid "by date asc" 244msgid "by date asc"
222msgstr "nach Datum aufsteigend" 245msgstr "nach Datum, aufsteigend"
223 246
224msgid "by date" 247msgid "by date"
225msgstr "nach Datum" 248msgstr "nach Datum"
226 249
227msgid "by date desc" 250msgid "by date desc"
228msgstr "nach Datum absteigend" 251msgstr "nach Datum, absteigend"
229 252
230msgid "by title asc" 253msgid "by title asc"
231msgstr "nach Titel aufsteigend" 254msgstr "nach Titel, aufsteigend"
232 255
233msgid "by title" 256msgid "by title"
234msgstr "nach Titel" 257msgstr "nach Titel"
235 258
236msgid "by title desc" 259msgid "by title desc"
237msgstr "nach Titel absteigend" 260msgstr "nach Titel, absteigend"
238
239#, fuzzy
240msgid "toggle view mode"
241msgstr "Favorit"
242 261
243msgid "home" 262msgid "Tag"
244msgstr "Start" 263msgstr "Schlagwort"
245 264
246msgid "favorites" 265msgid "No articles found."
247msgstr "Favoriten" 266msgstr "Keine Artikel gefunden."
248 267
249msgid "archive" 268msgid "Toggle mark as read"
250msgstr "Archiv" 269msgstr "Als gelesen/ungelesen markieren"
251 270
252msgid "tags" 271msgid "toggle favorite"
253msgstr "Tags" 272msgstr "favorisieren"
254 273
255msgid "save a link" 274msgid "delete"
256msgstr "Speichere einen Link" 275msgstr "löschen"
257 276
258msgid "search" 277msgid "original"
259msgstr "Suche" 278msgstr "original"
260 279
261msgid "logout" 280msgid "estimated reading time:"
262msgstr "Logout" 281msgstr "Geschätzte Lesezeit:"
263 282
264msgid "return home" 283msgid "mark all the entries as read"
265msgstr "Zu¼ck zum Start" 284msgstr "Alle Eint¤ge als gelesen markieren"
266 285
267#, fuzzy 286msgid "results"
268msgid "Search" 287msgstr "Ergebnisse"
269msgstr "Archiv"
270 288
271msgid "powered by" 289msgid "installation"
272msgstr "bereitgestellt von" 290msgstr "installation"
273 291
274msgid "debug mode is on so cache is off." 292msgid "install your wallabag"
275msgstr "Debug Modus ist aktiviert, das Caching ist somit deaktiviert" 293msgstr "deine wallabag installieren"
276 294
277msgid "your wallabag version:" 295msgid "wallabag is still not installed. Please fill the below form to install it. Don't hesitate to <a href='http://doc.wallabag.org/'>read the documentation on wallabag website</a>."
278msgstr "Deine wallabag Version" 296msgstr ""
297"wallabag ist noch nicht installiert. Fülle das untenstehende Formular aus, um wallabag zu installieren. Scheue dich nicht davor, die <a href='http://doc.wallabag.org/de'>Dokumentation "
298"auf der wallabag-Webseite</a> zur Hilfe zu ziehen."
279 299
280msgid "storage:" 300msgid "Login"
281msgstr "Speicher:" 301msgstr "Anmelden"
282 302
283msgid "Save a link" 303msgid "Repeat your password"
284msgstr "Speichere einen Link" 304msgstr "Passwort wiederholen"
285 305
286msgid "save link!" 306msgid "Install"
287msgstr "Link speichern!" 307msgstr "Installieren"
288 308
289msgid "unread" 309msgid "login to your wallabag"
290msgstr "ungelesen" 310msgstr "Melde dich in deiner wallabag an"
291 311
292msgid "Tag" 312msgid "Login to wallabag"
293msgstr "Tag" 313msgstr "In wallabag anmelden"
294 314
295msgid "No articles found." 315msgid "you are in demo mode, some features may be disabled."
296msgstr "Keine Artikel gefunden." 316msgstr "Du bist im Demo-Modus, einige Features sind möglicherweise deaktiviert."
297 317
298msgid "estimated reading time:" 318msgid "Username"
299msgstr "geschätzte Lesezeit:" 319msgstr "Benutzername"
300 320
301msgid "estimated reading time :" 321msgid "Stay signed in"
302msgstr "geschätzte Lesezeit:" 322msgstr "Angemeldet bleiben"
303 323
304msgid "Toggle mark as read" 324msgid "(Do not check on public computers)"
305msgstr "Als gelesen markieren" 325msgstr "(nicht auf öffentlichen Computern ankreuzen)"
306 326
307msgid "toggle favorite" 327msgid "Sign in"
308msgstr "Favorit" 328msgstr "Anmelden"
309 329
310msgid "delete" 330msgid "favorites"
311msgstr "Löschen" 331msgstr "favoriten"
312 332
313msgid "original" 333msgid "estimated reading time :"
314msgstr "Original" 334msgstr "Geschätzte Lesezeit:"
315 335
316msgid "Mark all the entries as read" 336msgid "Mark all the entries as read"
317msgstr "Markiere alle als gelesen" 337msgstr "Alle Einträge als gelesen markieren"
318 338
319msgid "results" 339msgid "Return home"
320msgstr "Ergebnisse" 340msgstr "Zur Startseite zurückkehren"
321 341
322msgid "Uh, there is a problem with the cron." 342msgid "Back to top"
323msgstr "Oh, es gab ein Problem mit dem cron." 343msgstr "Nach oben scrollen"
324 344
325msgid "Untitled" 345msgid "Mark as read"
326msgstr "Ohne Titel" 346msgstr "Als gelesen markieren"
327
328msgid "the link has been added successfully"
329msgstr "Speichern des Links erfolgreich"
330
331msgid "error during insertion : the link wasn't added"
332msgstr "Fehler beim Einfügen: Der Link wurde nicht hinzugefügt"
333
334msgid "the link has been deleted successfully"
335msgstr "Löschen des Links erfolgreich"
336
337msgid "the link wasn't deleted"
338msgstr "Der Link wurde nicht entfernt"
339 347
340msgid "Article not found!" 348msgid "Favorite"
341msgstr "Artikel nicht gefunden!" 349msgstr "Favorisieren"
342 350
343msgid "previous" 351msgid "Toggle favorite"
344msgstr "vorherige" 352msgstr "favorisieren"
345 353
346msgid "next" 354msgid "Delete"
347msgstr "nächste" 355msgstr "Löschen"
348 356
349msgid "in demo mode, you can't update your password" 357msgid "Tweet"
350msgstr "im Demo-Modus kann das Passwort nicht geändert werden" 358msgstr "Twittern"
351 359
352msgid "your password has been updated" 360msgid "Email"
353msgstr "Dein Passwort wurde geändert" 361msgstr "Email"
354 362
355msgid "" 363msgid "shaarli"
356"the two fields have to be filled & the password must be the same in the two " 364msgstr "shaarli"
357"fields"
358msgstr "Beide Felder müssen mit selbem Inhalt ausgefüllt sein"
359 365
360msgid "still using the \"" 366msgid "flattr"
361msgstr "nutze immernoch die \"" 367msgstr "flattr"
362 368
363msgid "that theme does not seem to be installed" 369msgid "Does this article appear wrong?"
364msgstr "dieses Theme scheint nicht installiert zu sein" 370msgstr "Erscheint dieser Artikel nicht richtig?"
365 371
366msgid "you have changed your theme preferences" 372msgid "tags:"
367msgstr "Du hast deine Theme Einstellungen geändert" 373msgstr "schlagworte:"
368 374
369msgid "that language does not seem to be installed" 375msgid "Edit tags"
370msgstr "Diese Sprache scheint nicht installiert zu sein" 376msgstr "Schlagworte bearbeiten"
371 377
372msgid "you have changed your language preferences" 378msgid "save link!"
373msgstr "Du hast deine Spracheinstellungen geändert" 379msgstr "link speichern!"
374 380
375msgid "login failed: you have to fill all fields" 381msgid "home"
376msgstr "Anmeldung fehlgeschlagen: Alle Felder müssen ausgefüllt werden" 382msgstr "start"
377 383
378msgid "welcome to your wallabag" 384msgid "tags"
379msgstr "Willkommen bei deiner wallabag" 385msgstr "schlagworte"
380 386
381msgid "login failed: bad login or password" 387msgid "logout"
382msgstr "Anmeldung fehlgeschlagen: Falscher Benutzername oder Passwort" 388msgstr "abmelden"
383 389
384msgid "" 390msgid "powered by"
385"import from instapaper completed. You have to execute the cron to fetch " 391msgstr "Angetrieben von"
386"content."
387msgstr ""
388"Import aus Instapaper vollständig. Führe den cronjob aus um den Inhalt "
389"abzurufen."
390 392
391msgid "" 393msgid "debug mode is on so cache is off."
392"import from pocket completed. You have to execute the cron to fetch content." 394msgstr "Der Debug-Modus ist aktiviert, also ist der Cache deaktiviert."
393msgstr ""
394"Import aus Pocket vollständig. Führe den cronjob aus um den Inhalt abzurufen."
395 395
396msgid "" 396msgid "your wallabag version:"
397"import from Readability completed. You have to execute the cron to fetch " 397msgstr "Deine wallabag-Version:"
398"content."
399msgstr ""
400"Import aus Readability vollständig. Führe den cronjob aus um den Inhalt "
401"abzurufen."
402 398
403msgid "" 399msgid "storage:"
404"import from Poche completed. You have to execute the cron to fetch content." 400msgstr "speicher:"
405msgstr ""
406"Import aus Poche vollständig. Führe den cronjob aus um den Inhalt abzurufen."
407 401
408msgid "Unknown import provider." 402msgid "save a link"
409msgstr "Unbekannter Import Anbieter." 403msgstr "einen link speichern"
410 404
411msgid "Could not find required \"" 405msgid "back to home"
412msgstr "Nicht gefunden: \"" 406msgstr "zurück zur startseite"
413 407
414msgid "File uploaded. You can now execute import." 408msgid "toggle mark as read"
415msgstr "Datei hochgeladen. Du kannst nun importieren." 409msgstr "als gelesen/ungelesen markieren"
416 410
417msgid "Error while importing file. Do you have access to upload it?" 411msgid "tweet"
418msgstr "Fehler beim Importieren. Hast du das Recht zum Hochladen?" 412msgstr "tweet"
419 413
420msgid "User with this id (" 414msgid "email"
421msgstr "Nutzer mit dieser id (" 415msgstr "email"
422 416
423msgid "Uh, there is a problem while generating feeds." 417msgid "this article appears wrong?"
424msgstr "Oh, es gab ein Problem beim Erstellen des Feeds." 418msgstr "dieser artikel erscheint falsch?"
425 419
426msgid "Cache deleted." 420msgid "No link available here!"
427msgstr "Cache gelöscht" 421msgstr "Kein Link verfügbar!"
428 422
429msgid "Oops, it seems you don't have PHP 5." 423msgid "Poching a link"
430msgstr "Oops, es scheint als würde PHP 5 fehlen." 424msgstr "Link speichern"
431 425
432msgid "wallabag, a read it later open source system" 426msgid "by filling this field"
433msgstr "wallabag, ein Später-Lesen Open Source System" 427msgstr "mit dem Ausfüllen dieses Feldes"
434 428
435msgid "login failed: user doesn't exist" 429msgid "bookmarklet: drag & drop this link to your bookmarks bar"
436msgstr "Anmeldung fehlgeschlagen: Benutzer existiert nicht" 430msgstr "Bookmarklet: Drag & drop diesen Link in deine Lesezeichen"
437 431
438#~ msgid "You can enter multiple tags, separated by commas." 432msgid "Drag &amp; drop this link to your bookmarks bar:"
439#~ msgstr "Du kannst mehrere Tags, durch Kommata getrennt, eingeben." 433msgstr "Drag &amp; drop diesen Link in deine Lesezeichen:"
440 434
441#~ msgid "return to article" 435msgid "your version"
442#~ msgstr "zurück zum Artikel" 436msgstr "deine Version"
443 437
444#, fuzzy 438msgid "latest stable version"
445#~ msgid "favoris" 439msgstr "letzte stabile Version"
446#~ msgstr "Favoriten"
447 440
448#~ msgid "mark all the entries as read" 441msgid "a more recent stable version is available."
449#~ msgstr "Markiere alle als gelesen" 442msgstr "Eine aktuellere Version ist verfügbar."
450 443
451#~ msgid "Back to top" 444msgid "you are up to date."
452#~ msgstr "Nach Oben" 445msgstr "Du bist auf dem aktuellsten Stand."
453 446
454#~ msgid "Mark as read" 447msgid "latest dev version"
455#~ msgstr "Als gelesen markieren" 448msgstr "Letzte Entwickler-Version"
456 449
457#~ msgid "Favorite" 450msgid "a more recent development version is available."
458#~ msgstr "Favoriten" 451msgstr "Eine neuere Entwickler-Version ist verfügbar."
459 452
460#~ msgid "Toggle favorite" 453msgid "Please execute the import script locally, it can take a very long time."
461#~ msgstr "Favorit" 454msgstr "Führe das Import-Skript lokal aus, da der Import sehr lange dauern kann."
462 455
463#~ msgid "Delete" 456msgid "More infos in the official doc:"
464#~ msgstr "Löschen" 457msgstr "Mehr Informationen in der offiziellen Dokumentation:"
465 458
466#~ msgid "Tweet" 459msgid "import from Pocket"
467#~ msgstr "Twittern" 460msgstr "Aus Pocket importieren"
468 461
469#~ msgid "Email" 462msgid "import from Readability"
470#~ msgstr "per E-Mail senden" 463msgstr "Aus Readability importieren"
471 464
472#~ msgid "shaarli" 465msgid "import from Instapaper"
473#~ msgstr "Shaarli" 466msgstr "Aus Instapaper importieren"
474 467
475#~ msgid "flattr" 468msgid "Tags"
476#~ msgstr "flattr" 469msgstr "Schlagworte"
477 470
478#~ msgid "Does this article appear wrong?" 471msgid "Untitled"
479#~ msgstr "Erscheint dieser Artikel falsch?" 472msgstr "Untitled"
480 473
481#~ msgid "Edit tags" 474msgid "the link has been added successfully"
482#~ msgstr "Tags bearbeiten" 475msgstr "Der Link wurde erfolgreich hinzugefügt"
483 476
484#~ msgid "Start typing for auto complete." 477msgid "error during insertion : the link wasn't added"
485#~ msgstr "Beginne zu tippen für die Autovervollständigung." 478msgstr "Fehler während des Imports: Der Link wurde nicht hinzugefügt."
486 479
487#~ msgid "Return home" 480msgid "the link has been deleted successfully"
488#~ msgstr "Zurück zum Start" 481msgstr "Der Link wurde erfolgreich gelöscht"
489 482
490#~ msgid "tags:" 483msgid "the link wasn't deleted"
491#~ msgstr "Tags:" 484msgstr "Der Link wurde nicht gelöscht."
492 485
493#~ msgid "login to your wallabag" 486msgid "Article not found!"
494#~ msgstr "Bei wallabag anmelden" 487msgstr "Artikel nicht gefunden!"
495 488
496#~ msgid "you are in demo mode, some features may be disabled." 489msgid "previous"
497#~ msgstr "" 490msgstr "vorherige"
498#~ "Du befindest dich im Demomodus, einige Funktionen könnten deaktiviert "
499#~ "sein."
500 491
501#~ msgid "Login" 492msgid "next"
502#~ msgstr "Benutzername" 493msgstr "nächste"
503 494
504#~ msgid "Stay signed in" 495msgid "in demo mode, you can't update your password"
505#~ msgstr "Angemeldet bleiben" 496msgstr "Im Demo-Modus kannst du as Kennwort nicht aktualisieren."
506 497
507#~ msgid "(Do not check on public computers)" 498msgid "your password has been updated"
508#~ msgstr "(nicht auf einem öffentlichen Computer anhaken)" 499msgstr "Dein Passwort wurde aktualisiert"
509 500
510#~ msgid "plop" 501msgid "the two fields have to be filled & the password must be the same in the two fields"
511#~ msgstr "plop" 502msgstr "Beide Felder müssen ausgefüllt sein und das gleiche Passwort beinhalten"
512 503
513#~ msgid "Login to wallabag" 504msgid "still using the \""
514#~ msgstr "Bei wallabag anmelden" 505msgstr "nutze immernoch die \""
515 506
516#~ msgid "Username" 507msgid "that theme does not seem to be installed"
517#~ msgstr "Benutzername" 508msgstr "Dieses Theme scheint nicht installiert zu sein."
518 509
519#~ msgid "Sign in" 510msgid "you have changed your theme preferences"
520#~ msgstr "Einloggen" 511msgstr "Du hast deine Theme-Einstellungen geändert"
521 512
522#~ msgid "Enter your search here" 513msgid "that language does not seem to be installed"
523#~ msgstr "Gib hier deine Suchanfrage ein" 514msgstr "Diese Sprache scheint nicht installiert zu sein"
524 515
525#~ msgid "installation" 516msgid "you have changed your language preferences"
526#~ msgstr "Installieren" 517msgstr "Du hast deine Spracheinstellungen geändert"
527 518
528#~ msgid "install your wallabag" 519msgid "login failed: you have to fill all fields"
529#~ msgstr "Installiere deine wallabag" 520msgstr "Anmeldung fehlgeschlagen: Du musst alle Felder ausfüllen"
530 521
531#~ msgid "" 522msgid "welcome to your wallabag"
532#~ "wallabag is still not installed. Please fill the below form to install " 523msgstr "Willkommen in deiner wallabag"
533#~ "it. Don't hesitate to <a href='http://doc.wallabag.org/'>read the "
534#~ "documentation on wallabag website</a>."
535#~ msgstr ""
536#~ "wallabag ist noch nicht installiert. Bitte fülle die Felder unten aus, um "
537#~ "die Installation durchzuführen. Zögere nicht, <a href='http://doc."
538#~ "wallabag.org/'>die Dokumentation auf der Website von wallabag zu lesen, "
539#~ "falls du Probleme haben solltest."
540 524
541#~ msgid "Repeat your password" 525msgid "login failed: bad login or password"
542#~ msgstr "Wiederhole dein Passwort" 526msgstr "Anmeldung fehlgeschlagen: Falscher Benutzername oder falsches Passwort"
543 527
544#~ msgid "Install" 528msgid "import from instapaper completed"
545#~ msgstr "Installieren" 529msgstr "Import aus Instapaper abgeschlossen"
546 530
547#~ msgid "No link available here!" 531msgid "import from pocket completed"
548#~ msgstr "Kein Link verfügbar!" 532msgstr "Import aus Pocket abgeschlossen"
549 533
550#~ msgid "toggle mark as read" 534msgid "import from Readability completed. "
551#~ msgstr "Als gelesen markieren" 535msgstr "Import aus Readability abgeschlossen."
552 536
553#~ msgid "" 537msgid "import from Poche completed. "
554#~ "You can <a href='wallabag_compatibility_test.php'>check your " 538msgstr "Import aus wallabag abgeschlossen."
555#~ "configuration here</a>."
556#~ msgstr ""
557#~ "Du kannst deine Konfiguration <a href='wallabag_compatibility_test."
558#~ "php'>hier testen</a>."
559 539
560#~ msgid "back to home" 540msgid "Unknown import provider."
561#~ msgstr "züruck zur Hauptseite" 541msgstr "Unbekannter Import-Provider."
562 542
563#~ msgid "tweet" 543msgid "Incomplete inc/poche/define.inc.php file, please define \""
564#~ msgstr "Twittern" 544msgstr "Die Datei /inc/poche/define.inc.php ist unvollständig, bitte definiere \""
565 545
566#~ msgid "email" 546msgid "Could not find required \""
567#~ msgstr "senden per E-Mail" 547msgstr "Nicht gefunden: \""
568 548
569#~ msgid "this article appears wrong?" 549msgid "Uh, there is a problem while generating feeds."
570#~ msgstr "dieser Artikel erscheint falsch?" 550msgstr "Oh, es gibt ein Problem bei dem Generieren der Feeds."
571 551
572#~ msgid "Poching a link" 552msgid "Cache deleted."
573#~ msgstr "Poche einen Link" 553msgstr "Cache geleert."
574 554
575#~ msgid "by filling this field" 555msgid "Oops, it seems you don't have PHP 5."
576#~ msgstr "durch das ausfüllen dieses Feldes:" 556msgstr "Ups, es sieht so aus, als ob du nicht PHP 5 hast."
577 557
578#~ msgid "bookmarklet: drag & drop this link to your bookmarks bar" 558msgid "Add user"
579#~ msgstr "Bookmarklet: Ziehe diesen Link in deine Lesezeichen-Leiste" 559msgstr "Benutzer hinzufügen"
580 560
581#~ msgid "your version" 561msgid "Add a new user :"
582#~ msgstr "Deine Version" 562msgstr "Neuen Benutzer hinzufügen:"
583 563
584#~ msgid "latest stable version" 564msgid "Login for new user"
585#~ msgstr "Neuste stabile Version" 565msgstr "Benutzername des neuen Benutzers"
586 566
587#~ msgid "a more recent stable version is available." 567msgid "Password for new user"
588#~ msgstr "Eine neuere stabile Version ist verfügbar." 568msgstr "Passwort des neuen Benutzers"
589 569
590#~ msgid "you are up to date." 570msgid "Email for new user (not required)"
591#~ msgstr "Du bist auf den neuesten Stand." 571msgstr "E-Mail-Adresse des neuen Benutzers (nicht erforderlich)"
592 572
593#~ msgid "latest dev version" 573msgid "Send"
594#~ msgstr "Neuste Entwicklungsversion" 574msgstr "Senden"
595 575
596#~ msgid "a more recent development version is available." 576msgid "Delete account"
597#~ msgstr "Eine neuere Entwicklungsversion ist verfügbar." 577msgstr "Account löschen"
598 578
599#~ msgid "" 579msgid "You can delete your account by entering your password and validating."
600#~ "Please execute the import script locally, it can take a very long time." 580msgstr "Du kannst deinen Account löschen, indem du dein Kennwort eintippst und validierst."
601#~ msgstr ""
602#~ "Bitte führe das Import Script lokal aus, dies kann eine Weile dauern."
603 581
604#~ msgid "More infos in the official doc:" 582msgid "Be careful, data will be erased forever (that is a very long time)."
605#~ msgstr "Mehr Informationen in der offiziellen Dokumentation:" 583msgstr "Pass auf, die Daten werden für immer gelöscht werden (eine sehr lange Zeit)."
606 584
607#~ msgid "import from Pocket" 585msgid "Type here your password"
608#~ msgstr "Import aus Pocket" 586msgstr "Kennwort hier eintippen"
609 587
610#~ msgid "(you must have a %s file on your server)" 588msgid "You are the only user, you cannot delete your own account."
611#~ msgstr "(du brauchst eine %s Datei auf deinem Server)" 589msgstr "Du kannst deinen Account nicht löschen, weil du der einzige Benutzer bist."
612 590
613#~ msgid "import from Readability" 591msgid "To completely remove wallabag, delete the wallabag folder on your web server (and eventual databases)."
614#~ msgstr "Import aus Readability" 592msgstr "Um wallabag komplett zu entfernen, lösche den wallabag-Ordner und die Datenbank(en) von deinem Webserver."
615 593
616#~ msgid "import from Instapaper" 594msgid "Enter your search here"
617#~ msgstr "Import aus Instapaper" 595msgstr "Suchbegriff hier eintippen"
618 596
619#~ msgid "You can also create a cron task:" 597msgid "Tag these results as"
620#~ msgstr "Du kannst auch einen cronjob anlegen:" 598msgstr "Diese Ergebnisse verschlagworten mit"
621 599
622#~ msgid "" 600# ebook
623#~ "Please execute the import script locally as it can take a very long time." 601msgid "Fancy an E-Book ?"
624#~ msgstr "" 602msgstr "Willst du ein E-Book?"
625#~ "Bitte führe das Import Script lokal aus, da dies eine Weile dauern kann."
626 603
627#~ msgid "More info in the official documentation:" 604msgid "Click on <a href=\"./?epub&amp;method=all\" title=\"Generate ePub\">this link</a> to get all your articles in one ebook (ePub 3 format)."
628#~ msgstr "Mehr Informationen in der offiziellen Dokumentation:" 605msgstr "Klicke auf <a href=\"./?epub&amp;method=all\" title=\"EPUB erstellen\">diesen Link</a>, um alle Artikel in ein E-Book (EPUB 3-Format) zu exportieren."
629 606
630#~ msgid "import from instapaper completed" 607msgid "This can <b>take a while</b> and can <b>even fail</b> if you have too many articles, depending on your server configuration."
631#~ msgstr "Import aus Instapaper erfolgreich" 608msgstr "Dies kann <b>eine Weile dauern</b> oder <b>sogar fehlschlagen</b>, wenn du zu viele Artikel hast, abhängig von deiner Server-Konfiguration."
632 609
633#~ msgid "import from pocket completed" 610msgid "Download the articles from this tag in an epub"
634#~ msgstr "Import aus Pocket erfolgreich" 611msgstr "Die Artikel von diesem Schlagwort als EPUB herunterladen"
635 612
636#~ msgid "import from Poche completed. " 613msgid "Download the articles from this search in an epub"
637#~ msgstr "Import aus Poche erfolgreich" 614msgstr "Alle Artikel aus dieser Suche als EPUB herunterladen"
638 615
639#~ msgid "Incomplete inc/poche/define.inc.php file, please define \"" 616msgid "Download the articles from this category in an epub"
640#~ msgstr "Unvollständige inc/poche/define.inc.php Datei, bitte setze \"" 617msgstr "Alle Artikel aus dieser Kategorie als EPUB herunterladen"
641 618
642#~ msgid "poche it!" 619#~ msgid "poche it!"
643#~ msgstr "Poche es!" 620#~ msgstr "poche it!"
644 621
645#~ msgid "Updating poche" 622#~ msgid "Updating poche"
646#~ msgstr "Poche aktualisieren" 623#~ msgstr "Updating poche"
647 624
648#~ msgid "create an issue" 625#~ msgid "create an issue"
649#~ msgstr "ein Ticket erstellen" 626#~ msgstr "create an issue"
650 627
651#~ msgid "or" 628#~ msgid "or"
652#~ msgstr "oder" 629#~ msgstr "or"
653 630
654#~ msgid "contact us by mail" 631#~ msgid "contact us by mail"
655#~ msgstr "kontaktieren Sie uns per E-Mail" 632#~ msgstr "contact us by mail"
656 633
657#~ msgid "your poche version:" 634#~ msgid "your poche version:"
658#~ msgstr "Deine Poche Version" 635#~ msgstr "your poche version:"
diff --git a/locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.mo b/locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.mo
index eed260b2..83f397a0 100644
--- a/locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.mo
+++ b/locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.mo
Binary files differ
diff --git a/locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.po b/locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.po
index 4bdb3cd5..fef31208 100644
--- a/locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.po
+++ b/locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.po
@@ -250,7 +250,7 @@ msgid ""
250"your config file: IMPORT_LIMIT (how many articles are fetched at once) and " 250"your config file: IMPORT_LIMIT (how many articles are fetched at once) and "
251"IMPORT_DELAY (delay between fetch of next batch of articles)." 251"IMPORT_DELAY (delay between fetch of next batch of articles)."
252msgstr "" 252msgstr ""
253"Sélectionner le fichier à importer sur votre disque dur, et pressez la " 253"Sélectionnez le fichier à importer sur votre disque dur, et pressez la "
254"bouton « Importer » ci-dessous.<br />wallabag analysera votre fichier, " 254"bouton « Importer » ci-dessous.<br />wallabag analysera votre fichier, "
255"ajoutera toutes les URL trouvées et commencera à télécharger les contenus si " 255"ajoutera toutes les URL trouvées et commencera à télécharger les contenus si "
256"nécessaire.<br />Le processus de téléchargement est contrôlé par deux " 256"nécessaire.<br />Le processus de téléchargement est contrôlé par deux "
diff --git a/themes/baggy/home.twig b/themes/baggy/home.twig
index 27eea422..d84c3f35 100755
--- a/themes/baggy/home.twig
+++ b/themes/baggy/home.twig
@@ -59,7 +59,11 @@
59 {{ block('pager') }} 59 {{ block('pager') }}
60 {% if view == 'home' %}{% if nb_results > 1 %}<p><a title="{% trans "Mark all the entries as read" %}" href="./?action=archive_all">{% trans "Mark all the entries as read" %}</a></p>{% endif %}{% endif %} 60 {% if view == 'home' %}{% if nb_results > 1 %}<p><a title="{% trans "Mark all the entries as read" %}" href="./?action=archive_all">{% trans "Mark all the entries as read" %}</a></p>{% endif %}{% endif %}
61 {% if searchterm is defined %}<a title="{% trans "Tag these results as" %} {{ searchterm }}" href="./?action=add_tag&search={{ searchterm }}">{% trans "Tag these results as" %} {{ searchterm }}</a>{% endif %}<br /> 61 {% if searchterm is defined %}<a title="{% trans "Tag these results as" %} {{ searchterm }}" href="./?action=add_tag&search={{ searchterm }}">{% trans "Tag these results as" %} {{ searchterm }}</a>{% endif %}<br />
62 62
63 {% if searchterm is defined %}<a title="{% trans "Delete results matching" %} {{ searchterm }}" href="./?action=delete&search={{ searchterm }}">{% trans "Delete results matching" %} {{ searchterm }}</a>{% endif %}<br />
64
65 {% if tag %}<a title="{% trans "Mark all articles from this tag as read" %}" href="./?action=toggle_archive&amp;tag_id={{ tag.id }}">{% trans "Mark all articles from this tag as read" %}</a><br />{% endif %}
66
63 {% if tag %} 67 {% if tag %}
64 {% if constant('EPUB') == 1 %}<a title="{% trans "Download the articles from this tag in an epub file" %}" href="./?epub&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download as ePub3" %}</a>{% endif %} 68 {% if constant('EPUB') == 1 %}<a title="{% trans "Download the articles from this tag in an epub file" %}" href="./?epub&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download as ePub3" %}</a>{% endif %}
65 {% if constant('MOBI') == 1 %}<a title="{% trans "Download the articles from this tag in a mobi file" %}" href="./?mobi&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download as Mobi" %}</a>{% endif %} 69 {% if constant('MOBI') == 1 %}<a title="{% trans "Download the articles from this tag in a mobi file" %}" href="./?mobi&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download as Mobi" %}</a>{% endif %}
diff --git a/themes/courgette/config.twig b/themes/courgette/config.twig
deleted file mode 100755
index 6b0fa308..00000000
--- a/themes/courgette/config.twig
+++ /dev/null
@@ -1,127 +0,0 @@
1{% extends "layout.twig" %}
2
3{% block title %}{% trans "config" %}{% endblock %}
4{% block menu %}
5{% include '_menu.twig' %}
6{% endblock %}
7{% block content %}
8 <div id="config">
9 <h2>{% trans "Poching a link" %}</h2>
10 <p>{% trans "There are several ways to save an article:" %} (<a class="special" href="http://doc.wallabag.org" title="{% trans "read the documentation" %}">?</a>)</p>
11 <ul>
12 <li>Firefox: <a href="https://addons.mozilla.org/firefox/addon/wallabag/" title="download the firefox extension">{% trans "download the extension" %}</a></li>
13 <li>Chrome: <a href="http://doc.wallabag.org/doku.php?id=users:chrome_extension" title="download the chrome extension">{% trans "download the extension" %}</a></li>
14 <li>Android: <a href="https://f-droid.org/app/fr.gaulupeau.apps.InThePoche" title="download the application">{% trans "via F-Droid" %}</a> {% trans " or " %} <a href="https://play.google.com/store/apps/details?id=fr.gaulupeau.apps.InThePoche" title="download the application">{% trans "via Google Play" %}</a></li>
15 <li>iOS: <a href="https://itunes.apple.com/app/wallabag/id828331015?mt=8" title="download the iOS application">{% trans "download the application" %}</a></li>
16 <li>Windows Phone: <a href="http://www.windowsphone.com/en-us/store/app/wallabag/ff890514-348c-4d0b-9b43-153fff3f7450" title="download the window phone application">{% trans "download the application" %}</a></li>
17 <li>
18 <form method="get" action="index.php">
19 <label class="addurl" for="plainurl">{% trans "by filling this field" %}:</label>
20 <input required placeholder="Ex:mywebsite.com/article" class="addurl" id="plainurl" name="plainurl" type="url" />
21 <input type="submit" value="{% trans "bag it!" %}" />
22 </form>
23 </li>
24 <li>{% trans "bookmarklet: drag & drop this link to your bookmarks bar" %} <a id="bookmarklet" ondragend="this.click();" title="i am a bookmarklet, use me !" href="javascript:if(top['bookmarklet-url@wallabag.org']){top['bookmarklet-url@wallabag.org'];}else{(function(){var%20url%20=%20location.href%20||%20url;window.open('{{ poche_url }}?action=add&url='%20+%20btoa(url),'_self');})();void(0);}">{% trans "bag it!" %}</a></li>
25 </ul>
26
27 <h2>{% trans "Upgrading wallabag" %}</h2>
28 <ul>
29 <li>{% trans "your version" %} : <strong>{{ constant('POCHE') }}</strong></li>
30 <li>{% trans "latest stable version" %} : {{ prod }}. {% if compare_prod == -1 %}<strong><a href="http://wallabag.org/">{% trans "a more recent stable version is available." %}</a></strong>{% else %}{% trans "you are up to date." %}{% endif %}</li>
31 {% if constant('DEBUG_POCHE') == 1 %}<li>{% trans "latest dev version" %} : {{ dev }}. {% if compare_dev == -1 %}<strong><a href="http://wallabag.org/">{% trans "a more recent development version is available." %}</a></strong>{% else %}{% trans "you are up to date." %}{% endif %}</li>{% endif %}
32 </ul>
33
34 <h2>{% trans "Change your theme" %}</h2>
35 <form method="post" action="?updatetheme" name="changethemeform">
36 <fieldset class="w500p">
37 <div class="row">
38 <label class="col w150p" for="theme">{% trans "Theme:" %}</label>
39 <select class="col" id="theme" name="theme">
40 {% for key, theme in themes %}
41 <option value="{{ key }}" {{ theme.current ? 'selected' : '' }}>{{ theme.name }}</option>
42 {% endfor %}
43 </select>
44 </div>
45 <div class="row mts txtcenter">
46 <button class="bouton" type="submit" tabindex="4">{% trans "Update" %}</button>
47 </div>
48 </fieldset>
49 <input type="hidden" name="returnurl" value="{{ referer }}">
50 <input type="hidden" name="token" value="{{ token }}">
51 </form>
52
53 <h2>{% trans "Change your password" %}</h2>
54 <form method="post" action="?config" name="loginform">
55 <fieldset class="w500p">
56 <div class="row">
57 <label class="col w150p" for="password">{% trans "New password:" %}</label>
58 <input class="col" type="password" id="password" name="password" placeholder="{% trans "Password" %}" tabindex="2">
59 </div>
60 <div class="row">
61 <label class="col w150p" for="password_repeat">{% trans "Repeat your new password:" %}</label>
62 <input class="col" type="password" id="password_repeat" name="password_repeat" placeholder="{% trans "Password" %}" tabindex="3">
63 </div>
64 <div class="row mts txtcenter">
65 <button class="bouton" type="submit" tabindex="4">{% trans "Update" %}</button>
66 </div>
67 </fieldset>
68 <input type="hidden" name="returnurl" value="{{ referer }}">
69 <input type="hidden" name="token" value="{{ token }}">
70 </form>
71
72 <h2>{% trans "Import" %}</h2>
73 <p>{% trans "Please execute the import script locally, it can take a very long time." %}</p>
74 <p>{% trans "More infos in the official doc:" %} <a href="http://doc.wallabag.org">wallabag.org</a></p>
75 <ul>
76 <li><a href="./?import&amp;from=pocket">{% trans "import from Pocket" %}</a> {{ '(you must have a %s file on your server)'|trans|format(constant('POCKET_FILE')) }}</li>
77 <li><a href="./?import&amp;from=readability">{% trans "import from Readability" %}</a> {{ '(you must have a %s file on your server)'|trans|format(constant('READABILITY_FILE')) }}</li>
78 <li><a href="./?import&amp;from=instapaper">{% trans "import from Instapaper" %}</a> {{ '(you must have a %s file on your server)'|trans|format(constant('INSTAPAPER_FILE')) }}</li>
79 </ul>
80
81 <h2>{% trans "Export your wallabag data" %}</h2>
82 <p><a href="./?export" target="_blank">{% trans "Click here" %}</a> {% trans "to export your wallabag data." %}</p>
83
84 <h2>{% trans "Fancy an E-Book ?" %}</h2>
85 <p>{% trans "Click to get all your articles in one ebook :" %}
86 <ul>
87 <li><a href="./?epub&amp;method=all" title="Generate ePub file">ePub 3</a></li>
88 <li><a href="./?mobi&amp;method=all" title="Generate Mobi file">Mobi</a></li>
89 <li><a href="./?pdf&amp;method=all" title="Generate PDF file">PDF</a></li>
90 </ul>
91
92 <br>{% trans "This can <b>take a while</b> and can <b>even fail</b> if you have too many articles, depending on your server configuration." %}</p>
93
94 <h2>{% trans 'Add user' %}</h2>
95 <p>{% trans 'Add a new user :' %}</p>
96 <form method="post" action="?newuser">
97 <fieldset class="w500p">
98 <div class="row">
99 <label class="col w150p" for="newusername">{% trans 'Login for new user' %}</label>
100 <input class="col" type="text" id="newusername" name="newusername" placeholder="{% trans 'Login' %}">
101 </div>
102 <div class="row">
103 <label class="col w150p" for="password4newuser">{% trans "Password for new user" %}</label>
104 <input class="col" type="password" id="password4newuser" name="password4newuser" placeholder="{% trans "Password" %}">
105 </div>
106 <div class="row mts txtcenter">
107 <button type="submit">{% trans "Send" %}</button>
108 </div>
109 </fieldset>
110 </form>
111
112 <h2>{% trans "Delete account" %}</h2>
113 {% if not only_user %}<form method="post" action="?deluser">
114 <p>{% trans "You can delete your account by entering your password and validating." %}<br /><b>{% trans "Be careful, data will be erased forever (that is a very long time)." %}</b></p>
115 <fieldset class="w500p">
116 <div class="row">
117 <label class="col w150p" for="password4deletinguser">{% trans "Type here your password" %}</label>
118 <input class="col" type="password" id="password4deletinguser" name="password4deletinguser" placeholder="{% trans "Password" %}">
119 </div>
120 <div class="row mts txtcenter">
121 <button type="submit">{% trans "Send" %}</button>
122 </div>
123 </form>
124 {% else %}<p>{% trans "You are the only user, you cannot delete your own account." %}<br />
125 {% trans "To completely remove wallabag, delete the wallabag folder on your web server." %}</p>{% endif %}
126 </div>
127{% endblock %}
diff --git a/themes/default/home.twig b/themes/default/home.twig
index 0c0f3283..abc96af8 100755
--- a/themes/default/home.twig
+++ b/themes/default/home.twig
@@ -60,7 +60,11 @@
60 {{ block('pager') }} 60 {{ block('pager') }}
61 {% if view == 'home' %}{% if nb_results > 1 %}<p><a title="{% trans "Mark all the entries as read" %}" href="./?action=archive_all">{% trans "Mark all the entries as read" %}</a></p>{% endif %}{% endif %} 61 {% if view == 'home' %}{% if nb_results > 1 %}<p><a title="{% trans "Mark all the entries as read" %}" href="./?action=archive_all">{% trans "Mark all the entries as read" %}</a></p>{% endif %}{% endif %}
62 {% if searchterm is defined %}<a title="{% trans "Tag these results as" %} {{ searchterm }}" href="./?action=add_tag&search={{ searchterm }}">{% trans "Tag these results as" %} {{ searchterm }}</a>{% endif %}<br /> 62 {% if searchterm is defined %}<a title="{% trans "Tag these results as" %} {{ searchterm }}" href="./?action=add_tag&search={{ searchterm }}">{% trans "Tag these results as" %} {{ searchterm }}</a>{% endif %}<br />
63 63
64 {% if searchterm is defined %}<a title="{% trans "Delete results matching" %} {{ searchterm }}" href="./?action=delete&search={{ searchterm }}">{% trans "Delete results matching" %} {{ searchterm }}</a>{% endif %}<br />
65
66 {% if tag %}<a title="{% trans "Mark all articles from this tag as read" %}" href="./?action=toggle_archive&amp;tag_id={{ tag.id }}">{% trans "Mark all articles from this tag as read" %}</a><br />{% endif %}
67
64 {% if tag %} 68 {% if tag %}
65 {% if constant('EPUB') == 1 %}<a title="{% trans "Download the articles from this tag in an epub file" %}" href="./?epub&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download as ePub3" %}</a>{% endif %} 69 {% if constant('EPUB') == 1 %}<a title="{% trans "Download the articles from this tag in an epub file" %}" href="./?epub&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download as ePub3" %}</a>{% endif %}
66 {% if constant('MOBI') == 1 %}<a title="{% trans "Download the articles from this tag in a mobi file" %}" href="./?mobi&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download as Mobi" %}</a>{% endif %} 70 {% if constant('MOBI') == 1 %}<a title="{% trans "Download the articles from this tag in a mobi file" %}" href="./?mobi&amp;method=tag&amp;value={{ tag.value }}">{% trans "Download as Mobi" %}</a>{% endif %}
@@ -74,6 +78,6 @@
74 {% if constant('MOBI') == 1 %}<a title="{% trans "Download the articles from this category in a mobi file" %}" href="./?mobi&amp;method=category&amp;value={{ view }}">{% trans "Download as Mobi" %}</a>{% endif %} 78 {% if constant('MOBI') == 1 %}<a title="{% trans "Download the articles from this category in a mobi file" %}" href="./?mobi&amp;method=category&amp;value={{ view }}">{% trans "Download as Mobi" %}</a>{% endif %}
75 {% if constant('PDF') == 1 %}<a title="{% trans "Download the articles from this category in a pdf file" %}" href="./?pdf&amp;method=category&amp;value={{ view }}">{% trans "Download as PDF" %}</a>{% endif %} 79 {% if constant('PDF') == 1 %}<a title="{% trans "Download the articles from this category in a pdf file" %}" href="./?pdf&amp;method=category&amp;value={{ view }}">{% trans "Download as PDF" %}</a>{% endif %}
76 {% endif %} 80 {% endif %}
77 81
78 {% endif %} 82 {% endif %}
79{% endblock %} 83{% endblock %}