Compare commits

..

266 Commits
1.5.2 ... 1.7.2

Author SHA1 Message Date
af8292c1de Merge branch 'fix/securityMaster' 2014-07-24 21:41:16 +02:00
38cf3413df 1.7.2 2014-07-24 21:41:01 +02:00
800868e27e security fix 2014-07-24 17:47:23 +03:00
0f6273cdb8 Merge pull request #761 from wallabag/dev
1.7.1
2014-07-15 11:49:24 +02:00
26452f891f Merge pull request #752 from mariroz/dev
fix of issue #650, #619 and other similar, error in JSLikeHTMLElement: node no longer exists.
2014-07-12 19:28:16 +02:00
d14e3f1e22 Merge pull request #754 from sinisterstuf/about.com
Add support for *.about.com
2014-07-12 15:10:05 +02:00
d59536deea Add support for *.about.com
Includes next_page_link for multi-page articles and strips pesky in-line
'next' links from the article body. Also includes an Xpath for author
but I can't see where this is used in the wallabag UI.

The 'tidy' option is turned off because it messed up bulleted lists.

Tested with psychology.about.com and food.about.com.
2014-07-11 00:04:24 +02:00
6400371ff9 I removed my previous commit. We have to create a new branch for that. 2014-07-10 13:17:04 +02:00
c1aad6d574 fix of issue #619 and other similar, error in JSLikeHTMLElement: node no longer exists. 2014-07-09 16:56:52 +03:00
cc1ec61b85 fix of issue #619 and other similar, error in JSLikeHTMLElement: node no longer exists. 2014-07-09 16:50:52 +03:00
c710f977b2 new call for having domain name in entry view 2014-07-08 21:57:53 +02:00
5425b0dd82 new fields in database, reading time / date and domain name are stored 2014-07-08 21:46:32 +02:00
4247b37551 Merge pull request #751 from mariroz/dev
quick fix of issue #750: mulipage content for politico.com/magazine articles
2014-07-07 21:11:07 +02:00
82980a148b quick fix of issue #750: mulipage content for politico.com/magazine articles 2014-07-07 19:17:55 +03:00
c13aac1bc3 1.7.1 2014-07-05 15:49:40 +02:00
da87848cee new config file, fix for #740 2014-07-01 10:18:44 +02:00
25052a76ca fix for #738 2014-06-30 23:24:46 +02:00
a13ff95777 security check 2014-06-30 22:15:55 +02:00
cdda041a90 Merge pull request #737 from mariroz/dev
fix of issue #677: When downloading images, wallabag doesnt respect html "base" tag, tnx to @fivefilters
2014-06-25 19:33:28 +02:00
6924253423 fix of issue #677: When downloading images, wallabag doesnt respect html "base" tag, tnx to @fivefilters 2014-06-25 20:00:00 +03:00
69213014d1 Merge pull request #736 from mariroz/dev
fix of issue #718: Error parsing file imported from Pocket #718
2014-06-25 18:54:39 +02:00
aa126ba458 fix of issue #718: Error parsing file imported from Pocket #718 2014-06-25 19:34:14 +03:00
c9563378ea Merge pull request #728 from Draky50110/dev
typo FR après vérif.
2014-06-12 23:30:53 +02:00
ba22fb1cef typo mineure 2014-06-12 23:10:26 +02:00
29cd317aff fin de correction typo FR 2014-06-12 22:21:44 +02:00
0bf95d865a Revert "Typo FR (suite)"
This reverts commit 7f186e21e0.

Conflicts:
	locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.mo
	locale/fr_FR.utf8/LC_MESSAGES/fr_FR.utf8.po
2014-06-12 22:16:04 +02:00
ae43ec99d9 typo FR 3 2014-06-12 20:32:02 +02:00
7f186e21e0 Typo FR (suite) 2014-06-12 18:55:38 +02:00
bca2853ade Merge pull request #724 from Draky50110/dev
typo FR
2014-06-12 09:34:05 +02:00
97d54f2ac8 typo FR 2014-06-12 01:00:49 +02:00
8142d4b1e6 Merge pull request #722 from tcitworld/dev
do not output debug while generating epub
2014-06-07 16:38:39 +02:00
35d4e27588 up to date 2014-06-07 16:36:57 +02:00
ec15d0a784 do not debug inside an epub 2014-06-07 15:53:39 +02:00
c93a5c137f Merge pull request #716 from mariroz/dev
error reporting level set in E_ALL & ~E_NOTICE by default, can be overriden in config
2014-06-05 16:59:39 +02:00
752cd4a8ef error reporting level set in E_ALL & ~E_NOTICE by default, can be overriden in config 2014-06-02 18:00:09 +03:00
5d198e2b98 Merge pull request #715 from mariroz/dev
fix of undefined ATOM constant warning in full-text-rss, will fix ios-app issue #14
2014-06-01 19:06:45 +02:00
1d14e65315 fix of undefined ATOM constant warning in full-text-rss, will fix ios-app issue #14 2014-06-01 19:49:22 +03:00
67a8848aed Merge pull request #713 from mariroz/dev
small xss vulnerability and translation ability fix
2014-05-30 16:51:13 +02:00
30bd273580 small xss vulnerability and translation ability fix 2014-05-30 17:17:34 +03:00
cbc75befb5 small xss vulnerability and translation ability fix 2014-05-30 17:14:53 +03:00
a9f5e572dd Merge pull request #712 from wallabag/dev
1.7, call me "Premium version"
2014-05-29 18:54:06 +02:00
8038b38802 1.7, premium version :) 2014-05-29 18:52:34 +02:00
79024eb004 fix #344 FQDN with non-standard ports broken 2014-05-29 18:32:55 +02:00
0c3db64585 Merge pull request #711 from mariroz/dev
fix of uninitialized object warning, issue #710
2014-05-29 16:04:26 +02:00
3dc8d84229 fix of uninitialized object warning, issue #710 2014-05-29 16:35:00 +03:00
87f01ea2e9 Merge pull request #707 from mariroz/dev
update to 3.2 version of full-text-rss, issue #694
2014-05-29 12:50:28 +02:00
0b9bb8cb78 add dailymotion videos, issue #708 2014-05-26 14:29:18 +03:00
009669360d fix of onmouseover displaying of wallbabag a link in wallabag form in default theme 2014-05-24 11:21:43 +03:00
a342945b61 fix of rearch form popup in default theme 2014-05-24 11:08:39 +03:00
1fce49fac7 full-text rss config file for ted.com, issue #676 2014-05-23 19:29:01 +03:00
a50583fb97 last 3 important changes to 3.2 version of full-text-rss, issue #694 2014-05-23 19:27:17 +03:00
d18ff7d956 two small unimportant forgotten changes to 3.2 version of full-text-rss, issue #694 2014-05-23 19:25:48 +03:00
3ec62cf95a update to 3.2 version of full-text-rss, issue #694 2014-05-22 17:16:38 +03:00
ab157bbb75 Merge pull request #706 from gboudreau/dev
Fixed Baggy theme CSS for Chrome Extension (and < 500px width layout)
2014-05-21 22:13:31 +02:00
f61ffec352 Fixed Baggy theme CSS for Chrome Extension (and < 500px width layout) 2014-05-21 15:54:54 -04:00
88f0e31622 Merge pull request #703 from tcitworld/images_security
Security fixes for downloaded images (thanks @leblanc-simon)
2014-05-20 11:55:20 +02:00
38eecef26b Added info for DOWNLOAD_PICTURES
We regenerate pictures, it might take some time
2014-05-20 11:46:05 +02:00
99408dfcf3 Merge pull request #1 from leblanc-simon/images_security
Optimisation et gestion des erreurs
2014-05-20 11:42:22 +02:00
0bf0dfe10d Optimisation et gestion des erreurs 2014-05-20 00:42:51 +02:00
e3b00bcaf5 Fixed bug for png images 2014-05-19 15:59:18 +02:00
6caba976ec Bug with bracket 2014-05-19 15:34:49 +02:00
1d6a9ac25a Option for setting quality 2014-05-19 15:24:11 +02:00
03e501dedd Merge branch 'dev' into images_security 2014-05-19 15:04:09 +02:00
18209292a4 Fix bad character encoding when downloading images 2014-05-19 15:01:36 +02:00
007f26e582 Security fix for Download Images 2014-05-18 22:11:56 +02:00
04b43dc097 Merge pull request #697 from tcitworld/dev
Up-to-date with me
2014-05-18 19:00:51 +02:00
becc5bfbf2 Fix for #678 2014-05-18 18:56:20 +02:00
230fa05eb7 Better Grammar 2014-05-17 20:32:38 +02:00
96834a47b0 Added PHPePub 2014-05-16 17:38:19 +02:00
e212e6b12a Cleaned epub fonction 2014-05-16 16:49:09 +02:00
404adf970d Merge branch 'epub' into dev
Conflicts:
	themes/baggy/home.twig
2014-05-16 16:31:18 +02:00
7d5d9ea449 Merge pull request #693 from tcitworld/dev
better wallabag in wallabag button (see #685)
2014-05-16 15:54:54 +02:00
74e09e562b better wallabag in wallabag button (see #685) 2014-05-16 15:34:13 +02:00
60c3a4d3e1 Merge pull request #689 from tcitworld/dev
Tag-related features
2014-05-16 13:31:53 +02:00
f3f0b11393 Better names for epub files and epub in all themes now 2014-05-15 15:42:36 +02:00
f2b6b4e230 Fix bugs and improved epub rendering 2014-05-14 22:03:16 +02:00
6a3c510157 Merge branch 'dev' of https://github.com/wallabag/wallabag into epub 2014-05-14 19:17:51 +02:00
4555c38d3b Changed theme for better translation method 2014-05-14 19:08:33 +02:00
24696800e5 Simplifed function which does tag cleanup 2014-05-14 18:51:02 +02:00
818b186f8a Merge pull request #680 from m-r-r/fr-1.6.1
French translation update
2014-05-13 16:44:16 +02:00
4910af33ff Removed unnecessary function for cleaning tags 2014-05-11 16:14:47 +02:00
0626e52f3c Merge branch 'dev' of https://github.com/wallabag/wallabag into dev 2014-05-11 15:44:43 +02:00
f034640ca3 Added advices to submit a bug
Discussion at #662.
2014-05-11 15:33:44 +02:00
1829b362fc Updated the french translation 2014-05-10 20:11:00 +02:00
34acb02cbb Added translation capabilities for epub system 2014-05-07 12:48:46 +02:00
4877836b12 Many improvements to epub produced : better cover, better tags 2014-05-07 12:40:09 +02:00
07ed2b0231 #568 missing rss.png files 2014-05-02 17:04:08 +02:00
9c743ab965 Clean old unused tags when deleting a tag 2014-04-30 12:14:20 +02:00
78bddb22be Remove unnecessary line 2014-04-30 11:31:21 +02:00
decc23aaf2 Added save search as tag functionality 2014-04-30 11:25:03 +02:00
2395a3802a Changed template organisation 2014-04-29 19:57:59 +02:00
7ec445b06e Big changes for epub export. Now possible to do it from a tag, a category and a search. Also, improved ebook rendering. 2014-04-25 16:20:25 +02:00
21f29fe492 Merge pull request #667 from mariroz/dev
fix of putenv warning under safe mode, issue #646
2014-04-25 13:03:09 +02:00
5b5e47c3ae fix of already defined constant notice, issue #653 2014-04-25 13:41:42 +03:00
b6413975c3 fix of putenv warning under safe mode, issue #646 2014-04-25 13:25:03 +03:00
d151b51c67 Merge pull request #665 from mariroz/dev
fix of rss headers problem
2014-04-24 18:05:16 +02:00
827f5b42a6 fix of rss headers problem 2014-04-24 11:48:00 +03:00
ef17914960 Fix for #664 - Missing source url attribute in RSS feeds 2014-04-24 09:39:50 +02:00
72a857158c Fixed a bug into PHPePub with special caracters 2014-04-24 03:08:31 +02:00
87090d8ae7 Added epub export function 2014-04-24 03:04:02 +02:00
8af31ae0f7 Added default statement for db system 2014-04-23 22:48:33 +02:00
feecea2806 Fix #657 and postgresql problems 2014-04-23 22:39:43 +02:00
07da861126 Added multi-user functionnality in all themes 2014-04-23 10:53:57 +02:00
c97d23c533 Merge branch 'dev' of https://github.com/wallabag/wallabag into dev 2014-04-23 10:34:22 +02:00
4d99bae893 Fixed Multi-user system 2014-04-23 10:29:53 +02:00
2a6440c134 Merge pull request #659 from mariroz/dev
last error: config.inc.default.php missed
2014-04-22 21:44:12 +02:00
4dbba60439 last error: config.inc.default.php missed 2014-04-22 22:38:10 +03:00
29cf52b677 Merge pull request #658 from mariroz/dev
inc/poche/config.inc.php.new removed
2014-04-22 20:48:42 +02:00
fd86559a5b inc/poche/config.inc.php.new removed 2014-04-22 21:39:03 +03:00
d70dd7ac69 Merge pull request #653 from mariroz/dev
print view fixed in baggy; print link added; read percent added in default theme; archive and favorite re-factored to be ajax action in article view
2014-04-22 20:18:46 +02:00
43c7b978c3 config.inc.php.new renamed in config.inc.default.php 2014-04-22 20:58:40 +03:00
dfff18f81b Merge pull request #655 from julien-m/patch-2
parse mobile.lemondeinformatique.fr
2014-04-22 18:24:17 +02:00
a4a870e1ec default config is included after user config to prevent undefined constant warning 2014-04-22 19:11:26 +03:00
03303cd71b parse mobile.lemondeinformatique.fr
site_config file created because the title isn't parsed by default for mobile version of lemondeinformatique.fr
2014-04-22 14:44:31 +02:00
c2cf7075c2 print view fixed in baggy; print link added; read percent added in default theme; archive and favorite re-factored to be ajax action in article view 2014-04-22 10:45:09 +03:00
bfe1ad6dbc Merge pull request #643 from wallabag/fix-636
[fix] rss feed content type set to text/xml #636
2014-04-15 21:49:37 +02:00
6212acfc81 [fix] rss feed content type set to text/xml #636 2014-04-15 21:49:00 +02:00
847f57686e Merge pull request #642 from jplock/patch-2
Added IF NOT EXISTS
2014-04-14 15:42:09 +02:00
44fd0faa23 Added IF NOT EXISTS 2014-04-14 09:40:35 -04:00
df6c8b3be9 Merge pull request #637 from Bubbendorf/dev
Improvements on french translation
2014-04-13 12:50:48 +02:00
a192c21c6a Improved french translation 2014-04-13 00:02:03 +02:00
f3312ce58d Merge pull request #635 from DmitrySandalov/dev
added missing image to dmagenta theme
2014-04-11 22:56:59 +02:00
603ecb0052 added missing image to dmagenta theme 2014-04-12 00:08:11 +04:00
4a74d9857c Merge pull request #634 from wallabag/dev
1.6.1
2014-04-11 17:22:04 +02:00
7256e9e139 1.6.1 version 2014-04-11 17:08:11 +02:00
f09d76b0ea Merge pull request #633 from mariroz/dev
error with empty content by import fixed. Also youtube and vimeo videos are allowd in content now.
2014-04-11 16:56:59 +02:00
0f859c6f32 error with empty content by import fixed. Also youtube and vimeo videos are allowd in content now. 2014-04-11 17:21:54 +03:00
389d751e92 Merge pull request #632 from mariroz/dev
logging by import added; error by creation table if exists in postgresql...
2014-04-11 14:00:04 +02:00
5ce3978472 logging by import added; error by creation table if exists in postgresql fixed. 2014-04-11 14:43:17 +03:00
d5f36a8d9e Merge pull request #623 from wallabag/fix-610
Fix display problem with smartphone and Baggy #610
2014-04-08 22:43:39 +02:00
08f539f738 responsive for search form #610 2014-04-08 22:42:34 +02:00
6e8030a0db [fix] display problem with smartphone and Baggy #610 2014-04-08 22:33:28 +02:00
b96b075b55 Merge pull request #622 from wallabag/fix-612
[fix] Escap key displays save a link form #612
2014-04-08 22:11:17 +02:00
f8e9d8bdbc [fix] Escap key displays save a link form #612 2014-04-08 22:10:40 +02:00
bf20b541ae Merge pull request #621 from wallabag/fix-613
can't close search popup with the cross picture #613
2014-04-08 21:59:40 +02:00
3945335f39 can't close search popup with the cross picture #613 2014-04-08 21:58:44 +02:00
2c534c184d Merge pull request #618 from mariroz/dev
remove duplicates by import; code formatting changes: tabs replaced with spaces
2014-04-08 10:54:17 +02:00
a8ef1f3f43 code formatting changes: tabs replaced with spaces, some other small formatting enhancements 2014-04-08 11:49:41 +03:00
86da39886d remove duplicates by import, code changes: tabs replaced with spaces 2014-04-08 11:41:06 +03:00
a7f39918bf Merge pull request #614 from wallabag/fix-host-getpocheurl
[fix] with some config, http host is different
2014-04-07 15:45:26 +02:00
69c57493e7 [fix] with some config, http host is different 2014-04-07 15:44:05 +02:00
5fe1948097 Merge pull request #611 from wallabag/fix-french-locale
update french locale, thx to @goofy-bz and @Draky50110 #596
2014-04-07 15:15:42 +02:00
d9b51a21fa update french locale, thx to @goofy-bz and @Draky50110 #596 2014-04-07 15:14:50 +02:00
9cb9ab552b Merge pull request #609 from wallabag/fix-desciption-typo
remove unnecessary variable declaration
2014-04-06 20:54:20 +02:00
7a873ef1d7 remove unnecessary variable declaration 2014-04-06 20:53:31 +02:00
292cd0dbd5 Merge pull request #606 from wallabag/fix-556
in RSS feed, add link to wallabag URL #556
2014-04-06 16:40:17 +02:00
f86784c22d in RSS feed, add link to wallabag URL #556 2014-04-06 16:39:11 +02:00
2dd5c1e4a3 Merge pull request #605 from wallabag/fix-604
[fix] Use of undefined constant ATOM #604
2014-04-06 16:22:57 +02:00
29d9c0ffe1 [fix] Use of undefined constant ATOM #604 2014-04-06 16:21:48 +02:00
d7ee9f986b Merge pull request #603 from mariroz/dev
postgres sequence error fix, issue #602
2014-04-05 12:36:20 +02:00
1bcbe8bebf postgres sequence error fix, issue #602 2014-04-05 11:22:33 +03:00
db117db3c5 Fix to #600 2014-04-04 22:36:33 +02:00
4a16f33dcc Changed copyright to 2014
Happy new year !
2014-04-04 22:13:06 +02:00
0d67b00d5d Merge pull request #595 from wallabag/dev
wallabag 1.6.0
2014-04-03 14:42:03 +02:00
7d2f1aa279 [add] link on config page to fetch content 2014-04-03 14:39:13 +02:00
bfa32856bc yeah, 1.6, one year after the 1st commit 2014-04-03 13:54:06 +02:00
06e1a9a98a import w/o cron: fix of "click to finish import" in baggy theme 2014-04-03 14:35:50 +03:00
d9bb0cdeb8 import w/o cron: explanation added 2014-04-03 13:53:47 +03:00
4d2bd6e507 import w/o cron: error in url fix 2014-04-03 13:19:54 +03:00
a297fb1e38 import w/o cron 2014-04-03 12:18:49 +03:00
a4585f7eaa import without cron 2014-04-02 22:33:06 +03:00
182faf2696 import without cron 2014-04-02 20:55:19 +03:00
d967a1fa14 Important fixes for search engine (thx @mariroz)
So sorry for the mess... :(
* search only in users' own articles
* sanitized what is searched
* display what is searched
* pagination, sorting available when searching
* use existing function to query db
* bad encoding caracters fixed
* link to JQuery into default theme, no longer in each theme
* some spaces instead of tabs
2014-04-02 17:44:47 +02:00
22db488d21 Merge branch 'dev' of https://github.com/wallabag/wallabag into dev 2014-03-30 21:17:28 +02:00
1be13ba1fc oops, restore @tcitworld commit. I'm so tired 2014-03-30 21:16:45 +02:00
d6d8a045e6 Merge pull request #588 from mariroz/dev
fix of bug with default theme constant
2014-03-30 20:04:55 +02:00
1d0995bb8e [fix] undefined vars in install script 2014-03-30 19:57:39 +02:00
3345c9dc39 fix of bug with default theme constant 2014-03-28 21:19:08 +02:00
fecb62a396 Improvements to install script
* automatically remove install/ folder
* go easier though the compatibility test <-> install script pages
* Small fixes which raised php warnings
2014-03-28 20:00:02 +01:00
ad697686c0 Final Fix of #570
Adds a date information to the exported data file.
2014-03-28 16:53:06 +01:00
cdada41505 Merge pull request #587 from mariroz/dev
problem with resources and localhost url fix
2014-03-28 10:30:51 +01:00
08718c01e4 problem with resources and localhost url fix 2014-03-28 11:26:48 +02:00
b152f2b6ba Fix to bug #570
Forces the download of the data exported file as a poche-export file.
2014-03-28 00:57:07 +01:00
04fbe8f5ef Merge pull request #586 from mariroz/wb-link-in-wb
wallabag a link in wallabag now in default theme, issue #505
2014-03-27 19:44:28 +01:00
e68348f627 wallabag a link in wallabag now in default theme, issue #505 2014-03-27 18:21:30 +02:00
9591ee2603 Merge pull request #585 from kevmeyer/dev
updated german localisation
2014-03-27 13:56:40 +01:00
5814ef0d25 updated german localisation 2014-03-27 13:44:19 +01:00
d607330557 Improvements for compatibility_test file
- gettext detection (not default on WAMP) ; part fix of #579
- added colors to make viewing what's wrong better and quicker
(green/orange/red)
- added a link to index.php if it's good
2014-03-26 18:46:46 +01:00
ad03eb6286 Fix of #580 : Add some random for Windows hosts 2014-03-26 17:19:57 +01:00
cc60cbbbab Finished search engine function
Now searches also in title and in original url
2014-03-26 16:36:42 +01:00
d619120fc4 Merge pull request #582 from mariroz/fix-session-livetime
fix of localhost cookie related to nginx binding to 0.0.0.0
2014-03-24 11:12:56 +01:00
2c4e7a1cea Fixes to search engine
Changed the search parameter from POST to GET.
Also, adapted the Baggy theme.
2014-03-23 23:52:05 +01:00
a33a3d2afb Implemented rudimental search engine 2014-03-22 11:09:18 +01:00
03832b45e1 fix of localhost cookie related to nginx binding to 0.0.0.0 2014-03-21 21:56:40 +02:00
028e34b6c4 Merge pull request #581 from mariroz/fix-session-livetime
fix of issue under nginx and php-fpm
2014-03-21 14:05:51 +01:00
ad53faf25c fix of issue under nginx and php-fpm 2014-03-21 14:59:30 +02:00
0c51bfea6f Merge pull request #576 from mariroz/fix-session-livetime
fix of  _SESSION - indefined variable
2014-03-19 19:26:05 +01:00
6fa3f70bc2 fix of _SESSION - indefined variable 2014-03-19 19:22:04 +02:00
db41c907aa Merge pull request #572 from mariroz/fix-session-livetime
fix of #115, server relater config value added
2014-03-18 21:29:58 +01:00
2a97194253 fix of #115, server relater config value added 2014-03-18 17:39:19 +02:00
a7048bc45d Merge pull request #567 from mariroz/fix-session-livetime
fix of #115 - stay connected and session livetime
2014-03-17 21:49:42 +01:00
eb5b677250 fix of #115 - stay connected and session livetime 2014-03-17 22:22:05 +02:00
897b2b5302 Merge pull request #566 from camporez/dev
Update brazilian traslation title to "Português (Brasil)"
2014-03-17 08:09:18 +01:00
5805ac4574 Update brazilian traslation title to "Português (Brasil)" 2014-03-16 16:43:46 -03:00
07e028fe5c Merge pull request #563 from camporez/dev
Update brazilian translation
2014-03-16 18:55:59 +01:00
08dde123b1 Correct README.md 2014-03-16 11:58:16 -03:00
82cff5af70 Update brazilian translation 2014-03-15 17:23:34 -03:00
8754bd88a5 Merge remote-tracking branches 'upstream/dev' and 'origin/master' into dev 2014-03-15 15:03:26 -03:00
6a915551ab acc 2014-03-14 14:15:26 -03:00
ed02e38e1d [fix] in RSS, link to original article 2014-03-14 09:35:48 +01:00
8d7cd2ccd5 [add] remove import file in CACHE when import is over 2014-03-14 08:54:44 +01:00
c0586a906c [fix] new import section in old themes #559 2014-03-14 08:37:40 +01:00
181d16fe22 Merge pull request #557 from mariroz/feature-add-link-inside-article-issue-505
saving link form now sends ajax request, article view is now justified (issue #554)
2014-03-13 20:57:22 +01:00
3ee27ee6ba saving link form now sends ajax request, article view is now justified 2014-03-13 18:37:08 +02:00
6775da70a8 feature #505 - it is now possible to add link from bagged article (TODO: redev it to ajax action). Some enhancements to "save a link" popup div 2014-03-12 17:36:04 +02:00
f7382cd8c3 Merge pull request #549 from mariroz/fix-tagform-and-shortcat-toggle-savelinkform-conflict
fix of conflict of s shortcat and entering s in input fields
2014-03-12 12:55:48 +01:00
7339b0b08d fix of conflict of s shortcat and entering s in input fields 2014-03-12 13:00:37 +02:00
1acd18510a Merge pull request #544 from mariroz/feature-tags-autocomplete
a lot of enhancements related to tags: tags list is now sorted, shows number of articles, autocomplete added according to #477, #542
2014-03-10 18:14:43 +01:00
fb26cc9375 a lot of enhancements related to tags: tags list is now sorted, shows number of articles, autocomplete added according to #477, #542 2014-03-10 16:28:47 +02:00
d47a05a9a5 Merge pull request #535 from bobmaerten/clarify-import-process
Changed config section to clarify import process.
2014-03-10 13:14:26 +01:00
17b2afefad [fix] test if user_id doesn't exist in feeds generation 2014-03-10 08:10:03 +01:00
4744cb0e1d bagit link + overlay save link + listmode 2014-03-08 13:47:15 +01:00
7c6aa8d826 Changed text to clarify import process. 2014-03-07 16:46:46 +01:00
b3f7b7d200 Merge branch 'dev' of https://github.com/wallabag/wallabag into dev 2014-03-07 14:49:46 +01:00
1ab567f6e3 [add] clean content articles in cron 2014-03-07 14:49:36 +01:00
f0d584503f Merge pull request #533 from mariroz/dev
fix of #530 - import fail from Poche
2014-03-07 13:59:38 +01:00
042486c511 fix of #530 - import fail from Poche 2014-03-07 14:52:52 +02:00
ded2c63312 Merge pull request #532 from wallabag/upload-file
New import system
2014-03-07 13:26:56 +01:00
bf79463070 Merge pull request #531 from mariroz/upload-file
getPageContent moved to Tools, fix of #426
2014-03-07 11:57:11 +01:00
f98373cc34 getPageContent moved to Tools, fix of #426 2014-03-07 12:54:08 +02:00
25114854b3 [fix] remember scroll position for baggy theme #519 2014-03-06 18:57:04 +01:00
4ca17924a1 [fix] links for firefox / android / ios apps 2014-03-06 18:45:15 +01:00
9a010227d7 Merge pull request #524 from kevmeyer/dev
updated german localization
2014-03-04 12:40:43 +01:00
e1a625ad35 added missing german localization strings 2014-03-04 11:53:40 +01:00
eace9f914d updated german localization 2014-03-04 11:32:45 +01:00
d3b52886f5 [change] ignore tmp files in HTML purifier 2014-03-02 08:52:03 +01:00
71b0d53c5e [fix] #115 cookie lifetime was empty 2014-03-02 08:38:26 +01:00
11c680f97a [add] display last check of wallabag release 2014-03-01 19:10:17 +01:00
223268c2fa [fix] RSS Feeds don't validate / W3C #384 2014-03-01 13:09:37 +01:00
53e3158dfe [add] cron to fetch content on imported entries 2014-02-28 21:49:38 +01:00
31a10069a5 [add] upload form for import 2014-02-28 20:36:32 +01:00
4c14936353 road to 1.5.3 2014-02-28 14:57:04 +01:00
2bb207d005 [fix] #483 pdo_sqlite not required if we want mysql / pgsql 2014-02-28 14:54:50 +01:00
d429305836 [fix] #490 flattr icon in baggy theme 2014-02-28 14:27:10 +01:00
49c803425c Merge branch 'dev' of https://github.com/wallabag/wallabag into dev 2014-02-28 14:06:59 +01:00
cf75bb31e9 Merge pull request #517 from mariroz/dev
effect of block rebuilding on next page removed, issue #479
2014-02-28 12:17:18 +01:00
fc52df0677 effect of block rebuilding on next page removed, issue #479 2014-02-28 13:13:30 +02:00
6065553c13 effect of block rebuilding on next page removed, issue #479 2014-02-28 13:08:11 +02:00
346380e131 [add] label for brazilian language on config screen 2014-02-27 21:37:25 +01:00
affbd83b48 Merge pull request #515 from mariroz/dev
fix of #509, related to php 5.3
2014-02-27 21:23:10 +01:00
381d182726 Syntax fix.
I think this will be the smallest commit I'll ever make.
2014-02-27 21:16:16 +01:00
2048661b0c Merge pull request #513 from camporez/dev
Brazilian portuguese translation
2014-02-27 20:59:59 +01:00
6a0329f756 Add brazilian portuguese (pt-BR) translation
modified:   locale/pt_BR.utf8/LC_MESSAGES/pt_BR.utf8.mo
	renamed:    locale/pt_BR.utf8/LC_MESSAGES/pt_BR.utf8.mo -> locale/pt_BR.utf8/LC_MESSAGES/pt_BR.utf8.po
2014-02-27 16:36:32 -03:00
35c7e0a69c Create pt_BR.utf8.mo 2014-02-27 16:18:53 -03:00
decb9a5814 fix of #509, related to php 5.3 2014-02-27 18:12:43 +02:00
61e79d9344 Merge pull request #510 from mariroz/dev
some baggy theme fixes and enhancement: issue #479
2014-02-27 15:20:01 +01:00
36a733af8d some baggy theme fixes and enhancement: issue #479 2014-02-27 16:11:37 +02:00
a8464c9719 [fix] hover problem with logout link #489 2014-02-27 13:36:06 +01:00
e145f767f3 [add] empty cache after changing language #492 2014-02-27 13:26:07 +01:00
56532c4e72 [add] Empty cache after changing theme #503 2014-02-27 13:24:29 +01:00
fa37042b32 [fix] Baggy theme navigation bug #485 2014-02-27 13:21:54 +01:00
0e7f04b04e Merge pull request #504 from mariroz/dev
translation related: how-to md file added, script to generate php from all twig templates, polish mo file compiled
2014-02-26 14:56:15 +01:00
cbcae4037c translation related: how-to md file added, script to generate php from all twig templates, polish mo file compiled 2014-02-26 15:43:49 +02:00
72f7ff0589 Merge pull request #502 from skibbipl/patch-1
Update pl_PL.utf8.po
2014-02-26 09:23:26 +01:00
2c83741171 Update pl_PL.utf8.po
First cleanup, more to come.
2014-02-25 18:20:13 +01:00
78dd437928 Merge pull request #501 from mariroz/dev
fix of #498, #493, #494 - because disappeared in last commit
2014-02-25 18:10:32 +01:00
f5b5622a89 fix of #498, #493, #494 - because disappeared in last commit 2014-02-25 19:08:18 +02:00
bb75d2b01a Merge pull request #499 from mariroz/dev
French translation added by @Draky50110, issue #488
2014-02-25 17:57:38 +01:00
2cf87a4da1 French translation added by @Draky50110, issue #488 2014-02-25 18:40:25 +02:00
9fad46bd0e Merge pull request #495 from mariroz/dev
fix of global $http visibility, issues #493, #494
2014-02-25 17:27:51 +01:00
dcc73856a9 "poche" word removed completely, all locales .po files updated, en, pl, ru and uk .mo files recompiled. 2014-02-25 15:45:39 +02:00
4b842b20ce fix of #486 - import issue 2014-02-24 19:13:54 +02:00
49b56f19d8 Polish, Russian and Ukrainian locales updated, Franch locale po file uopdated. issue #488 2014-02-24 15:38:49 +02:00
25e1213d1b fix of global $http visibility, issues #493, #494 2014-02-24 12:19:46 +02:00
92fc97eeb3 [fix] redirect on config page after token generation #491 2014-02-23 09:56:21 +01:00
48e063904d [change] remove old logo #484 2014-02-23 09:50:11 +01:00
150 changed files with 22576 additions and 7192 deletions

3
.gitignore vendored
View File

@ -3,4 +3,5 @@ cache/*
vendor
composer.phar
db/poche.sqlite
inc/poche/config.inc.php
inc/poche/config.inc.php
inc/3rdparty/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer/

View File

@ -1,11 +1,28 @@
# How contributing
# How to contribute
## You found a bug
Please [open a new issue](https://github.com/wallabag/wallabag/issues/new).
To fix the bug quickly, we need some infos:
* your wallabag version (in ./index.php)
* your wallabag version (on top of the ./index.php file, and also on config page)
* your webserver installation :
* type of hosting (shared or dedicaced)
* in case of a dedicaced server, the server and OS used
* the php version used, eventually `phpinfo()`
* which storage system you choose at install (SQLite, MySQL/MariaDB or PostgreSQL)
* any problem on the `wallabag_compatibility_test.php` page
* any particular details which could be related
If relevant :
* the link you want to save and which causes problem
* the file you want to import into wallabag, or just an extract
If you have the skills :
* enable DEBUG mode and look the output at cache/log.txt
* look for errors into php and server logs
Note : If you have large portions of text, use [Github's Gist service](https://gist.github.com/) or other pastebin-like.
## You want to fix a bug or to add a feature
Please fork wallabag and work with **the dev branch** only. **Do not work on master branch**.
Please fork wallabag and work with **the dev branch** only. **Do not work on master branch**.

View File

@ -9,7 +9,8 @@ wallabag is based on :
* Twig http://twig.sensiolabs.org
* Flash messages https://github.com/plasticbrain/PHP-Flash-Messages
* Pagination https://github.com/daveismyname/pagination
* PHPePub https://github.com/Grandt/PHPePub/
wallabag is developed by Nicolas Lœuillet under the Do What the Fuck You Want to Public License
Contributors : https://github.com/wallabag/wallabag/graphs/contributors
Contributors : https://github.com/wallabag/wallabag/graphs/contributors

View File

@ -4,7 +4,7 @@ wallabag is a self hostable application allowing you to not miss any content any
More informations on our website: [wallabag.org](http://wallabag.org)
## License
Copyright © 2010-2013 Nicolas Lœuillet <nicolas@loeuillet.org>
Copyright © 2010-2014 Nicolas Lœuillet <nicolas@loeuillet.org>
This work is free. You can redistribute it and/or modify it under the
terms of the Do What The Fuck You Want To Public License, Version 2,
as published by Sam Hocevar. See the COPYING file for more details.

67
TRANSLATION.md Executable file
View File

@ -0,0 +1,67 @@
# How to manage translations of wallabag
This guide will describe procedure of translation management of wallabag web application.
All translation are made using [gettext](http://en.wikipedia.org/wiki/Gettext) system and tools.
You will need [Poedit](http://www.poedit.net/download.php) editor to update, edit and create your translation files comfortably. In general, you can handle translations also without it: all can be done using gettext tools and your favorite plain text editor only. This guide, however, describes editing with Poedit. If you want to use gettext only, pls refer to xgettext manual page to update po files from sources (see also how it is used by Poedit below) and use msgunfmt tool to compile .mo files manually.
You need to know, that translation phrases are stored in **".po"** files (for example: `locale/pl_PL.utf8/LC_MESSAGES/pl_PL.utf8.po`), which are then complied in **".mo"** files using **msgfmt** gettext tool or by Poedit, which will run msgfmt for you in background.
**It's assumed, that you have wallabag installed locally on your computer or on the server you have access to.**
## To change existing translation you will need to do:
### 1. Clear cache
You can do this using **http://your-wallabag-host.com/?empty-cache** link (replace http://your-wallabag-host.com/ with real url of your wallabag application)
OR
from command line:
go to root of your installation of wallabag project and run next command:
`rm -rf ./cache/*`
(this may require root privileges if you run, for example Apatche web server with mod_php)
### 2. Generate php files from all twig templates
Do this using next command:
`php ./locale/tools/fillCache.php`
OR
from your browser: **http://your-wallabag-host.com/locale/tools/fillCache.php** (this may require removal of .htacces file in locale/ directory).
### 3. Configure your Poedit
Open Poedit editor, open Edit->Preferences. Go to "Parsers" tab, click on PHP and press "Edit" button. Make sure your "Parser command:" looks like
`xgettext --no-location --force-po -o %o %C %K %F`
Usualy it is required to add "--no-location" to default value.
### 4. Open .po file you want to edit in Poedit and change it's settings
Open, for example `locale/pl_PL.utf8/LC_MESSAGES/pl_PL.utf8.po` file in your Poedit.
Go to "Catalog"->"Settings..." menu. Go to "Path" tab and add path to wallabag installaion in your local file system. This step can't be ommited as you will not be able to update phrases otherwise.
You can also check "project into" tab to be sure, that "Language" is set correctly (this will allow you to spell check your translation).
### 5. Update opened .po file from sources
Once you have set your path correctly, you are able to update phrases from sources. Press "Update catalog - synchronize it with sources" button or go to "Catalog"->"Update from sources" menu.
As a result you will see confirmation popup with two tabs: "New strings" and "Obsolete strings". Pls review and accept changes (or press "Undo" if you see too many obsolete strings, as Poedit will remove them all - in this case please make sure all previous steps are performed w/o errors).
### 6. Translate and save your .po file
If you have any dificulties on this step, please consult with Poedit manual.
Every time you save your .po file, Poedit will also comple appropriate .mo file by default (of course, if not disabled in preferences).
So, you are almost done.
### 7. Clear cache again
This step may be required if your web server runs php scripts in name of, say, www user (i.e. Apache with mod_php, not cgi).
##To create new translation
Please simple create appropriate directories in locale folder and perform all steps, described above. Instead of opening an existing file just create new one.

View File

@ -13,16 +13,6 @@ if (version_compare(PHP_VERSION, '5.4.0', '<')) {
}
}
// Check PDO Sqlite
if (! extension_loaded('pdo_sqlite')) {
die('PHP extension required: pdo_sqlite');
}
// Check ZIP
if (! extension_loaded('zip')) {
die('PHP extension required: zip');
}
// Check if /cache is writeable
if (! is_writable('cache')) {
die('The directory "cache" must be writeable by your web server user');

View File

@ -31,9 +31,9 @@ class Session
public static $sessionName = '';
// If the user does not access any page within this time,
// his/her session is considered expired (3600 sec. = 1 hour)
public static $inactivityTimeout = 86400;
public static $inactivityTimeout = 3600;
// Extra timeout for long sessions (if enabled) (82800 sec. = 23 hours)
public static $longSessionTimeout = 31536000;
public static $longSessionTimeout = 7776000; // 7776000 = 90 days
// If you get disconnected often or if your IP address changes often.
// Let you disable session cookie hijacking protection
public static $disableSessionProtection = false;
@ -48,8 +48,13 @@ class Session
/**
* Initialize session
*/
public static function init()
public static function init($longlastingsession = false)
{
//check if session name is correct
if ( (session_id() && !empty(self::$sessionName) && session_name()!=self::$sessionName) || $longlastingsession ) {
session_destroy();
}
// Force cookie path (but do not change lifetime)
$cookie = session_get_cookie_params();
// Default cookie expiration and path.
@ -61,12 +66,22 @@ class Session
if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") {
$ssl = true;
}
session_set_cookie_params($cookie['lifetime'], $cookiedir, $_SERVER['HTTP_HOST'], $ssl);
if ( $longlastingsession ) {
session_set_cookie_params(self::$longSessionTimeout, $cookiedir, null, $ssl, true);
}
else {
session_set_cookie_params(0, $cookiedir, null, $ssl, true);
}
//set server side valid session timeout
//WARNING! this may not work in shared session environment. See http://www.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime about min value: it can be set in any application
ini_set('session.gc_maxlifetime', self::$longSessionTimeout);
// Use cookies to store session.
ini_set('session.use_cookies', 1);
// Force cookies for session (phpsessionID forbidden in URL)
ini_set('session.use_only_cookies', 1);
if (!session_id()) {
if ( !session_id() ) {
// Prevent php to use sessionID in URL if cookies are disabled.
ini_set('session.use_trans_sid', false);
if (!empty(self::$sessionName)) {
@ -115,6 +130,9 @@ class Session
if (self::banCanLogin()) {
if ($login === $loginTest && $password === $passwordTest) {
self::banLoginOk();
self::init($longlastingsession);
// Generate unique random number to sign forms (HMAC)
$_SESSION['uid'] = sha1(uniqid('', true).'_'.mt_rand());
$_SESSION['ip'] = self::_allIPs();
@ -135,6 +153,7 @@ class Session
self::banLoginFailed();
}
self::init();
return false;
}
@ -143,7 +162,14 @@ class Session
*/
public static function logout()
{
unset($_SESSION['uid'],$_SESSION['ip'],$_SESSION['expires_on'],$_SESSION['tokens'], $_SESSION['login'], $_SESSION['pass'], $_SESSION['longlastingsession'], $_SESSION['poche_user']);
// unset($_SESSION['uid'],$_SESSION['ip'],$_SESSION['expires_on'],$_SESSION['tokens'], $_SESSION['login'], $_SESSION['pass'], $_SESSION['longlastingsession'], $_SESSION['poche_user']);
// Destruction du cookie (le code peut paraître complexe mais c'est pour être certain de reprendre les mêmes paramètres)
$args = array_merge(array(session_name(), ''), array_values(session_get_cookie_params()));
$args[2] = time() - 3600;
call_user_func_array('setcookie', $args);
// Suppression physique de la session
session_destroy();
}
/**
@ -157,7 +183,7 @@ class Session
|| (self::$disableSessionProtection === false
&& $_SESSION['ip'] !== self::_allIPs())
|| time() >= $_SESSION['expires_on']) {
self::logout();
//self::logout();
return false;
}

View File

@ -59,6 +59,7 @@ class Messages {
$this->msgId = md5(uniqid());
// Create the session array if it doesnt already exist
settype($_SESSION, 'array');
if( !array_key_exists('flash_messages', $_SESSION) ) $_SESSION['flash_messages'] = array();
}
@ -228,4 +229,4 @@ class Messages {
} // end class
?>
?>

View File

@ -19,7 +19,7 @@ if (!isset($options)) $options = new stdClass();
// Enable service
// ----------------------
// Set this to false if you want to disable the service.
// If set to false, no feed is produced and users will
// If set to false, no feed is produced and users will
// be told that the service is disabled.
$options->enabled = true;
@ -43,10 +43,64 @@ $options->default_entries = 5;
// ----------------------
// The maximum number of feed items to process when no access key is supplied.
// This limits the user-supplied &max=x value. For example, if the user
// asks for 20 items to be processed (&max=20), if max_entries is set to
// asks for 20 items to be processed (&max=20), if max_entries is set to
// 10, only 10 will be processed.
$options->max_entries = 10;
// Full content
// ----------------------
// By default Full-Text RSS includes the extracted content in the output.
// You can exclude this from the output by passing '&content=0' in the querystring.
//
// Possible values...
// Always include: true
// Never include: false
// Include unless user overrides (&content=0): 'user' (default)
//
// Note: currently this does not disable full content extraction. It simply omits it
// from the output.
$options->content = 'user';
// Excerpts
// ----------------------
// By default Full-Text RSS does not include excerpts in the output.
// You can enable this by passing '&summary=1' in the querystring.
// This will include a plain text excerpt from the extracted content.
//
// Possible values...
// Always include: true (recommended for new users)
// Never include: false
// Don't include unless user overrides (&summary=1): 'user' (default)
//
// Important: if both content and excerpts are requested, the excerpt will be
// placed in the description element and the full content inside content:encoded.
// If excerpts are not requested, the full content will go inside the description element.
//
// Why are we not returning both excerpts and content by default?
// Mainly for backward compatibility.
// Excerpts should appear in the feed item's description element. Previous versions
// of Full-Text RSS did not return excerpts, so the description element was always
// used for the full content (as recommended by the RSS advisory). When returning both,
// we need somewhere else to place the content (content:encoded).
// Having both enabled should not create any problems for news readers, but it may create
// problems for developers upgrading from one of our earlier versions who may now find
// their applications are returning excerpts instead of the full content they were
// expecting. To avoid such surprises for users who are upgrading Full-Text RSS,
// excerpts must be explicitly requested in the querystring by default.
//
// Why not use a different element name for excerpts?
// According to the RSS advisory:
// "Publishers who employ summaries should store the summary in description and
// the full content in content:encoded, ordering description first within the item.
// On items with no summary, the full content should be stored in description."
// See: http://www.rssboard.org/rss-profile#namespace-elements-content-encoded
//
// For more consistent element naming, we recommend new users set this option to true.
// The full content can still be excluded via the querystring, but the element names
// will not change: when $options->summary = true, the description element will always
// be reserved for the excerpt and content:encoded always for full content.
$options->summary = 'user';
// Rewrite relative URLs
// ----------------------
// With this enabled relative URLs found in the extracted content
@ -67,7 +121,7 @@ $options->exclude_items_on_fail = 'user';
// Enable multi-page support
// -------------------------
// If enabled, we will try to follow next page links on multi-page articles.
// Currently this only happens for sites where next_page_link has been defined
// Currently this only happens for sites where next_page_link has been defined
// in a site config file.
$options->multipage = true;
@ -125,10 +179,10 @@ $options->detect_language = 1;
// Registration key
// ---------------
// The registration key is optional. It is not required to use Full-Text RSS,
// and does not affect the normal operation of Full-Text RSS. It is currently
// only used on admin pages which help you update site patterns with the
// latest version offered by FiveFilters.org. For these admin-related
// The registration key is optional. It is not required to use Full-Text RSS,
// and does not affect the normal operation of Full-Text RSS. It is currently
// only used on admin pages which help you update site patterns with the
// latest version offered by FiveFilters.org. For these admin-related
// tasks to complete, we will require a valid registration key.
// If you would like one, you can purchase the latest version of Full-Text RSS
// at http://fivefilters.org/content-only/
@ -144,12 +198,12 @@ $options->registration_key = '';
// ----------------------
// Certain pages/actions, e.g. updating site patterns with our online tool, will require admin credentials.
// To use these pages, enter a password here and you'll be prompted for it when you try to access those pages.
// If no password or username is set, pages requiring admin privelages will be inaccessible.
// If no password or username is set, pages requiring admin privelages will be inaccessible.
// The default username is 'admin'.
// If overriding with an environment variable, separate username and password with a colon, e.g.:
// ftr_admin_credentials: admin:my-secret-password
// Example: $options->admin_credentials = array('username'=>'admin', 'password'=>'my-secret-password');
$options->admin_credentials = array('username'=>'admin', 'password'=>'admin');
$options->admin_credentials = array('username'=>'admin', 'password'=>'');
// URLs to allow
// ----------------------
@ -178,12 +232,12 @@ $options->key_required = false;
// ----------------------
// By default, when processing feeds, we assume item titles in the feed
// have not been truncated. So after processing web pages, the extracted titles
// are not used in the generated feed. If you prefer to have extracted titles in
// the feed you can either set this to false, in which case we will always favour
// extracted titles. Alternatively, if set to 'user' (default) we'll use the
// are not used in the generated feed. If you prefer to have extracted titles in
// the feed you can either set this to false, in which case we will always favour
// extracted titles. Alternatively, if set to 'user' (default) we'll use the
// extracted title if you pass '&use_extracted_title' in the querystring.
// Possible values:
// * Favour feed titles: true
// * Favour feed titles: true
// * Favour extracted titles: false
// * Favour feed titles with user override: 'user' (default)
// Note: this has no effect when the input URL is to a web page - in these cases
@ -192,17 +246,17 @@ $options->favour_feed_titles = 'user';
// Access keys (password protected access)
// ------------------------------------
// NOTE: You do not need an API key from fivefilters.org to run your own
// NOTE: You do not need an API key from fivefilters.org to run your own
// copy of the code. This is here if you'd like to restrict access to
// _your_ copy.
// Keys let you group users - those with a key and those without - and
// restrict access to the service to those without a key.
// If you want everyone to access the service in the same way, you can
// leave the array below empty and ignore the access key options further down.
// The options further down let you control how the service should behave
// The options further down let you control how the service should behave
// in each mode.
// Note: Explicitly including the index number (1 and 2 in the examples below)
// is highly recommended (when generating feeds, we encode the key and
// Note: Explicitly including the index number (1 and 2 in the examples below)
// is highly recommended (when generating feeds, we encode the key and
// refer to it by index number and hash).
$options->api_keys = array();
// Example:
@ -232,13 +286,13 @@ $options->max_entries_with_key = 10;
// filter the resulting HTML for XSS attacks, making it redundant for
// Full-Text RSS do the same. Similarly with frameworks/CMS which display
// feed content - the content should be treated like any other user-submitted content.
//
//
// If you are writing an application yourself which is processing feeds generated by
// Full-Text RSS, you can either filter the HTML yourself to remove potential XSS attacks
// or enable this option. This might be useful if you are processing our generated
// feeds with JavaScript on the client side - although there's client side xss
// filtering available too, e.g. https://code.google.com/p/google-caja/wiki/JsHtmlSanitizer
//
//
// If enabled, we'll pass retrieved HTML content through htmLawed with
// safe flag on and style attributes denied, see
// http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/htmLawed_README.htm#s3.6
@ -253,8 +307,8 @@ $options->xss_filter = 'user';
// Allowed parsers
// ----------------------
// Full-Text RSS attempts to use PHP's libxml extension to process HTML.
// While fast, on some sites it may not always produce good results.
// For these sites, you can specify an alternative HTML parser:
// While fast, on some sites it may not always produce good results.
// For these sites, you can specify an alternative HTML parser:
// parser: html5lib
// The html5lib parser is bundled with Full-Text RSS.
// see http://code.google.com/p/html5lib/
@ -273,7 +327,7 @@ $options->cors = false;
// Use APC user cache?
// ----------------------
// If enabled we will store site config files (when requested
// If enabled we will store site config files (when requested
// for the first time) in APC's user cache. Keys prefixed with 'sc.'
// This improves performance by reducing disk access.
// Note: this has no effect if APC is unavailable on your server.
@ -346,7 +400,7 @@ $options->rewrite_url = array(
// Valid actions:
// * 'exclude' - exclude this item from the result
// * 'link' - create HTML link to the item
$options->content_type_exc = array(
$options->content_type_exc = array(
'application/pdf' => array('action'=>'link', 'name'=>'PDF'),
'image' => array('action'=>'link', 'name'=>'Image'),
'audio' => array('action'=>'link', 'name'=>'Audio'),
@ -375,13 +429,13 @@ $options->cache_cleanup = 100;
/// DO NOT CHANGE ANYTHING BELOW THIS ///////////
/////////////////////////////////////////////////
if (!defined('_FF_FTR_VERSION')) define('_FF_FTR_VERSION', '3.1');
if (!defined('_FF_FTR_VERSION')) define('_FF_FTR_VERSION', '3.2');
if (basename(__FILE__) == 'config.php') {
if (file_exists(dirname(__FILE__).'/custom_config.php')) {
require_once dirname(__FILE__).'/custom_config.php';
}
// check for environment variables - often used on cloud platforms
// environment variables should be prefixed with 'ftr_', e.g.
// ftr_max_entries: 1

View File

@ -0,0 +1,266 @@
<?php
/**
* This should be a complete list of all HTML entities, mapped to their UTF-8 character codes.
*
* @author A. Grandt
* @copyright A. Grandt 2009-2013
* @license GNU LGPL, Attribution required for commercial implementations, requested for everything else.
* @version 3.00
*/
global $htmlEntities;
$htmlEntities = array();
$htmlEntities["&quot;"] ="\x22"; // &#34; ((double) quotation mark)
$htmlEntities["&amp;"] ="\x26"; // &#38; (ampersand)
$htmlEntities["&apos;"] ="\x27"; // &#39; (apostrophe = apostrophe-quote)
$htmlEntities["&lt;"] ="\x3C"; // &#60; (less-than sign)
$htmlEntities["&gt;"] ="\x3E"; // &#62; (greater-than sign)
$htmlEntities["&nbsp;"] ="\xC2\xA0"; // &#160; (non-breaking space)
$htmlEntities["&iexcl;"] ="\xC2\xA1"; // &#161; (inverted exclamation mark)
$htmlEntities["&cent;"] ="\xC2\xA2"; // &#162; (cent)
$htmlEntities["&pound;"] ="\xC2\xA3"; // &#163; (pound)
$htmlEntities["&curren;"] ="\xC2\xA4"; // &#164; (currency)
$htmlEntities["&yen;"] ="\xC2\xA5"; // &#165; (yen)
$htmlEntities["&brvbar;"] ="\xC2\xA6"; // &#166; (broken vertical bar)
$htmlEntities["&sect;"] ="\xC2\xA7"; // &#167; (section)
$htmlEntities["&uml;"] ="\xC2\xA8"; // &#168; (spacing diaeresis)
$htmlEntities["&copy;"] ="\xC2\xA9"; // &#169; (copyright)
$htmlEntities["&ordf;"] ="\xC2\xAA"; // &#170; (feminine ordinal indicator)
$htmlEntities["&laquo;"] ="\xC2\xAB"; // &#171; (angle quotation mark (left))
$htmlEntities["&not;"] ="\xC2\xAC"; // &#172; (negation)
$htmlEntities["&shy;"] ="\xC2\xAD"; // &#173; (soft hyphen)
$htmlEntities["&reg;"] ="\xC2\xAE"; // &#174; (registered trademark)
$htmlEntities["&macr;"] ="\xC2\xAF"; // &#175; (spacing macron)
$htmlEntities["&deg;"] ="\xC2\xB0"; // &#176; (degree)
$htmlEntities["&plusmn;"] ="\xC2\xB1"; // &#177; (plus-or-minus)
$htmlEntities["&sup2;"] ="\xC2\xB2"; // &#178; (superscript 2)
$htmlEntities["&sup3;"] ="\xC2\xB3"; // &#179; (superscript 3)
$htmlEntities["&acute;"] ="\xC2\xB4"; // &#180; (spacing acute)
$htmlEntities["&micro;"] ="\xC2\xB5"; // &#181; (micro)
$htmlEntities["&para;"] ="\xC2\xB6"; // &#182; (paragraph)
$htmlEntities["&middot;"] ="\xC2\xB7"; // &#183; (middle dot)
$htmlEntities["&cedil;"] ="\xC2\xB8"; // &#184; (spacing cedilla)
$htmlEntities["&sup1;"] ="\xC2\xB9"; // &#185; (superscript 1)
$htmlEntities["&ordm;"] ="\xC2\xBA"; // &#186; (masculine ordinal indicator)
$htmlEntities["&raquo;"] ="\xC2\xBB"; // &#187; (angle quotation mark (right))
$htmlEntities["&frac14;"] ="\xC2\xBC"; // &#188; (fraction 1/4)
$htmlEntities["&frac12;"] ="\xC2\xBD"; // &#189; (fraction 1/2)
$htmlEntities["&frac34;"] ="\xC2\xBE"; // &#190; (fraction 3/4)
$htmlEntities["&iquest;"] ="\xC2\xBF"; // &#191; (inverted question mark)
$htmlEntities["&Agrave;"] ="\xC3\x80"; // &#192; (capital a, grave accent)
$htmlEntities["&Aacute;"] ="\xC3\x81"; // &#193; (capital a, acute accent)
$htmlEntities["&Acirc;"] ="\xC3\x82"; // &#194; (capital a, circumflex accent)
$htmlEntities["&Atilde;"] ="\xC3\x83"; // &#195; (capital a, tilde)
$htmlEntities["&Auml;"] ="\xC3\x84"; // &#196; (capital a, umlaut mark)
$htmlEntities["&Aring;"] ="\xC3\x85"; // &#197; (capital a, ring)
$htmlEntities["&AElig;"] ="\xC3\x86"; // &#198; (capital ae)
$htmlEntities["&Ccedil;"] ="\xC3\x87"; // &#199; (capital c, cedilla)
$htmlEntities["&Egrave;"] ="\xC3\x88"; // &#200; (capital e, grave accent)
$htmlEntities["&Eacute;"] ="\xC3\x89"; // &#201; (capital e, acute accent)
$htmlEntities["&Ecirc;"] ="\xC3\x8A"; // &#202; (capital e, circumflex accent)
$htmlEntities["&Euml;"] ="\xC3\x8B"; // &#203; (capital e, umlaut mark)
$htmlEntities["&Igrave;"] ="\xC3\x8C"; // &#204; (capital i, grave accent)
$htmlEntities["&Iacute;"] ="\xC3\x8D"; // &#205; (capital i, acute accent)
$htmlEntities["&Icirc;"] ="\xC3\x8E"; // &#206; (capital i, circumflex accent)
$htmlEntities["&Iuml;"] ="\xC3\x8F"; // &#207; (capital i, umlaut mark)
$htmlEntities["&ETH;"] ="\xC3\x90"; // &#208; (capital eth, Icelandic)
$htmlEntities["&Ntilde;"] ="\xC3\x91"; // &#209; (capital n, tilde)
$htmlEntities["&Ograve;"] ="\xC3\x92"; // &#210; (capital o, grave accent)
$htmlEntities["&Oacute;"] ="\xC3\x93"; // &#211; (capital o, acute accent)
$htmlEntities["&Ocirc;"] ="\xC3\x94"; // &#212; (capital o, circumflex accent)
$htmlEntities["&Otilde;"] ="\xC3\x95"; // &#213; (capital o, tilde)
$htmlEntities["&Ouml;"] ="\xC3\x96"; // &#214; (capital o, umlaut mark)
$htmlEntities["&times;"] ="\xC3\x97"; // &#215; (multiplication)
$htmlEntities["&Oslash;"] ="\xC3\x98"; // &#216; (capital o, slash)
$htmlEntities["&Ugrave;"] ="\xC3\x99"; // &#217; (capital u, grave accent)
$htmlEntities["&Uacute;"] ="\xC3\x9A"; // &#218; (capital u, acute accent)
$htmlEntities["&Ucirc;"] ="\xC3\x9B"; // &#219; (capital u, circumflex accent)
$htmlEntities["&Uuml;"] ="\xC3\x9C"; // &#220; (capital u, umlaut mark)
$htmlEntities["&Yacute;"] ="\xC3\x9D"; // &#221; (capital y, acute accent)
$htmlEntities["&THORN;"] ="\xC3\x9E"; // &#222; (capital THORN, Icelandic)
$htmlEntities["&szlig;"] ="\xC3\x9F"; // &#223; (small sharp s, German)
$htmlEntities["&agrave;"] ="\xC3\xA0"; // &#224; (small a, grave accent)
$htmlEntities["&aacute;"] ="\xC3\xA1"; // &#225; (small a, acute accent)
$htmlEntities["&acirc;"] ="\xC3\xA2"; // &#226; (small a, circumflex accent)
$htmlEntities["&atilde;"] ="\xC3\xA3"; // &#227; (small a, tilde)
$htmlEntities["&auml;"] ="\xC3\xA4"; // &#228; (small a, umlaut mark)
$htmlEntities["&aring;"] ="\xC3\xA5"; // &#229; (small a, ring)
$htmlEntities["&aelig;"] ="\xC3\xA6"; // &#230; (small ae)
$htmlEntities["&ccedil;"] ="\xC3\xA7"; // &#231; (small c, cedilla)
$htmlEntities["&egrave;"] ="\xC3\xA8"; // &#232; (small e, grave accent)
$htmlEntities["&eacute;"] ="\xC3\xA9"; // &#233; (small e, acute accent)
$htmlEntities["&ecirc;"] ="\xC3\xAA"; // &#234; (small e, circumflex accent)
$htmlEntities["&euml;"] ="\xC3\xAB"; // &#235; (small e, umlaut mark)
$htmlEntities["&igrave;"] ="\xC3\xAC"; // &#236; (small i, grave accent)
$htmlEntities["&iacute;"] ="\xC3\xAD"; // &#237; (small i, acute accent)
$htmlEntities["&icirc;"] ="\xC3\xAE"; // &#238; (small i, circumflex accent)
$htmlEntities["&iuml;"] ="\xC3\xAF"; // &#239; (small i, umlaut mark)
$htmlEntities["&eth;"] ="\xC3\xB0"; // &#240; (small eth, Icelandic)
$htmlEntities["&ntilde;"] ="\xC3\xB1"; // &#241; (small n, tilde)
$htmlEntities["&ograve;"] ="\xC3\xB2"; // &#242; (small o, grave accent)
$htmlEntities["&oacute;"] ="\xC3\xB3"; // &#243; (small o, acute accent)
$htmlEntities["&ocirc;"] ="\xC3\xB4"; // &#244; (small o, circumflex accent)
$htmlEntities["&otilde;"] ="\xC3\xB5"; // &#245; (small o, tilde)
$htmlEntities["&ouml;"] ="\xC3\xB6"; // &#246; (small o, umlaut mark)
$htmlEntities["&divide;"] ="\xC3\xB7"; // &#247; (division)
$htmlEntities["&oslash;"] ="\xC3\xB8"; // &#248; (small o, slash)
$htmlEntities["&ugrave;"] ="\xC3\xB9"; // &#249; (small u, grave accent)
$htmlEntities["&uacute;"] ="\xC3\xBA"; // &#250; (small u, acute accent)
$htmlEntities["&ucirc;"] ="\xC3\xBB"; // &#251; (small u, circumflex accent)
$htmlEntities["&uuml;"] ="\xC3\xBC"; // &#252; (small u, umlaut mark)
$htmlEntities["&yacute;"] ="\xC3\xBD"; // &#253; (small y, acute accent)
$htmlEntities["&thorn;"] ="\xC3\xBE"; // &#254; (small thorn, Icelandic)
$htmlEntities["&yuml;"] ="\xC3\xBF"; // &#255; (small y, umlaut mark)
$htmlEntities["&OElig;"] ="\xC5\x92"; // &#338; (capital ligature OE)
$htmlEntities["&oelig;"] ="\xC5\x93"; // &#339; (small ligature oe)
$htmlEntities["&Scaron;"] ="\xC5\xA0"; // &#352; (capital S with caron)
$htmlEntities["&scaron;"] ="\xC5\xA1"; // &#353; (small S with caron)
$htmlEntities["&Yuml;"] ="\xC5\xB8"; // &#376; (capital Y with diaeres)
$htmlEntities["&fnof;"] ="\xC6\x92"; // &#402; (f with hook)
$htmlEntities["&circ;"] ="\xCB\x86"; // &#710; (modifier letter circumflex accent)
$htmlEntities["&tilde;"] ="\xCB\x9C"; // &#732; (small tilde)
$htmlEntities["&Alpha;"] ="\xCE\x91"; // &#913; (Alpha)
$htmlEntities["&Beta;"] ="\xCE\x92"; // &#914; (Beta)
$htmlEntities["&Gamma;"] ="\xCE\x93"; // &#915; (Gamma)
$htmlEntities["&Delta;"] ="\xCE\x94"; // &#916; (Delta)
$htmlEntities["&Epsilon;"] ="\xCE\x95"; // &#917; (Epsilon)
$htmlEntities["&Zeta;"] ="\xCE\x96"; // &#918; (Zeta)
$htmlEntities["&Eta;"] ="\xCE\x97"; // &#919; (Eta)
$htmlEntities["&Theta;"] ="\xCE\x98"; // &#920; (Theta)
$htmlEntities["&Iota;"] ="\xCE\x99"; // &#921; (Iota)
$htmlEntities["&Kappa;"] ="\xCE\x9A"; // &#922; (Kappa)
$htmlEntities["&Lambda;"] ="\xCE\x9B"; // &#923; (Lambda)
$htmlEntities["&Mu;"] ="\xCE\x9C"; // &#924; (Mu)
$htmlEntities["&Nu;"] ="\xCE\x9D"; // &#925; (Nu)
$htmlEntities["&Xi;"] ="\xCE\x9E"; // &#926; (Xi)
$htmlEntities["&Omicron;"] ="\xCE\x9F"; // &#927; (Omicron)
$htmlEntities["&Pi;"] ="\xCE\xA0"; // &#928; (Pi)
$htmlEntities["&Rho;"] ="\xCE\xA1"; // &#929; (Rho)
$htmlEntities["&Sigma;"] ="\xCE\xA3"; // &#931; (Sigma)
$htmlEntities["&Tau;"] ="\xCE\xA4"; // &#932; (Tau)
$htmlEntities["&Upsilon;"] ="\xCE\xA5"; // &#933; (Upsilon)
$htmlEntities["&Phi;"] ="\xCE\xA6"; // &#934; (Phi)
$htmlEntities["&Chi;"] ="\xCE\xA7"; // &#935; (Chi)
$htmlEntities["&Psi;"] ="\xCE\xA8"; // &#936; (Psi)
$htmlEntities["&Omega;"] ="\xCE\xA9"; // &#937; (Omega)
$htmlEntities["&alpha;"] ="\xCE\xB1"; // &#945; (alpha)
$htmlEntities["&beta;"] ="\xCE\xB2"; // &#946; (beta)
$htmlEntities["&gamma;"] ="\xCE\xB3"; // &#947; (gamma)
$htmlEntities["&delta;"] ="\xCE\xB4"; // &#948; (delta)
$htmlEntities["&epsilon;"] ="\xCE\xB5"; // &#949; (epsilon)
$htmlEntities["&zeta;"] ="\xCE\xB6"; // &#950; (zeta)
$htmlEntities["&eta;"] ="\xCE\xB7"; // &#951; (eta)
$htmlEntities["&theta;"] ="\xCE\xB8"; // &#952; (theta)
$htmlEntities["&iota;"] ="\xCE\xB9"; // &#953; (iota)
$htmlEntities["&kappa;"] ="\xCE\xBA"; // &#954; (kappa)
$htmlEntities["&lambda;"] ="\xCE\xBB"; // &#955; (lambda)
$htmlEntities["&mu;"] ="\xCE\xBC"; // &#956; (mu)
$htmlEntities["&nu;"] ="\xCE\xBD"; // &#957; (nu)
$htmlEntities["&xi;"] ="\xCE\xBE"; // &#958; (xi)
$htmlEntities["&omicron;"] ="\xCE\xBF"; // &#959; (omicron)
$htmlEntities["&pi;"] ="\xCF\x80"; // &#960; (pi)
$htmlEntities["&rho;"] ="\xCF\x81"; // &#961; (rho)
$htmlEntities["&sigmaf;"] ="\xCF\x82"; // &#962; (sigmaf)
$htmlEntities["&sigma;"] ="\xCF\x83"; // &#963; (sigma)
$htmlEntities["&tau;"] ="\xCF\x84"; // &#964; (tau)
$htmlEntities["&upsilon;"] ="\xCF\x85"; // &#965; (upsilon)
$htmlEntities["&phi;"] ="\xCF\x86"; // &#966; (phi)
$htmlEntities["&chi;"] ="\xCF\x87"; // &#967; (chi)
$htmlEntities["&psi;"] ="\xCF\x88"; // &#968; (psi)
$htmlEntities["&omega;"] ="\xCF\x89"; // &#969; (omega)
$htmlEntities["&thetasym;"] ="\xCF\x91"; // &#977; (theta symbol)
$htmlEntities["&upsih;"] ="\xCF\x92"; // &#978; (upsilon symbol)
$htmlEntities["&piv;"] ="\xCF\x96"; // &#982; (pi symbol)
$htmlEntities["&ensp;"] ="\xE2\x80\x82"; // &#8194; (en space)
$htmlEntities["&emsp;"] ="\xE2\x80\x83"; // &#8195; (em space)
$htmlEntities["&thinsp;"] ="\xE2\x80\x89"; // &#8201; (thin space)
$htmlEntities["&zwnj;"] ="\xE2\x80\x8C"; // &#8204; (zero width non-joiner)
$htmlEntities["&zwj;"] ="\xE2\x80\x8D"; // &#8205; (zero width joiner)
$htmlEntities["&lrm;"] ="\xE2\x80\x8E"; // &#8206; (left-to-right mark)
$htmlEntities["&rlm;"] ="\xE2\x80\x8F"; // &#8207; (right-to-left mark)
$htmlEntities["&ndash;"] ="\xE2\x80\x93"; // &#8211; (en dash)
$htmlEntities["&mdash;"] ="\xE2\x80\x94"; // &#8212; (em dash)
$htmlEntities["&lsquo;"] ="\xE2\x80\x98"; // &#8216; (left single quotation mark)
$htmlEntities["&rsquo;"] ="\xE2\x80\x99"; // &#8217; (right single quotation mark)
$htmlEntities["&sbquo;"] ="\xE2\x80\x9A"; // &#8218; (single low-9 quotation mark)
$htmlEntities["&ldquo;"] ="\xE2\x80\x9C"; // &#8220; (left double quotation mark)
$htmlEntities["&rdquo;"] ="\xE2\x80\x9D"; // &#8221; (right double quotation mark)
$htmlEntities["&bdquo;"] ="\xE2\x80\x9E"; // &#8222; (double low-9 quotation mark)
$htmlEntities["&dagger;"] ="\xE2\x80\xA0"; // &#8224; (dagger)
$htmlEntities["&Dagger;"] ="\xE2\x80\xA1"; // &#8225; (double dagger)
$htmlEntities["&bull;"] ="\xE2\x80\xA2"; // &#8226; (bullet)
$htmlEntities["&hellip;"] ="\xE2\x80\xA6"; // &#8230; (horizontal ellipsis)
$htmlEntities["&permil;"] ="\xE2\x80\xB0"; // &#8240; (per mille)
$htmlEntities["&prime;"] ="\xE2\x80\xB2"; // &#8242; (minutes or prime)
$htmlEntities["&Prime;"] ="\xE2\x80\xB3"; // &#8243; (seconds or Double Prime)
$htmlEntities["&lsaquo;"] ="\xE2\x80\xB9"; // &#8249; (single left angle quotation)
$htmlEntities["&rsaquo;"] ="\xE2\x80\xBA"; // &#8250; (single right angle quotation)
$htmlEntities["&oline;"] ="\xE2\x80\xBE"; // &#8254; (overline)
$htmlEntities["&frasl;"] ="\xE2\x81\x84"; // &#8260; (fraction slash)
$htmlEntities["&euro;"] ="\xE2\x82\xAC"; // &#8364; (euro)
$htmlEntities["&image;"] ="\xE2\x84\x91"; // &#8465; (blackletter capital I)
$htmlEntities["&weierp;"] ="\xE2\x84\x98"; // &#8472; (script capital P)
$htmlEntities["&real;"] ="\xE2\x84\x9C"; // &#8476; (blackletter capital R)
$htmlEntities["&trade;"] ="\xE2\x84\xA2"; // &#8482; (trademark)
$htmlEntities["&alefsym;"] ="\xE2\x84\xB5"; // &#8501; (alef)
$htmlEntities["&larr;"] ="\xE2\x86\x90"; // &#8592; (left arrow)
$htmlEntities["&uarr;"] ="\xE2\x86\x91"; // &#8593; (up arrow)
$htmlEntities["&rarr;"] ="\xE2\x86\x92"; // &#8594; (right arrow)
$htmlEntities["&darr;"] ="\xE2\x86\x93"; // &#8595; (down arrow)
$htmlEntities["&harr;"] ="\xE2\x86\x94"; // &#8596; (left right arrow)
$htmlEntities["&crarr;"] ="\xE2\x86\xB5"; // &#8629; (carriage return arrow)
$htmlEntities["&lArr;"] ="\xE2\x87\x90"; // &#8656; (left double arrow)
$htmlEntities["&uArr;"] ="\xE2\x87\x91"; // &#8657; (up double arrow)
$htmlEntities["&rArr;"] ="\xE2\x87\x92"; // &#8658; (right double arrow)
$htmlEntities["&dArr;"] ="\xE2\x87\x93"; // &#8659; (down double arrow)
$htmlEntities["&hArr;"] ="\xE2\x87\x94"; // &#8660; (left right double arrow)
$htmlEntities["&forall;"] ="\xE2\x88\x80"; // &#8704; (for all)
$htmlEntities["&part;"] ="\xE2\x88\x82"; // &#8706; (partial differential)
$htmlEntities["&exist;"] ="\xE2\x88\x83"; // &#8707; (there exists)
$htmlEntities["&empty;"] ="\xE2\x88\x85"; // &#8709; (empty set)
$htmlEntities["&nabla;"] ="\xE2\x88\x87"; // &#8711; (backward difference)
$htmlEntities["&isin;"] ="\xE2\x88\x88"; // &#8712; (element of)
$htmlEntities["&notin;"] ="\xE2\x88\x89"; // &#8713; (not an element of)
$htmlEntities["&ni;"] ="\xE2\x88\x8B"; // &#8715; (ni = contains as member)
$htmlEntities["&prod;"] ="\xE2\x88\x8F"; // &#8719; (n-ary product)
$htmlEntities["&sum;"] ="\xE2\x88\x91"; // &#8721; (n-ary sumation)
$htmlEntities["&minus;"] ="\xE2\x88\x92"; // &#8722; (minus)
$htmlEntities["&lowast;"] ="\xE2\x88\x97"; // &#8727; (asterisk operator)
$htmlEntities["&radic;"] ="\xE2\x88\x9A"; // &#8730; (square root)
$htmlEntities["&prop;"] ="\xE2\x88\x9D"; // &#8733; (proportional to)
$htmlEntities["&infin;"] ="\xE2\x88\x9E"; // &#8734; (infinity)
$htmlEntities["&ang;"] ="\xE2\x88\xA0"; // &#8736; (angle)
$htmlEntities["&and;"] ="\xE2\x88\xA7"; // &#8743; (logical and)
$htmlEntities["&or;"] ="\xE2\x88\xA8"; // &#8744; (logical or)
$htmlEntities["&cap;"] ="\xE2\x88\xA9"; // &#8745; (intersection)
$htmlEntities["&cup;"] ="\xE2\x88\xAA"; // &#8746; (union)
$htmlEntities["&int;"] ="\xE2\x88\xAB"; // &#8747; (integral)
$htmlEntities["&there4;"] ="\xE2\x88\xB4"; // &#8756; (therefore)
$htmlEntities["&sim;"] ="\xE2\x88\xBC"; // &#8764; (similar to)
$htmlEntities["&cong;"] ="\xE2\x89\x85"; // &#8773; (congruent to)
$htmlEntities["&asymp;"] ="\xE2\x89\x88"; // &#8776; (approximately equal)
$htmlEntities["&ne;"] ="\xE2\x89\xA0"; // &#8800; (not equal)
$htmlEntities["&equiv;"] ="\xE2\x89\xA1"; // &#8801; (equivalent)
$htmlEntities["&le;"] ="\xE2\x89\xA4"; // &#8804; (less or equal)
$htmlEntities["&ge;"] ="\xE2\x89\xA5"; // &#8805; (greater or equal)
$htmlEntities["&sub;"] ="\xE2\x8A\x82"; // &#8834; (subset of)
$htmlEntities["&sup;"] ="\xE2\x8A\x83"; // &#8835; (superset of)
$htmlEntities["&nsub;"] ="\xE2\x8A\x84"; // &#8836; (not subset of)
$htmlEntities["&sube;"] ="\xE2\x8A\x86"; // &#8838; (subset or equal)
$htmlEntities["&supe;"] ="\xE2\x8A\x87"; // &#8839; (superset or equal)
$htmlEntities["&oplus;"] ="\xE2\x8A\x95"; // &#8853; (circled plus)
$htmlEntities["&otimes;"] ="\xE2\x8A\x87"; // &#8855; (circled times)
$htmlEntities["&perp;"] ="\xE2\x8A\xA5"; // &#8869; (perpendicular)
$htmlEntities["&sdot;"] ="\xE2\x8C\x85"; // &#8901; (dot operator)
$htmlEntities["&lceil;"] ="\xE2\x8C\x88"; // &#8968; (left ceiling)
$htmlEntities["&rceil;"] ="\xE2\x8C\x89"; // &#8969; (right ceiling)
$htmlEntities["&lfloor;"] ="\xE2\x8C\x8A"; // &#8970; (left floor)
$htmlEntities["&rfloor;"] ="\xE2\x8C\x8B"; // &#8971; (right floor)
$htmlEntities["&lang;"] ="\xE2\x8C\xA9"; // &#9001; (left angle bracket = bra)
$htmlEntities["&rang;"] ="\xE2\x8C\xAA"; // &#9002; (right angle bracket = ket)
$htmlEntities["&loz;"] ="\xE2\x97\x8A"; // &#9674; (lozenge)
$htmlEntities["&spades;"] ="\xE2\x99\xA0"; // &#9824; (spade)
$htmlEntities["&clubs;"] ="\xE2\x99\xA3"; // &#9827; (club)
$htmlEntities["&hearts;"] ="\xE2\x99\xA5"; // &#9829; (heart)
$htmlEntities["&diams;"] ="\xE2\x99\xA6"; // &#9830; (diamond)
?>

View File

@ -0,0 +1,782 @@
<?php
/**
* ePub NCX file structure
*
* @author A. Grandt <php@grandt.com>
* @copyright 2009-2014 A. Grandt
* @license GNU LGPL, Attribution required for commercial implementations, requested for everything else.
* @version 3.20
*/
class Ncx {
const _VERSION = 3.20;
const MIMETYPE = "application/x-dtbncx+xml";
private $bookVersion = EPub::BOOK_VERSION_EPUB2;
private $navMap = NULL;
private $uid = NULL;
private $meta = array();
private $docTitle = NULL;
private $docAuthor = NULL;
private $currentLevel = NULL;
private $lastLevel = NULL;
private $languageCode = "en";
private $writingDirection = EPub::DIRECTION_LEFT_TO_RIGHT;
public $chapterList = array();
public $referencesTitle = "Guide";
public $referencesClass = "references";
public $referencesId = "references";
public $referencesList = array();
public $referencesName = array();
public $referencesOrder = NULL;
/**
* Class constructor.
*
* @param string $uid
* @param string $docTitle
* @param string $docAuthor
* @param string $languageCode
* @param string $writingDirection
*/
function __construct($uid = NULL, $docTitle = NULL, $docAuthor = NULL, $languageCode = "en", $writingDirection = EPub::DIRECTION_LEFT_TO_RIGHT) {
$this->navMap = new NavMap($writingDirection);
$this->currentLevel = $this->navMap;
$this->setUid($uid);
$this->setDocTitle($docTitle);
$this->setDocAuthor($docAuthor);
$this->setLanguageCode($languageCode);
$this->setWritingDirection($writingDirection);
}
/**
* Class destructor
*
* @return void
*/
function __destruct() {
unset($this->bookVersion, $this->navMap, $this->uid, $this->meta);
unset($this->docTitle, $this->docAuthor, $this->currentLevel, $this->lastLevel);
unset($this->languageCode, $this->writingDirection, $this->chapterList, $this->referencesTitle);
unset($this->referencesClass, $this->referencesId, $this->referencesList, $this->referencesName);
unset($this->referencesOrder);
}
/**
*
* Enter description here ...
*
* @param string $bookVersion
*/
function setVersion($bookVersion) {
$this->bookVersion = is_string($bookVersion) ? trim($bookVersion) : EPub::BOOK_VERSION_EPUB2;
}
/**
*
* @return bool TRUE if the book is set to type ePub 2
*/
function isEPubVersion2() {
return $this->bookVersion === EPub::BOOK_VERSION_EPUB2;
}
/**
*
* Enter description here ...
*
* @param string $uid
*/
function setUid($uid) {
$this->uid = is_string($uid) ? trim($uid) : NULL;
}
/**
*
* Enter description here ...
*
* @param string $docTitle
*/
function setDocTitle($docTitle) {
$this->docTitle = is_string($docTitle) ? trim($docTitle) : NULL;
}
/**
*
* Enter description here ...
*
* @param string $docAuthor
*/
function setDocAuthor($docAuthor) {
$this->docAuthor = is_string($docAuthor) ? trim($docAuthor) : NULL;
}
/**
*
* Enter description here ...
*
* @param string $languageCode
*/
function setLanguageCode($languageCode) {
$this->languageCode = is_string($languageCode) ? trim($languageCode) : "en";
}
/**
*
* Enter description here ...
*
* @param string $writingDirection
*/
function setWritingDirection($writingDirection) {
$this->writingDirection = is_string($writingDirection) ? trim($writingDirection) : EPub::DIRECTION_LEFT_TO_RIGHT;
}
/**
*
* Enter description here ...
*
* @param NavMap $navMap
*/
function setNavMap($navMap) {
if ($navMap != NULL && is_object($navMap) && get_class($navMap) === "NavMap") {
$this->navMap = $navMap;
}
}
/**
* Add one chapter level.
*
* Subsequent chapters will be added to this level.
*
* @param string $navTitle
* @param string $navId
* @param string $navClass
* @param string $isNavHidden
* @param string $writingDirection
* @return NavPoint
*/
function subLevel($navTitle = NULL, $navId = NULL, $navClass = NULL, $isNavHidden = FALSE, $writingDirection = NULL) {
$navPoint = FALSE;
if (isset($navTitle) && isset($navClass)) {
$navPoint = new NavPoint($navTitle, NULL, $navId, $navClass, $isNavHidden, $writingDirection);
$this->addNavPoint($navPoint);
}
if ($this->lastLevel !== NULL) {
$this->currentLevel = $this->lastLevel;
}
return $navPoint;
}
/**
* Step back one chapter level.
*
* Subsequent chapters will be added to this chapters parent level.
*/
function backLevel() {
$this->lastLevel = $this->currentLevel;
$this->currentLevel = $this->currentLevel->getParent();
}
/**
* Step back to the root level.
*
* Subsequent chapters will be added to the rooot NavMap.
*/
function rootLevel() {
$this->lastLevel = $this->currentLevel;
$this->currentLevel = $this->navMap;
}
/**
* Step back to the given level.
* Useful for returning to a previous level from deep within the structure.
* Values below 2 will have the same effect as rootLevel()
*
* @param int $newLevel
*/
function setCurrentLevel($newLevel) {
if ($newLevel <= 1) {
$this->rootLevel();
} else {
while ($this->currentLevel->getLevel() > $newLevel) {
$this->backLevel();
}
}
}
/**
* Get current level count.
* The indentation of the current structure point.
*
* @return current level count;
*/
function getCurrentLevel() {
return $this->currentLevel->getLevel();
}
/**
* Add child NavPoints to current level.
*
* @param NavPoint $navPoint
*/
function addNavPoint($navPoint) {
$this->lastLevel = $this->currentLevel->addNavPoint($navPoint);
}
/**
*
* Enter description here ...
*
* @return NavMap
*/
function getNavMap() {
return $this->navMap;
}
/**
*
* Enter description here ...
*
* @param string $name
* @param string $content
*/
function addMetaEntry($name, $content) {
$name = is_string($name) ? trim($name) : NULL;
$content = is_string($content) ? trim($content) : NULL;
if ($name != NULL && $content != NULL) {
$this->meta[] = array($name => $content);
}
}
/**
*
* Enter description here ...
*
* @return string
*/
function finalize() {
$nav = $this->navMap->finalize();
$ncx = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
if ($this->isEPubVersion2()) {
$ncx .= "<!DOCTYPE ncx PUBLIC \"-//NISO//DTD ncx 2005-1//EN\"\n"
. " \"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd\">\n";
}
$ncx .= "<ncx xmlns=\"http://www.daisy.org/z3986/2005/ncx/\" version=\"2005-1\" xml:lang=\"" . $this->languageCode . "\" dir=\"" . $this->writingDirection . "\">\n"
. "\t<head>\n"
. "\t\t<meta name=\"dtb:uid\" content=\"" . $this->uid . "\" />\n"
. "\t\t<meta name=\"dtb:depth\" content=\"" . $this->navMap->getNavLevels() . "\" />\n"
. "\t\t<meta name=\"dtb:totalPageCount\" content=\"0\" />\n"
. "\t\t<meta name=\"dtb:maxPageNumber\" content=\"0\" />\n";
if (sizeof($this->meta)) {
foreach ($this->meta as $metaEntry) {
list($name, $content) = each($metaEntry);
$ncx .= "\t\t<meta name=\"" . $name . "\" content=\"" . $content . "\" />\n";
}
}
$ncx .= "\t</head>\n\n\t<docTitle>\n\t\t<text>"
. $this->docTitle
. "</text>\n\t</docTitle>\n\n\t<docAuthor>\n\t\t<text>"
. $this->docAuthor
. "</text>\n\t</docAuthor>\n\n"
. $nav;
return $ncx . "</ncx>\n";
}
/**
*
* @param string $title
* @param string $cssFileName
* @return string
*/
function finalizeEPub3($title = "Table of Contents", $cssFileName = NULL) {
$end = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
. "<html xmlns=\"http://www.w3.org/1999/xhtml\"\n"
. " xmlns:epub=\"http://www.idpf.org/2007/ops\"\n"
. " xml:lang=\"" . $this->languageCode . "\" lang=\"" . $this->languageCode . "\" dir=\"" . $this->writingDirection . "\">\n"
. "\t<head>\n"
. "\t\t<title>" . $this->docTitle . "</title>\n"
. "\t\t<meta http-equiv=\"default-style\" content=\"text/html; charset=utf-8\"/>\n";
if ($cssFileName !== NULL) {
$end .= "\t\t<link rel=\"stylesheet\" href=\"" . $cssFileName . "\" type=\"text/css\"/>\n";
}
$end .= "\t</head>\n"
. "\t<body epub:type=\"frontmatter toc\">\n"
. "\t\t<header>\n"
. "\t\t\t<h1>" . $title . "</h1>\n"
. "\t\t</header>\n"
. $this->navMap->finalizeEPub3()
. $this->finalizeEPub3Landmarks()
. "\t</body>\n"
. "</html>\n";
return $end;
}
/**
* Build the references for the ePub 2 toc.
* These are merely reference pages added to the end of the navMap though.
*
* @return string
*/
function finalizeReferences() {
if (isset($this->referencesList) && sizeof($this->referencesList) > 0) {
$this->rootLevel();
$this->subLevel($this->referencesTitle, $this->referencesId, $this->referencesClass);
$refId = 1;
while (list($item, $descriptive) = each($this->referencesOrder)) {
if (array_key_exists($item, $this->referencesList)) {
$name = (empty($this->referencesName[$item]) ? $descriptive : $this->referencesName[$item]);
$navPoint = new NavPoint($name, $this->referencesList[$item], "ref-" . $refId++);
$this->addNavPoint($navPoint);
}
}
}
}
/**
* Build the landmarks for the ePub 3 toc.
* @return string
*/
function finalizeEPub3Landmarks() {
$lm = "";
if (isset($this->referencesList) && sizeof($this->referencesList) > 0) {
$lm = "\t\t\t<nav epub:type=\"landmarks\">\n"
. "\t\t\t\t<h2"
. ($this->writingDirection === EPub::DIRECTION_RIGHT_TO_LEFT ? " dir=\"rtl\"" : "")
. ">" . $this->referencesTitle . "</h2>\n"
. "\t\t\t\t<ol>\n";
$li = "";
while (list($item, $descriptive) = each($this->referencesOrder)) {
if (array_key_exists($item, $this->referencesList)) {
$li .= "\t\t\t\t\t<li><a epub:type=\""
. $item
. "\" href=\"" . $this->referencesList[$item] . "\">"
. (empty($this->referencesName[$item]) ? $descriptive : $this->referencesName[$item])
. "</a></li>\n";
}
}
if (empty($li)) {
return "";
}
$lm .= $li
. "\t\t\t\t</ol>\n"
. "\t\t\t</nav>\n";
}
return $lm;
}
}
/**
* ePub NavMap class
*/
class NavMap {
const _VERSION = 3.00;
private $navPoints = array();
private $navLevels = 0;
private $writingDirection = NULL;
/**
* Class constructor.
*
* @return void
*/
function __construct($writingDirection = NULL) {
$this->setWritingDirection($writingDirection);
}
/**
* Class destructor
*
* @return void
*/
function __destruct() {
unset($this->navPoints, $this->navLevels, $this->writingDirection);
}
/**
* Set the writing direction to be used for this NavPoint.
*
* @param string $writingDirection
*/
function setWritingDirection($writingDirection) {
$this->writingDirection = isset($writingDirection) && is_string($writingDirection) ? trim($writingDirection) : NULL;
}
function getWritingDirection() {
return $this->writingDirection;
}
/**
* Add a navPoint to the root of the NavMap.
*
* @param NavPoint $navPoint
* @return NavMap
*/
function addNavPoint($navPoint) {
if ($navPoint != NULL && is_object($navPoint) && get_class($navPoint) === "NavPoint") {
$navPoint->setParent($this);
if ($navPoint->getWritingDirection() == NULL) {
$navPoint->setWritingDirection($this->writingDirection);
}
$this->navPoints[] = $navPoint;
return $navPoint;
}
return $this;
}
/**
* The final max depth for the "dtb:depth" meta attribute
* Only available after finalize have been called.
*
* @return number
*/
function getNavLevels() {
return $this->navLevels+1;
}
function getLevel() {
return 1;
}
function getParent() {
return $this;
}
/**
* Finalize the navMap, the final max depth for the "dtb:depth" meta attribute can be retrieved with getNavLevels after finalization
*
*/
function finalize() {
$playOrder = 0;
$this->navLevels = 0;
$nav = "\t<navMap>\n";
if (sizeof($this->navPoints) > 0) {
$this->navLevels++;
foreach ($this->navPoints as $navPoint) {
$retLevel = $navPoint->finalize($nav, $playOrder, 0);
if ($retLevel > $this->navLevels) {
$this->navLevels = $retLevel;
}
}
}
return $nav . "\t</navMap>\n";
}
/**
* Finalize the navMap, the final max depth for the "dtb:depth" meta attribute can be retrieved with getNavLevels after finalization
*
*/
function finalizeEPub3() {
$playOrder = 0;
$level = 0;
$this->navLevels = 0;
$nav = "\t\t<nav epub:type=\"toc\" id=\"toc\">\n";
if (sizeof($this->navPoints) > 0) {
$this->navLevels++;
$nav .= str_repeat("\t", $level) . "\t\t\t<ol epub:type=\"list\">\n";
foreach ($this->navPoints as $navPoint) {
$retLevel = $navPoint->finalizeEPub3($nav, $playOrder, 0);
if ($retLevel > $this->navLevels) {
$this->navLevels = $retLevel;
}
}
$nav .= str_repeat("\t", $level) . "\t\t\t</ol>\n";
}
return $nav . "\t\t</nav>\n";
}
}
/**
* ePub NavPoint class
*/
class NavPoint {
const _VERSION = 3.00;
private $label = NULL;
private $contentSrc = NULL;
private $id = NULL;
private $navClass = NULL;
private $isNavHidden = FALSE;
private $navPoints = array();
private $parent = NULL;
/**
* Class constructor.
*
* All three attributes are mandatory, though if ID is set to null (default) the value will be generated.
*
* @param string $label
* @param string $contentSrc
* @param string $id
* @param string $navClass
* @param bool $isNavHidden
* @param string $writingDirection
*/
function __construct($label, $contentSrc = NULL, $id = NULL, $navClass = NULL, $isNavHidden = FALSE, $writingDirection = NULL) {
$this->setLabel($label);
$this->setContentSrc($contentSrc);
$this->setId($id);
$this->setNavClass($navClass);
$this->setNavHidden($isNavHidden);
$this->setWritingDirection($writingDirection);
}
/**
* Class destructor
*
* @return void
*/
function __destruct() {
unset($this->label, $this->contentSrc, $this->id, $this->navClass);
unset($this->isNavHidden, $this->navPoints, $this->parent);
}
/**
* Set the Text label for the NavPoint.
*
* The label is mandatory.
*
* @param string $label
*/
function setLabel($label) {
$this->label = is_string($label) ? trim($label) : NULL;
}
/**
* Get the Text label for the NavPoint.
*
* @return string Label
*/
function getLabel() {
return $this->label;
}
/**
* Set the src reference for the NavPoint.
*
* The src is mandatory for ePub 2.
*
* @param string $contentSrc
*/
function setContentSrc($contentSrc) {
$this->contentSrc = isset($contentSrc) && is_string($contentSrc) ? trim($contentSrc) : NULL;
}
/**
* Get the src reference for the NavPoint.
*
* @return string content src url.
*/
function getContentSrc() {
return $this->contentSrc;
}
/**
* Set the parent for this NavPoint.
*
* @param NavPoint or NavMap $parent
*/
function setParent($parent) {
if ($parent != NULL && is_object($parent) &&
(get_class($parent) === "NavPoint" || get_class($parent) === "NavMap") ) {
$this->parent = $parent;
}
}
/**
* Get the parent to this NavPoint.
*
* @return NavPoint, or NavMap if the parent is the root.
*/
function getParent() {
return $this->parent;
}
/**
* Get the current level. 1 = document root.
*
* @return int level
*/
function getLevel() {
return $this->parent === NULL ? 1 : $this->parent->getLevel()+1;
}
/**
* Set the id for the NavPoint.
*
* The id must be unique, and is mandatory.
*
* @param string $id
*/
function setId($id) {
$this->id = is_string($id) ? trim($id) : NULL;
}
/**
* Set the class to be used for this NavPoint.
*
* @param string $navClass
*/
function setNavClass($navClass) {
$this->navClass = isset($navClass) && is_string($navClass) ? trim($navClass) : NULL;
}
/**
* Set the class to be used for this NavPoint.
*
* @param string $navClass
*/
function setNavHidden($isNavHidden) {
$this->isNavHidden = $isNavHidden === TRUE;
}
/**
* Set the writing direction to be used for this NavPoint.
*
* @param string $writingDirection
*/
function setWritingDirection($writingDirection) {
$this->writingDirection = isset($writingDirection) && is_string($writingDirection) ? trim($writingDirection) : NULL;
}
function getWritingDirection() {
return $this->writingDirection;
}
/**
* Add child NavPoints for multi level NavMaps.
*
* @param NavPoint $navPoint
*/
function addNavPoint($navPoint) {
if ($navPoint != NULL && is_object($navPoint) && get_class($navPoint) === "NavPoint") {
$navPoint->setParent($this);
if ($navPoint->getWritingDirection() == NULL) {
$navPoint->setWritingDirection($this->writingDirection);
}
$this->navPoints[] = $navPoint;
return $navPoint;
}
return $this;
}
/**
*
* Enter description here ...
*
* @param string $nav
* @param int $playOrder
* @param int $level
* @return int
*/
function finalize(&$nav = "", &$playOrder = 0, $level = 0) {
$maxLevel = $level;
$levelAdjust = 0;
if ($this->isNavHidden) {
return $maxLevel;
}
if (isset($this->contentSrc)) {
$playOrder++;
if ($this->id == NULL) {
$this->id = "navpoint-" . $playOrder;
}
$nav .= str_repeat("\t", $level) . "\t\t<navPoint id=\"" . $this->id . "\" playOrder=\"" . $playOrder . "\">\n"
. str_repeat("\t", $level) . "\t\t\t<navLabel>\n"
. str_repeat("\t", $level) . "\t\t\t\t<text>" . $this->label . "</text>\n"
. str_repeat("\t", $level) . "\t\t\t</navLabel>\n"
. str_repeat("\t", $level) . "\t\t\t<content src=\"" . $this->contentSrc . "\" />\n";
} else {
$levelAdjust++;
}
if (sizeof($this->navPoints) > 0) {
$maxLevel++;
foreach ($this->navPoints as $navPoint) {
$retLevel = $navPoint->finalize($nav, $playOrder, ($level+1+$levelAdjust));
if ($retLevel > $maxLevel) {
$maxLevel = $retLevel;
}
}
}
if (isset($this->contentSrc)) {
$nav .= str_repeat("\t", $level) . "\t\t</navPoint>\n";
}
return $maxLevel;
}
/**
*
* Enter description here ...
*
* @param string $nav
* @param int $playOrder
* @param int $level
* @return int
*/
function finalizeEPub3(&$nav = "", &$playOrder = 0, $level = 0, $subLevelClass = NULL, $subLevelHidden = FALSE) {
$maxLevel = $level;
if ($this->id == NULL) {
$this->id = "navpoint-" . $playOrder;
}
$indent = str_repeat("\t", $level) . "\t\t\t\t";
$nav .= $indent . "<li id=\"" . $this->id . "\"";
if (isset($this->writingDirection)) {
$nav .= " dir=\"" . $this->writingDirection . "\"";
}
$nav .= ">\n";
if (isset($this->contentSrc)) {
$nav .= $indent . "\t<a href=\"" . $this->contentSrc . "\">" . $this->label . "</a>\n";
} else {
$nav .= $indent . "\t<span>" . $this->label . "</span>\n";
}
if (sizeof($this->navPoints) > 0) {
$maxLevel++;
$nav .= $indent . "\t<ol epub:type=\"list\"";
if (isset($subLevelClass)) {
$nav .= " class=\"" . $subLevelClass . "\"";
}
if ($subLevelHidden) {
$nav .= " hidden=\"hidden\"";
}
$nav .= ">\n";
foreach ($this->navPoints as $navPoint) {
$retLevel = $navPoint->finalizeEPub3($nav, $playOrder, ($level+2), $subLevelClass, $subLevelHidden);
if ($retLevel > $maxLevel) {
$maxLevel = $retLevel;
}
}
$nav .= $indent . "\t</ol>\n";
}
$nav .= $indent . "</li>\n";
return $maxLevel;
}
}
?>

File diff suppressed because it is too large Load Diff

2438
inc/3rdparty/libraries/PHPePub/EPub.php vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,201 @@
<?php
/**
* Split an HTML file into smaller html files, retaining the formatting and structure for the individual parts.
* What this splitter does is using DOM to try and retain any formatting in the file, including rebuilding the DOM tree for subsequent parts.
* Split size is considered max target size. The actual size is the result of an even split across the resulting files.
*
* @author A. Grandt <php@grandt.com>
* @copyright 2009-2014 A. Grandt
* @license GNU LGPL 2.1
* @link http://www.phpclasses.org/package/6115
* @link https://github.com/Grandt/PHPePub
* @version 3.20
*/
class EPubChapterSplitter {
const VERSION = 3.20;
private $splitDefaultSize = 250000;
private $bookVersion = EPub::BOOK_VERSION_EPUB2;
/**
*
* Enter description here ...
*
* @param unknown_type $ident
*/
function setVersion($bookVersion) {
$this->bookVersion = is_string($bookVersion) ? trim($bookVersion) : EPub::BOOK_VERSION_EPUB2;
}
/**
* Set default chapter target size.
* Default is 250000 bytes, and minimum is 10240 bytes.
*
* @param $size segment size in bytes
* @return void
*/
function setSplitSize($size) {
$this->splitDefaultSize = (int)$size;
if ($size < 10240) {
$this->splitDefaultSize = 10240; // Making the file smaller than 10k is not a good idea.
}
}
/**
* Get the chapter target size.
*
* @return $size
*/
function getSplitSize() {
return $this->splitDefaultSize;
}
/**
* Split $chapter into multiple parts.
*
* The search string can either be a regular string or a PHP PECL Regular Expression pattern as defined here: http://www.php.net/manual/en/pcre.pattern.php
* If the search string is a regular string, the matching will be for lines in the HTML starting with the string given
*
* @param String $chapter XHTML file
* @param Bool $splitOnSearchString Split on chapter boundaries, Splitting on search strings disables the split size check.
* @param String $searchString Chapter string to search for can be fixed text, or a regular expression pattern.
*
* @return array with 1 or more parts
*/
function splitChapter($chapter, $splitOnSearchString = false, $searchString = '/^Chapter\\ /i') {
$chapterData = array();
$isSearchRegexp = $splitOnSearchString && (preg_match('#^(\D|\S|\W).+\1[imsxeADSUXJu]*$#m', $searchString) == 1);
if ($splitOnSearchString && !$isSearchRegexp) {
$searchString = '#^<.+?>' . preg_quote($searchString, '#') . "#";
}
if (!$splitOnSearchString && strlen($chapter) <= $this->splitDefaultSize) {
return array($chapter);
}
$xmlDoc = new DOMDocument();
@$xmlDoc->loadHTML($chapter);
$head = $xmlDoc->getElementsByTagName("head");
$body = $xmlDoc->getElementsByTagName("body");
$htmlPos = stripos($chapter, "<html");
$htmlEndPos = stripos($chapter, ">", $htmlPos);
$newXML = substr($chapter, 0, $htmlEndPos+1) . "\n</html>";
if (strpos(trim($newXML), "<?xml ") === FALSE) {
$newXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" . $newXML;
}
$headerLength = strlen($newXML);
$files = array();
$chapterNames = array();
$domDepth = 0;
$domPath = array();
$domClonedPath = array();
$curFile = $xmlDoc->createDocumentFragment();
$files[] = $curFile;
$curParent = $curFile;
$curSize = 0;
$bodyLen = strlen($xmlDoc->saveXML($body->item(0)));
$headLen = strlen($xmlDoc->saveXML($head->item(0))) + $headerLength;
$partSize = $this->splitDefaultSize - $headLen;
if ($bodyLen > $partSize) {
$parts = ceil($bodyLen / $partSize);
$partSize = ($bodyLen / $parts) - $headLen;
}
$node = $body->item(0)->firstChild;
do {
$nodeData = $xmlDoc->saveXML($node);
$nodeLen = strlen($nodeData);
if ($nodeLen > $partSize && $node->hasChildNodes()) {
$domPath[] = $node;
$domClonedPath[] = $node->cloneNode(false);
$domDepth++;
$node = $node->firstChild;
}
$node2 = $node->nextSibling;
if ($node != null && $node->nodeName != "#text") {
$doSplit = false;
if ($splitOnSearchString) {
$doSplit = preg_match($searchString, $nodeData) == 1;
if ($doSplit) {
$chapterNames[] = trim($nodeData);
}
}
if ($curSize > 0 && ($doSplit || (!$splitOnSearchString && $curSize + $nodeLen > $partSize))) {
$curFile = $xmlDoc->createDocumentFragment();
$files[] = $curFile;
$curParent = $curFile;
if ($domDepth > 0) {
reset($domPath);
reset($domClonedPath);
$oneDomClonedPath = each($domClonedPath);
while ($oneDomClonedPath) {
list($k, $v) = $oneDomClonedPath;
$newParent = $v->cloneNode(false);
$curParent->appendChild($newParent);
$curParent = $newParent;
$oneDomClonedPath = each($domClonedPath);
}
}
$curSize = strlen($xmlDoc->saveXML($curFile));
}
$curParent->appendChild($node->cloneNode(true));
$curSize += $nodeLen;
}
$node = $node2;
while ($node == null && $domDepth > 0) {
$domDepth--;
$node = end($domPath)->nextSibling;
array_pop($domPath);
array_pop($domClonedPath);
$curParent = $curParent->parentNode;
}
} while ($node != null);
$curFile = null;
$curSize = 0;
$xml = new DOMDocument('1.0', $xmlDoc->xmlEncoding);
$xml->lookupPrefix("http://www.w3.org/1999/xhtml");
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
for ($idx = 0; $idx < count($files); $idx++) {
$xml2Doc = new DOMDocument('1.0', $xmlDoc->xmlEncoding);
$xml2Doc->lookupPrefix("http://www.w3.org/1999/xhtml");
$xml2Doc->loadXML($newXML);
$html = $xml2Doc->getElementsByTagName("html")->item(0);
$html->appendChild($xml2Doc->importNode($head->item(0), true));
$body = $xml2Doc->createElement("body");
$html->appendChild($body);
$body->appendChild($xml2Doc->importNode($files[$idx], true));
// force pretty printing and correct formatting, should not be needed, but it is.
$xml->loadXML($xml2Doc->saveXML());
$doc = $xml->saveXML();
if ($this->bookVersion === EPub::BOOK_VERSION_EPUB3) {
$doc = preg_replace('#^\s*<!DOCTYPE\ .+?>\s*#im', '', $doc);
}
$chapterData[$splitOnSearchString ? $chapterNames[$idx] : $idx] = $doc;
}
return $chapterData;
}
}
?>

View File

@ -0,0 +1,92 @@
<?php
/**
* Simple log line aggregator.
*
* @author A. Grandt <php@grandt.com>
* @copyright 2012-2013 A. Grandt
* @license GNU LGPL, Attribution required for commercial implementations, requested for everything else.
* @version 1.00
*/
class Logger {
const VERSION = 1.00;
private $log = "";
private $tStart;
private $tLast;
private $name = NULL;
private $isLogging = FALSE;
private $isDebugging = FALSE;
/**
* Class constructor.
*
* @return void
*/
function __construct($name = NULL, $isLogging = FALSE) {
if ($name === NULL) {
$this->name = "";
} else {
$this->name = $name . " : ";
}
$this->isLogging = $isLogging;
$this->start();
}
/**
* Class destructor
*
* @return void
* @TODO make sure elements in the destructor match the current class elements
*/
function __destruct() {
unset($this->log);
}
function start() {
/* Prepare Logging. Just in case it's used. later */
if ($this->isLogging) {
$this->tStart = gettimeofday();
$this->tLast = $this->tStart;
$this->log = "<h1>Log: " . $this->name . "</h1>\n<pre>Started: " . gmdate("D, d M Y H:i:s T", $this->tStart['sec']) . "\n &#916; Start ; &#916; Last ;";
$this->logLine("Start");
}
}
function dumpInstalledModules() {
if ($this->isLogging) {
$isCurlInstalled = extension_loaded('curl') && function_exists('curl_version');
$isGdInstalled = extension_loaded('gd') && function_exists('gd_info');
$isExifInstalled = extension_loaded('exif') && function_exists('exif_imagetype');
$isFileGetContentsInstalled = function_exists('file_get_contents');
$isFileGetContentsExtInstalled = $isFileGetContentsInstalled && ini_get('allow_url_fopen');
$this->logLine("isCurlInstalled...............: " . ($isCurlInstalled ? "Yes" : "No"));
$this->logLine("isGdInstalled.................: " . ($isGdInstalled ? "Yes" : "No"));
$this->logLine("isExifInstalled...............: " . ($isExifInstalled ? "Yes" : "No"));
$this->logLine("isFileGetContentsInstalled....: " . ($isFileGetContentsInstalled ? "Yes" : "No"));
$this->logLine("isFileGetContentsExtInstalled.: " . ($isFileGetContentsExtInstalled ? "Yes" : "No"));
}
}
function logLine($line) {
if ($this->isLogging) {
$tTemp = gettimeofday();
$tS = $this->tStart['sec'] + (((int)($this->tStart['usec']/100))/10000);
$tL = $this->tLast['sec'] + (((int)($this->tLast['usec']/100))/10000);
$tT = $tTemp['sec'] + (((int)($tTemp['usec']/100))/10000);
$logline = sprintf("\n+%08.04f; +%08.04f; ", ($tT-$tS), ($tT-$tL)) . $this->name . $line;
$this->log .= $logline;
$this->tLast = $tTemp;
if ($this->isDebugging) {
echo "<pre>" . $logline . "\n</pre>\n";
}
}
}
function getLog() {
return $this->log;
}
}
?>

818
inc/3rdparty/libraries/PHPePub/Zip.php vendored Normal file
View File

@ -0,0 +1,818 @@
<?php
/**
* Class to create and manage a Zip file.
*
* Initially inspired by CreateZipFile by Rochak Chauhan www.rochakchauhan.com (http://www.phpclasses.org/browse/package/2322.html)
* and
* http://www.pkware.com/documents/casestudies/APPNOTE.TXT Zip file specification.
*
* License: GNU LGPL, Attribution required for commercial implementations, requested for everything else.
*
* @author A. Grandt <php@grandt.com>
* @copyright 2009-2014 A. Grandt
* @license GNU LGPL 2.1
* @link http://www.phpclasses.org/package/6110
* @link https://github.com/Grandt/PHPZip
* @version 1.60
*/
class Zip {
const VERSION = 1.60;
const ZIP_LOCAL_FILE_HEADER = "\x50\x4b\x03\x04"; // Local file header signature
const ZIP_CENTRAL_FILE_HEADER = "\x50\x4b\x01\x02"; // Central file header signature
const ZIP_END_OF_CENTRAL_DIRECTORY = "\x50\x4b\x05\x06\x00\x00\x00\x00"; //end of Central directory record
const EXT_FILE_ATTR_DIR = 010173200020; // Permission 755 drwxr-xr-x = (((S_IFDIR | 0755) << 16) | S_DOS_D);
const EXT_FILE_ATTR_FILE = 020151000040; // Permission 644 -rw-r--r-- = (((S_IFREG | 0644) << 16) | S_DOS_A);
const ATTR_VERSION_TO_EXTRACT = "\x14\x00"; // Version needed to extract
const ATTR_MADE_BY_VERSION = "\x1E\x03"; // Made By Version
// Unix file types
const S_IFIFO = 0010000; // named pipe (fifo)
const S_IFCHR = 0020000; // character special
const S_IFDIR = 0040000; // directory
const S_IFBLK = 0060000; // block special
const S_IFREG = 0100000; // regular
const S_IFLNK = 0120000; // symbolic link
const S_IFSOCK = 0140000; // socket
// setuid/setgid/sticky bits, the same as for chmod:
const S_ISUID = 0004000; // set user id on execution
const S_ISGID = 0002000; // set group id on execution
const S_ISTXT = 0001000; // sticky bit
// And of course, the other 12 bits are for the permissions, the same as for chmod:
// When addding these up, you can also just write the permissions as a simgle octal number
// ie. 0755. The leading 0 specifies octal notation.
const S_IRWXU = 0000700; // RWX mask for owner
const S_IRUSR = 0000400; // R for owner
const S_IWUSR = 0000200; // W for owner
const S_IXUSR = 0000100; // X for owner
const S_IRWXG = 0000070; // RWX mask for group
const S_IRGRP = 0000040; // R for group
const S_IWGRP = 0000020; // W for group
const S_IXGRP = 0000010; // X for group
const S_IRWXO = 0000007; // RWX mask for other
const S_IROTH = 0000004; // R for other
const S_IWOTH = 0000002; // W for other
const S_IXOTH = 0000001; // X for other
const S_ISVTX = 0001000; // save swapped text even after use
// Filetype, sticky and permissions are added up, and shifted 16 bits left BEFORE adding the DOS flags.
// DOS file type flags, we really only use the S_DOS_D flag.
const S_DOS_A = 0000040; // DOS flag for Archive
const S_DOS_D = 0000020; // DOS flag for Directory
const S_DOS_V = 0000010; // DOS flag for Volume
const S_DOS_S = 0000004; // DOS flag for System
const S_DOS_H = 0000002; // DOS flag for Hidden
const S_DOS_R = 0000001; // DOS flag for Read Only
private $zipMemoryThreshold = 1048576; // Autocreate tempfile if the zip data exceeds 1048576 bytes (1 MB)
private $zipData = NULL;
private $zipFile = NULL;
private $zipComment = NULL;
private $cdRec = array(); // central directory
private $offset = 0;
private $isFinalized = FALSE;
private $addExtraField = TRUE;
private $streamChunkSize = 65536;
private $streamFilePath = NULL;
private $streamTimestamp = NULL;
private $streamFileComment = NULL;
private $streamFile = NULL;
private $streamData = NULL;
private $streamFileLength = 0;
private $streamExtFileAttr = null;
/**
* Constructor.
*
* @param boolean $useZipFile Write temp zip data to tempFile? Default FALSE
*/
function __construct($useZipFile = FALSE) {
if ($useZipFile) {
$this->zipFile = tmpfile();
} else {
$this->zipData = "";
}
}
function __destruct() {
if (is_resource($this->zipFile)) {
fclose($this->zipFile);
}
$this->zipData = NULL;
}
/**
* Extra fields on the Zip directory records are Unix time codes needed for compatibility on the default Mac zip archive tool.
* These are enabled as default, as they do no harm elsewhere and only add 26 bytes per file added.
*
* @param bool $setExtraField TRUE (default) will enable adding of extra fields, anything else will disable it.
*/
function setExtraField($setExtraField = TRUE) {
$this->addExtraField = ($setExtraField === TRUE);
}
/**
* Set Zip archive comment.
*
* @param string $newComment New comment. NULL to clear.
* @return bool $success
*/
public function setComment($newComment = NULL) {
if ($this->isFinalized) {
return FALSE;
}
$this->zipComment = $newComment;
return TRUE;
}
/**
* Set zip file to write zip data to.
* This will cause all present and future data written to this class to be written to this file.
* This can be used at any time, even after the Zip Archive have been finalized. Any previous file will be closed.
* Warning: If the given file already exists, it will be overwritten.
*
* @param string $fileName
* @return bool $success
*/
public function setZipFile($fileName) {
if (is_file($fileName)) {
unlink($fileName);
}
$fd=fopen($fileName, "x+b");
if (is_resource($this->zipFile)) {
rewind($this->zipFile);
while (!feof($this->zipFile)) {
fwrite($fd, fread($this->zipFile, $this->streamChunkSize));
}
fclose($this->zipFile);
} else {
fwrite($fd, $this->zipData);
$this->zipData = NULL;
}
$this->zipFile = $fd;
return TRUE;
}
/**
* Add an empty directory entry to the zip archive.
* Basically this is only used if an empty directory is added.
*
* @param string $directoryPath Directory Path and name to be added to the archive.
* @param int $timestamp (Optional) Timestamp for the added directory, if omitted or set to 0, the current time will be used.
* @param string $fileComment (Optional) Comment to be added to the archive for this directory. To use fileComment, timestamp must be given.
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
* @return bool $success
*/
public function addDirectory($directoryPath, $timestamp = 0, $fileComment = NULL, $extFileAttr = self::EXT_FILE_ATTR_DIR) {
if ($this->isFinalized) {
return FALSE;
}
$directoryPath = str_replace("\\", "/", $directoryPath);
$directoryPath = rtrim($directoryPath, "/");
if (strlen($directoryPath) > 0) {
$this->buildZipEntry($directoryPath.'/', $fileComment, "\x00\x00", "\x00\x00", $timestamp, "\x00\x00\x00\x00", 0, 0, $extFileAttr);
return TRUE;
}
return FALSE;
}
/**
* Add a file to the archive at the specified location and file name.
*
* @param string $data File data.
* @param string $filePath Filepath and name to be used in the archive.
* @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
* @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
* @param bool $compress (Optional) Compress file, if set to FALSE the file will only be stored. Default TRUE.
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
* @return bool $success
*/
public function addFile($data, $filePath, $timestamp = 0, $fileComment = NULL, $compress = TRUE, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if ($this->isFinalized) {
return FALSE;
}
if (is_resource($data) && get_resource_type($data) == "stream") {
$this->addLargeFile($data, $filePath, $timestamp, $fileComment, $extFileAttr);
return FALSE;
}
$gzData = "";
$gzType = "\x08\x00"; // Compression type 8 = deflate
$gpFlags = "\x00\x00"; // General Purpose bit flags for compression type 8 it is: 0=Normal, 1=Maximum, 2=Fast, 3=super fast compression.
$dataLength = strlen($data);
$fileCRC32 = pack("V", crc32($data));
if ($compress) {
$gzTmp = gzcompress($data);
$gzData = substr(substr($gzTmp, 0, strlen($gzTmp) - 4), 2); // gzcompress adds a 2 byte header and 4 byte CRC we can't use.
// The 2 byte header does contain useful data, though in this case the 2 parameters we'd be interrested in will always be 8 for compression type, and 2 for General purpose flag.
$gzLength = strlen($gzData);
} else {
$gzLength = $dataLength;
}
if ($gzLength >= $dataLength) {
$gzLength = $dataLength;
$gzData = $data;
$gzType = "\x00\x00"; // Compression type 0 = stored
$gpFlags = "\x00\x00"; // Compression type 0 = stored
}
if (!is_resource($this->zipFile) && ($this->offset + $gzLength) > $this->zipMemoryThreshold) {
$this->zipflush();
}
$this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr);
$this->zipwrite($gzData);
return TRUE;
}
/**
* Add the content to a directory.
*
* @author Adam Schmalhofer <Adam.Schmalhofer@gmx.de>
* @author A. Grandt
*
* @param string $realPath Path on the file system.
* @param string $zipPath Filepath and name to be used in the archive.
* @param bool $recursive Add content recursively, default is TRUE.
* @param bool $followSymlinks Follow and add symbolic links, if they are accessible, default is TRUE.
* @param array &$addedFiles Reference to the added files, this is used to prevent duplicates, efault is an empty array.
* If you start the function by parsing an array, the array will be populated with the realPath
* and zipPath kay/value pairs added to the archive by the function.
* @param bool $overrideFilePermissions Force the use of the file/dir permissions set in the $extDirAttr
* and $extFileAttr parameters.
* @param int $extDirAttr Permissions for directories.
* @param int $extFileAttr Permissions for files.
*/
public function addDirectoryContent($realPath, $zipPath, $recursive = TRUE, $followSymlinks = TRUE, &$addedFiles = array(),
$overrideFilePermissions = FALSE, $extDirAttr = self::EXT_FILE_ATTR_DIR, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if (file_exists($realPath) && !isset($addedFiles[realpath($realPath)])) {
if (is_dir($realPath)) {
if ($overrideFilePermissions) {
$this->addDirectory($zipPath, 0, null, $extDirAttr);
} else {
$this->addDirectory($zipPath, 0, null, self::getFileExtAttr($realPath));
}
}
$addedFiles[realpath($realPath)] = $zipPath;
$iter = new DirectoryIterator($realPath);
foreach ($iter as $file) {
if ($file->isDot()) {
continue;
}
$newRealPath = $file->getPathname();
$newZipPath = self::pathJoin($zipPath, $file->getFilename());
if (file_exists($newRealPath) && ($followSymlinks === TRUE || !is_link($newRealPath))) {
if ($file->isFile()) {
$addedFiles[realpath($newRealPath)] = $newZipPath;
if ($overrideFilePermissions) {
$this->addLargeFile($newRealPath, $newZipPath, 0, null, $extFileAttr);
} else {
$this->addLargeFile($newRealPath, $newZipPath, 0, null, self::getFileExtAttr($newRealPath));
}
} else if ($recursive === TRUE) {
$this->addDirectoryContent($newRealPath, $newZipPath, $recursive, $followSymlinks, $addedFiles, $overrideFilePermissions, $extDirAttr, $extFileAttr);
} else {
if ($overrideFilePermissions) {
$this->addDirectory($zipPath, 0, null, $extDirAttr);
} else {
$this->addDirectory($zipPath, 0, null, self::getFileExtAttr($newRealPath));
}
}
}
}
}
}
/**
* Add a file to the archive at the specified location and file name.
*
* @param string $dataFile File name/path.
* @param string $filePath Filepath and name to be used in the archive.
* @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
* @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
* @return bool $success
*/
public function addLargeFile($dataFile, $filePath, $timestamp = 0, $fileComment = NULL, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if ($this->isFinalized) {
return FALSE;
}
if (is_string($dataFile) && is_file($dataFile)) {
$this->processFile($dataFile, $filePath, $timestamp, $fileComment, $extFileAttr);
} else if (is_resource($dataFile) && get_resource_type($dataFile) == "stream") {
$fh = $dataFile;
$this->openStream($filePath, $timestamp, $fileComment, $extFileAttr);
while (!feof($fh)) {
$this->addStreamData(fread($fh, $this->streamChunkSize));
}
$this->closeStream($this->addExtraField);
}
return TRUE;
}
/**
* Create a stream to be used for large entries.
*
* @param string $filePath Filepath and name to be used in the archive.
* @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
* @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
* @return bool $success
*/
public function openStream($filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if (!function_exists('sys_get_temp_dir')) {
die ("ERROR: Zip " . self::VERSION . " requires PHP version 5.2.1 or above if large files are used.");
}
if ($this->isFinalized) {
return FALSE;
}
$this->zipflush();
if (strlen($this->streamFilePath) > 0) {
$this->closeStream();
}
$this->streamFile = tempnam(sys_get_temp_dir(), 'Zip');
$this->streamData = fopen($this->streamFile, "wb");
$this->streamFilePath = $filePath;
$this->streamTimestamp = $timestamp;
$this->streamFileComment = $fileComment;
$this->streamFileLength = 0;
$this->streamExtFileAttr = $extFileAttr;
return TRUE;
}
/**
* Add data to the open stream.
*
* @param string $data
* @return mixed length in bytes added or FALSE if the archive is finalized or there are no open stream.
*/
public function addStreamData($data) {
if ($this->isFinalized || strlen($this->streamFilePath) == 0) {
return FALSE;
}
$length = fwrite($this->streamData, $data, strlen($data));
if ($length != strlen($data)) {
die ("<p>Length mismatch</p>\n");
}
$this->streamFileLength += $length;
return $length;
}
/**
* Close the current stream.
*
* @return bool $success
*/
public function closeStream() {
if ($this->isFinalized || strlen($this->streamFilePath) == 0) {
return FALSE;
}
fflush($this->streamData);
fclose($this->streamData);
$this->processFile($this->streamFile, $this->streamFilePath, $this->streamTimestamp, $this->streamFileComment, $this->streamExtFileAttr);
$this->streamData = null;
$this->streamFilePath = null;
$this->streamTimestamp = null;
$this->streamFileComment = null;
$this->streamFileLength = 0;
$this->streamExtFileAttr = null;
// Windows is a little slow at times, so a millisecond later, we can unlink this.
unlink($this->streamFile);
$this->streamFile = null;
return TRUE;
}
private function processFile($dataFile, $filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if ($this->isFinalized) {
return FALSE;
}
$tempzip = tempnam(sys_get_temp_dir(), 'ZipStream');
$zip = new ZipArchive;
if ($zip->open($tempzip) === TRUE) {
$zip->addFile($dataFile, 'file');
$zip->close();
}
$file_handle = fopen($tempzip, "rb");
$stats = fstat($file_handle);
$eof = $stats['size']-72;
fseek($file_handle, 6);
$gpFlags = fread($file_handle, 2);
$gzType = fread($file_handle, 2);
fread($file_handle, 4);
$fileCRC32 = fread($file_handle, 4);
$v = unpack("Vval", fread($file_handle, 4));
$gzLength = $v['val'];
$v = unpack("Vval", fread($file_handle, 4));
$dataLength = $v['val'];
$this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr);
fseek($file_handle, 34);
$pos = 34;
while (!feof($file_handle) && $pos < $eof) {
$datalen = $this->streamChunkSize;
if ($pos + $this->streamChunkSize > $eof) {
$datalen = $eof-$pos;
}
$data = fread($file_handle, $datalen);
$pos += $datalen;
$this->zipwrite($data);
}
fclose($file_handle);
unlink($tempzip);
}
/**
* Close the archive.
* A closed archive can no longer have new files added to it.
*
* @return bool $success
*/
public function finalize() {
if (!$this->isFinalized) {
if (strlen($this->streamFilePath) > 0) {
$this->closeStream();
}
$cd = implode("", $this->cdRec);
$cdRecSize = pack("v", sizeof($this->cdRec));
$cdRec = $cd . self::ZIP_END_OF_CENTRAL_DIRECTORY
. $cdRecSize . $cdRecSize
. pack("VV", strlen($cd), $this->offset);
if (!empty($this->zipComment)) {
$cdRec .= pack("v", strlen($this->zipComment)) . $this->zipComment;
} else {
$cdRec .= "\x00\x00";
}
$this->zipwrite($cdRec);
$this->isFinalized = TRUE;
$this->cdRec = NULL;
return TRUE;
}
return FALSE;
}
/**
* Get the handle ressource for the archive zip file.
* If the zip haven't been finalized yet, this will cause it to become finalized
*
* @return zip file handle
*/
public function getZipFile() {
if (!$this->isFinalized) {
$this->finalize();
}
$this->zipflush();
rewind($this->zipFile);
return $this->zipFile;
}
/**
* Get the zip file contents
* If the zip haven't been finalized yet, this will cause it to become finalized
*
* @return zip data
*/
public function getZipData() {
if (!$this->isFinalized) {
$this->finalize();
}
if (!is_resource($this->zipFile)) {
return $this->zipData;
} else {
rewind($this->zipFile);
$filestat = fstat($this->zipFile);
return fread($this->zipFile, $filestat['size']);
}
}
/**
* Send the archive as a zip download
*
* @param String $fileName The name of the Zip archive, in ISO-8859-1 (or ASCII) encoding, ie. "archive.zip". Optional, defaults to NULL, which means that no ISO-8859-1 encoded file name will be specified.
* @param String $contentType Content mime type. Optional, defaults to "application/zip".
* @param String $utf8FileName The name of the Zip archive, in UTF-8 encoding. Optional, defaults to NULL, which means that no UTF-8 encoded file name will be specified.
* @param bool $inline Use Content-Disposition with "inline" instead of "attached". Optional, defaults to FALSE.
* @return bool $success
*/
function sendZip($fileName = null, $contentType = "application/zip", $utf8FileName = null, $inline = false) {
if (!$this->isFinalized) {
$this->finalize();
}
$headerFile = null;
$headerLine = null;
if (!headers_sent($headerFile, $headerLine) or die("<p><strong>Error:</strong> Unable to send file $fileName. HTML Headers have already been sent from <strong>$headerFile</strong> in line <strong>$headerLine</strong></p>")) {
if ((ob_get_contents() === FALSE || ob_get_contents() == '') or die("\n<p><strong>Error:</strong> Unable to send file <strong>$fileName</strong>. Output buffer contains the following text (typically warnings or errors):<br>" . htmlentities(ob_get_contents()) . "</p>")) {
if (ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'Off');
}
header("Pragma: public");
header("Last-Modified: " . gmdate("D, d M Y H:i:s T"));
header("Expires: 0");
header("Accept-Ranges: bytes");
header("Connection: close");
header("Content-Type: " . $contentType);
$cd = "Content-Disposition: ";
if ($inline) {
$cd .= "inline";
} else{
$cd .= "attached";
}
if ($fileName) {
$cd .= '; filename="' . $fileName . '"';
}
if ($utf8FileName) {
$cd .= "; filename*=UTF-8''" . rawurlencode($utf8FileName);
}
header($cd);
header("Content-Length: ". $this->getArchiveSize());
if (!is_resource($this->zipFile)) {
echo $this->zipData;
} else {
rewind($this->zipFile);
while (!feof($this->zipFile)) {
echo fread($this->zipFile, $this->streamChunkSize);
}
}
}
return TRUE;
}
return FALSE;
}
/**
* Return the current size of the archive
*
* @return $size Size of the archive
*/
public function getArchiveSize() {
if (!is_resource($this->zipFile)) {
return strlen($this->zipData);
}
$filestat = fstat($this->zipFile);
return $filestat['size'];
}
/**
* Calculate the 2 byte dostime used in the zip entries.
*
* @param int $timestamp
* @return 2-byte encoded DOS Date
*/
private function getDosTime($timestamp = 0) {
$timestamp = (int)$timestamp;
$oldTZ = @date_default_timezone_get();
date_default_timezone_set('UTC');
$date = ($timestamp == 0 ? getdate() : getdate($timestamp));
date_default_timezone_set($oldTZ);
if ($date["year"] >= 1980) {
return pack("V", (($date["mday"] + ($date["mon"] << 5) + (($date["year"]-1980) << 9)) << 16) |
(($date["seconds"] >> 1) + ($date["minutes"] << 5) + ($date["hours"] << 11)));
}
return "\x00\x00\x00\x00";
}
/**
* Build the Zip file structures
*
* @param string $filePath
* @param string $fileComment
* @param string $gpFlags
* @param string $gzType
* @param int $timestamp
* @param string $fileCRC32
* @param int $gzLength
* @param int $dataLength
* @param int $extFileAttr Use self::EXT_FILE_ATTR_FILE for files, self::EXT_FILE_ATTR_DIR for Directories.
*/
private function buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr) {
$filePath = str_replace("\\", "/", $filePath);
$fileCommentLength = (empty($fileComment) ? 0 : strlen($fileComment));
$timestamp = (int)$timestamp;
$timestamp = ($timestamp == 0 ? time() : $timestamp);
$dosTime = $this->getDosTime($timestamp);
$tsPack = pack("V", $timestamp);
$ux = "\x75\x78\x0B\x00\x01\x04\xE8\x03\x00\x00\x04\x00\x00\x00\x00";
if (!isset($gpFlags) || strlen($gpFlags) != 2) {
$gpFlags = "\x00\x00";
}
$isFileUTF8 = mb_check_encoding($filePath, "UTF-8") && !mb_check_encoding($filePath, "ASCII");
$isCommentUTF8 = !empty($fileComment) && mb_check_encoding($fileComment, "UTF-8") && !mb_check_encoding($fileComment, "ASCII");
if ($isFileUTF8 || $isCommentUTF8) {
$flag = 0;
$gpFlagsV = unpack("vflags", $gpFlags);
if (isset($gpFlagsV['flags'])) {
$flag = $gpFlagsV['flags'];
}
$gpFlags = pack("v", $flag | (1 << 11));
}
$header = $gpFlags . $gzType . $dosTime. $fileCRC32
. pack("VVv", $gzLength, $dataLength, strlen($filePath)); // File name length
$zipEntry = self::ZIP_LOCAL_FILE_HEADER;
$zipEntry .= self::ATTR_VERSION_TO_EXTRACT;
$zipEntry .= $header;
$zipEntry .= pack("v", ($this->addExtraField ? 28 : 0)); // Extra field length
$zipEntry .= $filePath; // FileName
// Extra fields
if ($this->addExtraField) {
$zipEntry .= "\x55\x54\x09\x00\x03" . $tsPack . $tsPack . $ux;
}
$this->zipwrite($zipEntry);
$cdEntry = self::ZIP_CENTRAL_FILE_HEADER;
$cdEntry .= self::ATTR_MADE_BY_VERSION;
$cdEntry .= ($dataLength === 0 ? "\x0A\x00" : self::ATTR_VERSION_TO_EXTRACT);
$cdEntry .= $header;
$cdEntry .= pack("v", ($this->addExtraField ? 24 : 0)); // Extra field length
$cdEntry .= pack("v", $fileCommentLength); // File comment length
$cdEntry .= "\x00\x00"; // Disk number start
$cdEntry .= "\x00\x00"; // internal file attributes
$cdEntry .= pack("V", $extFileAttr); // External file attributes
$cdEntry .= pack("V", $this->offset); // Relative offset of local header
$cdEntry .= $filePath; // FileName
// Extra fields
if ($this->addExtraField) {
$cdEntry .= "\x55\x54\x05\x00\x03" . $tsPack . $ux;
}
if (!empty($fileComment)) {
$cdEntry .= $fileComment; // Comment
}
$this->cdRec[] = $cdEntry;
$this->offset += strlen($zipEntry) + $gzLength;
}
private function zipwrite($data) {
if (!is_resource($this->zipFile)) {
$this->zipData .= $data;
} else {
fwrite($this->zipFile, $data);
fflush($this->zipFile);
}
}
private function zipflush() {
if (!is_resource($this->zipFile)) {
$this->zipFile = tmpfile();
fwrite($this->zipFile, $this->zipData);
$this->zipData = NULL;
}
}
/**
* Join $file to $dir path, and clean up any excess slashes.
*
* @param string $dir
* @param string $file
*/
public static function pathJoin($dir, $file) {
if (empty($dir) || empty($file)) {
return self::getRelativePath($dir . $file);
}
return self::getRelativePath($dir . '/' . $file);
}
/**
* Clean up a path, removing any unnecessary elements such as /./, // or redundant ../ segments.
* If the path starts with a "/", it is deemed an absolute path and any /../ in the beginning is stripped off.
* The returned path will not end in a "/".
*
* Sometimes, when a path is generated from multiple fragments,
* you can get something like "../data/html/../images/image.jpeg"
* This will normalize that example path to "../data/images/image.jpeg"
*
* @param string $path The path to clean up
* @return string the clean path
*/
public static function getRelativePath($path) {
$path = preg_replace("#/+\.?/+#", "/", str_replace("\\", "/", $path));
$dirs = explode("/", rtrim(preg_replace('#^(?:\./)+#', '', $path), '/'));
$offset = 0;
$sub = 0;
$subOffset = 0;
$root = "";
if (empty($dirs[0])) {
$root = "/";
$dirs = array_splice($dirs, 1);
} else if (preg_match("#[A-Za-z]:#", $dirs[0])) {
$root = strtoupper($dirs[0]) . "/";
$dirs = array_splice($dirs, 1);
}
$newDirs = array();
foreach ($dirs as $dir) {
if ($dir !== "..") {
$subOffset--;
$newDirs[++$offset] = $dir;
} else {
$subOffset++;
if (--$offset < 0) {
$offset = 0;
if ($subOffset > $sub) {
$sub++;
}
}
}
}
if (empty($root)) {
$root = str_repeat("../", $sub);
}
return $root . implode("/", array_slice($newDirs, 0, $offset));
}
/**
* Create the file permissions for a file or directory, for use in the extFileAttr parameters.
*
* @param int $owner Unix permisions for owner (octal from 00 to 07)
* @param int $group Unix permisions for group (octal from 00 to 07)
* @param int $other Unix permisions for others (octal from 00 to 07)
* @param bool $isFile
* @return EXTRERNAL_REF field.
*/
public static function generateExtAttr($owner = 07, $group = 05, $other = 05, $isFile = true) {
$fp = $isFile ? self::S_IFREG : self::S_IFDIR;
$fp |= (($owner & 07) << 6) | (($group & 07) << 3) | ($other & 07);
return ($fp << 16) | ($isFile ? self::S_DOS_A : self::S_DOS_D);
}
/**
* Get the file permissions for a file or directory, for use in the extFileAttr parameters.
*
* @param string $filename
* @return external ref field, or FALSE if the file is not found.
*/
public static function getFileExtAttr($filename) {
if (file_exists($filename)) {
$fp = fileperms($filename) << 16;
return $fp | (is_dir($filename) ? self::S_DOS_D : self::S_DOS_A);
}
return FALSE;
}
}
?>

View File

@ -0,0 +1,31 @@
DrUUID RFC4122 library for PHP5
by J. King (http://jkingweb.ca/)
Licensed under MIT license
See http://jkingweb.ca/code/php/lib.uuid/
for documentation
Last revised 2010-02-15
Copyright (c) 2009 J. King
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,314 @@
<?php
/*
DrUUID RFC4122 library for PHP5
by J. King (http://jkingweb.ca/)
Licensed under MIT license
See http://jkingweb.ca/code/php/lib.uuid/
for documentation
Last revised 2010-02-15
*/
/*
Copyright (c) 2009 J. King
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
class UUID {
const MD5 = 3;
const SHA1 = 5;
const clearVer = 15; // 00001111 Clears all bits of version byte with AND
const clearVar = 63; // 00111111 Clears all relevant bits of variant byte with AND
const varRes = 224; // 11100000 Variant reserved for future use
const varMS = 192; // 11000000 Microsft GUID variant
const varRFC = 128; // 10000000 The RFC 4122 variant (this variant)
const varNCS = 0; // 00000000 The NCS compatibility variant
const version1 = 16; // 00010000
const version3 = 48; // 00110000
const version4 = 64; // 01000000
const version5 = 80; // 01010000
const interval = 0x01b21dd213814000; // Time (in 100ns steps) between the start of the UTC and Unix epochs
const nsDNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
const nsURL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
const nsOID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8';
const nsX500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8';
protected static $randomFunc = 'randomTwister';
protected static $randomSource = NULL;
//instance properties
protected $bytes;
protected $hex;
protected $string;
protected $urn;
protected $version;
protected $variant;
protected $node;
protected $time;
public static function mint($ver = 1, $node = NULL, $ns = NULL) {
/* Create a new UUID based on provided data. */
switch((int) $ver) {
case 1:
return new self(self::mintTime($node));
case 2:
// Version 2 is not supported
throw new UUIDException("Version 2 is unsupported.");
case 3:
return new self(self::mintName(self::MD5, $node, $ns));
case 4:
return new self(self::mintRand());
case 5:
return new self(self::mintName(self::SHA1, $node, $ns));
default:
throw new UUIDException("Selected version is invalid or unsupported.");
}
}
public static function import($uuid) {
/* Import an existing UUID. */
return new self(self::makeBin($uuid, 16));
}
public static function compare($a, $b) {
/* Compares the binary representations of two UUIDs.
The comparison will return true if they are bit-exact,
or if neither is valid. */
if (self::makeBin($a, 16)==self::makeBin($b, 16)) {
return TRUE;
} else {
return FALSE;
}
}
public function __toString() {
return $this->string;
}
public function __get($var) {
switch($var) {
case "bytes":
return $this->bytes;
case "hex":
return bin2hex($this->bytes);
case "string":
return $this->__toString();
case "urn":
return "urn:uuid:".$this->__toString();
case "version":
return ord($this->bytes[6]) >> 4;
case "variant":
$byte = ord($this->bytes[8]);
if ($byte >= self::varRes) {
return 3;
}
if ($byte >= self::varMS) {
return 2;
}
if ($byte >= self::varRFC) {
return 1;
}
return 0;
case "node":
if (ord($this->bytes[6])>>4==1) {
return bin2hex(substr($this->bytes,10));
} else {
return NULL;
}
case "time":
if (ord($this->bytes[6])>>4==1) {
// Restore contiguous big-endian byte order
$time = bin2hex($this->bytes[6].$this->bytes[7].$this->bytes[4].$this->bytes[5].$this->bytes[0].$this->bytes[1].$this->bytes[2].$this->bytes[3]);
// Clear version flag
$time[0] = "0";
// Do some reverse arithmetic to get a Unix timestamp
$time = (hexdec($time) - self::interval) / 10000000;
return $time;
} else {
return NULL;
}
default:
return NULL;
}
}
protected function __construct($uuid) {
if (strlen($uuid) != 16) {
throw new UUIDException("Input must be a 128-bit integer.");
}
$this->bytes = $uuid;
// Optimize the most common use
$this->string =
bin2hex(substr($uuid,0,4))."-".
bin2hex(substr($uuid,4,2))."-".
bin2hex(substr($uuid,6,2))."-".
bin2hex(substr($uuid,8,2))."-".
bin2hex(substr($uuid,10,6));
}
protected static function mintTime($node = NULL) {
/* Generates a Version 1 UUID.
These are derived from the time at which they were generated. */
// Get time since Gregorian calendar reform in 100ns intervals
// This is exceedingly difficult because of PHP's (and pack()'s)
// integer size limits.
// Note that this will never be more accurate than to the microsecond.
$time = microtime(1) * 10000000 + self::interval;
// Convert to a string representation
$time = sprintf("%F", $time);
preg_match("/^\d+/", $time, $time); //strip decimal point
// And now to a 64-bit binary representation
$time = base_convert($time[0], 10, 16);
$time = pack("H*", str_pad($time, 16, "0", STR_PAD_LEFT));
// Reorder bytes to their proper locations in the UUID
$uuid = $time[4].$time[5].$time[6].$time[7].$time[2].$time[3].$time[0].$time[1];
// Generate a random clock sequence
$uuid .= self::randomBytes(2);
// set variant
$uuid[8] = chr(ord($uuid[8]) & self::clearVar | self::varRFC);
// set version
$uuid[6] = chr(ord($uuid[6]) & self::clearVer | self::version1);
// Set the final 'node' parameter, a MAC address
if ($node) {
$node = self::makeBin($node, 6);
}
if (!$node) {
// If no node was provided or if the node was invalid,
// generate a random MAC address and set the multicast bit
$node = self::randomBytes(6);
$node[0] = pack("C", ord($node[0]) | 1);
}
$uuid .= $node;
return $uuid;
}
protected static function mintRand() {
/* Generate a Version 4 UUID.
These are derived soly from random numbers. */
// generate random fields
$uuid = self::randomBytes(16);
// set variant
$uuid[8] = chr(ord($uuid[8]) & self::clearVar | self::varRFC);
// set version
$uuid[6] = chr(ord($uuid[6]) & self::clearVer | self::version4);
return $uuid;
}
protected static function mintName($ver, $node, $ns) {
/* Generates a Version 3 or Version 5 UUID.
These are derived from a hash of a name and its namespace, in binary form. */
if (!$node) {
throw new UUIDException("A name-string is required for Version 3 or 5 UUIDs.");
}
// if the namespace UUID isn't binary, make it so
$ns = self::makeBin($ns, 16);
if (!$ns) {
throw new UUIDException("A binary namespace is required for Version 3 or 5 UUIDs.");
}
$uuid = null;
$version = self::version3;
switch($ver) {
case self::MD5:
$version = self::version3;
$uuid = md5($ns.$node,1);
break;
case self::SHA1:
$version = self::version5;
$uuid = substr(sha1($ns.$node,1),0, 16);
break;
}
// set variant
$uuid[8] = chr(ord($uuid[8]) & self::clearVar | self::varRFC);
// set version
$uuid[6] = chr(ord($uuid[6]) & self::clearVer | $version);
return ($uuid);
}
protected static function makeBin($str, $len) {
/* Insure that an input string is either binary or hexadecimal.
Returns binary representation, or false on failure. */
if ($str instanceof self) {
return $str->bytes;
}
if (strlen($str)==$len) {
return $str;
} else {
$str = preg_replace("/^urn:uuid:/is", "", $str); // strip URN scheme and namespace
}
$str = preg_replace("/[^a-f0-9]/is", "", $str); // strip non-hex characters
if (strlen($str) != ($len * 2)) {
return FALSE;
} else {
return pack("H*", $str);
}
}
public static function initRandom() {
/* Look for a system-provided source of randomness, which is usually crytographically secure.
/dev/urandom is tried first simply out of bias for Linux systems. */
if (is_readable('/dev/urandom')) {
self::$randomSource = fopen('/dev/urandom', 'rb');
self::$randomFunc = 'randomFRead';
}
else if (class_exists('COM', 0)) {
try {
self::$randomSource = new COM('CAPICOM.Utilities.1'); // See http://msdn.microsoft.com/en-us/library/aa388182(VS.85).aspx
self::$randomFunc = 'randomCOM';
}
catch(Exception $e) {
}
}
return self::$randomFunc;
}
public static function randomBytes($bytes) {
return call_user_func(array('self', self::$randomFunc), $bytes);
}
protected static function randomTwister($bytes) {
/* Get the specified number of random bytes, using mt_rand().
Randomness is returned as a string of bytes. */
$rand = "";
for ($a = 0; $a < $bytes; $a++) {
$rand .= chr(mt_rand(0, 255));
}
return $rand;
}
protected static function randomFRead($bytes) {
/* Get the specified number of random bytes using a file handle
previously opened with UUID::initRandom().
Randomness is returned as a string of bytes. */
return fread(self::$randomSource, $bytes);
}
protected static function randomCOM($bytes) {
/* Get the specified number of random bytes using Windows'
randomness source via a COM object previously created by UUID::initRandom().
Randomness is returned as a string of bytes. */
return base64_decode(self::$randomSource->GetRandom($bytes,0)); // straight binary mysteriously doesn't work, hence the base64
}
}
class UUIDException extends Exception {
}

File diff suppressed because it is too large Load Diff

View File

@ -1,338 +1,343 @@
<?php
/**
* Site Config
*
* Each instance of this class should hold extraction patterns and other directives
* for a website. See ContentExtractor class to see how it's used.
*
* @version 0.7
* @date 2012-08-27
* @author Keyvan Minoukadeh
* @copyright 2012 Keyvan Minoukadeh
* @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3
*/
class SiteConfig
{
// Use first matching element as title (0 or more xpath expressions)
public $title = array();
// Use first matching element as body (0 or more xpath expressions)
public $body = array();
// Use first matching element as author (0 or more xpath expressions)
public $author = array();
// Use first matching element as date (0 or more xpath expressions)
public $date = array();
// Strip elements matching these xpath expressions (0 or more)
public $strip = array();
// Strip elements which contain these strings (0 or more) in the id or class attribute
public $strip_id_or_class = array();
// Strip images which contain these strings (0 or more) in the src attribute
public $strip_image_src = array();
// Additional HTTP headers to send
// NOT YET USED
public $http_header = array();
// Process HTML with tidy before creating DOM (bool or null if undeclared)
public $tidy = null;
protected $default_tidy = true; // used if undeclared
// Autodetect title/body if xpath expressions fail to produce results.
// Note that this applies to title and body separately, ie.
// * if we get a body match but no title match, this option will determine whether we autodetect title
// * if neither match, this determines whether we autodetect title and body.
// Also note that this only applies when there is at least one xpath expression in title or body, ie.
// * if title and body are both empty (no xpath expressions), this option has no effect (both title and body will be auto-detected)
// * if there's an xpath expression for title and none for body, body will be auto-detected and this option will determine whether we auto-detect title if the xpath expression for it fails to produce results.
// Usage scenario: you want to extract something specific from a set of URLs, e.g. a table, and if the table is not found, you want to ignore the entry completely. Auto-detection is unlikely to succeed here, so you construct your patterns and set this option to false. Another scenario may be a site where auto-detection has proven to fail (or worse, picked up the wrong content).
// bool or null if undeclared
public $autodetect_on_failure = null;
protected $default_autodetect_on_failure = true; // used if undeclared
// Clean up content block - attempt to remove elements that appear to be superfluous
// bool or null if undeclared
public $prune = null;
protected $default_prune = true; // used if undeclared
// Test URL - if present, can be used to test the config above
public $test_url = array();
// Single-page link - should identify a link element or URL pointing to the page holding the entire article
// This is useful for sites which split their articles across multiple pages. Links to such pages tend to
// display the first page with links to the other pages at the bottom. Often there is also a link to a page
// which displays the entire article on one page (e.g. 'print view').
// This should be an XPath expression identifying the link to that page. If present and we find a match,
// we will retrieve that page and the rest of the options in this config will be applied to the new page.
public $single_page_link = array();
public $next_page_link = array();
// Single-page link in feed? - same as above, but patterns applied to item description HTML taken from feed
public $single_page_link_in_feed = array();
// Which parser to use for turning raw HTML into a DOMDocument (either 'libxml' or 'html5lib')
// string or null if undeclared
public $parser = null;
protected $default_parser = 'libxml'; // used if undeclared
// Strings to search for in HTML before processing begins (used with $replace_string)
public $find_string = array();
// Strings to replace those found in $find_string before HTML processing begins
public $replace_string = array();
// the options below cannot be set in the config files which this class represents
//public $cache_in_apc = false; // used to decide if we should cache in apc or not
public $cache_key = null;
public static $debug = false;
protected static $apc = false;
protected static $config_path;
protected static $config_path_fallback;
protected static $config_cache = array();
const HOSTNAME_REGEX = '/^(([a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9-]*[A-Za-z0-9])$/';
protected static function debug($msg) {
if (self::$debug) {
//$mem = round(memory_get_usage()/1024, 2);
//$memPeak = round(memory_get_peak_usage()/1024, 2);
echo '* ',$msg;
//echo ' - mem used: ',$mem," (peak: $memPeak)\n";
echo "\n";
ob_flush();
flush();
}
}
// enable APC caching of certain site config files?
// If enabled the following site config files will be
// cached in APC cache (when requested for first time):
// * anything in site_config/custom/ and its corresponding file in site_config/standard/
// * the site config files associated with HTML fingerprints
// * the global site config file
// returns true if enabled, false otherwise
public static function use_apc($apc=true) {
if (!function_exists('apc_add')) {
if ($apc) self::debug('APC will not be used (function apc_add does not exist)');
return false;
}
self::$apc = $apc;
return $apc;
}
// return bool or null
public function tidy($use_default=true) {
if ($use_default) return (isset($this->tidy)) ? $this->tidy : $this->default_tidy;
return $this->tidy;
}
// return bool or null
public function prune($use_default=true) {
if ($use_default) return (isset($this->prune)) ? $this->prune : $this->default_prune;
return $this->prune;
}
// return string or null
public function parser($use_default=true) {
if ($use_default) return (isset($this->parser)) ? $this->parser : $this->default_parser;
return $this->parser;
}
// return bool or null
public function autodetect_on_failure($use_default=true) {
if ($use_default) return (isset($this->autodetect_on_failure)) ? $this->autodetect_on_failure : $this->default_autodetect_on_failure;
return $this->autodetect_on_failure;
}
public static function set_config_path($path, $fallback=null) {
self::$config_path = $path;
self::$config_path_fallback = $fallback;
}
public static function add_to_cache($key, SiteConfig $config, $use_apc=true) {
$key = strtolower($key);
if (substr($key, 0, 4) == 'www.') $key = substr($key, 4);
if ($config->cache_key) $key = $config->cache_key;
self::$config_cache[$key] = $config;
if (self::$apc && $use_apc) {
self::debug("Adding site config to APC cache with key sc.$key");
apc_add("sc.$key", $config);
}
self::debug("Cached site config with key $key");
}
public static function is_cached($key) {
$key = strtolower($key);
if (substr($key, 0, 4) == 'www.') $key = substr($key, 4);
if (array_key_exists($key, self::$config_cache)) {
return true;
} elseif (self::$apc && (bool)apc_fetch("sc.$key")) {
return true;
}
return false;
}
public function append(SiteConfig $newconfig) {
// check for commands where we accept multiple statements (no test_url)
foreach (array('title', 'body', 'author', 'date', 'strip', 'strip_id_or_class', 'strip_image_src', 'single_page_link', 'single_page_link_in_feed', 'next_page_link', 'http_header', 'find_string', 'replace_string') as $var) {
// append array elements for this config variable from $newconfig to this config
//$this->$var = $this->$var + $newconfig->$var;
$this->$var = array_unique(array_merge($this->$var, $newconfig->$var));
}
// check for single statement commands
// we do not overwrite existing non null values
foreach (array('tidy', 'prune', 'parser', 'autodetect_on_failure') as $var) {
if ($this->$var === null) $this->$var = $newconfig->$var;
}
}
// returns SiteConfig instance if an appropriate one is found, false otherwise
// if $exact_host_match is true, we will not look for wildcard config matches
// by default if host is 'test.example.org' we will look for and load '.example.org.txt' if it exists
public static function build($host, $exact_host_match=false) {
$host = strtolower($host);
if (substr($host, 0, 4) == 'www.') $host = substr($host, 4);
if (!$host || (strlen($host) > 200) || !preg_match(self::HOSTNAME_REGEX, ltrim($host, '.'))) return false;
// check for site configuration
$try = array($host);
// should we look for wildcard matches
if (!$exact_host_match) {
$split = explode('.', $host);
if (count($split) > 1) {
array_shift($split);
$try[] = '.'.implode('.', $split);
}
}
// look for site config file in primary folder
self::debug(". looking for site config for $host in primary folder");
foreach ($try as $h) {
if (array_key_exists($h, self::$config_cache)) {
self::debug("... site config for $h already loaded in this request");
return self::$config_cache[$h];
} elseif (self::$apc && ($sconfig = apc_fetch("sc.$h"))) {
self::debug("... site config for $h in APC cache");
return $sconfig;
} elseif (file_exists(self::$config_path."/$h.txt")) {
self::debug("... found site config ($h.txt)");
$file_primary = self::$config_path."/$h.txt";
$matched_name = $h;
break;
}
}
// if we found site config, process it
if (isset($file_primary)) {
$config_lines = file($file_primary, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!$config_lines || !is_array($config_lines)) return false;
$config = self::build_from_array($config_lines);
// if APC caching is available and enabled, mark this for cache
//$config->cache_in_apc = true;
$config->cache_key = $matched_name;
// if autodetec on failure is off (on by default) we do not need to look
// in secondary folder
if (!$config->autodetect_on_failure()) {
self::debug('... autodetect on failure is disabled (no other site config files will be loaded)');
return $config;
}
}
// look for site config file in secondary folder
if (isset(self::$config_path_fallback)) {
self::debug(". looking for site config for $host in secondary folder");
foreach ($try as $h) {
if (file_exists(self::$config_path_fallback."/$h.txt")) {
self::debug("... found site config in secondary folder ($h.txt)");
$file_secondary = self::$config_path_fallback."/$h.txt";
$matched_name = $h;
break;
}
}
if (!isset($file_secondary)) {
self::debug("... no site config match in secondary folder");
}
}
// return false if no config file found
if (!isset($file_primary) && !isset($file_secondary)) {
self::debug("... no site config match for $host");
return false;
}
// return primary config if secondary not found
if (!isset($file_secondary) && isset($config)) {
return $config;
}
// process secondary config file
$config_lines = file($file_secondary, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!$config_lines || !is_array($config_lines)) {
// failed to process secondary
if (isset($config)) {
// return primary config
return $config;
} else {
return false;
}
}
// merge with primary and return
if (isset($config)) {
self::debug('. merging config files');
$config->append(self::build_from_array($config_lines));
return $config;
} else {
// return just secondary
$config = self::build_from_array($config_lines);
// if APC caching is available and enabled, mark this for cache
//$config->cache_in_apc = true;
$config->cache_key = $matched_name;
return $config;
}
}
public static function build_from_array(array $lines) {
$config = new SiteConfig();
foreach ($lines as $line) {
$line = trim($line);
// skip comments, empty lines
if ($line == '' || $line[0] == '#') continue;
// get command
$command = explode(':', $line, 2);
// if there's no colon ':', skip this line
if (count($command) != 2) continue;
$val = trim($command[1]);
$command = trim($command[0]);
if ($command == '' || $val == '') continue;
// check for commands where we accept multiple statements
if (in_array($command, array('title', 'body', 'author', 'date', 'strip', 'strip_id_or_class', 'strip_image_src', 'single_page_link', 'single_page_link_in_feed', 'next_page_link', 'http_header', 'test_url', 'find_string', 'replace_string'))) {
array_push($config->$command, $val);
// check for single statement commands that evaluate to true or false
} elseif (in_array($command, array('tidy', 'prune', 'autodetect_on_failure'))) {
$config->$command = ($val == 'yes');
// check for single statement commands stored as strings
} elseif (in_array($command, array('parser'))) {
$config->$command = $val;
// check for replace_string(find): replace
} elseif ((substr($command, -1) == ')') && preg_match('!^([a-z0-9_]+)\((.*?)\)$!i', $command, $match)) {
if (in_array($match[1], array('replace_string'))) {
$command = $match[1];
array_push($config->find_string, $match[2]);
array_push($config->$command, $val);
}
}
}
return $config;
}
}
?>
<?php
/**
* Site Config
*
* Each instance of this class should hold extraction patterns and other directives
* for a website. See ContentExtractor class to see how it's used.
*
* @version 0.8
* @date 2013-04-16
* @author Keyvan Minoukadeh
* @copyright 2013 Keyvan Minoukadeh
* @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3
*/
class SiteConfig
{
// Use first matching element as title (0 or more xpath expressions)
public $title = array();
// Use first matching element as body (0 or more xpath expressions)
public $body = array();
// Use first matching element as author (0 or more xpath expressions)
public $author = array();
// Use first matching element as date (0 or more xpath expressions)
public $date = array();
// Strip elements matching these xpath expressions (0 or more)
public $strip = array();
// Strip elements which contain these strings (0 or more) in the id or class attribute
public $strip_id_or_class = array();
// Strip images which contain these strings (0 or more) in the src attribute
public $strip_image_src = array();
// Additional HTTP headers to send
// NOT YET USED
public $http_header = array();
// Process HTML with tidy before creating DOM (bool or null if undeclared)
public $tidy = null;
protected $default_tidy = true; // used if undeclared
// Autodetect title/body if xpath expressions fail to produce results.
// Note that this applies to title and body separately, ie.
// * if we get a body match but no title match, this option will determine whether we autodetect title
// * if neither match, this determines whether we autodetect title and body.
// Also note that this only applies when there is at least one xpath expression in title or body, ie.
// * if title and body are both empty (no xpath expressions), this option has no effect (both title and body will be auto-detected)
// * if there's an xpath expression for title and none for body, body will be auto-detected and this option will determine whether we auto-detect title if the xpath expression for it fails to produce results.
// Usage scenario: you want to extract something specific from a set of URLs, e.g. a table, and if the table is not found, you want to ignore the entry completely. Auto-detection is unlikely to succeed here, so you construct your patterns and set this option to false. Another scenario may be a site where auto-detection has proven to fail (or worse, picked up the wrong content).
// bool or null if undeclared
public $autodetect_on_failure = null;
protected $default_autodetect_on_failure = true; // used if undeclared
// Clean up content block - attempt to remove elements that appear to be superfluous
// bool or null if undeclared
public $prune = null;
protected $default_prune = true; // used if undeclared
// Test URL - if present, can be used to test the config above
public $test_url = array();
// Single-page link - should identify a link element or URL pointing to the page holding the entire article
// This is useful for sites which split their articles across multiple pages. Links to such pages tend to
// display the first page with links to the other pages at the bottom. Often there is also a link to a page
// which displays the entire article on one page (e.g. 'print view').
// This should be an XPath expression identifying the link to that page. If present and we find a match,
// we will retrieve that page and the rest of the options in this config will be applied to the new page.
public $single_page_link = array();
public $next_page_link = array();
// Single-page link in feed? - same as above, but patterns applied to item description HTML taken from feed
public $single_page_link_in_feed = array();
// Which parser to use for turning raw HTML into a DOMDocument (either 'libxml' or 'html5lib')
// string or null if undeclared
public $parser = null;
protected $default_parser = 'libxml'; // used if undeclared
// Strings to search for in HTML before processing begins (used with $replace_string)
public $find_string = array();
// Strings to replace those found in $find_string before HTML processing begins
public $replace_string = array();
// the options below cannot be set in the config files which this class represents
//public $cache_in_apc = false; // used to decide if we should cache in apc or not
public $cache_key = null;
public static $debug = false;
protected static $apc = false;
protected static $config_path;
protected static $config_path_fallback;
protected static $config_cache = array();
const HOSTNAME_REGEX = '/^(([a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9-]*[A-Za-z0-9])$/';
protected static function debug($msg) {
if (self::$debug) {
//$mem = round(memory_get_usage()/1024, 2);
//$memPeak = round(memory_get_peak_usage()/1024, 2);
echo '* ',$msg;
//echo ' - mem used: ',$mem," (peak: $memPeak)\n";
echo "\n";
ob_flush();
flush();
}
}
// enable APC caching of certain site config files?
// If enabled the following site config files will be
// cached in APC cache (when requested for first time):
// * anything in site_config/custom/ and its corresponding file in site_config/standard/
// * the site config files associated with HTML fingerprints
// * the global site config file
// returns true if enabled, false otherwise
public static function use_apc($apc=true) {
if (!function_exists('apc_add')) {
if ($apc) self::debug('APC will not be used (function apc_add does not exist)');
return false;
}
self::$apc = $apc;
return $apc;
}
// return bool or null
public function tidy($use_default=true) {
if ($use_default) return (isset($this->tidy)) ? $this->tidy : $this->default_tidy;
return $this->tidy;
}
// return bool or null
public function prune($use_default=true) {
if ($use_default) return (isset($this->prune)) ? $this->prune : $this->default_prune;
return $this->prune;
}
// return string or null
public function parser($use_default=true) {
if ($use_default) return (isset($this->parser)) ? $this->parser : $this->default_parser;
return $this->parser;
}
// return bool or null
public function autodetect_on_failure($use_default=true) {
if ($use_default) return (isset($this->autodetect_on_failure)) ? $this->autodetect_on_failure : $this->default_autodetect_on_failure;
return $this->autodetect_on_failure;
}
public static function set_config_path($path, $fallback=null) {
self::$config_path = $path;
self::$config_path_fallback = $fallback;
}
public static function add_to_cache($key, SiteConfig $config, $use_apc=true) {
$key = strtolower($key);
if (substr($key, 0, 4) == 'www.') $key = substr($key, 4);
if ($config->cache_key) $key = $config->cache_key;
self::$config_cache[$key] = $config;
if (self::$apc && $use_apc) {
self::debug("Adding site config to APC cache with key sc.$key");
apc_add("sc.$key", $config);
}
self::debug("Cached site config with key $key");
}
public static function is_cached($key) {
$key = strtolower($key);
if (substr($key, 0, 4) == 'www.') $key = substr($key, 4);
if (array_key_exists($key, self::$config_cache)) {
return true;
} elseif (self::$apc && (bool)apc_fetch("sc.$key")) {
return true;
}
return false;
}
public function append(SiteConfig $newconfig) {
// check for commands where we accept multiple statements (no test_url)
foreach (array('title', 'body', 'author', 'date', 'strip', 'strip_id_or_class', 'strip_image_src', 'single_page_link', 'single_page_link_in_feed', 'next_page_link', 'http_header') as $var) {
// append array elements for this config variable from $newconfig to this config
//$this->$var = $this->$var + $newconfig->$var;
$this->$var = array_unique(array_merge($this->$var, $newconfig->$var));
}
// check for single statement commands
// we do not overwrite existing non null values
foreach (array('tidy', 'prune', 'parser', 'autodetect_on_failure') as $var) {
if ($this->$var === null) $this->$var = $newconfig->$var;
}
// treat find_string and replace_string separately (don't apply array_unique) (thanks fabrizio!)
foreach (array('find_string', 'replace_string') as $var) {
// append array elements for this config variable from $newconfig to this config
//$this->$var = $this->$var + $newconfig->$var;
$this->$var = array_merge($this->$var, $newconfig->$var);
}
}
// returns SiteConfig instance if an appropriate one is found, false otherwise
// if $exact_host_match is true, we will not look for wildcard config matches
// by default if host is 'test.example.org' we will look for and load '.example.org.txt' if it exists
public static function build($host, $exact_host_match=false) {
$host = strtolower($host);
if (substr($host, 0, 4) == 'www.') $host = substr($host, 4);
if (!$host || (strlen($host) > 200) || !preg_match(self::HOSTNAME_REGEX, ltrim($host, '.'))) return false;
// check for site configuration
$try = array($host);
// should we look for wildcard matches
if (!$exact_host_match) {
$split = explode('.', $host);
if (count($split) > 1) {
array_shift($split);
$try[] = '.'.implode('.', $split);
}
}
// look for site config file in primary folder
self::debug(". looking for site config for $host in primary folder");
foreach ($try as $h) {
if (array_key_exists($h, self::$config_cache)) {
self::debug("... site config for $h already loaded in this request");
return self::$config_cache[$h];
} elseif (self::$apc && ($sconfig = apc_fetch("sc.$h"))) {
self::debug("... site config for $h in APC cache");
return $sconfig;
} elseif (file_exists(self::$config_path."/$h.txt")) {
self::debug("... found site config ($h.txt)");
$file_primary = self::$config_path."/$h.txt";
$matched_name = $h;
break;
}
}
// if we found site config, process it
if (isset($file_primary)) {
$config_lines = file($file_primary, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!$config_lines || !is_array($config_lines)) return false;
$config = self::build_from_array($config_lines);
// if APC caching is available and enabled, mark this for cache
//$config->cache_in_apc = true;
$config->cache_key = $matched_name;
// if autodetec on failure is off (on by default) we do not need to look
// in secondary folder
if (!$config->autodetect_on_failure()) {
self::debug('... autodetect on failure is disabled (no other site config files will be loaded)');
return $config;
}
}
// look for site config file in secondary folder
if (isset(self::$config_path_fallback)) {
self::debug(". looking for site config for $host in secondary folder");
foreach ($try as $h) {
if (file_exists(self::$config_path_fallback."/$h.txt")) {
self::debug("... found site config in secondary folder ($h.txt)");
$file_secondary = self::$config_path_fallback."/$h.txt";
$matched_name = $h;
break;
}
}
if (!isset($file_secondary)) {
self::debug("... no site config match in secondary folder");
}
}
// return false if no config file found
if (!isset($file_primary) && !isset($file_secondary)) {
self::debug("... no site config match for $host");
return false;
}
// return primary config if secondary not found
if (!isset($file_secondary) && isset($config)) {
return $config;
}
// process secondary config file
$config_lines = file($file_secondary, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!$config_lines || !is_array($config_lines)) {
// failed to process secondary
if (isset($config)) {
// return primary config
return $config;
} else {
return false;
}
}
// merge with primary and return
if (isset($config)) {
self::debug('. merging config files');
$config->append(self::build_from_array($config_lines));
return $config;
} else {
// return just secondary
$config = self::build_from_array($config_lines);
// if APC caching is available and enabled, mark this for cache
//$config->cache_in_apc = true;
$config->cache_key = $matched_name;
return $config;
}
}
public static function build_from_array(array $lines) {
$config = new SiteConfig();
foreach ($lines as $line) {
$line = trim($line);
// skip comments, empty lines
if ($line == '' || $line[0] == '#') continue;
// get command
$command = explode(':', $line, 2);
// if there's no colon ':', skip this line
if (count($command) != 2) continue;
$val = trim($command[1]);
$command = trim($command[0]);
if ($command == '' || $val == '') continue;
// check for commands where we accept multiple statements
if (in_array($command, array('title', 'body', 'author', 'date', 'strip', 'strip_id_or_class', 'strip_image_src', 'single_page_link', 'single_page_link_in_feed', 'next_page_link', 'http_header', 'test_url', 'find_string', 'replace_string'))) {
array_push($config->$command, $val);
// check for single statement commands that evaluate to true or false
} elseif (in_array($command, array('tidy', 'prune', 'autodetect_on_failure'))) {
$config->$command = ($val == 'yes');
// check for single statement commands stored as strings
} elseif (in_array($command, array('parser'))) {
$config->$command = $val;
// check for replace_string(find): replace
} elseif ((substr($command, -1) == ')') && preg_match('!^([a-z0-9_]+)\((.*?)\)$!i', $command, $match)) {
if (in_array($match[1], array('replace_string'))) {
$command = $match[1];
array_push($config->find_string, $match[2]);
array_push($config->$command, $val);
}
}
}
return $config;
}
}

363
inc/3rdparty/libraries/feedwriter/FeedItem.php vendored Normal file → Executable file
View File

@ -1,7 +1,7 @@
<?php
/**
* Univarsel Feed Writer
*
*
* FeedItem class - Used as feed element in FeedWriter class
*
* @package UnivarselFeedWriter
@ -10,176 +10,195 @@
*/
class FeedItem
{
private $elements = array(); //Collection of feed elements
private $version;
/**
* Constructor
*
* @param contant (RSS1/RSS2/ATOM) RSS2 is default.
*/
function __construct($version = RSS2)
{
$this->version = $version;
}
private $elements = array(); //Collection of feed elements
private $version;
/**
* Constructor
*
* @param contant (RSS1/RSS2/ATOM) RSS2 is default.
*/
function __construct($version = RSS2)
{
$this->version = $version;
}
/**
* Set element (overwrites existing elements with $elementName)
*
* @access public
* @param srting The tag name of an element
* @param srting The content of tag
* @param array Attributes(if any) in 'attrName' => 'attrValue' format
* @return void
*/
public function setElement($elementName, $content, $attributes = null)
{
if (isset($this->elements[$elementName])) {
unset($this->elements[$elementName]);
}
$this->addElement($elementName, $content, $attributes);
}
/**
* Add an element to elements array
*
* @access public
* @param srting The tag name of an element
* @param srting The content of tag
* @param array Attributes(if any) in 'attrName' => 'attrValue' format
* @return void
*/
public function addElement($elementName, $content, $attributes = null)
{
$i = 0;
if (isset($this->elements[$elementName])) {
$i = count($this->elements[$elementName]);
} else {
$this->elements[$elementName] = array();
}
$this->elements[$elementName][$i]['name'] = $elementName;
$this->elements[$elementName][$i]['content'] = $content;
$this->elements[$elementName][$i]['attributes'] = $attributes;
}
/**
* Set multiple feed elements from an array.
* Elements which have attributes cannot be added by this method
*
* @access public
* @param array array of elements in 'tagName' => 'tagContent' format.
* @return void
*/
public function addElementArray($elementArray)
{
if(! is_array($elementArray)) return;
foreach ($elementArray as $elementName => $content)
{
$this->addElement($elementName, $content);
}
}
/**
* Return the collection of elements in this feed item
*
* @access public
* @return array
*/
public function getElements()
{
return $this->elements;
}
// Wrapper functions ------------------------------------------------------
/**
* Set the 'dscription' element of feed item
*
* @access public
* @param string The content of 'description' element
* @return void
*/
public function setDescription($description)
{
$tag = ($this->version == ATOM)? 'summary' : 'description';
$this->setElement($tag, $description);
}
/**
* @desc Set the 'title' element of feed item
* @access public
* @param string The content of 'title' element
* @return void
*/
public function setTitle($title)
{
$this->setElement('title', $title);
}
/**
* Set the 'date' element of feed item
*
* @access public
* @param string The content of 'date' element
* @return void
*/
public function setDate($date)
{
if(! is_numeric($date))
{
$date = strtotime($date);
}
if($this->version == ATOM)
{
$tag = 'updated';
$value = date(DATE_ATOM, $date);
}
elseif($this->version == RSS2)
{
$tag = 'pubDate';
$value = date(DATE_RSS, $date);
}
else
{
$tag = 'dc:date';
$value = date("Y-m-d", $date);
}
$this->setElement($tag, $value);
}
/**
* Set the 'link' element of feed item
*
* @access public
* @param string The content of 'link' element
* @return void
*/
public function setLink($link)
{
if($this->version == RSS2 || $this->version == RSS1)
{
$this->setElement('link', $link);
$this->setElement('guid', $link);
}
else
{
$this->setElement('link','',array('href'=>$link));
$this->setElement('id', FeedWriter::uuid($link,'urn:uuid:'));
}
}
/**
* Set the 'source' element of feed item
*
* @access public
* @param string The content of 'source' element
* @return void
*/
public function setSource($link)
{
$attributes = array('url'=>$link);
$this->setElement('source', "wallabag",$attributes);
}
/**
* Set the 'encloser' element of feed item
* For RSS 2.0 only
*
* @access public
* @param string The url attribute of encloser tag
* @param string The length attribute of encloser tag
* @param string The type attribute of encloser tag
* @return void
*/
public function setEncloser($url, $length, $type)
{
$attributes = array('url'=>$url, 'length'=>$length, 'type'=>$type);
$this->setElement('enclosure','',$attributes);
}
/**
* Set element (overwrites existing elements with $elementName)
*
* @access public
* @param srting The tag name of an element
* @param srting The content of tag
* @param array Attributes(if any) in 'attrName' => 'attrValue' format
* @return void
*/
public function setElement($elementName, $content, $attributes = null)
{
if (isset($this->elements[$elementName])) {
unset($this->elements[$elementName]);
}
$this->addElement($elementName, $content, $attributes);
}
/**
* Add an element to elements array
*
* @access public
* @param srting The tag name of an element
* @param srting The content of tag
* @param array Attributes(if any) in 'attrName' => 'attrValue' format
* @return void
*/
public function addElement($elementName, $content, $attributes = null)
{
$i = 0;
if (isset($this->elements[$elementName])) {
$i = count($this->elements[$elementName]);
} else {
$this->elements[$elementName] = array();
}
$this->elements[$elementName][$i]['name'] = $elementName;
$this->elements[$elementName][$i]['content'] = $content;
$this->elements[$elementName][$i]['attributes'] = $attributes;
}
/**
* Set multiple feed elements from an array.
* Elements which have attributes cannot be added by this method
*
* @access public
* @param array array of elements in 'tagName' => 'tagContent' format.
* @return void
*/
public function addElementArray($elementArray)
{
if(! is_array($elementArray)) return;
foreach ($elementArray as $elementName => $content)
{
$this->addElement($elementName, $content);
}
}
/**
* Return the collection of elements in this feed item
*
* @access public
* @return array
*/
public function getElements()
{
return $this->elements;
}
// Wrapper functions ------------------------------------------------------
/**
* Set the 'dscription' element of feed item
*
* @access public
* @param string The content of 'description' element
* @return void
*/
public function setDescription($description)
{
$tag = 'description';
$this->setElement($tag, $description);
}
/**
* @desc Set the 'title' element of feed item
* @access public
* @param string The content of 'title' element
* @return void
*/
public function setTitle($title)
{
$this->setElement('title', $title);
}
/**
* Set the 'date' element of feed item
*
* @access public
* @param string The content of 'date' element
* @return void
*/
public function setDate($date)
{
if(! is_numeric($date))
{
$date = strtotime($date);
}
if($this->version == RSS2)
{
$tag = 'pubDate';
$value = date(DATE_RSS, $date);
}
else
{
$tag = 'dc:date';
$value = date("Y-m-d", $date);
}
$this->setElement($tag, $value);
}
/**
* Set the 'link' element of feed item
*
* @access public
* @param string The content of 'link' element
* @return void
*/
public function setLink($link)
{
if($this->version == RSS2 || $this->version == RSS1)
{
$this->setElement('link', $link);
}
else
{
$this->setElement('link','',array('href'=>$link));
$this->setElement('id', FeedWriter::uuid($link,'urn:uuid:'));
}
}
/**
* Set the 'encloser' element of feed item
* For RSS 2.0 only
*
* @access public
* @param string The url attribute of encloser tag
* @param string The length attribute of encloser tag
* @param string The type attribute of encloser tag
* @return void
*/
public function setEncloser($url, $length, $type)
{
$attributes = array('url'=>$url, 'length'=>$length, 'type'=>$type);
$this->setElement('enclosure','',$attributes);
}
} // end of class FeedItem
?>
?>

852
inc/3rdparty/libraries/feedwriter/FeedWriter.php vendored Normal file → Executable file
View File

@ -2,6 +2,7 @@
define('RSS2', 1, true);
define('JSON', 2, true);
define('JSONP', 3, true);
define('ATOM', 4, true);
/**
* Univarsel Feed Writer class
@ -9,433 +10,444 @@ define('JSONP', 3, true);
* Genarate RSS2 or JSON (original: RSS 1.0, RSS2.0 and ATOM Feed)
*
* Modified for FiveFilters.org's Full-Text RSS project
* to allow for inclusion of hubs, JSON output.
* to allow for inclusion of hubs, JSON output.
* Stripped RSS1 and ATOM support.
*
*
* @package UnivarselFeedWriter
* @author Anis uddin Ahmad <anisniit@gmail.com>
* @link http://www.ajaxray.com/projects/rss
*/
class FeedWriter
{
private $self = null; // self URL - http://feed2.w3.org/docs/warning/MissingAtomSelfLink.html
private $hubs = array(); // PubSubHubbub hubs
private $channels = array(); // Collection of channel elements
private $items = array(); // Collection of items as object of FeedItem class.
private $data = array(); // Store some other version wise data
private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA
private $xsl = null; // stylesheet to render RSS (used by Chrome)
private $json = null; // JSON object
private $version = null;
/**
* Constructor
*
* @param constant the version constant (RSS2 or JSON).
*/
function __construct($version = RSS2)
{
$this->version = $version;
// Setting default value for assential channel elements
$this->channels['title'] = $version . ' Feed';
$this->channels['link'] = 'http://www.ajaxray.com/blog';
//Tag names to encode in CDATA
$this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary');
}
public function setFormat($format) {
$this->version = $format;
}
private $self = null; // self URL - http://feed2.w3.org/docs/warning/MissingAtomSelfLink.html
private $hubs = array(); // PubSubHubbub hubs
private $channels = array(); // Collection of channel elements
private $items = array(); // Collection of items as object of FeedItem class.
private $data = array(); // Store some other version wise data
private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA
private $xsl = null; // stylesheet to render RSS (used by Chrome)
private $json = null; // JSON object
// Start # public functions ---------------------------------------------
/**
* Set a channel element
* @access public
* @param srting name of the channel tag
* @param string content of the channel tag
* @return void
*/
public function setChannelElement($elementName, $content)
{
$this->channels[$elementName] = $content ;
}
/**
* Set multiple channel elements from an array. Array elements
* should be 'channelName' => 'channelContent' format.
*
* @access public
* @param array array of channels
* @return void
*/
public function setChannelElementsFromArray($elementArray)
{
if(! is_array($elementArray)) return;
foreach ($elementArray as $elementName => $content)
{
$this->setChannelElement($elementName, $content);
}
}
/**
* Genarate the actual RSS/JSON file
*
* @access public
* @return void
*/
public function genarateFeed()
{
if ($this->version == RSS2) {
header('Content-type: text/xml; charset=UTF-8');
// this line prevents Chrome 20 from prompting download
// used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss
header('X-content-type-options: nosniff');
} elseif ($this->version == JSON) {
header('Content-type: application/json; charset=UTF-8');
$this->json = new stdClass();
} elseif ($this->version == JSONP) {
header('Content-type: application/javascript; charset=UTF-8');
$this->json = new stdClass();
}
$this->printHead();
$this->printChannels();
$this->printItems();
$this->printTale();
if ($this->version == JSON || $this->version == JSONP) {
echo json_encode($this->json);
}
}
/**
* Create a new FeedItem.
*
* @access public
* @return object instance of FeedItem class
*/
public function createNewItem()
{
$Item = new FeedItem($this->version);
return $Item;
}
/**
* Add a FeedItem to the main class
*
* @access public
* @param object instance of FeedItem class
* @return void
*/
public function addItem($feedItem)
{
$this->items[] = $feedItem;
}
// Wrapper functions -------------------------------------------------------------------
/**
* Set the 'title' channel element
*
* @access public
* @param srting value of 'title' channel tag
* @return void
*/
public function setTitle($title)
{
$this->setChannelElement('title', $title);
}
/**
* Add a hub to the channel element
*
* @access public
* @param string URL
* @return void
*/
public function addHub($hub)
{
$this->hubs[] = $hub;
}
/**
* Set XSL URL
*
* @access public
* @param string URL
* @return void
*/
public function setXsl($xsl)
{
$this->xsl = $xsl;
}
/**
* Set self URL
*
* @access public
* @param string URL
* @return void
*/
public function setSelf($self)
{
$this->self = $self;
}
/**
* Set the 'description' channel element
*
* @access public
* @param srting value of 'description' channel tag
* @return void
*/
public function setDescription($desciption)
{
$tag = ($this->version == ATOM)? 'subtitle' : 'description';
$this->setChannelElement($tag, $desciption);
}
/**
* Set the 'link' channel element
*
* @access public
* @param srting value of 'link' channel tag
* @return void
*/
public function setLink($link)
{
$this->setChannelElement('link', $link);
}
/**
* Set the 'image' channel element
*
* @access public
* @param srting title of image
* @param srting link url of the imahe
* @param srting path url of the image
* @return void
*/
public function setImage($title, $link, $url)
{
$this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));
}
// End # public functions ----------------------------------------------
// Start # private functions ----------------------------------------------
/**
* Prints the xml and rss namespace
*
* @access private
* @return void
*/
private function printHead()
{
if ($this->version == RSS2)
{
$out = '<?xml version="1.0" encoding="utf-8"?>'."\n";
if ($this->xsl) $out .= '<?xml-stylesheet type="text/xsl" href="'.htmlspecialchars($this->xsl).'"?>' . PHP_EOL;
$out .= '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">' . PHP_EOL;
echo $out;
}
elseif ($this->version == JSON || $this->version == JSONP)
{
$this->json->rss = array('@attributes' => array('version' => '2.0'));
}
}
/**
* Closes the open tags at the end of file
*
* @access private
* @return void
*/
private function printTale()
{
if ($this->version == RSS2)
{
echo '</channel>',PHP_EOL,'</rss>';
}
// do nothing for JSON
}
private $version = null;
/**
* Creates a single node as xml format
*
* @access private
* @param string name of the tag
* @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format
* @param array Attributes(if any) in 'attrName' => 'attrValue' format
* @return string formatted xml tag
*/
private function makeNode($tagName, $tagContent, $attributes = null)
{
if ($this->version == RSS2)
{
$nodeText = '';
$attrText = '';
if (is_array($attributes))
{
foreach ($attributes as $key => $value)
{
$attrText .= " $key=\"$value\" ";
}
}
$nodeText .= "<{$tagName}{$attrText}>";
if (is_array($tagContent))
{
foreach ($tagContent as $key => $value)
{
$nodeText .= $this->makeNode($key, $value);
}
}
else
{
//$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);
$nodeText .= htmlspecialchars($tagContent);
}
//$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";
$nodeText .= "</$tagName>";
return $nodeText . PHP_EOL;
}
elseif ($this->version == JSON || $this->version == JSONP)
{
$tagName = (string)$tagName;
$tagName = strtr($tagName, ':', '_');
$node = null;
if (!$tagContent && is_array($attributes) && count($attributes))
{
$node = array('@attributes' => $this->json_keys($attributes));
} else {
if (is_array($tagContent)) {
$node = $this->json_keys($tagContent);
} else {
$node = $tagContent;
}
}
return $node;
}
return ''; // should not get here
}
private function json_keys(array $array) {
$new = array();
foreach ($array as $key => $val) {
if (is_string($key)) $key = strtr($key, ':', '_');
if (is_array($val)) {
$new[$key] = $this->json_keys($val);
} else {
$new[$key] = $val;
}
}
return $new;
}
/**
* @desc Print channels
* @access private
* @return void
*/
private function printChannels()
{
//Start channel tag
if ($this->version == RSS2) {
echo '<channel>' . PHP_EOL;
// add hubs
foreach ($this->hubs as $hub) {
//echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom'));
echo '<link rel="hub" href="'.htmlspecialchars($hub).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;
}
// add self
if (isset($this->self)) {
//echo $this->makeNode('link', '', array('rel'=>'self', 'href'=>$this->self, 'xmlns'=>'http://www.w3.org/2005/Atom'));
echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;
}
//Print Items of channel
foreach ($this->channels as $key => $value)
{
echo $this->makeNode($key, $value);
}
} elseif ($this->version == JSON || $this->version == JSONP) {
$this->json->rss['channel'] = (object)$this->json_keys($this->channels);
}
}
/**
* Prints formatted feed items
*
* @access private
* @return void
*/
private function printItems()
{
foreach ($this->items as $item) {
$itemElements = $item->getElements();
echo $this->startItem();
if ($this->version == JSON || $this->version == JSONP) {
$json_item = array();
}
foreach ($itemElements as $thisElement) {
foreach ($thisElement as $instance) {
if ($this->version == RSS2) {
echo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);
} elseif ($this->version == JSON || $this->version == JSONP) {
$_json_node = $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);
if (count($thisElement) > 1) {
$json_item[strtr($instance['name'], ':', '_')][] = $_json_node;
} else {
$json_item[strtr($instance['name'], ':', '_')] = $_json_node;
}
}
}
}
echo $this->endItem();
if ($this->version == JSON || $this->version == JSONP) {
if (count($this->items) > 1) {
$this->json->rss['channel']->item[] = $json_item;
} else {
$this->json->rss['channel']->item = $json_item;
}
}
}
}
/**
* Make the starting tag of channels
*
* @access private
* @return void
*/
private function startItem()
{
if ($this->version == RSS2)
{
echo '<item>' . PHP_EOL;
}
// nothing for JSON
}
/**
* Closes feed item tag
*
* @access private
* @return void
*/
private function endItem()
{
if ($this->version == RSS2)
{
echo '</item>' . PHP_EOL;
}
// nothing for JSON
}
// End # private functions ----------------------------------------------
/**
* Constructor
*
* @param constant the version constant (RSS2 or JSON).
*/
function __construct($version = RSS2)
{
$this->version = $version;
// Setting default value for assential channel elements
$this->channels['title'] = $version . ' Feed';
$this->channels['link'] = 'http://www.ajaxray.com/blog';
//Tag names to encode in CDATA
$this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary');
}
public function setFormat($format) {
$this->version = $format;
}
// Start # public functions ---------------------------------------------
/**
* Set a channel element
* @access public
* @param srting name of the channel tag
* @param string content of the channel tag
* @return void
*/
public function setChannelElement($elementName, $content)
{
$this->channels[$elementName] = $content ;
}
/**
* Set multiple channel elements from an array. Array elements
* should be 'channelName' => 'channelContent' format.
*
* @access public
* @param array array of channels
* @return void
*/
public function setChannelElementsFromArray($elementArray)
{
if(! is_array($elementArray)) return;
foreach ($elementArray as $elementName => $content)
{
$this->setChannelElement($elementName, $content);
}
}
/**
* Genarate the actual RSS/JSON file
*
* @access public
* @return void
*/
public function genarateFeed($withHeaders = true)
{
if ($withHeaders) {
if ($this->version == RSS2) {
header('Content-type: text/xml; charset=UTF-8');
// this line prevents Chrome 20 from prompting download
// used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss
header('X-content-type-options: nosniff');
} elseif ($this->version == JSON) {
header('Content-type: application/json; charset=UTF-8');
} elseif ($this->version == JSONP) {
header('Content-type: application/javascript; charset=UTF-8');
}
}
if ($this->version == JSON || $this->version == JSONP) {
$this->json = new stdClass();
}
$this->printHead();
$this->printChannels();
$this->printItems();
$this->printTale();
if ($this->version == JSON || $this->version == JSONP) {
echo json_encode($this->json);
}
}
public function &getItems()
{
return $this->items;
}
/**
* Create a new FeedItem.
*
* @access public
* @return object instance of FeedItem class
*/
public function createNewItem()
{
$Item = new FeedItem($this->version);
return $Item;
}
/**
* Add a FeedItem to the main class
*
* @access public
* @param object instance of FeedItem class
* @return void
*/
public function addItem($feedItem)
{
$this->items[] = $feedItem;
}
// Wrapper functions -------------------------------------------------------------------
/**
* Set the 'title' channel element
*
* @access public
* @param srting value of 'title' channel tag
* @return void
*/
public function setTitle($title)
{
$this->setChannelElement('title', $title);
}
/**
* Add a hub to the channel element
*
* @access public
* @param string URL
* @return void
*/
public function addHub($hub)
{
$this->hubs[] = $hub;
}
/**
* Set XSL URL
*
* @access public
* @param string URL
* @return void
*/
public function setXsl($xsl)
{
$this->xsl = $xsl;
}
/**
* Set self URL
*
* @access public
* @param string URL
* @return void
*/
public function setSelf($self)
{
$this->self = $self;
}
/**
* Set the 'description' channel element
*
* @access public
* @param srting value of 'description' channel tag
* @return void
*/
public function setDescription($description)
{
$tag = ($this->version == ATOM)? 'subtitle' : 'description';
$this->setChannelElement($tag, $description);
}
/**
* Set the 'link' channel element
*
* @access public
* @param srting value of 'link' channel tag
* @return void
*/
public function setLink($link)
{
$this->setChannelElement('link', $link);
}
/**
* Set the 'image' channel element
*
* @access public
* @param srting title of image
* @param srting link url of the imahe
* @param srting path url of the image
* @return void
*/
public function setImage($title, $link, $url)
{
$this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));
}
// End # public functions ----------------------------------------------
// Start # private functions ----------------------------------------------
/**
* Prints the xml and rss namespace
*
* @access private
* @return void
*/
private function printHead()
{
if ($this->version == RSS2)
{
$out = '<?xml version="1.0" encoding="utf-8"?>'."\n";
if ($this->xsl) $out .= '<?xml-stylesheet type="text/xsl" href="'.htmlspecialchars($this->xsl).'"?>' . PHP_EOL;
$out .= '<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">' . PHP_EOL;
echo $out;
}
elseif ($this->version == JSON || $this->version == JSONP)
{
$this->json->rss = array('@attributes' => array('version' => '2.0'));
}
}
/**
* Closes the open tags at the end of file
*
* @access private
* @return void
*/
private function printTale()
{
if ($this->version == RSS2)
{
echo '</channel>',PHP_EOL,'</rss>';
}
// do nothing for JSON
}
/**
* Creates a single node as xml format
*
* @access private
* @param string name of the tag
* @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format
* @param array Attributes(if any) in 'attrName' => 'attrValue' format
* @return string formatted xml tag
*/
private function makeNode($tagName, $tagContent, $attributes = null)
{
if ($this->version == RSS2)
{
$nodeText = '';
$attrText = '';
if (is_array($attributes))
{
foreach ($attributes as $key => $value)
{
$attrText .= " $key=\"$value\" ";
}
}
$nodeText .= "<{$tagName}{$attrText}>";
if (is_array($tagContent))
{
foreach ($tagContent as $key => $value)
{
$nodeText .= $this->makeNode($key, $value);
}
}
else
{
//$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);
$nodeText .= htmlspecialchars($tagContent);
}
//$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";
$nodeText .= "</$tagName>";
return $nodeText . PHP_EOL;
}
elseif ($this->version == JSON || $this->version == JSONP)
{
$tagName = (string)$tagName;
$tagName = strtr($tagName, ':', '_');
$node = null;
if (!$tagContent && is_array($attributes) && count($attributes))
{
$node = array('@attributes' => $this->json_keys($attributes));
} else {
if (is_array($tagContent)) {
$node = $this->json_keys($tagContent);
} else {
$node = $tagContent;
}
}
return $node;
}
return ''; // should not get here
}
private function json_keys(array $array) {
$new = array();
foreach ($array as $key => $val) {
if (is_string($key)) $key = strtr($key, ':', '_');
if (is_array($val)) {
$new[$key] = $this->json_keys($val);
} else {
$new[$key] = $val;
}
}
return $new;
}
/**
* @desc Print channels
* @access private
* @return void
*/
private function printChannels()
{
//Start channel tag
if ($this->version == RSS2) {
echo '<channel>' . PHP_EOL;
// add hubs
foreach ($this->hubs as $hub) {
//echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom'));
echo '<link rel="hub" href="'.htmlspecialchars($hub).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;
}
// add self
if (isset($this->self)) {
//echo $this->makeNode('link', '', array('rel'=>'self', 'href'=>$this->self, 'xmlns'=>'http://www.w3.org/2005/Atom'));
echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;
}
//Print Items of channel
foreach ($this->channels as $key => $value)
{
echo $this->makeNode($key, $value);
}
} elseif ($this->version == JSON || $this->version == JSONP) {
$this->json->rss['channel'] = (object)$this->json_keys($this->channels);
}
}
/**
* Prints formatted feed items
*
* @access private
* @return void
*/
private function printItems()
{
foreach ($this->items as $item) {
$itemElements = $item->getElements();
echo $this->startItem();
if ($this->version == JSON || $this->version == JSONP) {
$json_item = array();
}
foreach ($itemElements as $thisElement) {
foreach ($thisElement as $instance) {
if ($this->version == RSS2) {
echo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);
} elseif ($this->version == JSON || $this->version == JSONP) {
$_json_node = $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);
if (count($thisElement) > 1) {
$json_item[strtr($instance['name'], ':', '_')][] = $_json_node;
} else {
$json_item[strtr($instance['name'], ':', '_')] = $_json_node;
}
}
}
}
echo $this->endItem();
if ($this->version == JSON || $this->version == JSONP) {
if (count($this->items) > 1) {
$this->json->rss['channel']->item[] = $json_item;
} else {
$this->json->rss['channel']->item = $json_item;
}
}
}
}
/**
* Make the starting tag of channels
*
* @access private
* @return void
*/
private function startItem()
{
if ($this->version == RSS2)
{
echo '<item>' . PHP_EOL;
}
// nothing for JSON
}
/**
* Closes feed item tag
*
* @access private
* @return void
*/
private function endItem()
{
if ($this->version == RSS2)
{
echo '</item>' . PHP_EOL;
}
// nothing for JSON
}
// End # private functions ----------------------------------------------
}

View File

@ -134,6 +134,7 @@ class HTML5_TreeBuilder {
// Namespaces for foreign content
const NS_HTML = null; // to prevent DOM from requiring NS on everything
const NS_XHTML = 'http://www.w3.org/1999/xhtml';
const NS_MATHML = 'http://www.w3.org/1998/Math/MathML';
const NS_SVG = 'http://www.w3.org/2000/svg';
const NS_XLINK = 'http://www.w3.org/1999/xlink';
@ -3157,11 +3158,19 @@ class HTML5_TreeBuilder {
}
private function insertElement($token, $append = true) {
$el = $this->dom->createElementNS(self::NS_HTML, $token['name']);
//$el = $this->dom->createElementNS(self::NS_HTML, $token['name']);
$namespaceURI = strpos($token['name'], ':') ? self::NS_XHTML : self::NS_HTML;
$el = $this->dom->createElementNS($namespaceURI, $token['name']);
if (!empty($token['attr'])) {
foreach($token['attr'] as $attr) {
if(!$el->hasAttribute($attr['name'])) {
// mike@macgirvin.com 2011-11-17, check attribute name for
// validity (ignoring extenders and combiners) as illegal chars in names
// causes everything to abort
$valid = preg_match('/^[a-zA-Z\_\:]([\-a-zA-Z0-9\_\:\.]+$)/',$attr['name']);
if($attr['name'] && (!$el->hasAttribute($attr['name'])) && ($valid)) {
$el->setAttribute($attr['name'], $attr['value']);
}
}

View File

@ -1,404 +1,403 @@
<?php
/**
* Cookie Jar
*
* PHP class for handling cookies, as defined by the Netscape spec:
* <http://curl.haxx.se/rfc/cookie_spec.html>
*
* This class should be used to handle cookies (storing cookies from HTTP response messages, and
* sending out cookies in HTTP request messages). This has been adapted for FiveFilters.org
* from the original version used in HTTP Navigator. See http://www.keyvan.net/code/http-navigator/
*
* This class is mainly based on Cookies.pm <http://search.cpan.org/author/GAAS/libwww-perl-5.65/
* lib/HTTP/Cookies.pm> from the libwww-perl collection <http://www.linpro.no/lwp/>.
* Unlike Cookies.pm, this class only supports the Netscape cookie spec, not RFC 2965.
*
* @version 0.5
* @date 2011-03-15
* @see http://php.net/HttpRequestPool
* @author Keyvan Minoukadeh
* @copyright 2011 Keyvan Minoukadeh
* @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3
*/
class CookieJar
{
/**
* Cookies - array containing all cookies.
*
* <pre>
* Cookies are stored like this:
* [domain][path][name] = array
* where array is:
* 0 => value, 1 => secure, 2 => expires
* </pre>
* @var array
* @access private
*/
public $cookies = array();
public $debug = false;
/**
* Constructor
*/
function __construct() {
}
protected function debug($msg, $file=null, $line=null) {
if ($this->debug) {
$mem = round(memory_get_usage()/1024, 2);
$memPeak = round(memory_get_peak_usage()/1024, 2);
echo '* ',$msg;
if (isset($file, $line)) echo " ($file line $line)";
echo ' - mem used: ',$mem," (peak: $memPeak)\n";
ob_flush();
flush();
}
}
/**
* Get matching cookies
*
* Only use this method if you cannot use add_cookie_header(), for example, if you want to use
* this cookie jar class without using the request class.
*
* @param array $param associative array containing 'domain', 'path', 'secure' keys
* @return string
* @see add_cookie_header()
*/
public function getMatchingCookies($url)
{
if (($parts = @parse_url($url)) && isset($parts['scheme'], $parts['host'], $parts['path'])) {
$param['domain'] = $parts['host'];
$param['path'] = $parts['path'];
$param['secure'] = (strtolower($parts['scheme']) == 'https');
unset($parts);
} else {
return false;
}
// RFC 2965 notes:
// If multiple cookies satisfy the criteria above, they are ordered in
// the Cookie header such that those with more specific Path attributes
// precede those with less specific. Ordering with respect to other
// attributes (e.g., Domain) is unspecified.
$domain = $param['domain'];
if (strpos($domain, '.') === false) $domain .= '.local';
$request_path = $param['path'];
if ($request_path == '') $request_path = '/';
$request_secure = $param['secure'];
$now = time();
$matched_cookies = array();
// domain - find matching domains
$this->debug('Finding matching domains for '.$domain, __FILE__, __LINE__);
while (strpos($domain, '.') !== false) {
if (isset($this->cookies[$domain])) {
$this->debug(' domain match found: '.$domain);
$cookies =& $this->cookies[$domain];
} else {
$domain = $this->_reduce_domain($domain);
continue;
}
// paths - find matching paths starting from most specific
$this->debug(' - Finding matching paths for '.$request_path);
$paths = array_keys($cookies);
usort($paths, array($this, '_cmp_length'));
foreach ($paths as $path) {
// continue to next cookie if request path does not path-match cookie path
if (!$this->_path_match($request_path, $path)) continue;
// loop through cookie names
$this->debug(' path match found: '.$path);
foreach ($cookies[$path] as $name => $values) {
// if this cookie is secure but request isn't, continue to next cookie
if ($values[1] && !$request_secure) continue;
// if cookie is not a session cookie and has expired, continue to next cookie
if (is_int($values[2]) && ($values[2] < $now)) continue;
// cookie matches request
$this->debug(' cookie match: '.$name.'='.$values[0]);
$matched_cookies[] = $name.'='.$values[0];
}
}
$domain = $this->_reduce_domain($domain);
}
// return cookies
return implode('; ', $matched_cookies);
}
/**
* Parse Set-Cookie values.
*
* Only use this method if you cannot use extract_cookies(), for example, if you want to use
* this cookie jar class without using the response class.
*
* @param array $set_cookies array holding 1 or more "Set-Cookie" header values
* @param array $param associative array containing 'host', 'path' keys
* @return void
* @see extract_cookies()
*/
public function storeCookies($url, $set_cookies)
{
if (count($set_cookies) == 0) return;
$param = @parse_url($url);
if (!is_array($param) || !isset($param['host'])) return;
$request_host = $param['host'];
if (strpos($request_host, '.') === false) $request_host .= '.local';
$request_path = @$param['path'];
if ($request_path == '') $request_path = '/';
//
// loop through set-cookie headers
//
foreach ($set_cookies as $set_cookie) {
$this->debug('Parsing: '.$set_cookie);
// temporary cookie store (before adding to jar)
$tmp_cookie = array();
$param = explode(';', $set_cookie);
// loop through params
for ($x=0; $x<count($param); $x++) {
$key_val = explode('=', $param[$x], 2);
if (count($key_val) != 2) {
// if the first param isn't a name=value pair, continue to the next set-cookie
// header
if ($x == 0) continue 2;
// check for secure flag
if (strtolower(trim($key_val[0])) == 'secure') $tmp_cookie['secure'] = true;
// continue to next param
continue;
}
list($key, $val) = array_map('trim', $key_val);
// first name=value pair is the cookie name and value
// the name and value are stored under 'name' and 'value' to avoid conflicts
// with later parameters.
if ($x == 0) {
$tmp_cookie = array('name'=>$key, 'value'=>$val);
continue;
}
$key = strtolower($key);
if (in_array($key, array('expires', 'path', 'domain', 'secure'))) {
$tmp_cookie[$key] = $val;
}
}
//
// set cookie
//
// check domain
if (isset($tmp_cookie['domain']) && ($tmp_cookie['domain'] != $request_host) &&
($tmp_cookie['domain'] != ".$request_host")) {
$domain = $tmp_cookie['domain'];
if ((strpos($domain, '.') === false) && ($domain != 'local')) {
$this->debug(' - domain "'.$domain.'" has no dot and is not a local domain');
continue;
}
if (preg_match('/\.[0-9]+$/', $domain)) {
$this->debug(' - domain "'.$domain.'" appears to be an ip address');
continue;
}
if (substr($domain, 0, 1) != '.') $domain = ".$domain";
if (!$this->_domain_match($request_host, $domain)) {
$this->debug(' - request host "'.$request_host.'" does not domain-match "'.$domain.'"');
continue;
}
} else {
// if domain is not specified in the set-cookie header, domain will default to
// the request host
$domain = $request_host;
}
// check path
if (isset($tmp_cookie['path']) && ($tmp_cookie['path'] != '')) {
$path = urldecode($tmp_cookie['path']);
if (!$this->_path_match($request_path, $path)) {
$this->debug(' - request path "'.$request_path.'" does not path-match "'.$path.'"');
continue;
}
} else {
$path = $request_path;
$path = substr($path, 0, strrpos($path, '/'));
if ($path == '') $path = '/';
}
// check if secure
$secure = (isset($tmp_cookie['secure'])) ? true : false;
// check expiry
if (isset($tmp_cookie['expires'])) {
if (($expires = strtotime($tmp_cookie['expires'])) < 0) {
$expires = null;
}
} else {
$expires = null;
}
// set cookie
$this->set_cookie($domain, $path, $tmp_cookie['name'], $tmp_cookie['value'], $secure, $expires);
}
}
// return array of set-cookie values extracted from HTTP response headers (string $h)
public function extractCookies($h) {
$x = 0;
$lines = 0;
$headers = array();
$last_match = false;
$h = explode("\n", $h);
foreach ($h as $line) {
$line = rtrim($line);
$lines++;
$trimmed_line = trim($line);
if (isset($line_last)) {
// check if we have \r\n\r\n (indicating the end of headers)
// some servers will not use CRLF (\r\n), so we make CR (\r) optional.
// if (preg_match('/\015?\012\015?\012/', $line_last.$line)) {
// break;
// }
// As an alternative, we can check if the current trimmed line is empty
if ($trimmed_line == '') {
break;
}
// check for continuation line...
// RFC 2616 Section 2.2 "Basic Rules":
// HTTP/1.1 header field values can be folded onto multiple lines if the
// continuation line begins with a space or horizontal tab. All linear
// white space, including folding, has the same semantics as SP. A
// recipient MAY replace any linear white space with a single SP before
// interpreting the field value or forwarding the message downstream.
if ($last_match && preg_match('/^\s+(.*)/', $line, $match)) {
// append to previous header value
$headers[$x-1] .= ' '.rtrim($match[1]);
continue;
}
}
$line_last = $line;
// split header name and value
if (preg_match('/^Set-Cookie\s*:\s*(.*)/i', $line, $match)) {
$headers[$x++] = rtrim($match[1]);
$last_match = true;
} else {
$last_match = false;
}
}
return $headers;
}
/**
* Set Cookie
* @param string $domain
* @param string $path
* @param string $name cookie name
* @param string $value cookie value
* @param bool $secure
* @param int $expires expiry time (null if session cookie, <= 0 will delete cookie)
* @return void
*/
function set_cookie($domain, $path, $name, $value, $secure=false, $expires=null)
{
if ($domain == '') return;
if ($path == '') return;
if ($name == '') return;
// check if cookie needs to go
if (isset($expires) && ($expires <= 0)) {
if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);
return;
}
if ($value == '') return;
$this->cookies[$domain][$path][$name] = array($value, $secure, $expires);
return;
}
/**
* Clear cookies - [domain [,path [,name]]] - call method with no arguments to clear all cookies.
* @param string $domain
* @param string $path
* @param string $name
* @return void
*/
function clear($domain=null, $path=null, $name=null)
{
if (!isset($domain)) {
$this->cookies = array();
} elseif (!isset($path)) {
if (isset($this->cookies[$domain])) unset($this->cookies[$domain]);
} elseif (!isset($name)) {
if (isset($this->cookies[$domain][$path])) unset($this->cookies[$domain][$path]);
} elseif (isset($name)) {
if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);
}
}
/**
* Compare string length - used for sorting
* @access private
* @return int
*/
function _cmp_length($a, $b)
{
$la = strlen($a); $lb = strlen($b);
if ($la == $lb) return 0;
return ($la > $lb) ? -1 : 1;
}
/**
* Reduce domain
* @param string $domain
* @return string
* @access private
*/
function _reduce_domain($domain)
{
if ($domain == '') return '';
if (substr($domain, 0, 1) == '.') return substr($domain, 1);
return substr($domain, strpos($domain, '.'));
}
/**
* Path match - check if path1 path-matches path2
*
* From RFC 2965:
* <i>For two strings that represent paths, P1 and P2, P1 path-matches P2
* if P2 is a prefix of P1 (including the case where P1 and P2 string-
* compare equal). Thus, the string /tec/waldo path-matches /tec.</i>
* @param string $path1
* @param string $path2
* @return bool
* @access private
*/
function _path_match($path1, $path2)
{
return (substr($path1, 0, strlen($path2)) == $path2);
}
/**
* Domain match - check if domain1 domain-matches domain2
*
* A few extracts from RFC 2965:
* - A Set-Cookie2 from request-host y.x.foo.com for Domain=.foo.com
* would be rejected, because H is y.x and contains a dot.
*
* - A Set-Cookie2 from request-host x.foo.com for Domain=.foo.com
* would be accepted.
*
* - A Set-Cookie2 with Domain=.com or Domain=.com., will always be
* rejected, because there is no embedded dot.
*
* - A Set-Cookie2 from request-host example for Domain=.local will
* be accepted, because the effective host name for the request-
* host is example.local, and example.local domain-matches .local.
*
* I'm ignoring the first point for now (must check to see how other browsers handle
* this rule for Set-Cookie headers)
*
* @param string $domain1
* @param string $domain2
* @return bool
* @access private
*/
function _domain_match($domain1, $domain2)
{
$domain1 = strtolower($domain1);
$domain2 = strtolower($domain2);
while (strpos($domain1, '.') !== false) {
if ($domain1 == $domain2) return true;
$domain1 = $this->_reduce_domain($domain1);
continue;
}
return false;
}
}
?>
<?php
/**
* Cookie Jar
*
* PHP class for handling cookies, as defined by the Netscape spec:
* <http://curl.haxx.se/rfc/cookie_spec.html>
*
* This class should be used to handle cookies (storing cookies from HTTP response messages, and
* sending out cookies in HTTP request messages). This has been adapted for FiveFilters.org
* from the original version used in HTTP Navigator. See http://www.keyvan.net/code/http-navigator/
*
* This class is mainly based on Cookies.pm <http://search.cpan.org/author/GAAS/libwww-perl-5.65/
* lib/HTTP/Cookies.pm> from the libwww-perl collection <http://www.linpro.no/lwp/>.
* Unlike Cookies.pm, this class only supports the Netscape cookie spec, not RFC 2965.
*
* @version 0.5
* @date 2011-03-15
* @see http://php.net/HttpRequestPool
* @author Keyvan Minoukadeh
* @copyright 2011 Keyvan Minoukadeh
* @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3
*/
class CookieJar
{
/**
* Cookies - array containing all cookies.
*
* <pre>
* Cookies are stored like this:
* [domain][path][name] = array
* where array is:
* 0 => value, 1 => secure, 2 => expires
* </pre>
* @var array
* @access private
*/
public $cookies = array();
public $debug = false;
/**
* Constructor
*/
function __construct() {
}
protected function debug($msg, $file=null, $line=null) {
if ($this->debug) {
$mem = round(memory_get_usage()/1024, 2);
$memPeak = round(memory_get_peak_usage()/1024, 2);
echo '* ',$msg;
if (isset($file, $line)) echo " ($file line $line)";
echo ' - mem used: ',$mem," (peak: $memPeak)\n";
ob_flush();
flush();
}
}
/**
* Get matching cookies
*
* Only use this method if you cannot use add_cookie_header(), for example, if you want to use
* this cookie jar class without using the request class.
*
* @param array $param associative array containing 'domain', 'path', 'secure' keys
* @return string
* @see add_cookie_header()
*/
public function getMatchingCookies($url)
{
if (($parts = @parse_url($url)) && isset($parts['scheme'], $parts['host'], $parts['path'])) {
$param['domain'] = $parts['host'];
$param['path'] = $parts['path'];
$param['secure'] = (strtolower($parts['scheme']) == 'https');
unset($parts);
} else {
return false;
}
// RFC 2965 notes:
// If multiple cookies satisfy the criteria above, they are ordered in
// the Cookie header such that those with more specific Path attributes
// precede those with less specific. Ordering with respect to other
// attributes (e.g., Domain) is unspecified.
$domain = $param['domain'];
if (strpos($domain, '.') === false) $domain .= '.local';
$request_path = $param['path'];
if ($request_path == '') $request_path = '/';
$request_secure = $param['secure'];
$now = time();
$matched_cookies = array();
// domain - find matching domains
$this->debug('Finding matching domains for '.$domain, __FILE__, __LINE__);
while (strpos($domain, '.') !== false) {
if (isset($this->cookies[$domain])) {
$this->debug(' domain match found: '.$domain);
$cookies =& $this->cookies[$domain];
} else {
$domain = $this->_reduce_domain($domain);
continue;
}
// paths - find matching paths starting from most specific
$this->debug(' - Finding matching paths for '.$request_path);
$paths = array_keys($cookies);
usort($paths, array($this, '_cmp_length'));
foreach ($paths as $path) {
// continue to next cookie if request path does not path-match cookie path
if (!$this->_path_match($request_path, $path)) continue;
// loop through cookie names
$this->debug(' path match found: '.$path);
foreach ($cookies[$path] as $name => $values) {
// if this cookie is secure but request isn't, continue to next cookie
if ($values[1] && !$request_secure) continue;
// if cookie is not a session cookie and has expired, continue to next cookie
if (is_int($values[2]) && ($values[2] < $now)) continue;
// cookie matches request
$this->debug(' cookie match: '.$name.'='.$values[0]);
$matched_cookies[] = $name.'='.$values[0];
}
}
$domain = $this->_reduce_domain($domain);
}
// return cookies
return implode('; ', $matched_cookies);
}
/**
* Parse Set-Cookie values.
*
* Only use this method if you cannot use extract_cookies(), for example, if you want to use
* this cookie jar class without using the response class.
*
* @param array $set_cookies array holding 1 or more "Set-Cookie" header values
* @param array $param associative array containing 'host', 'path' keys
* @return void
* @see extract_cookies()
*/
public function storeCookies($url, $set_cookies)
{
if (count($set_cookies) == 0) return;
$param = @parse_url($url);
if (!is_array($param) || !isset($param['host'])) return;
$request_host = $param['host'];
if (strpos($request_host, '.') === false) $request_host .= '.local';
$request_path = @$param['path'];
if ($request_path == '') $request_path = '/';
//
// loop through set-cookie headers
//
foreach ($set_cookies as $set_cookie) {
$this->debug('Parsing: '.$set_cookie);
// temporary cookie store (before adding to jar)
$tmp_cookie = array();
$param = explode(';', $set_cookie);
// loop through params
for ($x=0; $x<count($param); $x++) {
$key_val = explode('=', $param[$x], 2);
if (count($key_val) != 2) {
// if the first param isn't a name=value pair, continue to the next set-cookie
// header
if ($x == 0) continue 2;
// check for secure flag
if (strtolower(trim($key_val[0])) == 'secure') $tmp_cookie['secure'] = true;
// continue to next param
continue;
}
list($key, $val) = array_map('trim', $key_val);
// first name=value pair is the cookie name and value
// the name and value are stored under 'name' and 'value' to avoid conflicts
// with later parameters.
if ($x == 0) {
$tmp_cookie = array('name'=>$key, 'value'=>$val);
continue;
}
$key = strtolower($key);
if (in_array($key, array('expires', 'path', 'domain', 'secure'))) {
$tmp_cookie[$key] = $val;
}
}
//
// set cookie
//
// check domain
if (isset($tmp_cookie['domain']) && ($tmp_cookie['domain'] != $request_host) &&
($tmp_cookie['domain'] != ".$request_host")) {
$domain = $tmp_cookie['domain'];
if ((strpos($domain, '.') === false) && ($domain != 'local')) {
$this->debug(' - domain "'.$domain.'" has no dot and is not a local domain');
continue;
}
if (preg_match('/\.[0-9]+$/', $domain)) {
$this->debug(' - domain "'.$domain.'" appears to be an ip address');
continue;
}
if (substr($domain, 0, 1) != '.') $domain = ".$domain";
if (!$this->_domain_match($request_host, $domain)) {
$this->debug(' - request host "'.$request_host.'" does not domain-match "'.$domain.'"');
continue;
}
} else {
// if domain is not specified in the set-cookie header, domain will default to
// the request host
$domain = $request_host;
}
// check path
if (isset($tmp_cookie['path']) && ($tmp_cookie['path'] != '')) {
$path = urldecode($tmp_cookie['path']);
if (!$this->_path_match($request_path, $path)) {
$this->debug(' - request path "'.$request_path.'" does not path-match "'.$path.'"');
continue;
}
} else {
$path = $request_path;
$path = substr($path, 0, strrpos($path, '/'));
if ($path == '') $path = '/';
}
// check if secure
$secure = (isset($tmp_cookie['secure'])) ? true : false;
// check expiry
if (isset($tmp_cookie['expires'])) {
if (($expires = strtotime($tmp_cookie['expires'])) < 0) {
$expires = null;
}
} else {
$expires = null;
}
// set cookie
$this->set_cookie($domain, $path, $tmp_cookie['name'], $tmp_cookie['value'], $secure, $expires);
}
}
// return array of set-cookie values extracted from HTTP response headers (string $h)
public function extractCookies($h) {
$x = 0;
$lines = 0;
$headers = array();
$last_match = false;
$h = explode("\n", $h);
foreach ($h as $line) {
$line = rtrim($line);
$lines++;
$trimmed_line = trim($line);
if (isset($line_last)) {
// check if we have \r\n\r\n (indicating the end of headers)
// some servers will not use CRLF (\r\n), so we make CR (\r) optional.
// if (preg_match('/\015?\012\015?\012/', $line_last.$line)) {
// break;
// }
// As an alternative, we can check if the current trimmed line is empty
if ($trimmed_line == '') {
break;
}
// check for continuation line...
// RFC 2616 Section 2.2 "Basic Rules":
// HTTP/1.1 header field values can be folded onto multiple lines if the
// continuation line begins with a space or horizontal tab. All linear
// white space, including folding, has the same semantics as SP. A
// recipient MAY replace any linear white space with a single SP before
// interpreting the field value or forwarding the message downstream.
if ($last_match && preg_match('/^\s+(.*)/', $line, $match)) {
// append to previous header value
$headers[$x-1] .= ' '.rtrim($match[1]);
continue;
}
}
$line_last = $line;
// split header name and value
if (preg_match('/^Set-Cookie\s*:\s*(.*)/i', $line, $match)) {
$headers[$x++] = rtrim($match[1]);
$last_match = true;
} else {
$last_match = false;
}
}
return $headers;
}
/**
* Set Cookie
* @param string $domain
* @param string $path
* @param string $name cookie name
* @param string $value cookie value
* @param bool $secure
* @param int $expires expiry time (null if session cookie, <= 0 will delete cookie)
* @return void
*/
function set_cookie($domain, $path, $name, $value, $secure=false, $expires=null)
{
if ($domain == '') return;
if ($path == '') return;
if ($name == '') return;
// check if cookie needs to go
if (isset($expires) && ($expires <= 0)) {
if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);
return;
}
if ($value == '') return;
$this->cookies[$domain][$path][$name] = array($value, $secure, $expires);
return;
}
/**
* Clear cookies - [domain [,path [,name]]] - call method with no arguments to clear all cookies.
* @param string $domain
* @param string $path
* @param string $name
* @return void
*/
function clear($domain=null, $path=null, $name=null)
{
if (!isset($domain)) {
$this->cookies = array();
} elseif (!isset($path)) {
if (isset($this->cookies[$domain])) unset($this->cookies[$domain]);
} elseif (!isset($name)) {
if (isset($this->cookies[$domain][$path])) unset($this->cookies[$domain][$path]);
} elseif (isset($name)) {
if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);
}
}
/**
* Compare string length - used for sorting
* @access private
* @return int
*/
function _cmp_length($a, $b)
{
$la = strlen($a); $lb = strlen($b);
if ($la == $lb) return 0;
return ($la > $lb) ? -1 : 1;
}
/**
* Reduce domain
* @param string $domain
* @return string
* @access private
*/
function _reduce_domain($domain)
{
if ($domain == '') return '';
if (substr($domain, 0, 1) == '.') return substr($domain, 1);
return substr($domain, strpos($domain, '.'));
}
/**
* Path match - check if path1 path-matches path2
*
* From RFC 2965:
* <i>For two strings that represent paths, P1 and P2, P1 path-matches P2
* if P2 is a prefix of P1 (including the case where P1 and P2 string-
* compare equal). Thus, the string /tec/waldo path-matches /tec.</i>
* @param string $path1
* @param string $path2
* @return bool
* @access private
*/
function _path_match($path1, $path2)
{
return (substr($path1, 0, strlen($path2)) == $path2);
}
/**
* Domain match - check if domain1 domain-matches domain2
*
* A few extracts from RFC 2965:
* - A Set-Cookie2 from request-host y.x.foo.com for Domain=.foo.com
* would be rejected, because H is y.x and contains a dot.
*
* - A Set-Cookie2 from request-host x.foo.com for Domain=.foo.com
* would be accepted.
*
* - A Set-Cookie2 with Domain=.com or Domain=.com., will always be
* rejected, because there is no embedded dot.
*
* - A Set-Cookie2 from request-host example for Domain=.local will
* be accepted, because the effective host name for the request-
* host is example.local, and example.local domain-matches .local.
*
* I'm ignoring the first point for now (must check to see how other browsers handle
* this rule for Set-Cookie headers)
*
* @param string $domain1
* @param string $domain2
* @return bool
* @access private
*/
function _domain_match($domain1, $domain2)
{
$domain1 = strtolower($domain1);
$domain2 = strtolower($domain2);
while (strpos($domain1, '.') !== false) {
if ($domain1 == $domain2) return true;
$domain1 = $this->_reduce_domain($domain1);
continue;
}
return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +1,78 @@
<?php
/**
* Humble HTTP Agent extension for SimplePie_File
*
* This class is designed to extend and override SimplePie_File
* in order to prevent duplicate HTTP requests being sent out.
* The idea is to initialise an instance of Humble HTTP Agent
* and attach it, to a static class variable, of this class.
* SimplePie will then automatically initialise this class
*
* @date 2011-02-28
*/
class SimplePie_HumbleHttpAgent extends SimplePie_File
{
protected static $agent;
var $url;
var $useragent;
var $success = true;
var $headers = array();
var $body;
var $status_code;
var $redirects = 0;
var $error;
var $method = SIMPLEPIE_FILE_SOURCE_NONE;
public static function set_agent(HumbleHttpAgent $agent) {
self::$agent = $agent;
}
public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {
if (class_exists('idna_convert'))
{
$idn = new idna_convert();
$parsed = SimplePie_Misc::parse_url($url);
$url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
}
$this->url = $url;
$this->useragent = $useragent;
if (preg_match('/^http(s)?:\/\//i', $url))
{
if (!is_array($headers))
{
$headers = array();
}
$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
$headers2 = array();
foreach ($headers as $key => $value) {
$headers2[] = "$key: $value";
}
//TODO: allow for HTTP headers
// curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
$response = self::$agent->get($url);
if ($response === false || !isset($response['status_code'])) {
$this->error = 'failed to fetch URL';
$this->success = false;
} else {
// The extra lines at the end are there to satisfy SimplePie's HTTP parser.
// The class expects a full HTTP message, whereas we're giving it only
// headers - the new lines indicate the start of the body.
$parser = new SimplePie_HTTP_Parser($response['headers']."\r\n\r\n");
if ($parser->parse()) {
$this->headers = $parser->headers;
//$this->body = $parser->body;
$this->body = $response['body'];
$this->status_code = $parser->status_code;
}
}
}
else
{
$this->error = 'invalid URL';
$this->success = false;
}
}
}
?>
<?php
/**
* Humble HTTP Agent extension for SimplePie_File
*
* This class is designed to extend and override SimplePie_File
* in order to prevent duplicate HTTP requests being sent out.
* The idea is to initialise an instance of Humble HTTP Agent
* and attach it, to a static class variable, of this class.
* SimplePie will then automatically initialise this class
*
* @date 2011-02-28
*/
class SimplePie_HumbleHttpAgent extends SimplePie_File
{
protected static $agent;
var $url;
var $useragent;
var $success = true;
var $headers = array();
var $body;
var $status_code;
var $redirects = 0;
var $error;
var $method = SIMPLEPIE_FILE_SOURCE_NONE;
public static function set_agent(HumbleHttpAgent $agent) {
self::$agent = $agent;
}
public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {
if (class_exists('idna_convert'))
{
$idn = new idna_convert();
$parsed = SimplePie_Misc::parse_url($url);
$url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
}
$this->url = $url;
$this->useragent = $useragent;
if (preg_match('/^http(s)?:\/\//i', $url))
{
if (!is_array($headers))
{
$headers = array();
}
$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
$headers2 = array();
foreach ($headers as $key => $value) {
$headers2[] = "$key: $value";
}
//TODO: allow for HTTP headers
// curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
$response = self::$agent->get($url);
if ($response === false || !isset($response['status_code'])) {
$this->error = 'failed to fetch URL';
$this->success = false;
} else {
// The extra lines at the end are there to satisfy SimplePie's HTTP parser.
// The class expects a full HTTP message, whereas we're giving it only
// headers - the new lines indicate the start of the body.
$parser = new SimplePie_HTTP_Parser($response['headers']."\r\n\r\n");
if ($parser->parse()) {
$this->headers = $parser->headers;
//$this->body = $parser->body;
$this->body = $response['body'];
$this->status_code = $parser->status_code;
}
}
}
else
{
$this->error = 'invalid URL';
$this->success = false;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
<?php
class Text_LanguageDetect_Exception extends Exception
{
/**
* Database file could not be found
*/
const DB_NOT_FOUND = 10;
/**
* Database file found, but not readable
*/
const DB_NOT_READABLE = 11;
/**
* Database file is empty
*/
const DB_EMPTY = 12;
/**
* Database contents is not a PHP array
*/
const DB_NOT_ARRAY = 13;
/**
* Magic quotes are activated
*/
const MAGIC_QUOTES = 14;
/**
* Parameter of invalid type passed to method
*/
const PARAM_TYPE = 20;
/**
* Character in parameter is invalid
*/
const INVALID_CHAR = 21;
/**
* Language is not in the database
*/
const UNKNOWN_LANGUAGE = 30;
/**
* Error during block detection
*/
const BLOCK_DETECTION = 40;
/**
* Error while clustering languages
*/
const NO_HIGHEST_KEY = 50;
}

View File

@ -0,0 +1,339 @@
<?php
/**
* Part of Text_LanguageDetect
*
* PHP version 5
*
* @category Text
* @package Text_LanguageDetect
* @author Christian Weiske <cweiske@php.net>
* @copyright 2011 Christian Weiske <cweiske@php.net>
* @license http://www.debian.org/misc/bsd.license BSD
* @version SVN: $Id$
* @link http://pear.php.net/package/Text_LanguageDetect/
*/
/**
* Provides a mapping between the languages from lang.dat and the
* ISO 639-1 and ISO-639-2 codes.
*
* Note that this class contains only languages that exist in lang.dat.
*
* @category Text
* @package Text_LanguageDetect
* @author Christian Weiske <cweiske@php.net>
* @copyright 2011 Christian Weiske <cweiske@php.net>
* @license http://www.debian.org/misc/bsd.license BSD
* @link http://www.loc.gov/standards/iso639-2/php/code_list.php
*/
class Text_LanguageDetect_ISO639
{
/**
* Maps all language names from the language database to the
* ISO 639-1 2-letter language code.
*
* NULL indicates that there is no 2-letter code.
*
* @var array
*/
public static $nameToCode2 = array(
'albanian' => 'sq',
'arabic' => 'ar',
'azeri' => 'az',
'bengali' => 'bn',
'bulgarian' => 'bg',
'cebuano' => null,
'croatian' => 'hr',
'czech' => 'cs',
'danish' => 'da',
'dutch' => 'nl',
'english' => 'en',
'estonian' => 'et',
'farsi' => 'fa',
'finnish' => 'fi',
'french' => 'fr',
'german' => 'de',
'hausa' => 'ha',
'hawaiian' => null,
'hindi' => 'hi',
'hungarian' => 'hu',
'icelandic' => 'is',
'indonesian' => 'id',
'italian' => 'it',
'kazakh' => 'kk',
'kyrgyz' => 'ky',
'latin' => 'la',
'latvian' => 'lv',
'lithuanian' => 'lt',
'macedonian' => 'mk',
'mongolian' => 'mn',
'nepali' => 'ne',
'norwegian' => 'no',
'pashto' => 'ps',
'pidgin' => null,
'polish' => 'pl',
'portuguese' => 'pt',
'romanian' => 'ro',
'russian' => 'ru',
'serbian' => 'sr',
'slovak' => 'sk',
'slovene' => 'sl',
'somali' => 'so',
'spanish' => 'es',
'swahili' => 'sw',
'swedish' => 'sv',
'tagalog' => 'tl',
'turkish' => 'tr',
'ukrainian' => 'uk',
'urdu' => 'ur',
'uzbek' => 'uz',
'vietnamese' => 'vi',
'welsh' => 'cy',
);
/**
* Maps all language names from the language database to the
* ISO 639-2 3-letter language code.
*
* @var array
*/
public static $nameToCode3 = array(
'albanian' => 'sqi',
'arabic' => 'ara',
'azeri' => 'aze',
'bengali' => 'ben',
'bulgarian' => 'bul',
'cebuano' => 'ceb',
'croatian' => 'hrv',
'czech' => 'ces',
'danish' => 'dan',
'dutch' => 'nld',
'english' => 'eng',
'estonian' => 'est',
'farsi' => 'fas',
'finnish' => 'fin',
'french' => 'fra',
'german' => 'deu',
'hausa' => 'hau',
'hawaiian' => 'haw',
'hindi' => 'hin',
'hungarian' => 'hun',
'icelandic' => 'isl',
'indonesian' => 'ind',
'italian' => 'ita',
'kazakh' => 'kaz',
'kyrgyz' => 'kir',
'latin' => 'lat',
'latvian' => 'lav',
'lithuanian' => 'lit',
'macedonian' => 'mkd',
'mongolian' => 'mon',
'nepali' => 'nep',
'norwegian' => 'nor',
'pashto' => 'pus',
'pidgin' => 'crp',
'polish' => 'pol',
'portuguese' => 'por',
'romanian' => 'ron',
'russian' => 'rus',
'serbian' => 'srp',
'slovak' => 'slk',
'slovene' => 'slv',
'somali' => 'som',
'spanish' => 'spa',
'swahili' => 'swa',
'swedish' => 'swe',
'tagalog' => 'tgl',
'turkish' => 'tur',
'ukrainian' => 'ukr',
'urdu' => 'urd',
'uzbek' => 'uzb',
'vietnamese' => 'vie',
'welsh' => 'cym',
);
/**
* Maps ISO 639-1 2-letter language codes to the language names
* in the language database
*
* Not all languages have a 2 letter code, so some are missing
*
* @var array
*/
public static $code2ToName = array(
'ar' => 'arabic',
'az' => 'azeri',
'bg' => 'bulgarian',
'bn' => 'bengali',
'cs' => 'czech',
'cy' => 'welsh',
'da' => 'danish',
'de' => 'german',
'en' => 'english',
'es' => 'spanish',
'et' => 'estonian',
'fa' => 'farsi',
'fi' => 'finnish',
'fr' => 'french',
'ha' => 'hausa',
'hi' => 'hindi',
'hr' => 'croatian',
'hu' => 'hungarian',
'id' => 'indonesian',
'is' => 'icelandic',
'it' => 'italian',
'kk' => 'kazakh',
'ky' => 'kyrgyz',
'la' => 'latin',
'lt' => 'lithuanian',
'lv' => 'latvian',
'mk' => 'macedonian',
'mn' => 'mongolian',
'ne' => 'nepali',
'nl' => 'dutch',
'no' => 'norwegian',
'pl' => 'polish',
'ps' => 'pashto',
'pt' => 'portuguese',
'ro' => 'romanian',
'ru' => 'russian',
'sk' => 'slovak',
'sl' => 'slovene',
'so' => 'somali',
'sq' => 'albanian',
'sr' => 'serbian',
'sv' => 'swedish',
'sw' => 'swahili',
'tl' => 'tagalog',
'tr' => 'turkish',
'uk' => 'ukrainian',
'ur' => 'urdu',
'uz' => 'uzbek',
'vi' => 'vietnamese',
);
/**
* Maps ISO 639-2 3-letter language codes to the language names
* in the language database.
*
* @var array
*/
public static $code3ToName = array(
'ara' => 'arabic',
'aze' => 'azeri',
'ben' => 'bengali',
'bul' => 'bulgarian',
'ceb' => 'cebuano',
'ces' => 'czech',
'crp' => 'pidgin',
'cym' => 'welsh',
'dan' => 'danish',
'deu' => 'german',
'eng' => 'english',
'est' => 'estonian',
'fas' => 'farsi',
'fin' => 'finnish',
'fra' => 'french',
'hau' => 'hausa',
'haw' => 'hawaiian',
'hin' => 'hindi',
'hrv' => 'croatian',
'hun' => 'hungarian',
'ind' => 'indonesian',
'isl' => 'icelandic',
'ita' => 'italian',
'kaz' => 'kazakh',
'kir' => 'kyrgyz',
'lat' => 'latin',
'lav' => 'latvian',
'lit' => 'lithuanian',
'mkd' => 'macedonian',
'mon' => 'mongolian',
'nep' => 'nepali',
'nld' => 'dutch',
'nor' => 'norwegian',
'pol' => 'polish',
'por' => 'portuguese',
'pus' => 'pashto',
'rom' => 'romanian',
'rus' => 'russian',
'slk' => 'slovak',
'slv' => 'slovene',
'som' => 'somali',
'spa' => 'spanish',
'sqi' => 'albanian',
'srp' => 'serbian',
'swa' => 'swahili',
'swe' => 'swedish',
'tgl' => 'tagalog',
'tur' => 'turkish',
'ukr' => 'ukrainian',
'urd' => 'urdu',
'uzb' => 'uzbek',
'vie' => 'vietnamese',
);
/**
* Returns the 2-letter ISO 639-1 code for the given language name.
*
* @param string $lang English language name like "swedish"
*
* @return string Two-letter language code (e.g. "sv") or NULL if not found
*/
public static function nameToCode2($lang)
{
$lang = strtolower($lang);
if (!isset(self::$nameToCode2[$lang])) {
return null;
}
return self::$nameToCode2[$lang];
}
/**
* Returns the 3-letter ISO 639-2 code for the given language name.
*
* @param string $lang English language name like "swedish"
*
* @return string Three-letter language code (e.g. "swe") or NULL if not found
*/
public static function nameToCode3($lang)
{
$lang = strtolower($lang);
if (!isset(self::$nameToCode3[$lang])) {
return null;
}
return self::$nameToCode3[$lang];
}
/**
* Returns the language name for the given 2-letter ISO 639-1 code.
*
* @param string $code Two-letter language code (e.g. "sv")
*
* @return string English language name like "swedish"
*/
public static function code2ToName($code)
{
$lang = strtolower($code);
if (!isset(self::$code2ToName[$code])) {
return null;
}
return self::$code2ToName[$code];
}
/**
* Returns the language name for the given 3-letter ISO 639-2 code.
*
* @param string $code Three-letter language code (e.g. "swe")
*
* @return string English language name like "swedish"
*/
public static function code3ToName($code)
{
$lang = strtolower($code);
if (!isset(self::$code3ToName[$code])) {
return null;
}
return self::$code3ToName[$code];
}
}

View File

@ -8,7 +8,7 @@
* @author Nicholas Pisarro
* @copyright 2006
* @license BSD
* @version CVS: $Id: Parser.php,v 1.5 2006/03/11 05:45:05 taak Exp $
* @version CVS: $Id: Parser.php 322327 2012-01-15 17:55:59Z cweiske $
* @link http://pear.php.net/package/Text_LanguageDetect/
* @link http://langdetect.blogspot.com/
*/
@ -28,7 +28,7 @@
* @author Nicholas Pisarro
* @copyright 2006
* @license BSD
* @version release: 0.2.3
* @version release: 0.3.0
*/
class Text_LanguageDetect_Parser extends Text_LanguageDetect
{
@ -102,21 +102,17 @@ class Text_LanguageDetect_Parser extends Text_LanguageDetect
* @access private
* @param string $string string to be parsed
*/
function Text_LanguageDetect_Parser($string, $db=null, $unicode_db=null) {
if (isset($db)) $this->_db_filename = $db;
if (isset($unicode_db)) $this->_unicode_db_filename = $unicode_db;
function Text_LanguageDetect_Parser($string) {
$this->_string = $string;
}
/**
* Returns true if a string is suitable for parsing
*
* @static
* @access public
* @param string $str input string to test
* @return bool true if acceptable, false if not
*/
function validateString($str) {
public static function validateString($str) {
if (!empty($str) && strlen($str) > 3 && preg_match('/\S/', $str)) {
return true;
} else {
@ -222,8 +218,7 @@ class Text_LanguageDetect_Parser extends Text_LanguageDetect
// unicode startup
if ($this->_compile_unicode) {
$blocks =& $this->_read_unicode_block_db();
$blocks = $this->_read_unicode_block_db();
$block_count = count($blocks);
$skipped_count = 0;
@ -349,6 +344,4 @@ class Text_LanguageDetect_Parser extends Text_LanguageDetect
}
}
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
?>
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

2281
inc/3rdparty/libraries/readability/Readability.php vendored Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,8 @@
// Author: Keyvan Minoukadeh
// Copyright (c) 2013 Keyvan Minoukadeh
// License: AGPLv3
// Version: 3.1
// Date: 2013-03-05
// Version: 3.2
// Date: 2013-05-13
// More info: http://fivefilters.org/content-only/
// Help: http://help.fivefilters.org
@ -25,14 +25,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Usage
// -----
// Request this file passing it your feed in the querystring: makefulltextfeed.php?url=mysite.org
// The following options can be passed in the querystring:
// * URL: url=[feed or website url] (required, should be URL-encoded - in php: urlencode($url))
// * URL points to HTML (not feed): html=true (optional, by default it's automatically detected)
// * API key: key=[api key] (optional, refer to config.php)
// * Max entries to process: max=[max number of items] (optional)
// Request this file passing it a web page or feed URL in the querystring: makefulltextfeed.php?url=example.org/article
// For more request parameters, see http://help.fivefilters.org/customer/portal/articles/226660-usage
error_reporting(E_ALL ^ E_NOTICE);
//error_reporting(E_ALL ^ E_NOTICE);
ini_set("display_errors", 1);
@set_time_limit(120);
@ -55,42 +51,8 @@ if (get_magic_quotes_gpc()) {
// set include path
set_include_path(realpath(dirname(__FILE__).'/libraries').PATH_SEPARATOR.get_include_path());
// Autoloading of classes allows us to include files only when they're
// needed. If we've got a cached copy, for example, only Zend_Cache is loaded.
function autoload($class_name) {
static $dir = null;
if ($dir === null) $dir = dirname(__FILE__).'/libraries/';
static $mapping = array(
// Include FeedCreator for RSS/Atom creation
'FeedWriter' => 'feedwriter/FeedWriter.php',
'FeedItem' => 'feedwriter/FeedItem.php',
// Include ContentExtractor and Readability for identifying and extracting content from URLs
'ContentExtractor' => 'content-extractor/ContentExtractor.php',
'SiteConfig' => 'content-extractor/SiteConfig.php',
'Readability' => 'readability/Readability.php',
// Include Humble HTTP Agent to allow parallel requests and response caching
'HumbleHttpAgent' => 'humble-http-agent/HumbleHttpAgent.php',
'SimplePie_HumbleHttpAgent' => 'humble-http-agent/SimplePie_HumbleHttpAgent.php',
'CookieJar' => 'humble-http-agent/CookieJar.php',
// Include Zend Cache to improve performance (cache results)
'Zend_Cache' => 'Zend/Cache.php',
// Language detect
'Text_LanguageDetect' => 'language-detect/LanguageDetect.php',
// HTML5 Lib
'HTML5_Parser' => 'html5/Parser.php',
// htmLawed - used if XSS filter is enabled (xss_filter)
'htmLawed' => 'htmLawed/htmLawed.php'
);
if (isset($mapping[$class_name])) {
debug("** Loading class $class_name ({$mapping[$class_name]})");
require $dir.$mapping[$class_name];
return true;
} else {
return false;
}
}
spl_autoload_register('autoload');
require dirname(__FILE__).'/libraries/simplepie/autoloader.php';
require_once dirname(__FILE__).'/makefulltextfeedHelpers.php';
////////////////////////////////
// Load config file
@ -110,8 +72,8 @@ header('X-Robots-Tag: noindex, nofollow');
////////////////////////////////
// Check if service is enabled
////////////////////////////////
if (!$options->enabled) {
die('The full-text RSS service is currently disabled');
if (!$options->enabled) {
die('The full-text RSS service is currently disabled');
}
////////////////////////////////
@ -155,8 +117,8 @@ $options->smart_cache = $options->smart_cache && function_exists('apc_inc');
////////////////////////////////
// Check for feed URL
////////////////////////////////
if (!isset($_GET['url'])) {
die('No URL supplied');
if (!isset($_GET['url'])) {
die('No URL supplied');
}
$url = trim($_GET['url']);
if (strtolower(substr($url, 0, 7)) == 'feed://') {
@ -195,10 +157,12 @@ if (isset($_GET['key']) && ($key_index = array_search($_GET['key'], $options->ap
if (isset($_GET['links'])) $redirect .= '&links='.urlencode($_GET['links']);
if (isset($_GET['exc'])) $redirect .= '&exc='.urlencode($_GET['exc']);
if (isset($_GET['format'])) $redirect .= '&format='.urlencode($_GET['format']);
if (isset($_GET['callback'])) $redirect .= '&callback='.urlencode($_GET['callback']);
if (isset($_GET['callback'])) $redirect .= '&callback='.urlencode($_GET['callback']);
if (isset($_GET['l'])) $redirect .= '&l='.urlencode($_GET['l']);
if (isset($_GET['xss'])) $redirect .= '&xss';
if (isset($_GET['use_extracted_title'])) $redirect .= '&use_extracted_title';
if (isset($_GET['content'])) $redirect .= '&content='.urlencode($_GET['content']);
if (isset($_GET['summary'])) $redirect .= '&summary='.urlencode($_GET['summary']);
if (isset($_GET['debug'])) $redirect .= '&debug';
if ($debug_mode) {
debug('Redirecting to hide access key, follow URL below to continue');
@ -211,7 +175,7 @@ if (isset($_GET['key']) && ($key_index = array_search($_GET['key'], $options->ap
///////////////////////////////////////////////
// Set timezone.
// Prevents warnings, but needs more testing -
// Prevents warnings, but needs more testing -
// perhaps if timezone is set in php.ini we
// don't need to set it at all...
///////////////////////////////////////////////
@ -233,7 +197,7 @@ if (isset($_GET['key']) && isset($_GET['hash']) && isset($options->api_keys[(int
}
$key_index = ($valid_key) ? (int)$_GET['key'] : 0;
if (!$valid_key && $options->key_required) {
die('A valid key must be supplied');
die('A valid key must be supplied');
}
if (!$valid_key && isset($_GET['key']) && $_GET['key'] != '') {
die('The entered key is invalid');
@ -284,6 +248,28 @@ if ($options->favour_feed_titles == 'user') {
$favour_feed_titles = $options->favour_feed_titles;
}
///////////////////////////////////////////////
// Include full content in output?
///////////////////////////////////////////////
if ($options->content === 'user') {
if (isset($_GET['content']) && $_GET['content'] === '0') {
$options->content = false;
} else {
$options->content = true;
}
}
///////////////////////////////////////////////
// Include summaries in output?
///////////////////////////////////////////////
if ($options->summary === 'user') {
if (isset($_GET['summary']) && $_GET['summary'] === '1') {
$options->summary = true;
} else {
$options->summary = false;
}
}
///////////////////////////////////////////////
// Exclude items if extraction fails
///////////////////////////////////////////////
@ -306,15 +292,6 @@ if ($options->detect_language === 'user') {
$detect_language = $options->detect_language;
}
if ($detect_language >= 2) {
$language_codes = array('albanian' => 'sq','arabic' => 'ar','azeri' => 'az','bengali' => 'bn','bulgarian' => 'bg',
'cebuano' => 'ceb', // ISO 639-2
'croatian' => 'hr','czech' => 'cs','danish' => 'da','dutch' => 'nl','english' => 'en','estonian' => 'et','farsi' => 'fa','finnish' => 'fi','french' => 'fr','german' => 'de','hausa' => 'ha',
'hawaiian' => 'haw', // ISO 639-2
'hindi' => 'hi','hungarian' => 'hu','icelandic' => 'is','indonesian' => 'id','italian' => 'it','kazakh' => 'kk','kyrgyz' => 'ky','latin' => 'la','latvian' => 'lv','lithuanian' => 'lt','macedonian' => 'mk','mongolian' => 'mn','nepali' => 'ne','norwegian' => 'no','pashto' => 'ps',
'pidgin' => 'cpe', // ISO 639-2
'polish' => 'pl','portuguese' => 'pt','romanian' => 'ro','russian' => 'ru','serbian' => 'sr','slovak' => 'sk','slovene' => 'sl','somali' => 'so','spanish' => 'es','swahili' => 'sw','swedish' => 'sv','tagalog' => 'tl','turkish' => 'tr','ukrainian' => 'uk','urdu' => 'ur','uzbek' => 'uz','vietnamese' => 'vi','welsh' => 'cy');
}
$use_cld = extension_loaded('cld') && (version_compare(PHP_VERSION, '5.3.0') >= 0);
/////////////////////////////////////
@ -364,7 +341,7 @@ if ($options->cors) header('Access-Control-Allow-Origin: *');
//////////////////////////////////
if ($options->caching) {
debug('Caching is enabled...');
$cache_id = md5($max.$url.$valid_key.$links.$favour_feed_titles.$xss_filter.$exclude_on_fail.$format.$detect_language.(int)isset($_GET['pubsub']));
$cache_id = md5($max.$url.(int)$valid_key.$links.(int)$favour_feed_titles.(int)$options->content.(int)$options->summary.(int)$xss_filter.(int)$exclude_on_fail.$format.$detect_language.(int)isset($_GET['pubsub']));
$check_cache = true;
if ($options->apc && $options->smart_cache) {
apc_add("cache.$cache_id", 0, 10*60);
@ -415,6 +392,7 @@ if (!$debug_mode) {
//////////////////////////////////
// Set up HTTP agent
//////////////////////////////////
global $http;
$http = new HumbleHttpAgent();
$http->debug = $debug_mode;
$http->userAgentMap = $options->user_agents;
@ -478,29 +456,6 @@ if ($html_only || !$result) {
$isDummyFeed = true;
unset($feed, $result);
// create single item dummy feed object
class DummySingleItemFeed {
public $item;
function __construct($url) { $this->item = new DummySingleItem($url); }
public function get_title() { return ''; }
public function get_description() { return 'Content extracted from '.$this->item->url; }
public function get_link() { return $this->item->url; }
public function get_language() { return false; }
public function get_image_url() { return false; }
public function get_items($start=0, $max=1) { return array(0=>$this->item); }
}
class DummySingleItem {
public $url;
function __construct($url) { $this->url = $url; }
public function get_permalink() { return $this->url; }
public function get_title() { return null; }
public function get_date($format='') { return false; }
public function get_author($key=0) { return null; }
public function get_authors() { return null; }
public function get_description() { return ''; }
public function get_enclosure($key=0, $prefer=null) { return null; }
public function get_enclosures() { return null; }
public function get_categories() { return null; }
}
$feed = new DummySingleItemFeed($url);
}
@ -524,7 +479,7 @@ if ($img_url = $feed->get_image_url()) {
////////////////////////////////////////////
// Loop through feed items
////////////////////////////////////////////
$items = $feed->get_items(0, $max);
$items = $feed->get_items(0, $max);
// Request all feed items in parallel (if supported)
$urls_sanitized = array();
$urls = array();
@ -606,24 +561,43 @@ foreach ($items as $key => $item) {
$is_single_page = false;
if ($single_page_response = getSinglePage($item, $html, $effective_url)) {
$is_single_page = true;
$html = $single_page_response['body'];
// remove strange things
$html = str_replace('</[>', '', $html);
$html = convert_to_utf8($html, $single_page_response['headers']);
$effective_url = $single_page_response['effective_url'];
debug("Retrieved single-page view from $effective_url");
// check if action defined for returned Content-Type
$mime_info = get_mime_action_info($single_page_response['headers']);
if (isset($mime_info['action'])) {
if ($mime_info['action'] == 'exclude') {
continue; // skip this feed item entry
} elseif ($mime_info['action'] == 'link') {
if ($mime_info['type'] == 'image') {
$html = "<a href=\"$effective_url\"><img src=\"$effective_url\" alt=\"{$mime_info['name']}\" /></a>";
} else {
$html = "<a href=\"$effective_url\">Download {$mime_info['name']}</a>";
}
$extracted_title = $mime_info['name'];
$do_content_extraction = false;
}
}
if ($do_content_extraction) {
$html = $single_page_response['body'];
// remove strange things
$html = str_replace('</[>', '', $html);
$html = convert_to_utf8($html, $single_page_response['headers']);
debug("Retrieved single-page view from $effective_url");
}
unset($single_page_response);
}
}
if ($do_content_extraction) {
debug('--------');
debug('Attempting to extract content');
$extract_result = $extractor->process($html, $effective_url);
$readability = $extractor->readability;
$content_block = ($extract_result) ? $extractor->getContent() : null;
$content_block = ($extract_result) ? $extractor->getContent() : null;
$extracted_title = ($extract_result) ? $extractor->getTitle() : '';
// Deal with multi-page articles
//die('Next: '.$extractor->getNextPageUrl());
$is_multi_page = (!$is_single_page && $extract_result && $extractor->getNextPageUrl());
if ($options->multipage && $is_multi_page) {
if ($options->multipage && $is_multi_page && $options->content) {
debug('--------');
debug('Attempting to process multi-page article');
$multi_page_urls = array();
@ -636,7 +610,7 @@ foreach ($items as $key => $item) {
// check it's not what we have already!
if (!in_array($next_page_url, $multi_page_urls)) {
// it's not, so let's attempt to fetch it
$multi_page_urls[] = $next_page_url;
$multi_page_urls[] = $next_page_url;
$_prev_ref = $http->referer;
if (($response = $http->get($next_page_url, true)) && $response['status_code'] < 300) {
// make sure mime type is not something with a different action associated
@ -661,13 +635,15 @@ foreach ($items as $key => $item) {
// did we successfully deal with this multi-page article?
if (empty($multi_page_content)) {
debug('Failed to extract all parts of multi-page article, so not going to include them');
$multi_page_content[] = $readability->dom->createElement('p')->innerHTML = '<em>This article appears to continue on subsequent pages which we could not extract</em>';
$_page = $readability->dom->createElement('p');
$_page->innerHTML = '<em>This article appears to continue on subsequent pages which we could not extract</em>';
$multi_page_content[] = $_page;
}
foreach ($multi_page_content as $_page) {
$_page = $content_block->ownerDocument->importNode($_page, true);
$content_block->appendChild($_page);
}
unset($multi_page_urls, $multi_page_content, $page_mime_info, $next_page_url);
unset($multi_page_urls, $multi_page_content, $page_mime_info, $next_page_url, $_page);
}
}
// use extracted title for both feed and item title if we're using single-item dummy feed
@ -695,7 +671,11 @@ foreach ($items as $key => $item) {
$html .= $item->get_description();
} else {
$readability->clean($content_block, 'select');
if ($options->rewrite_relative_urls) makeAbsolute($effective_url, $content_block);
// get base URL
$base_url = get_base_url($readability->dom);
if (!$base_url) $base_url = $effective_url;
// rewrite URLs
if ($options->rewrite_relative_urls) makeAbsolute($base_url, $content_block);
// footnotes
if (($links == 'footnotes') && (strpos($effective_url, 'wikipedia.org') === false)) {
$readability->addFootnotes($content_block);
@ -714,7 +694,7 @@ foreach ($items as $key => $item) {
} else {
$html = $content_block->ownerDocument->saveXML($content_block); // essentially outerHTML
}
unset($content_block);
//unset($content_block);
// post-processing cleanup
$html = preg_replace('!<p>[\s\h\v]*</p>!u', '', $html);
if ($links == 'remove') {
@ -727,130 +707,155 @@ foreach ($items as $key => $item) {
}
}
if ($valid_key && isset($_GET['pubsub'])) { // used only on fivefilters.org at the moment
$newitem->addElement('guid', 'http://fivefilters.org/content-only/redirect.php?url='.urlencode($item->get_permalink()), array('isPermaLink'=>'false'));
if ($valid_key && isset($_GET['pubsub'])) { // used only on fivefilters.org at the moment
$newitem->addElement('guid', 'http://fivefilters.org/content-only/redirect.php?url='.urlencode($item->get_permalink()), array('isPermaLink'=>'false'));
} else {
$newitem->addElement('guid', $item->get_permalink(), array('isPermaLink'=>'true'));
}
// filter xss?
if ($xss_filter) {
debug('Filtering HTML to remove XSS');
$html = htmLawed::hl($html, array('safe'=>1, 'deny_attribute'=>'style', 'comment'=>1, 'cdata'=>1));
}
// add content
if ($options->summary === true) {
// get summary
$summary = '';
if (!$do_content_extraction) {
$summary = $html;
} else {
$newitem->addElement('guid', $item->get_permalink(), array('isPermaLink'=>'true'));
}
// filter xss?
if ($xss_filter) {
debug('Filtering HTML to remove XSS');
$html = htmLawed::hl($html, array('safe'=>1, 'deny_attribute'=>'style', 'comment'=>1, 'cdata'=>1));
}
$newitem->setDescription($html);
// set date
if ((int)$item->get_date('U') > 0) {
$newitem->setDate((int)$item->get_date('U'));
} elseif ($extractor->getDate()) {
$newitem->setDate($extractor->getDate());
}
// add authors
if ($authors = $item->get_authors()) {
foreach ($authors as $author) {
// for some feeds, SimplePie stores author's name as email, e.g. http://feeds.feedburner.com/nymag/intel
if ($author->get_name() !== null) {
$newitem->addElement('dc:creator', $author->get_name());
} elseif ($author->get_email() !== null) {
$newitem->addElement('dc:creator', $author->get_email());
// Try to get first few paragraphs
if (isset($content_block) && ($content_block instanceof DOMElement)) {
$_paras = $content_block->getElementsByTagName('p');
foreach ($_paras as $_para) {
$summary .= preg_replace("/[\n\r\t ]+/", ' ', $_para->textContent).' ';
if (strlen($summary) > 200) break;
}
}
} elseif ($authors = $extractor->getAuthors()) {
//TODO: make sure the list size is reasonable
foreach ($authors as $author) {
// TODO: xpath often selects authors from other articles linked from the page.
// for now choose first item
$newitem->addElement('dc:creator', $author);
break;
} else {
$summary = $html;
}
}
// add language
if ($detect_language) {
$language = $extractor->getLanguage();
if (!$language) $language = $feed->get_language();
if (($detect_language == 3 || (!$language && $detect_language == 2)) && $text_sample) {
try {
if ($use_cld) {
// Use PHP-CLD extension
$php_cld = 'CLD\detect'; // in quotes to prevent PHP 5.2 parse error
$res = $php_cld($text_sample);
if (is_array($res) && count($res) > 0) {
$language = $res[0]['code'];
}
} else {
//die('what');
// Use PEAR's Text_LanguageDetect
if (!isset($l)) {
$l = new Text_LanguageDetect('libraries/language-detect/lang.dat', 'libraries/language-detect/unicode_blocks.dat');
}
$l_result = $l->detect($text_sample, 1);
if (count($l_result) > 0) {
$language = $language_codes[key($l_result)];
}
unset($_paras, $_para);
$summary = get_excerpt($summary);
$newitem->setDescription($summary);
if ($options->content) $newitem->setElement('content:encoded', $html);
} else {
if ($options->content) $newitem->setDescription($html);
}
// set date
if ((int)$item->get_date('U') > 0) {
$newitem->setDate((int)$item->get_date('U'));
} elseif ($extractor->getDate()) {
$newitem->setDate($extractor->getDate());
}
// add authors
if ($authors = $item->get_authors()) {
foreach ($authors as $author) {
// for some feeds, SimplePie stores author's name as email, e.g. http://feeds.feedburner.com/nymag/intel
if ($author->get_name() !== null) {
$newitem->addElement('dc:creator', $author->get_name());
} elseif ($author->get_email() !== null) {
$newitem->addElement('dc:creator', $author->get_email());
}
}
} elseif ($authors = $extractor->getAuthors()) {
//TODO: make sure the list size is reasonable
foreach ($authors as $author) {
// TODO: xpath often selects authors from other articles linked from the page.
// for now choose first item
$newitem->addElement('dc:creator', $author);
break;
}
}
// add language
if ($detect_language) {
$language = $extractor->getLanguage();
if (!$language) $language = $feed->get_language();
if (($detect_language == 3 || (!$language && $detect_language == 2)) && $text_sample) {
try {
if ($use_cld) {
// Use PHP-CLD extension
$php_cld = 'CLD\detect'; // in quotes to prevent PHP 5.2 parse error
$res = $php_cld($text_sample);
if (is_array($res) && count($res) > 0) {
$language = $res[0]['code'];
}
} catch (Exception $e) {
//die('error: '.$e);
// do nothing
}
}
if ($language && (strlen($language) < 7)) {
$newitem->addElement('dc:language', $language);
}
}
// add MIME type (if it appeared in our exclusions lists)
if (isset($mime_info['mime'])) $newitem->addElement('dc:format', $mime_info['mime']);
// add effective URL (URL after redirects)
if (isset($effective_url)) {
//TODO: ensure $effective_url is valid witout - sometimes it causes problems, e.g.
//http://www.siasat.pk/forum/showthread.php?108883-Pakistan-Chowk-by-Rana-Mubashir-<2D>-25th-March-2012-Special-Program-from-Liari-(Karachi)
//temporary measure: use utf8_encode()
$newitem->addElement('dc:identifier', remove_url_cruft(utf8_encode($effective_url)));
} else {
$newitem->addElement('dc:identifier', remove_url_cruft($item->get_permalink()));
}
// add categories
if ($categories = $item->get_categories()) {
foreach ($categories as $category) {
if ($category->get_label() !== null) {
$newitem->addElement('category', $category->get_label());
}
}
}
// check for enclosures
if ($options->keep_enclosures) {
if ($enclosures = $item->get_enclosures()) {
foreach ($enclosures as $enclosure) {
// thumbnails
foreach ((array)$enclosure->get_thumbnails() as $thumbnail) {
$newitem->addElement('media:thumbnail', '', array('url'=>$thumbnail));
} else {
//die('what');
// Use PEAR's Text_LanguageDetect
if (!isset($l)) {
$l = new Text_LanguageDetect();
$l->setNameMode(2); // return ISO 639-1 codes (e.g. "en")
}
$l_result = $l->detect($text_sample, 1);
if (count($l_result) > 0) {
$language = key($l_result);
}
if (!$enclosure->get_link()) continue;
$enc = array();
// Media RSS spec ($enc): http://search.yahoo.com/mrss
// SimplePie methods ($enclosure): http://simplepie.org/wiki/reference/start#methods4
$enc['url'] = $enclosure->get_link();
if ($enclosure->get_length()) $enc['fileSize'] = $enclosure->get_length();
if ($enclosure->get_type()) $enc['type'] = $enclosure->get_type();
if ($enclosure->get_medium()) $enc['medium'] = $enclosure->get_medium();
if ($enclosure->get_expression()) $enc['expression'] = $enclosure->get_expression();
if ($enclosure->get_bitrate()) $enc['bitrate'] = $enclosure->get_bitrate();
if ($enclosure->get_framerate()) $enc['framerate'] = $enclosure->get_framerate();
if ($enclosure->get_sampling_rate()) $enc['samplingrate'] = $enclosure->get_sampling_rate();
if ($enclosure->get_channels()) $enc['channels'] = $enclosure->get_channels();
if ($enclosure->get_duration()) $enc['duration'] = $enclosure->get_duration();
if ($enclosure->get_height()) $enc['height'] = $enclosure->get_height();
if ($enclosure->get_width()) $enc['width'] = $enclosure->get_width();
if ($enclosure->get_language()) $enc['lang'] = $enclosure->get_language();
$newitem->addElement('media:content', '', $enc);
}
} catch (Exception $e) {
//die('error: '.$e);
// do nothing
}
}
/* } */
if ($language && (strlen($language) < 7)) {
$newitem->addElement('dc:language', $language);
}
}
// add MIME type (if it appeared in our exclusions lists)
if (isset($mime_info['mime'])) $newitem->addElement('dc:format', $mime_info['mime']);
// add effective URL (URL after redirects)
if (isset($effective_url)) {
//TODO: ensure $effective_url is valid witout - sometimes it causes problems, e.g.
//http://www.siasat.pk/forum/showthread.php?108883-Pakistan-Chowk-by-Rana-Mubashir-<2D>-25th-March-2012-Special-Program-from-Liari-(Karachi)
//temporary measure: use utf8_encode()
$newitem->addElement('dc:identifier', remove_url_cruft(utf8_encode($effective_url)));
} else {
$newitem->addElement('dc:identifier', remove_url_cruft($item->get_permalink()));
}
// add categories
if ($categories = $item->get_categories()) {
foreach ($categories as $category) {
if ($category->get_label() !== null) {
$newitem->addElement('category', $category->get_label());
}
}
}
// check for enclosures
if ($options->keep_enclosures) {
if ($enclosures = $item->get_enclosures()) {
foreach ($enclosures as $enclosure) {
// thumbnails
foreach ((array)$enclosure->get_thumbnails() as $thumbnail) {
$newitem->addElement('media:thumbnail', '', array('url'=>$thumbnail));
}
if (!$enclosure->get_link()) continue;
$enc = array();
// Media RSS spec ($enc): http://search.yahoo.com/mrss
// SimplePie methods ($enclosure): http://simplepie.org/wiki/reference/start#methods4
$enc['url'] = $enclosure->get_link();
if ($enclosure->get_length()) $enc['fileSize'] = $enclosure->get_length();
if ($enclosure->get_type()) $enc['type'] = $enclosure->get_type();
if ($enclosure->get_medium()) $enc['medium'] = $enclosure->get_medium();
if ($enclosure->get_expression()) $enc['expression'] = $enclosure->get_expression();
if ($enclosure->get_bitrate()) $enc['bitrate'] = $enclosure->get_bitrate();
if ($enclosure->get_framerate()) $enc['framerate'] = $enclosure->get_framerate();
if ($enclosure->get_sampling_rate()) $enc['samplingrate'] = $enclosure->get_sampling_rate();
if ($enclosure->get_channels()) $enc['channels'] = $enclosure->get_channels();
if ($enclosure->get_duration()) $enc['duration'] = $enclosure->get_duration();
if ($enclosure->get_height()) $enc['height'] = $enclosure->get_height();
if ($enclosure->get_width()) $enc['width'] = $enclosure->get_width();
if ($enclosure->get_language()) $enc['lang'] = $enclosure->get_language();
$newitem->addElement('media:content', '', $enc);
}
}
}
$output->addItem($newitem);
unset($html);
$item_count++;
@ -887,7 +892,7 @@ if (!$debug_mode) {
}
if ($add_to_cache) {
ob_start();
$output->genarateFeed();
$output->genarateFeed(false);
$output = ob_get_contents();
ob_end_clean();
if ($html_only && $item_count == 0) {
@ -898,299 +903,8 @@ if (!$debug_mode) {
}
echo $output;
} else {
$output->genarateFeed();
$output->genarateFeed(false);
}
if ($callback) echo ');';
}
///////////////////////////////
// HELPER FUNCTIONS
///////////////////////////////
function url_allowed($url) {
global $options;
if (!empty($options->allowed_urls)) {
$allowed = false;
foreach ($options->allowed_urls as $allowurl) {
if (stristr($url, $allowurl) !== false) {
$allowed = true;
break;
}
}
if (!$allowed) return false;
} else {
foreach ($options->blocked_urls as $blockurl) {
if (stristr($url, $blockurl) !== false) {
return false;
}
}
}
return true;
}
//////////////////////////////////////////////
// Convert $html to UTF8
// (uses HTTP headers and HTML to find encoding)
// adapted from http://stackoverflow.com/questions/910793/php-detect-encoding-and-make-everything-utf-8
//////////////////////////////////////////////
function convert_to_utf8($html, $header=null)
{
$encoding = null;
if ($html || $header) {
if (is_array($header)) $header = implode("\n", $header);
if (!$header || !preg_match_all('/^Content-Type:\s+([^;]+)(?:;\s*charset=["\']?([^;"\'\n]*))?/im', $header, $match, PREG_SET_ORDER)) {
// error parsing the response
debug('Could not find Content-Type header in HTTP response');
} else {
$match = end($match); // get last matched element (in case of redirects)
if (isset($match[2])) $encoding = trim($match[2], "\"' \r\n\0\x0B\t");
}
// TODO: check to see if encoding is supported (can we convert it?)
// If it's not, result will be empty string.
// For now we'll check for invalid encoding types returned by some sites, e.g. 'none'
// Problem URL: http://facta.co.jp/blog/archives/20111026001026.html
if (!$encoding || $encoding == 'none') {
// search for encoding in HTML - only look at the first 50000 characters
// Why 50000? See, for example, http://www.lemonde.fr/festival-de-cannes/article/2012/05/23/deux-cretes-en-goguette-sur-la-croisette_1705732_766360.html
// TODO: improve this so it looks at smaller chunks first
$html_head = substr($html, 0, 50000);
if (preg_match('/^<\?xml\s+version=(?:"[^"]*"|\'[^\']*\')\s+encoding=("[^"]*"|\'[^\']*\')/s', $html_head, $match)) {
$encoding = trim($match[1], '"\'');
} elseif (preg_match('/<meta\s+http-equiv=["\']?Content-Type["\']? content=["\'][^;]+;\s*charset=["\']?([^;"\'>]+)/i', $html_head, $match)) {
$encoding = trim($match[1]);
} elseif (preg_match_all('/<meta\s+([^>]+)>/i', $html_head, $match)) {
foreach ($match[1] as $_test) {
if (preg_match('/charset=["\']?([^"\']+)/i', $_test, $_m)) {
$encoding = trim($_m[1]);
break;
}
}
}
}
if (isset($encoding)) $encoding = trim($encoding);
// trim is important here!
if (!$encoding || (strtolower($encoding) == 'iso-8859-1')) {
// replace MS Word smart qutoes
$trans = array();
$trans[chr(130)] = '&sbquo;'; // Single Low-9 Quotation Mark
$trans[chr(131)] = '&fnof;'; // Latin Small Letter F With Hook
$trans[chr(132)] = '&bdquo;'; // Double Low-9 Quotation Mark
$trans[chr(133)] = '&hellip;'; // Horizontal Ellipsis
$trans[chr(134)] = '&dagger;'; // Dagger
$trans[chr(135)] = '&Dagger;'; // Double Dagger
$trans[chr(136)] = '&circ;'; // Modifier Letter Circumflex Accent
$trans[chr(137)] = '&permil;'; // Per Mille Sign
$trans[chr(138)] = '&Scaron;'; // Latin Capital Letter S With Caron
$trans[chr(139)] = '&lsaquo;'; // Single Left-Pointing Angle Quotation Mark
$trans[chr(140)] = '&OElig;'; // Latin Capital Ligature OE
$trans[chr(145)] = '&lsquo;'; // Left Single Quotation Mark
$trans[chr(146)] = '&rsquo;'; // Right Single Quotation Mark
$trans[chr(147)] = '&ldquo;'; // Left Double Quotation Mark
$trans[chr(148)] = '&rdquo;'; // Right Double Quotation Mark
$trans[chr(149)] = '&bull;'; // Bullet
$trans[chr(150)] = '&ndash;'; // En Dash
$trans[chr(151)] = '&mdash;'; // Em Dash
$trans[chr(152)] = '&tilde;'; // Small Tilde
$trans[chr(153)] = '&trade;'; // Trade Mark Sign
$trans[chr(154)] = '&scaron;'; // Latin Small Letter S With Caron
$trans[chr(155)] = '&rsaquo;'; // Single Right-Pointing Angle Quotation Mark
$trans[chr(156)] = '&oelig;'; // Latin Small Ligature OE
$trans[chr(159)] = '&Yuml;'; // Latin Capital Letter Y With Diaeresis
$html = strtr($html, $trans);
}
if (!$encoding) {
debug('No character encoding found, so treating as UTF-8');
$encoding = 'utf-8';
} else {
debug('Character encoding: '.$encoding);
if (strtolower($encoding) != 'utf-8') {
debug('Converting to UTF-8');
$html = SimplePie_Misc::change_encoding($html, $encoding, 'utf-8');
/*
if (function_exists('iconv')) {
// iconv appears to handle certain character encodings better than mb_convert_encoding
$html = iconv($encoding, 'utf-8', $html);
} else {
$html = mb_convert_encoding($html, 'utf-8', $encoding);
}
*/
}
}
}
return $html;
}
function makeAbsolute($base, $elem) {
$base = new SimplePie_IRI($base);
// remove '//' in URL path (used to prevent URLs from resolving properly)
// TODO: check if this is still the case
if (isset($base->path)) $base->path = preg_replace('!//+!', '/', $base->path);
foreach(array('a'=>'href', 'img'=>'src') as $tag => $attr) {
$elems = $elem->getElementsByTagName($tag);
for ($i = $elems->length-1; $i >= 0; $i--) {
$e = $elems->item($i);
//$e->parentNode->replaceChild($articleContent->ownerDocument->createTextNode($e->textContent), $e);
makeAbsoluteAttr($base, $e, $attr);
}
if (strtolower($elem->tagName) == $tag) makeAbsoluteAttr($base, $elem, $attr);
}
}
function makeAbsoluteAttr($base, $e, $attr) {
if ($e->hasAttribute($attr)) {
// Trim leading and trailing white space. I don't really like this but
// unfortunately it does appear on some sites. e.g. <img src=" /path/to/image.jpg" />
$url = trim(str_replace('%20', ' ', $e->getAttribute($attr)));
$url = str_replace(' ', '%20', $url);
if (!preg_match('!https?://!i', $url)) {
if ($absolute = SimplePie_IRI::absolutize($base, $url)) {
$e->setAttribute($attr, $absolute);
}
}
}
}
function makeAbsoluteStr($base, $url) {
$base = new SimplePie_IRI($base);
// remove '//' in URL path (causes URLs not to resolve properly)
if (isset($base->path)) $base->path = preg_replace('!//+!', '/', $base->path);
if (preg_match('!^https?://!i', $url)) {
// already absolute
return $url;
} else {
if ($absolute = SimplePie_IRI::absolutize($base, $url)) {
return $absolute;
}
return false;
}
}
// returns single page response, or false if not found
function getSinglePage($item, $html, $url) {
global $http, $extractor;
debug('Looking for site config files to see if single page link exists');
$site_config = $extractor->buildSiteConfig($url, $html);
$splink = null;
if (!empty($site_config->single_page_link)) {
$splink = $site_config->single_page_link;
} elseif (!empty($site_config->single_page_link_in_feed)) {
// single page link xpath is targeted at feed
$splink = $site_config->single_page_link_in_feed;
// so let's replace HTML with feed item description
$html = $item->get_description();
}
if (isset($splink)) {
// Build DOM tree from HTML
$readability = new Readability($html, $url);
$xpath = new DOMXPath($readability->dom);
// Loop through single_page_link xpath expressions
$single_page_url = null;
foreach ($splink as $pattern) {
$elems = @$xpath->evaluate($pattern, $readability->dom);
if (is_string($elems)) {
$single_page_url = trim($elems);
break;
} elseif ($elems instanceof DOMNodeList && $elems->length > 0) {
foreach ($elems as $item) {
if ($item instanceof DOMElement && $item->hasAttribute('href')) {
$single_page_url = $item->getAttribute('href');
break 2;
} elseif ($item instanceof DOMAttr && $item->value) {
$single_page_url = $item->value;
break 2;
}
}
}
}
// If we've got URL, resolve against $url
if (isset($single_page_url) && ($single_page_url = makeAbsoluteStr($url, $single_page_url))) {
// check it's not what we have already!
if ($single_page_url != $url) {
// it's not, so let's try to fetch it...
$_prev_ref = $http->referer;
$http->referer = $single_page_url;
if (($response = $http->get($single_page_url, true)) && $response['status_code'] < 300) {
$http->referer = $_prev_ref;
return $response;
}
$http->referer = $_prev_ref;
}
}
}
return false;
}
// based on content-type http header, decide what to do
// param: HTTP headers string
// return: array with keys: 'mime', 'type', 'subtype', 'action', 'name'
// e.g. array('mime'=>'image/jpeg', 'type'=>'image', 'subtype'=>'jpeg', 'action'=>'link', 'name'=>'Image')
function get_mime_action_info($headers) {
global $options;
// check if action defined for returned Content-Type
$info = array();
if (preg_match('!^Content-Type:\s*(([-\w]+)/([-\w\+]+))!im', $headers, $match)) {
// look for full mime type (e.g. image/jpeg) or just type (e.g. image)
// match[1] = full mime type, e.g. image/jpeg
// match[2] = first part, e.g. image
// match[3] = last part, e.g. jpeg
$info['mime'] = strtolower(trim($match[1]));
$info['type'] = strtolower(trim($match[2]));
$info['subtype'] = strtolower(trim($match[3]));
foreach (array($info['mime'], $info['type']) as $_mime) {
if (isset($options->content_type_exc[$_mime])) {
$info['action'] = $options->content_type_exc[$_mime]['action'];
$info['name'] = $options->content_type_exc[$_mime]['name'];
break;
}
}
}
return $info;
}
function remove_url_cruft($url) {
// remove google analytics for the time being
// regex adapted from http://navitronic.co.uk/2010/12/removing-google-analytics-cruft-from-urls/
// https://gist.github.com/758177
return preg_replace('/(\?|\&)utm_[a-z]+=[^\&]+/', '', $url);
}
function make_substitutions($string) {
if ($string == '') return $string;
global $item, $effective_url;
$string = str_replace('{url}', htmlspecialchars($item->get_permalink()), $string);
$string = str_replace('{effective-url}', htmlspecialchars($effective_url), $string);
return $string;
}
function get_cache() {
global $options, $valid_key;
static $cache = null;
if ($cache === null) {
$frontendOptions = array(
'lifetime' => 10*60, // cache lifetime of 10 minutes
'automatic_serialization' => false,
'write_control' => false,
'automatic_cleaning_factor' => $options->cache_cleanup,
'ignore_user_abort' => false
);
$backendOptions = array(
'cache_dir' => ($valid_key) ? $options->cache_dir.'/rss-with-key/' : $options->cache_dir.'/rss/', // directory where to put the cache files
'file_locking' => false,
'read_control' => true,
'read_control_type' => 'strlen',
'hashed_directory_level' => $options->cache_directory_level,
'hashed_directory_perm' => 0777,
'cache_file_perm' => 0664,
'file_name_prefix' => 'ff'
);
// getting a Zend_Cache_Core object
$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
}
return $cache;
}
function debug($msg) {
global $debug_mode;
if ($debug_mode) {
echo '* ',$msg,"\n";
ob_flush();
flush();
}
}

389
inc/3rdparty/makefulltextfeedHelpers.php vendored Executable file
View File

@ -0,0 +1,389 @@
<?php
// Autoloading of classes allows us to include files only when they're
// needed. If we've got a cached copy, for example, only Zend_Cache is loaded.
function autoload($class_name) {
static $dir = null;
if ($dir === null) $dir = dirname(__FILE__).'/libraries/';
static $mapping = array(
// Include FeedCreator for RSS/Atom creation
'FeedWriter' => 'feedwriter/FeedWriter.php',
'FeedItem' => 'feedwriter/FeedItem.php',
// Include ContentExtractor and Readability for identifying and extracting content from URLs
'ContentExtractor' => 'content-extractor/ContentExtractor.php',
'SiteConfig' => 'content-extractor/SiteConfig.php',
'Readability' => 'readability/Readability.php',
// Include Humble HTTP Agent to allow parallel requests and response caching
'HumbleHttpAgent' => 'humble-http-agent/HumbleHttpAgent.php',
'SimplePie_HumbleHttpAgent' => 'humble-http-agent/SimplePie_HumbleHttpAgent.php',
'CookieJar' => 'humble-http-agent/CookieJar.php',
// Include Zend Cache to improve performance (cache results)
'Zend_Cache' => 'Zend/Cache.php',
// Language detect
'Text_LanguageDetect' => 'language-detect/LanguageDetect.php',
// HTML5 Lib
'HTML5_Parser' => 'html5/Parser.php',
// htmLawed - used if XSS filter is enabled (xss_filter)
'htmLawed' => 'htmLawed/htmLawed.php'
);
if (isset($mapping[$class_name])) {
debug("** Loading class $class_name ({$mapping[$class_name]})");
require $dir.$mapping[$class_name];
return true;
} else {
return false;
}
}
spl_autoload_register('autoload');
require dirname(__FILE__).'/libraries/simplepie/autoloader.php';
class DummySingleItemFeed {
public $item;
function __construct($url) { $this->item = new DummySingleItem($url); }
public function get_title() { return ''; }
public function get_description() { return 'Content extracted from '.$this->item->url; }
public function get_link() { return $this->item->url; }
public function get_language() { return false; }
public function get_image_url() { return false; }
public function get_items($start=0, $max=1) { return array(0=>$this->item); }
}
class DummySingleItem {
public $url;
function __construct($url) { $this->url = $url; }
public function get_permalink() { return $this->url; }
public function get_title() { return null; }
public function get_date($format='') { return false; }
public function get_author($key=0) { return null; }
public function get_authors() { return null; }
public function get_description() { return ''; }
public function get_enclosure($key=0, $prefer=null) { return null; }
public function get_enclosures() { return null; }
public function get_categories() { return null; }
}
///////////////////////////////
// HELPER FUNCTIONS
///////////////////////////////
// Adapted from WordPress
// http://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/formatting.php#L2173
function get_excerpt($text, $num_words=55, $more=null) {
if (null === $more) $more = '&hellip;';
$text = strip_tags($text);
//TODO: Check if word count is based on single characters (East Asian characters)
/*
if (1==2) {
$text = trim(preg_replace("/[\n\r\t ]+/", ' ', $text), ' ');
preg_match_all('/./u', $text, $words_array);
$words_array = array_slice($words_array[0], 0, $num_words + 1);
$sep = '';
} else {
$words_array = preg_split("/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY);
$sep = ' ';
}
*/
$words_array = preg_split("/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY);
$sep = ' ';
if (count($words_array) > $num_words) {
array_pop($words_array);
$text = implode($sep, $words_array);
$text = $text.$more;
} else {
$text = implode($sep, $words_array);
}
// trim whitespace at beginning or end of string
// See: http://stackoverflow.com/questions/4166896/trim-unicode-whitespace-in-php-5-2
$text = preg_replace('/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $text);
return $text;
}
function url_allowed($url) {
global $options;
if (!empty($options->allowed_urls)) {
$allowed = false;
foreach ($options->allowed_urls as $allowurl) {
if (stristr($url, $allowurl) !== false) {
$allowed = true;
break;
}
}
if (!$allowed) return false;
} else {
foreach ($options->blocked_urls as $blockurl) {
if (stristr($url, $blockurl) !== false) {
return false;
}
}
}
return true;
}
//////////////////////////////////////////////
// Convert $html to UTF8
// (uses HTTP headers and HTML to find encoding)
// adapted from http://stackoverflow.com/questions/910793/php-detect-encoding-and-make-everything-utf-8
//////////////////////////////////////////////
function convert_to_utf8($html, $header=null)
{
$encoding = null;
if ($html || $header) {
if (is_array($header)) $header = implode("\n", $header);
if (!$header || !preg_match_all('/^Content-Type:\s+([^;]+)(?:;\s*charset=["\']?([^;"\'\n]*))?/im', $header, $match, PREG_SET_ORDER)) {
// error parsing the response
debug('Could not find Content-Type header in HTTP response');
} else {
$match = end($match); // get last matched element (in case of redirects)
if (isset($match[2])) $encoding = trim($match[2], "\"' \r\n\0\x0B\t");
}
// TODO: check to see if encoding is supported (can we convert it?)
// If it's not, result will be empty string.
// For now we'll check for invalid encoding types returned by some sites, e.g. 'none'
// Problem URL: http://facta.co.jp/blog/archives/20111026001026.html
if (!$encoding || $encoding == 'none') {
// search for encoding in HTML - only look at the first 50000 characters
// Why 50000? See, for example, http://www.lemonde.fr/festival-de-cannes/article/2012/05/23/deux-cretes-en-goguette-sur-la-croisette_1705732_766360.html
// TODO: improve this so it looks at smaller chunks first
$html_head = substr($html, 0, 50000);
if (preg_match('/^<\?xml\s+version=(?:"[^"]*"|\'[^\']*\')\s+encoding=("[^"]*"|\'[^\']*\')/s', $html_head, $match)) {
$encoding = trim($match[1], '"\'');
} elseif (preg_match('/<meta\s+http-equiv=["\']?Content-Type["\']? content=["\'][^;]+;\s*charset=["\']?([^;"\'>]+)/i', $html_head, $match)) {
$encoding = trim($match[1]);
} elseif (preg_match_all('/<meta\s+([^>]+)>/i', $html_head, $match)) {
foreach ($match[1] as $_test) {
if (preg_match('/charset=["\']?([^"\']+)/i', $_test, $_m)) {
$encoding = trim($_m[1]);
break;
}
}
}
}
if (isset($encoding)) $encoding = trim($encoding);
// trim is important here!
if (!$encoding || (strtolower($encoding) == 'iso-8859-1')) {
// replace MS Word smart qutoes
$trans = array();
$trans[chr(130)] = '&sbquo;'; // Single Low-9 Quotation Mark
$trans[chr(131)] = '&fnof;'; // Latin Small Letter F With Hook
$trans[chr(132)] = '&bdquo;'; // Double Low-9 Quotation Mark
$trans[chr(133)] = '&hellip;'; // Horizontal Ellipsis
$trans[chr(134)] = '&dagger;'; // Dagger
$trans[chr(135)] = '&Dagger;'; // Double Dagger
$trans[chr(136)] = '&circ;'; // Modifier Letter Circumflex Accent
$trans[chr(137)] = '&permil;'; // Per Mille Sign
$trans[chr(138)] = '&Scaron;'; // Latin Capital Letter S With Caron
$trans[chr(139)] = '&lsaquo;'; // Single Left-Pointing Angle Quotation Mark
$trans[chr(140)] = '&OElig;'; // Latin Capital Ligature OE
$trans[chr(145)] = '&lsquo;'; // Left Single Quotation Mark
$trans[chr(146)] = '&rsquo;'; // Right Single Quotation Mark
$trans[chr(147)] = '&ldquo;'; // Left Double Quotation Mark
$trans[chr(148)] = '&rdquo;'; // Right Double Quotation Mark
$trans[chr(149)] = '&bull;'; // Bullet
$trans[chr(150)] = '&ndash;'; // En Dash
$trans[chr(151)] = '&mdash;'; // Em Dash
$trans[chr(152)] = '&tilde;'; // Small Tilde
$trans[chr(153)] = '&trade;'; // Trade Mark Sign
$trans[chr(154)] = '&scaron;'; // Latin Small Letter S With Caron
$trans[chr(155)] = '&rsaquo;'; // Single Right-Pointing Angle Quotation Mark
$trans[chr(156)] = '&oelig;'; // Latin Small Ligature OE
$trans[chr(159)] = '&Yuml;'; // Latin Capital Letter Y With Diaeresis
$html = strtr($html, $trans);
}
if (!$encoding) {
debug('No character encoding found, so treating as UTF-8');
$encoding = 'utf-8';
} else {
debug('Character encoding: '.$encoding);
if (strtolower($encoding) != 'utf-8') {
debug('Converting to UTF-8');
$html = SimplePie_Misc::change_encoding($html, $encoding, 'utf-8');
}
}
}
return $html;
}
function makeAbsolute($base, $elem) {
$base = new SimplePie_IRI($base);
// remove '//' in URL path (used to prevent URLs from resolving properly)
// TODO: check if this is still the case
if (isset($base->path)) $base->path = preg_replace('!//+!', '/', $base->path);
foreach(array('a'=>'href', 'img'=>'src') as $tag => $attr) {
$elems = $elem->getElementsByTagName($tag);
for ($i = $elems->length-1; $i >= 0; $i--) {
$e = $elems->item($i);
//$e->parentNode->replaceChild($articleContent->ownerDocument->createTextNode($e->textContent), $e);
makeAbsoluteAttr($base, $e, $attr);
}
if (strtolower($elem->tagName) == $tag) makeAbsoluteAttr($base, $elem, $attr);
}
}
function makeAbsoluteAttr($base, $e, $attr) {
if ($e->hasAttribute($attr)) {
// Trim leading and trailing white space. I don't really like this but
// unfortunately it does appear on some sites. e.g. <img src=" /path/to/image.jpg" />
$url = trim(str_replace('%20', ' ', $e->getAttribute($attr)));
$url = str_replace(' ', '%20', $url);
if (!preg_match('!https?://!i', $url)) {
if ($absolute = SimplePie_IRI::absolutize($base, $url)) {
$e->setAttribute($attr, $absolute);
}
}
}
}
function makeAbsoluteStr($base, $url) {
$base = new SimplePie_IRI($base);
// remove '//' in URL path (causes URLs not to resolve properly)
if (isset($base->path)) $base->path = preg_replace('!//+!', '/', $base->path);
if (preg_match('!^https?://!i', $url)) {
// already absolute
return $url;
} else {
if ($absolute = SimplePie_IRI::absolutize($base, $url)) {
return $absolute;
}
return false;
}
}
// returns single page response, or false if not found
function getSinglePage($item, $html, $url) {
global $http, $extractor;
debug('Looking for site config files to see if single page link exists');
$site_config = $extractor->buildSiteConfig($url, $html);
$splink = null;
if (!empty($site_config->single_page_link)) {
$splink = $site_config->single_page_link;
} elseif (!empty($site_config->single_page_link_in_feed)) {
// single page link xpath is targeted at feed
$splink = $site_config->single_page_link_in_feed;
// so let's replace HTML with feed item description
$html = $item->get_description();
}
if (isset($splink)) {
// Build DOM tree from HTML
$readability = new Readability($html, $url);
$xpath = new DOMXPath($readability->dom);
// Loop through single_page_link xpath expressions
$single_page_url = null;
foreach ($splink as $pattern) {
$elems = @$xpath->evaluate($pattern, $readability->dom);
if (is_string($elems)) {
$single_page_url = trim($elems);
break;
} elseif ($elems instanceof DOMNodeList && $elems->length > 0) {
foreach ($elems as $item) {
if ($item instanceof DOMElement && $item->hasAttribute('href')) {
$single_page_url = $item->getAttribute('href');
break 2;
} elseif ($item instanceof DOMAttr && $item->value) {
$single_page_url = $item->value;
break 2;
}
}
}
}
// If we've got URL, resolve against $url
if (isset($single_page_url) && ($single_page_url = makeAbsoluteStr($url, $single_page_url))) {
// check it's not what we have already!
if ($single_page_url != $url) {
// it's not, so let's try to fetch it...
$_prev_ref = $http->referer;
$http->referer = $single_page_url;
if (($response = $http->get($single_page_url, true)) && $response['status_code'] < 300) {
$http->referer = $_prev_ref;
return $response;
}
$http->referer = $_prev_ref;
}
}
}
return false;
}
// based on content-type http header, decide what to do
// param: HTTP headers string
// return: array with keys: 'mime', 'type', 'subtype', 'action', 'name'
// e.g. array('mime'=>'image/jpeg', 'type'=>'image', 'subtype'=>'jpeg', 'action'=>'link', 'name'=>'Image')
function get_mime_action_info($headers) {
global $options;
// check if action defined for returned Content-Type
$info = array();
if (preg_match('!^Content-Type:\s*(([-\w]+)/([-\w\+]+))!im', $headers, $match)) {
// look for full mime type (e.g. image/jpeg) or just type (e.g. image)
// match[1] = full mime type, e.g. image/jpeg
// match[2] = first part, e.g. image
// match[3] = last part, e.g. jpeg
$info['mime'] = strtolower(trim($match[1]));
$info['type'] = strtolower(trim($match[2]));
$info['subtype'] = strtolower(trim($match[3]));
foreach (array($info['mime'], $info['type']) as $_mime) {
if (isset($options->content_type_exc[$_mime])) {
$info['action'] = $options->content_type_exc[$_mime]['action'];
$info['name'] = $options->content_type_exc[$_mime]['name'];
break;
}
}
}
return $info;
}
function remove_url_cruft($url) {
// remove google analytics for the time being
// regex adapted from http://navitronic.co.uk/2010/12/removing-google-analytics-cruft-from-urls/
// https://gist.github.com/758177
return preg_replace('/(\?|\&)utm_[a-z]+=[^\&]+/', '', $url);
}
function make_substitutions($string) {
if ($string == '') return $string;
global $item, $effective_url;
$string = str_replace('{url}', htmlspecialchars($item->get_permalink()), $string);
$string = str_replace('{effective-url}', htmlspecialchars($effective_url), $string);
return $string;
}
function get_cache() {
global $options, $valid_key;
static $cache = null;
if ($cache === null) {
$frontendOptions = array(
'lifetime' => 10*60, // cache lifetime of 10 minutes
'automatic_serialization' => false,
'write_control' => false,
'automatic_cleaning_factor' => $options->cache_cleanup,
'ignore_user_abort' => false
);
$backendOptions = array(
'cache_dir' => ($valid_key) ? $options->cache_dir.'/rss-with-key/' : $options->cache_dir.'/rss/', // directory where to put the cache files
'file_locking' => false,
'read_control' => true,
'read_control_type' => 'strlen',
'hashed_directory_level' => $options->cache_directory_level,
'hashed_directory_perm' => 0777,
'cache_file_perm' => 0664,
'file_name_prefix' => 'ff'
);
// getting a Zend_Cache_Core object
$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
}
return $cache;
}
function debug($msg) {
global $debug_mode;
if ($debug_mode) {
echo '* ',$msg,"\n";
ob_flush();
flush();
}
}
function get_base_url($dom) {
$xpath = new DOMXPath($dom);
$base_url = @$xpath->evaluate('string(//head/base/@href)', $dom);
if ($base_url !== '') {
return $base_url;
} else {
return false;
}
}

105
inc/3rdparty/simple_html_dom.php vendored Normal file → Executable file
View File

@ -34,7 +34,7 @@
* @author S.C. Chen <me578022@gmail.com>
* @author John Schlick
* @author Rus Carroll
* @version 1.5 ($Rev: 202 $)
* @version 1.5 ($Rev: 210 $)
* @package PlaceLocalInclude
* @subpackage simple_html_dom
*/
@ -269,7 +269,10 @@ class simple_html_dom_node
{
return $this->children;
}
if (isset($this->children[$idx])) return $this->children[$idx];
if (isset($this->children[$idx]))
{
return $this->children[$idx];
}
return null;
}
@ -330,14 +333,14 @@ class simple_html_dom_node
function find_ancestor_tag($tag)
{
global $debug_object;
if (is_object($debug_object)) { $debug_object->debugLogEntry(1); }
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
// Start by including ourselves in the comparison.
$returnDom = $this;
while (!is_null($returnDom))
{
if (is_object($debug_object)) { $debug_object->debugLog(2, "Current tag is: " . $returnDom->tag); }
if (is_object($debug_object)) { $debug_object->debug_log(2, "Current tag is: " . $returnDom->tag); }
if ($returnDom->tag == $tag)
{
@ -374,7 +377,7 @@ class simple_html_dom_node
$text = " with text: " . $this->text;
}
}
$debug_object->debugLog(1, 'Innertext of tag: ' . $this->tag . $text);
$debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text);
}
if ($this->tag==='root') return $this->innertext();
@ -532,7 +535,9 @@ class simple_html_dom_node
foreach ($head as $k=>$v)
{
if (!isset($found_keys[$k]))
{
$found_keys[$k] = 1;
}
}
}
@ -554,7 +559,7 @@ class simple_html_dom_node
protected function seek($selector, &$ret, $lowercase=false)
{
global $debug_object;
if (is_object($debug_object)) { $debug_object->debugLogEntry(1); }
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
list($tag, $key, $val, $exp, $no_key) = $selector;
@ -615,7 +620,7 @@ class simple_html_dom_node
// this is a normal search, we want the value of that attribute of the tag.
$nodeKeyValue = $node->attr[$key];
}
if (is_object($debug_object)) {$debug_object->debugLog(2, "testing node: " . $node->tag . " for attribute: " . $key . $exp . $val . " where nodes value is: " . $nodeKeyValue);}
if (is_object($debug_object)) {$debug_object->debug_log(2, "testing node: " . $node->tag . " for attribute: " . $key . $exp . $val . " where nodes value is: " . $nodeKeyValue);}
//PaperG - If lowercase is set, do a case insensitive test of the value of the selector.
if ($lowercase) {
@ -623,7 +628,7 @@ class simple_html_dom_node
} else {
$check = $this->match($exp, $val, $nodeKeyValue);
}
if (is_object($debug_object)) {$debug_object->debugLog(2, "after match: " . ($check ? "true" : "false"));}
if (is_object($debug_object)) {$debug_object->debug_log(2, "after match: " . ($check ? "true" : "false"));}
// handle multiple class
if (!$check && strcasecmp($key, 'class')===0) {
@ -645,12 +650,12 @@ class simple_html_dom_node
unset($node);
}
// It's passed by reference so this is actually what this function returns.
if (is_object($debug_object)) {$debug_object->debugLog(1, "EXIT - ret: ", $ret);}
if (is_object($debug_object)) {$debug_object->debug_log(1, "EXIT - ret: ", $ret);}
}
protected function match($exp, $pattern, $value) {
global $debug_object;
if (is_object($debug_object)) {$debug_object->debugLogEntry(1);}
if (is_object($debug_object)) {$debug_object->debug_log_entry(1);}
switch ($exp) {
case '=':
@ -672,7 +677,7 @@ class simple_html_dom_node
protected function parse_selector($selector_string) {
global $debug_object;
if (is_object($debug_object)) {$debug_object->debugLogEntry(1);}
if (is_object($debug_object)) {$debug_object->debug_log_entry(1);}
// pattern of CSS selectors, modified from mootools
// Paperg: Add the colon to the attrbute, so that it properly finds <tag attr:ibute="something" > like google does.
@ -683,7 +688,7 @@ class simple_html_dom_node
// $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
$pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER);
if (is_object($debug_object)) {$debug_object->debugLog(2, "Matches Array: ", $matches);}
if (is_object($debug_object)) {$debug_object->debug_log(2, "Matches Array: ", $matches);}
$selectors = array();
$result = array();
@ -718,12 +723,14 @@ class simple_html_dom_node
return $selectors;
}
function __get($name) {
function __get($name)
{
if (isset($this->attr[$name]))
{
return $this->convert_text($this->attr[$name]);
}
switch ($name) {
switch ($name)
{
case 'outertext': return $this->outertext();
case 'innertext': return $this->innertext();
case 'plaintext': return $this->text();
@ -732,22 +739,30 @@ class simple_html_dom_node
}
}
function __set($name, $value) {
switch ($name) {
function __set($name, $value)
{
global $debug_object;
if (is_object($debug_object)) {$debug_object->debug_log_entry(1);}
switch ($name)
{
case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value;
case 'innertext':
if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value;
return $this->_[HDOM_INFO_INNER] = $value;
}
if (!isset($this->attr[$name])) {
if (!isset($this->attr[$name]))
{
$this->_[HDOM_INFO_SPACE][] = array(' ', '', '');
$this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
}
$this->attr[$name] = $value;
}
function __isset($name) {
switch ($name) {
function __isset($name)
{
switch ($name)
{
case 'outertext': return true;
case 'innertext': return true;
case 'plaintext': return true;
@ -765,7 +780,7 @@ class simple_html_dom_node
function convert_text($text)
{
global $debug_object;
if (is_object($debug_object)) {$debug_object->debugLogEntry(1);}
if (is_object($debug_object)) {$debug_object->debug_log_entry(1);}
$converted_text = $text;
@ -777,7 +792,7 @@ class simple_html_dom_node
$sourceCharset = strtoupper($this->dom->_charset);
$targetCharset = strtoupper($this->dom->_target_charset);
}
if (is_object($debug_object)) {$debug_object->debugLog(3, "source charset: " . $sourceCharset . " target charaset: " . $targetCharset);}
if (is_object($debug_object)) {$debug_object->debug_log(3, "source charset: " . $sourceCharset . " target charaset: " . $targetCharset);}
if (!empty($sourceCharset) && !empty($targetCharset) && (strcasecmp($sourceCharset, $targetCharset) != 0))
{
@ -1045,10 +1060,10 @@ class simple_html_dom
// prepare
$this->prepare($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText);
// strip out comments
$this->remove_noise("'<!--(.*?)-->'is");
// strip out cdata
$this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true);
// strip out comments
$this->remove_noise("'<!--(.*?)-->'is");
// Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037
// Script tags removal now preceeds style tag removal.
// strip out <script> tags
@ -1078,10 +1093,15 @@ class simple_html_dom
// load html from file
function load_file()
{
//external error: NOT related to dom loading
$extError=error_get_last();
$args = func_get_args();
$this->load(call_user_func_array('file_get_contents', $args), true);
// Throw an error if we can't properly load the dom.
if (($error=error_get_last())!==null) {
$error=error_get_last();
if ($error!==$extError) {
$this->clear();
return false;
}
@ -1198,22 +1218,22 @@ class simple_html_dom
if ($success)
{
$charset = $matches[1];
if (is_object($debug_object)) {$debug_object->debugLog(2, 'header content-type found charset of: ' . $charset);}
if (is_object($debug_object)) {$debug_object->debug_log(2, 'header content-type found charset of: ' . $charset);}
}
}
if (empty($charset))
{
$el = $this->root->find('meta[http-equiv=Content-Type]',0);
$el = $this->root->find('meta[http-equiv=Content-Type]',0, true);
if (!empty($el))
{
$fullvalue = $el->content;
if (is_object($debug_object)) {$debug_object->debugLog(2, 'meta content-type tag found' . $fullvalue);}
if (is_object($debug_object)) {$debug_object->debug_log(2, 'meta content-type tag found' . $fullvalue);}
if (!empty($fullvalue))
{
$success = preg_match('/charset=(.+)/', $fullvalue, $matches);
$success = preg_match('/charset=(.+)/i', $fullvalue, $matches);
if ($success)
{
$charset = $matches[1];
@ -1221,7 +1241,7 @@ class simple_html_dom
else
{
// If there is a meta tag, and they don't specify the character set, research says that it's typically ISO-8859-1
if (is_object($debug_object)) {$debug_object->debugLog(2, 'meta content-type tag couldn\'t be parsed. using iso-8859 default.');}
if (is_object($debug_object)) {$debug_object->debug_log(2, 'meta content-type tag couldn\'t be parsed. using iso-8859 default.');}
$charset = 'ISO-8859-1';
}
}
@ -1231,14 +1251,19 @@ class simple_html_dom
// If we couldn't find a charset above, then lets try to detect one based on the text we got...
if (empty($charset))
{
// Have php try to detect the encoding from the text given to us.
$charset = mb_detect_encoding($this->root->plaintext . "ascii", $encoding_list = array( "UTF-8", "CP1252" ) );
if (is_object($debug_object)) {$debug_object->debugLog(2, 'mb_detect found: ' . $charset);}
// Use this in case mb_detect_charset isn't installed/loaded on this machine.
$charset = false;
if (function_exists('mb_detect_encoding'))
{
// Have php try to detect the encoding from the text given to us.
$charset = mb_detect_encoding($this->root->plaintext . "ascii", $encoding_list = array( "UTF-8", "CP1252" ) );
if (is_object($debug_object)) {$debug_object->debug_log(2, 'mb_detect found: ' . $charset);}
}
// and if this doesn't work... then we need to just wrongheadedly assume it's UTF-8 so that we can move on - cause this will usually give us most of what we need...
if ($charset === false)
{
if (is_object($debug_object)) {$debug_object->debugLog(2, 'since mb_detect failed - using default of utf-8');}
if (is_object($debug_object)) {$debug_object->debug_log(2, 'since mb_detect failed - using default of utf-8');}
$charset = 'UTF-8';
}
}
@ -1246,11 +1271,11 @@ class simple_html_dom
// Since CP1252 is a superset, if we get one of it's subsets, we want it instead.
if ((strtolower($charset) == strtolower('ISO-8859-1')) || (strtolower($charset) == strtolower('Latin1')) || (strtolower($charset) == strtolower('Latin-1')))
{
if (is_object($debug_object)) {$debug_object->debugLog(2, 'replacing ' . $charset . ' with CP1252 as its a superset');}
if (is_object($debug_object)) {$debug_object->debug_log(2, 'replacing ' . $charset . ' with CP1252 as its a superset');}
$charset = 'CP1252';
}
if (is_object($debug_object)) {$debug_object->debugLog(1, 'EXIT - ' . $charset);}
if (is_object($debug_object)) {$debug_object->debug_log(1, 'EXIT - ' . $charset);}
return $this->_charset = $charset;
}
@ -1616,14 +1641,14 @@ class simple_html_dom
protected function remove_noise($pattern, $remove_tag=false)
{
global $debug_object;
if (is_object($debug_object)) { $debug_object->debugLogEntry(1); }
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
$count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
for ($i=$count-1; $i>-1; --$i)
{
$key = '___noise___'.sprintf('% 5d', count($this->noise)+1000);
if (is_object($debug_object)) { $debug_object->debugLog(2, 'key is: ' . $key); }
if (is_object($debug_object)) { $debug_object->debug_log(2, 'key is: ' . $key); }
$idx = ($remove_tag) ? 0 : 1;
$this->noise[$key] = $matches[$i][$idx][0];
$this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0]));
@ -1641,7 +1666,7 @@ class simple_html_dom
function restore_noise($text)
{
global $debug_object;
if (is_object($debug_object)) { $debug_object->debugLogEntry(1); }
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
while (($pos=strpos($text, '___noise___'))!==false)
{
@ -1649,7 +1674,7 @@ class simple_html_dom
if (strlen($text) > $pos+15)
{
$key = '___noise___'.$text[$pos+11].$text[$pos+12].$text[$pos+13].$text[$pos+14].$text[$pos+15];
if (is_object($debug_object)) { $debug_object->debugLog(2, 'located key of: ' . $key); }
if (is_object($debug_object)) { $debug_object->debug_log(2, 'located key of: ' . $key); }
if (isset($this->noise[$key]))
{
@ -1674,7 +1699,7 @@ class simple_html_dom
function search_noise($text)
{
global $debug_object;
if (is_object($debug_object)) { $debug_object->debugLogEntry(1); }
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
foreach($this->noise as $noiseElement)
{

View File

@ -0,0 +1,12 @@
title: //title
body: //iframe
replace_string(<![CDATA[): _
replace_string(]]>): _
single_page_link: //link[@type='application/xml+oembed']
prune: no
tidy: no
http://www.dailymotion.com/video/x1vk5oh_before-they-were-on-game-of-thrones_people

View File

@ -0,0 +1,3 @@
<?php
// this is here to prevent directory listing over the web
?>

View File

@ -0,0 +1,6 @@
title: //h2
body: div[@id='illustration'] | //p
prune: no
tidy: no
test_url: http://mobile.lemondeinformatique.fr/actualites/lire-les-datacenters-d-apple-google-et-facebook-eco-responsables-selon-greenpeace-le-monde-informatique-57122.html

11
inc/3rdparty/site_config/custom/ted.com.txt vendored Executable file
View File

@ -0,0 +1,11 @@
title: //title
body: //div[@class='talk-article__body talk-transcript__body'] | //div[@class='media__image media__image--thumb talk-link__image']
strip_id_or_class: talk-transcript__para__time
single_page_link: //a[@id='hero-transcript-link']
#prune: no
tidy: no
test_url: http://www.ted.com/talks/andrew_solomon_how_the_worst_moments_in_our_lives_make_us_who_we_are

View File

@ -1,3 +1,2 @@
<?php
// this is here to prevent directory listing over the web
?>
<?php
// this is here to prevent directory listing over the web

View File

@ -0,0 +1,14 @@
body: //div[@id='articlebody']
title: //h1
author: //p[@id='by']//a
next_page_link: //span[@class='next']/a
# Not the same as below!
prune: yes
tidy: no
# Annoying 'next' links plainly inside the article body
strip: //*[text()[contains(.,'Next: ')]]
test_url: http://psychology.about.com/od/theoriesofpersonality/ss/defensemech.htm

View File

@ -0,0 +1,9 @@
title: //div[@id='header']//h1[1]
body: //div[@id='content']
strip_id_or_class: toc
prune: no
test_url: http://moo.nac.uci.edu/~hjm/HOWTO_move_data.html

4
inc/3rdparty/site_config/standard/politico.com.txt vendored Normal file → Executable file
View File

@ -4,10 +4,14 @@ body://div[contains(@class,"story-text")]
# Why doesn't this work? next_page_link://ul[contains(@class,"pagination")]/li/a[@rel="next"]
next_page_link://ul[contains(@class,"pagination")]/li[contains(@class, "current")]/following-sibling::node()/a
next_page_link://div[contains(@class,"pagination")]/ol/li[contains(@class, "current")]/following-sibling::node()/a
date://meta[@name="publish_date"]/@content
strip://div[contains(@class, "breadcrumbs")]
strip://a[contains(@class, "hidden")]
strip://div[contains(@class, "story-embed")]
strip://div[contains(@class, "story-text")]//p/a[contains(text(), "Also on POLITICO:")]/..
strip://div[contains(@class, "story-interrupt")]
strip://footer[contains(@class, "author-bio")]
test_url: http://www.politico.com/news/stories/0712/78105.html

View File

@ -1 +1 @@
4
2013-05-12T22:53:07Z

View File

@ -18,7 +18,7 @@ class Database {
'default' => 'ORDER BY entries.id'
);
function __construct()
function __construct()
{
switch (STORAGE) {
case 'sqlite':
@ -27,12 +27,14 @@ class Database {
break;
case 'mysql':
$db_path = 'mysql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB;
$this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
$this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
break;
case 'postgres':
$db_path = 'pgsql:host=' . STORAGE_SERVER . ';dbname=' . STORAGE_DB;
$this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
$this->handle = new PDO($db_path, STORAGE_USER, STORAGE_PASSWORD);
break;
default:
die(STORAGE . ' is not a recognised database system !');
}
$this->handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
@ -51,7 +53,7 @@ class Database {
}
$hasAdmin = count($query->fetchAll());
if ($hasAdmin == 0)
if ($hasAdmin == 0)
return false;
return true;
@ -77,7 +79,7 @@ class Database {
}
else {
$sql = '
CREATE TABLE tags (
CREATE TABLE IF NOT EXISTS tags (
id bigserial primary key,
value varchar(255) NOT NULL
);
@ -110,7 +112,7 @@ class Database {
}
else {
$sql = '
CREATE TABLE tags_entries (
CREATE TABLE IF NOT EXISTS tags_entries (
id bigserial primary key,
entry_id integer NOT NULL,
tag_id integer NOT NULL
@ -140,7 +142,7 @@ class Database {
$sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
$params = array($id_user, 'language', LANG);
$query = $this->executeQuery($sql, $params);
$sql = 'INSERT INTO users_config ( user_id, name, value ) VALUES (?, ?, ?)';
$params = array($id_user, 'theme', DEFAULT_THEME);
$query = $this->executeQuery($sql, $params);
@ -153,7 +155,7 @@ class Database {
$query = $this->executeQuery($sql, array($id));
$result = $query->fetchAll();
$user_config = array();
foreach ($result as $key => $value) {
$user_config[$value['name']] = $value['value'];
}
@ -201,10 +203,10 @@ class Database {
$params_update = array($password, $userId);
$query = $this->executeQuery($sql_update, $params_update);
}
public function updateUserConfig($userId, $key, $value) {
$config = $this->getConfigUser($userId);
if (! isset($config[$key])) {
$sql = "INSERT INTO users_config (value, user_id, name) VALUES (?, ?, ?)";
}
@ -229,6 +231,73 @@ class Database {
return FALSE;
}
}
public function listUsers($username=null) {
$sql = 'SELECT count(*) FROM users'.( $username ? ' WHERE username=?' : '');
$query = $this->executeQuery($sql, ( $username ? array($username) : array()));
list($count) = $query->fetch();
return $count;
}
public function getUserPassword($userID) {
$sql = "SELECT * FROM users WHERE id=?";
$query = $this->executeQuery($sql, array($userID));
$password = $query->fetchAll();
return isset($password[0]['password']) ? $password[0]['password'] : null;
}
public function deleteUserConfig($userID) {
$sql_action = 'DELETE from users_config WHERE user_id=?';
$params_action = array($userID);
$query = $this->executeQuery($sql_action, $params_action);
return $query;
}
public function deleteTagsEntriesAndEntries($userID) {
$entries = $this->retrieveAll($userID);
foreach($entries as $entryid) {
$tags = $this->retrieveTagsByEntry($entryid);
foreach($tags as $tag) {
$this->removeTagForEntry($entryid,$tags);
}
$this->deleteById($entryid,$userID);
}
}
public function deleteUser($userID) {
$sql_action = 'DELETE from users WHERE id=?';
$params_action = array($userID);
$query = $this->executeQuery($sql_action, $params_action);
}
public function updateContentAndTitle($id, $title, $body, $user_id) {
$sql_action = 'UPDATE entries SET content = ?, title = ? WHERE id=? AND user_id=?';
$params_action = array($body, $title, $id, $user_id);
$query = $this->executeQuery($sql_action, $params_action);
return $query;
}
public function retrieveUnfetchedEntries($user_id, $limit) {
$sql_limit = "LIMIT 0,".$limit;
if (STORAGE == 'postgres') {
$sql_limit = "LIMIT ".$limit." OFFSET 0";
}
$sql = "SELECT * FROM entries WHERE (content = '' OR content IS NULL) AND title LIKE 'Untitled - Import%' AND user_id=? ORDER BY id " . $sql_limit;
$query = $this->executeQuery($sql, array($user_id));
$entries = $query->fetchAll();
return $entries;
}
public function retrieveUnfetchedEntriesCount($user_id) {
$sql = "SELECT count(*) FROM entries WHERE (content = '' OR content IS NULL) AND title LIKE 'Untitled - Import%' AND user_id=?";
$query = $this->executeQuery($sql, array($user_id));
list($count) = $query->fetch();
return $count;
}
public function retrieveAll($user_id) {
$sql = "SELECT * FROM entries WHERE user_id=? ORDER BY id";
@ -294,24 +363,24 @@ class Database {
return $entries;
}
public function getEntriesByViewCount($view, $user_id, $tag_id = 0) {
switch ($view) {
public function getEntriesByViewCount($view, $user_id, $tag_id = 0) {
switch ($view) {
case 'archive':
$sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? ";
$sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? ";
$params = array($user_id, 1);
break;
case 'fav' :
$sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_fav=? ";
$sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_fav=? ";
$params = array($user_id, 1);
break;
case 'tag' :
$sql = "SELECT count(*) FROM entries
LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
WHERE entries.user_id=? AND tags_entries.tag_id = ? ";
$params = array($user_id, $tag_id);
break;
case 'tag' :
$sql = "SELECT count(*) FROM entries
LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
WHERE entries.user_id=? AND tags_entries.tag_id = ? ";
$params = array($user_id, $tag_id);
break;
default:
$sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? ";
$sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? ";
$params = array($user_id, 0);
break;
}
@ -319,7 +388,7 @@ class Database {
$query = $this->executeQuery($sql, $params);
list($count) = $query->fetch();
return $count;
return $count;
}
public function updateContent($id, $content, $user_id) {
@ -329,11 +398,25 @@ class Database {
return $query;
}
public function add($url, $title, $content, $user_id) {
$sql_action = 'INSERT INTO entries ( url, title, content, user_id ) VALUES (?, ?, ?, ?)';
$params_action = array($url, $title, $content, $user_id);
$query = $this->executeQuery($sql_action, $params_action);
return $query;
/**
*
* @param string $url
* @param string $title
* @param string $content
* @param integer $user_id
* @return integer $id of inserted record
*/
public function add($url, $title, $content, $user_id, $isFavorite=0, $isRead=0) {
$sql_action = 'INSERT INTO entries ( url, title, content, user_id, is_fav, is_read ) VALUES (?, ?, ?, ?, ?, ?)';
$params_action = array($url, $title, $content, $user_id, $isFavorite, $isRead);
if ( !$this->executeQuery($sql_action, $params_action) ) {
$id = null;
}
else {
$id = intval($this->getLastId( (STORAGE == 'postgres') ? 'entries_id_seq' : '') );
}
return $id;
}
public function deleteById($id, $user_id) {
@ -365,12 +448,24 @@ class Database {
return $this->getHandle()->lastInsertId($column);
}
public function retrieveAllTags($user_id) {
$sql = "SELECT DISTINCT tags.* FROM tags
public function search($term, $user_id, $limit = '') {
$search = '%'.$term.'%';
$sql_action = "SELECT * FROM entries WHERE user_id=? AND (content LIKE ? OR title LIKE ? OR url LIKE ?) "; //searches in content, title and URL
$sql_action .= $this->getEntriesOrder().' ' . $limit;
$params_action = array($user_id, $search, $search, $search);
$query = $this->executeQuery($sql_action, $params_action);
return $query->fetchAll();
}
public function retrieveAllTags($user_id, $term = null) {
$sql = "SELECT DISTINCT tags.*, count(entries.id) AS entriescount FROM tags
LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id
LEFT JOIN entries ON tags_entries.entry_id=entries.id
WHERE entries.user_id=?";
$query = $this->executeQuery($sql, array($user_id));
WHERE entries.user_id=?
". (($term) ? "AND lower(tags.value) LIKE ?" : '') ."
GROUP BY tags.id, tags.value
ORDER BY tags.value";
$query = $this->executeQuery($sql, (($term)? array($user_id, strtolower('%'.$term.'%')) : array($user_id) ));
$tags = $query->fetchAll();
return $tags;
@ -390,10 +485,10 @@ class Database {
}
public function retrieveEntriesByTag($tag_id, $user_id) {
$sql =
$sql =
"SELECT entries.* FROM entries
LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
WHERE tags_entries.tag_id = ? AND entries.user_id=?";
WHERE tags_entries.tag_id = ? AND entries.user_id=? ORDER by entries.id DESC";
$query = $this->executeQuery($sql, array($tag_id, $user_id));
$entries = $query->fetchAll();
@ -401,7 +496,7 @@ class Database {
}
public function retrieveTagsByEntry($entry_id) {
$sql =
$sql =
"SELECT tags.* FROM tags
LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id
WHERE tags_entries.entry_id = ?";
@ -417,6 +512,25 @@ class Database {
$query = $this->executeQuery($sql_action, $params_action);
return $query;
}
public function cleanUnusedTag($tag_id) {
$sql_action = "SELECT tags.* FROM tags JOIN tags_entries ON tags_entries.tag_id=tags.id WHERE tags.id=?";
$query = $this->executeQuery($sql_action,array($tag_id));
$tagstokeep = $query->fetchAll();
$sql_action = "SELECT tags.* FROM tags LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id WHERE tags.id=?";
$query = $this->executeQuery($sql_action,array($tag_id));
$alltags = $query->fetchAll();
foreach ($alltags as $tag) {
if ($tag && !in_array($tag,$tagstokeep)) {
$sql_action = "DELETE FROM tags WHERE id=?";
$params_action = array($tag[0]);
$this->executeQuery($sql_action, $params_action);
return true;
}
}
}
public function retrieveTagByValue($value) {
$tag = NULL;

File diff suppressed because it is too large Load Diff

93
inc/poche/Tools.class.php Normal file → Executable file
View File

@ -7,7 +7,7 @@
* @copyright 2013
* @license http://www.wtfpl.net/ see COPYING file
*/
class Tools
{
public static function initPhp()
@ -18,8 +18,6 @@ class Tools
die(_('Oops, it seems you don\'t have PHP 5.'));
}
error_reporting(E_ALL);
function stripslashesDeep($value) {
return is_array($value)
? array_map('stripslashesDeep', $value)
@ -42,7 +40,7 @@ class Tools
&& (strtolower($_SERVER['HTTPS']) == 'on'))
|| (isset($_SERVER["SERVER_PORT"])
&& $_SERVER["SERVER_PORT"] == '443') // HTTPS detection.
|| (isset($_SERVER["SERVER_PORT"]) //Custom HTTPS port detection
|| (isset($_SERVER["SERVER_PORT"]) //Custom HTTPS port detection
&& $_SERVER["SERVER_PORT"] == SSL_PORT)
|| (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https');
@ -59,8 +57,14 @@ class Tools
return $scriptname;
}
$host = (isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']));
if (strpos($host, ':') !== false) {
$serverport = '';
}
return 'http' . ($https ? 's' : '') . '://'
. $_SERVER["HTTP_HOST"] . $serverport . $scriptname;
. $host . $serverport . $scriptname;
}
public static function redirect($url = '')
@ -148,7 +152,7 @@ class Tools
);
# only download page lesser than 4MB
$data = @file_get_contents($url, false, $context, -1, 4000000);
$data = @file_get_contents($url, false, $context, -1, 4000000);
if (isset($http_response_header) and isset($http_response_header[0])) {
$httpcodeOK = isset($http_response_header) and isset($http_response_header[0]) and ((strpos($http_response_header[0], '200 OK') !== FALSE) or (strpos($http_response_header[0], '301 Moved Permanently') !== FALSE));
@ -193,14 +197,14 @@ class Tools
public static function logm($message)
{
if (DEBUG_POCHE) {
if (DEBUG_POCHE && php_sapi_name() != 'cli') {
$t = strval(date('Y/m/d_H:i:s')) . ' - ' . $_SERVER["REMOTE_ADDR"] . ' - ' . strval($message) . "\n";
file_put_contents(CACHE . '/log.txt', $t, FILE_APPEND);
error_log('DEBUG POCHE : ' . $message);
}
}
public static function encodeString($string)
public static function encodeString($string)
{
return sha1($string . SALT);
}
@ -212,7 +216,7 @@ class Tools
public static function getDomain($url)
{
return parse_url($url, PHP_URL_HOST);
return parse_url($url, PHP_URL_HOST);
}
public static function getReadingTime($text) {
@ -241,7 +245,6 @@ class Tools
}
}
public static function download_db() {
header('Content-Disposition: attachment; filename="poche.sqlite.gz"');
self::status(200);
@ -252,4 +255,74 @@ class Tools
exit;
}
public static function getPageContent(Url $url)
{
// Saving and clearing context
$REAL = array();
foreach( $GLOBALS as $key => $value ) {
if( $key != 'GLOBALS' && $key != '_SESSION' && $key != 'HTTP_SESSION_VARS' ) {
$GLOBALS[$key] = array();
$REAL[$key] = $value;
}
}
// Saving and clearing session
if ( isset($_SESSION) ) {
$REAL_SESSION = array();
foreach( $_SESSION as $key => $value ) {
$REAL_SESSION[$key] = $value;
unset($_SESSION[$key]);
}
}
// Running code in different context
$scope = function() {
extract( func_get_arg(1) );
$_GET = $_REQUEST = array(
"url" => $url->getUrl(),
"max" => 5,
"links" => "preserve",
"exc" => "",
"format" => "json",
"submit" => "Create Feed"
);
ob_start();
require func_get_arg(0);
$json = ob_get_contents();
ob_end_clean();
return $json;
};
$json = $scope( "inc/3rdparty/makefulltextfeed.php", array("url" => $url) );
// Clearing and restoring context
foreach( $GLOBALS as $key => $value ) {
if( $key != "GLOBALS" && $key != "_SESSION" ) {
unset($GLOBALS[$key]);
}
}
foreach( $REAL as $key => $value ) {
$GLOBALS[$key] = $value;
}
// Clearing and restoring session
if ( isset($REAL_SESSION) ) {
foreach( $_SESSION as $key => $value ) {
unset($_SESSION[$key]);
}
foreach( $REAL_SESSION as $key => $value ) {
$_SESSION[$key] = $value;
}
}
return json_decode($json, true);
}
/**
* Returns whether we handle an AJAX (XMLHttpRequest) request.
* @return boolean whether we handle an AJAX (XMLHttpRequest) request.
*/
public static function isAjaxRequest()
{
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
}
}

View File

@ -0,0 +1,68 @@
<?php
/**
* wallabag, self hostable application allowing you to not miss any content anymore
*
* @category wallabag
* @author Nicolas Lœuillet <nicolas@loeuillet.org>
* @copyright 2013
* @license http://www.wtfpl.net/ see COPYING file
*/
@define ('SALT', ''); # put a strong string here
@define ('LANG', 'en_EN.utf8');
@define ('STORAGE', 'sqlite'); # postgres, mysql or sqlite
@define ('STORAGE_SQLITE', ROOT . '/db/poche.sqlite'); # if you are using sqlite, where the database file is located
# only for postgres & mysql
@define ('STORAGE_SERVER', 'localhost');
@define ('STORAGE_DB', 'poche');
@define ('STORAGE_USER', 'poche');
@define ('STORAGE_PASSWORD', 'poche');
#################################################################################
# Do not trespass unless you know what you are doing
#################################################################################
// Change this if not using the standart port for SSL - i.e you server is behind sslh
@define ('SSL_PORT', 443);
@define ('MODE_DEMO', FALSE);
@define ('DEBUG_POCHE', FALSE);
//default level of error reporting in application. Developers should override it in their config.inc.php: set to E_ALL.
@define ('ERROR_REPORTING', E_ALL & ~E_NOTICE);
@define ('DOWNLOAD_PICTURES', FALSE); # This can slow down the process of adding articles
@define ('REGENERATE_PICTURES_QUALITY', 75);
@define ('CONVERT_LINKS_FOOTNOTES', FALSE);
@define ('REVERT_FORCED_PARAGRAPH_ELEMENTS', FALSE);
@define ('SHARE_TWITTER', TRUE);
@define ('SHARE_MAIL', TRUE);
@define ('SHARE_SHAARLI', FALSE);
@define ('SHAARLI_URL', 'http://myshaarliurl.com');
@define ('FLATTR', TRUE);
@define ('FLATTR_API', 'https://api.flattr.com/rest/v2/things/lookup/?url=');
@define ('NOT_FLATTRABLE', '0');
@define ('FLATTRABLE', '1');
@define ('FLATTRED', '2');
// display or not print link in article view
@define ('SHOW_PRINTLINK', '1');
// display or not percent of read in article view. Affects only default theme.
@define ('SHOW_READPERCENT', '1');
@define ('ABS_PATH', 'assets/');
@define ('DEFAULT_THEME', 'baggy');
@define ('THEME', ROOT . '/themes');
@define ('LOCALE', ROOT . '/locale');
@define ('CACHE', ROOT . '/cache');
@define ('PAGINATION', '10');
//limit for download of articles during import
@define ('IMPORT_LIMIT', 5);
//delay between downloads (in sec)
@define ('IMPORT_DELAY', 5);

View File

@ -1,63 +0,0 @@
<?php
/**
* wallabag, self hostable application allowing you to not miss any content anymore
*
* @category wallabag
* @author Nicolas Lœuillet <nicolas@loeuillet.org>
* @copyright 2013
* @license http://www.wtfpl.net/ see COPYING file
*/
define ('SALT', ''); # put a strong string here
define ('LANG', 'en_EN.utf8');
define ('STORAGE', 'sqlite'); # postgres, mysql or sqlite
define ('STORAGE_SQLITE', ROOT . '/db/poche.sqlite'); # if you are using sqlite, where the database file is located
# only for postgres & mysql
define ('STORAGE_SERVER', 'localhost');
define ('STORAGE_DB', 'poche');
define ('STORAGE_USER', 'poche');
define ('STORAGE_PASSWORD', 'poche');
#################################################################################
# Do not trespass unless you know what you are doing
#################################################################################
// Change this if not using the standart port for SSL - i.e you server is behind sslh
define ('SSL_PORT', 443);
define ('MODE_DEMO', FALSE);
define ('DEBUG_POCHE', FALSE);
define ('DOWNLOAD_PICTURES', FALSE);
define ('CONVERT_LINKS_FOOTNOTES', FALSE);
define ('REVERT_FORCED_PARAGRAPH_ELEMENTS', FALSE);
define ('SHARE_TWITTER', TRUE);
define ('SHARE_MAIL', TRUE);
define ('SHARE_SHAARLI', FALSE);
define ('SHAARLI_URL', 'http://myshaarliurl.com');
define ('FLATTR', TRUE);
define ('FLATTR_API', 'https://api.flattr.com/rest/v2/things/lookup/?url=');
define ('NOT_FLATTRABLE', '0');
define ('FLATTRABLE', '1');
define ('FLATTRED', '2');
define ('ABS_PATH', 'assets/');
define ('DEFAULT_THEME', 'baggy');
define ('THEME', ROOT . '/themes');
define ('LOCALE', ROOT . '/locale');
define ('CACHE', ROOT . '/cache');
define ('PAGINATION', '10');
define ('POCKET_FILE', '/ril_export.html');
define ('READABILITY_FILE', '/readability');
define ('INSTAPAPER_FILE', '/instapaper-export.html');
define ('POCHE_FILE', '/poche-export');
define ('IMPORT_POCKET_FILE', ROOT . POCKET_FILE);
define ('IMPORT_READABILITY_FILE', ROOT . READABILITY_FILE);
define ('IMPORT_INSTAPAPER_FILE', ROOT . INSTAPAPER_FILE);
define ('IMPORT_POCHE_FILE', ROOT . POCHE_FILE);

8
inc/poche/global.inc.php Normal file → Executable file
View File

@ -31,6 +31,11 @@ require_once INCLUDES . '/3rdparty/FlattrItem.class.php';
require_once INCLUDES . '/3rdparty/htmlpurifier/HTMLPurifier.auto.php';
# epub library
require_once INCLUDES . '/3rdparty/libraries/PHPePub/Logger.php';
require_once INCLUDES . '/3rdparty/libraries/PHPePub/EPub.php';
require_once INCLUDES . '/3rdparty/libraries/PHPePub/EPubChapterSplitter.php';
# Composer its autoloader for automatically loading Twig
if (! file_exists(ROOT . '/vendor/autoload.php')) {
Poche::$canRenderTemplates = false;
@ -38,11 +43,12 @@ if (! file_exists(ROOT . '/vendor/autoload.php')) {
require_once ROOT . '/vendor/autoload.php';
}
# system configuration; database credentials et cetera
# system configuration; database credentials et caetera
if (! file_exists(INCLUDES . '/poche/config.inc.php')) {
Poche::$configFileAvailable = false;
} else {
require_once INCLUDES . '/poche/config.inc.php';
require_once INCLUDES . '/poche/config.inc.default.php';
}
if (Poche::$configFileAvailable && DOWNLOAD_PICTURES) {

View File

@ -14,6 +14,7 @@
function filtre_picture($content, $url, $id)
{
$matches = array();
$processing_pictures = array(); // list of processing image to avoid processing the same pictures twice
preg_match_all('#<\s*(img)[^>]+src="([^"]*)"[^>]*>#Si', $content, $matches, PREG_SET_ORDER);
foreach($matches as $i => $link) {
$link[1] = trim($link[1]);
@ -22,8 +23,17 @@ function filtre_picture($content, $url, $id)
$filename = basename(parse_url($absolute_path, PHP_URL_PATH));
$directory = create_assets_directory($id);
$fullpath = $directory . '/' . $filename;
download_pictures($absolute_path, $fullpath);
$content = str_replace($matches[$i][2], $fullpath, $content);
if (in_array($absolute_path, $processing_pictures) === true) {
// replace picture's URL only if processing is OK : already processing -> go to next picture
continue;
}
if (download_pictures($absolute_path, $fullpath) === true) {
$content = str_replace($matches[$i][2], $fullpath, $content);
}
$processing_pictures[] = $absolute_path;
}
}
@ -64,17 +74,55 @@ function get_absolute_link($relative_link, $url) {
/**
* Téléchargement des images
*
* @return bool true if the download and processing is OK, false else
*/
function download_pictures($absolute_path, $fullpath)
{
$rawdata = Tools::getFile($absolute_path);
$fullpath = urldecode($fullpath);
if(file_exists($fullpath)) {
unlink($fullpath);
}
$fp = fopen($fullpath, 'x');
fwrite($fp, $rawdata);
fclose($fp);
// check extension
$file_ext = strrchr($fullpath, '.');
$whitelist = array(".jpg",".jpeg",".gif",".png");
if (!(in_array($file_ext, $whitelist))) {
Tools::logm('processed image with not allowed extension. Skipping ' . $fullpath);
return false;
}
// check headers
$imageinfo = getimagesize($absolute_path);
if ($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg'&& $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
Tools::logm('processed image with bad header. Skipping ' . $fullpath);
return false;
}
// regenerate image
$im = imagecreatefromstring($rawdata);
if ($im === false) {
Tools::logm('error while regenerating image ' . $fullpath);
return false;
}
switch ($imageinfo['mime']) {
case 'image/gif':
$result = imagegif($im, $fullpath);
break;
case 'image/jpeg':
case 'image/jpg':
$result = imagejpeg($im, $fullpath, REGENERATE_PICTURES_QUALITY);
break;
case 'image/png':
$result = imagepng($im, $fullpath, ceil(REGENERATE_PICTURES_QUALITY / 100 * 9));
break;
}
imagedestroy($im);
return $result;
}
/**

90
index.php Normal file → Executable file
View File

@ -8,10 +8,18 @@
* @license http://www.wtfpl.net/ see COPYING file
*/
define ('POCHE', '1.5.2');
define ('POCHE', '1.7.2');
require 'check_setup.php';
require_once 'inc/poche/global.inc.php';
session_start();
# Set error reporting level
if (defined('ERROR_REPORTING')) {
error_reporting(ERROR_REPORTING);
}
# Start session
Session::$sessionName = 'poche';
Session::init();
# Start Poche
$poche = new Poche();
@ -30,14 +38,14 @@ $tpl_vars = array(
'referer' => $referer,
'view' => $view,
'poche_url' => Tools::getPocheUrl(),
'title' => _('poche, a read it later open source system'),
'title' => _('wallabag, a read it later open source system'),
'token' => Session::getToken(),
'theme' => $poche->getTheme()
);
if (! empty($notInstalledMessage)) {
if (! Poche::$canRenderTemplates || ! Poche::$configFileAvailable) {
# We cannot use Twig to display the error message
# We cannot use Twig to display the error message
echo '<h1>Errors</h1><ol>';
foreach ($notInstalledMessage as $message) {
echo '<li>' . $message . '</li>';
@ -55,45 +63,54 @@ if (! empty($notInstalledMessage)) {
# poche actions
if (isset($_GET['login'])) {
# hello you
# hello to you
$poche->login($referer);
} elseif (isset($_GET['logout'])) {
# see you soon !
$poche->logout();
} elseif (isset($_GET['config'])) {
# Update password
$poche->updatePassword();
} elseif (isset($_GET['import'])) {
$import = $poche->import($_GET['from']);
} elseif (isset($_GET['download'])) {
Tools::download_db();
} elseif (isset($_GET['empty-cache'])) {
$poche->emptyCache();
} elseif (isset($_GET['export'])) {
$poche->export();
} elseif (isset($_GET['updatetheme'])) {
$poche->updateTheme();
} elseif (isset($_GET['updatelanguage'])) {
$poche->updateLanguage();
} elseif (isset($_GET['feed'])) {
if (isset($_GET['action']) && $_GET['action'] == 'generate') {
$poche->generateToken();
}
else {
$tag_id = (isset($_GET['tag_id']) ? intval($_GET['tag_id']) : 0);
$poche->generateFeeds($_GET['token'], $_GET['user_id'], $tag_id, $_GET['type']);
}
}
elseif (isset($_GET['plainurl']) && !empty($_GET['plainurl'])) {
$plain_url = new Url(base64_encode($_GET['plainurl']));
$poche->action('add', $plain_url);
} elseif (isset($_GET['feed']) && isset($_GET['user_id'])) {
$tag_id = (isset($_GET['tag_id']) ? intval($_GET['tag_id']) : 0);
$poche->generateFeeds($_GET['token'], filter_var($_GET['user_id'],FILTER_SANITIZE_NUMBER_INT), $tag_id, $_GET['type']);
}
if (Session::isLogged()) {
if (isset($_GET['logout'])) {
# see you soon !
$poche->logout();
} elseif (isset($_GET['config'])) {
# Update password
$poche->updatePassword();
} elseif (isset($_GET['newuser'])) {
$poche->createNewUser();
} elseif (isset($_GET['deluser'])) {
$poche->deleteUser();
} elseif (isset($_GET['epub'])) {
$poche->createEpub();
} elseif (isset($_GET['import'])) {
$import = $poche->import();
$tpl_vars = array_merge($tpl_vars, $import);
} elseif (isset($_GET['download'])) {
Tools::download_db();
} elseif (isset($_GET['empty-cache'])) {
$poche->emptyCache();
} elseif (isset($_GET['export'])) {
$poche->export();
} elseif (isset($_GET['updatetheme'])) {
$poche->updateTheme();
} elseif (isset($_GET['updatelanguage'])) {
$poche->updateLanguage();
} elseif (isset($_GET['uploadfile'])) {
$poche->uploadFile();
} elseif (isset($_GET['feed']) && isset($_GET['action']) && $_GET['action'] == 'generate') {
$poche->generateToken();
}
elseif (isset($_GET['plainurl']) && !empty($_GET['plainurl'])) {
$plain_url = new Url(base64_encode($_GET['plainurl']));
$poche->action('add', $plain_url);
}
$poche->action($action, $url, $id);
$tpl_file = Tools::getTplFile($view);
$tpl_vars = array_merge($tpl_vars, $poche->displayView($view, $id));
} elseif(isset($_SERVER['PHP_AUTH_USER'])) {
if($poche->store->userExists($_SERVER['PHP_AUTH_USER'])) {
$poche->login($referer);
@ -115,6 +132,7 @@ if (Session::isLogged()) {
} else {
$tpl_file = Tools::getTplFile('login');
$tpl_vars['http_auth'] = 0;
Session::logout();
}
# because messages can be added in $poche->action(), we have to add this entry now (we can add it before)

81
install/index.php Normal file → Executable file
View File

@ -1,9 +1,30 @@
<?php
$errors = array();
$successes = array();
if ($_POST['download']) {
/* Function taken from at http://php.net/manual/en/function.rmdir.php#110489
* Idea : nbari at dalmp dot com
* Rights unknown
* Here in case of .gitignore files
*/
function delTree($dir) {
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
}
return rmdir($dir);
}
if (isset($_GET['clean'])) {
if (is_dir('install')){
delTree('install');
header('Location: index.php');
}
}
if (isset($_POST['download'])) {
if (!file_put_contents("cache/vendor.zip", fopen("http://static.wallabag.org/files/vendor.zip", 'r'))) {
$errors[] = 'Impossible to download vendor.zip. Please <a href="http://wllbg.org/vendor">download it manually<a> and unzip it in your wallabag folder.';
$errors[] = 'Impossible to download vendor.zip. Please <a href="http://wllbg.org/vendor">download it manually</a> and unzip it in your wallabag folder.';
}
else {
if (extension_loaded('zip')) {
@ -25,14 +46,14 @@ if ($_POST['download']) {
}
}
}
else if ($_POST['install']) {
else if (isset($_POST['install'])) {
if (!is_dir('vendor')) {
$errors[] = 'You must install twig before.';
}
else {
$continue = true;
// Create config.inc.php
if (!copy('inc/poche/config.inc.php.new', 'inc/poche/config.inc.php')) {
if (!copy('inc/poche/config.inc.default.php', 'inc/poche/config.inc.php')) {
$errors[] = 'Installation aborted, impossible to create inc/poche/config.inc.php file. Maybe you don\'t have write access to create it.';
$continue = false;
}
@ -64,6 +85,7 @@ else if ($_POST['install']) {
else {
$db_path = 'sqlite:' . realpath('') . '/db/poche.sqlite';
$handle = new PDO($db_path);
$sql_structure = "";
}
}
else {
@ -79,7 +101,7 @@ else if ($_POST['install']) {
$sql_structure = file_get_contents('install/mysql.sql');
}
else if ($_POST['db_engine'] == 'postgresql') {
else if ($_POST['db_engine'] == 'postgres') {
$db_path = 'pgsql:host=' . $_POST['pg_server'] . ';dbname=' . $_POST['pg_database'];
$content = str_replace("define ('STORAGE_SERVER', 'localhost');", "define ('STORAGE_SERVER', '".$_POST['pg_server']."');", $content);
$content = str_replace("define ('STORAGE_DB', 'poche');", "define ('STORAGE_DB', '".$_POST['pg_database']."');", $content);
@ -129,7 +151,7 @@ else if ($_POST['install']) {
$params = array($id_user, 'language', 'en_EN.UTF8');
$query = executeQuery($handle, $sql, $params);
$successes[] = 'wallabag is now installed. Don\'t forget to delete install folder. Then, <a href="index.php">reload this page</a>.';
$successes[] = 'wallabag is now installed. You can now <a href="index.php?clean=0">access it !</a>';
}
}
}
@ -143,7 +165,7 @@ else if ($_POST['install']) {
<!--[if IE]>
<meta http-equiv="X-UA-Compatible" content="IE=10">
<![endif]-->
<title>wallabag installation</title>
<title>wallabag - installation</title>
<link rel="shortcut icon" type="image/x-icon" href="themes/baggy/img/favicon.ico" />
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="themes/baggy/img/apple-touch-icon-144x144-precomposed.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="themes/baggy/img/apple-touch-icon-72x72-precomposed.png">
@ -154,7 +176,7 @@ else if ($_POST['install']) {
<link rel="stylesheet" href="themes/baggy/css/main.css" media="all">
<link rel="stylesheet" href="themes/baggy/css/messages.css" media="all">
<link rel="stylesheet" href="themes/baggy/css/print.css" media="print">
<script src="themes/baggy/js/jquery-2.0.3.min.js"></script>
<script src="themes/default/js/jquery-2.0.3.min.js"></script>
<script src="themes/baggy/js/init.js"></script>
</head>
<body>
@ -198,18 +220,18 @@ else if ($_POST['install']) {
<?php if (file_exists('inc/poche/config.inc.php') && is_dir('vendor')) : ?>
<div class='messages success install'>
<p>
wallabag seems already installed. If you want to update it, you only have to delete install folder.
wallabag seems already installed. If you want to update it, you only have to delete install folder, then <a href="index.php">reload this page</a>.
</p>
</div>
<?php endif; ?>
<?php endif; ?>
<p>To install wallabag, you just have to fill the following fields. That's all.</p>
<p>Don't forget to check your server compatibility <a href="wallabag_compatibility_test.php">here</a>.</p>
<p>Don't forget to check your server compatibility <a href="wallabag_compatibility_test.php?from=install">here</a>.</p>
<form method="post">
<fieldset>
<legend><strong>Technical settings</strong></legend>
<?php if (!is_dir('vendor')) : ?>
<div class='messages notice install'>wallabag needs twig, a template engine (<a href="http://twig.sensiolabs.org/">?</a>). Two ways to install it:
<div class='messages notice install'>wallabag needs twig, a template engine (<a href="http://twig.sensiolabs.org/">?</a>). Two ways to install it:<br />
<ul>
<li>automatically download and extract vendor.zip into your wallabag folder.
<p><input type="submit" name="download" value="Download vendor.zip" /></p>
@ -225,7 +247,11 @@ php composer.phar install</code></pre></li>
<p>
Database engine:
<ul>
<li><label for="sqlite">SQLite</label> <input name="db_engine" type="radio" checked="" id="sqlite" value="sqlite" /></li>
<li><label for="sqlite">SQLite</label> <input name="db_engine" type="radio" checked="" id="sqlite" value="sqlite" />
<div id="pdo_sqlite" class='messages error install'>
<p>You have to enable <a href="http://php.net/manual/ref.pdo-sqlite.php">pdo_sqlite extension</a>.</p>
</div>
</li>
<li>
<label for="mysql">MySQL</label> <input name="db_engine" type="radio" id="mysql" value="mysql" />
<ul id="mysql_infos">
@ -236,12 +262,12 @@ php composer.phar install</code></pre></li>
</ul>
</li>
<li>
<label for="postgresql">PostgreSQL</label> <input name="db_engine" type="radio" id="postgresql" value="postgresql" />
<label for="postgres">PostgreSQL</label> <input name="db_engine" type="radio" id="postgres" value="postgres" />
<ul id="pg_infos">
<li><label for="pg_server">Server</label> <input type="text" placeholder="localhost" id="pg_server" name="pg_server" /></li>
<li><label for="pg_database">Database</label> <input type="text" placeholder="wallabag" id="pg_database" name="pg_database" /></li>
<li><label for="pg_user">User</label> <input type="text" placeholder="user" id="pg_user" name="pg_user" /></li>
id <li><label for="pg_password">Password</label> <input type="text" placeholder="p4ssw0rd" id="pg_password" name="pg_password" /></li>
<li><label for="pg_password">Password</label> <input type="text" placeholder="p4ssw0rd" id="pg_password" name="pg_password" /></li>
</ul>
</li>
</ul>
@ -263,26 +289,49 @@ php composer.phar install</code></pre></li>
</p>
</fieldset>
<input type="submit" value="Install wallabag" name="install" />
<input type="submit" id="install_button" value="Install wallabag" name="install" />
</form>
</div>
<script>
$("#mysql_infos").hide();
$("#pg_infos").hide();
<?php
if (!extension_loaded('pdo_sqlite')) : ?>
$("#install_button").hide();
<?php
else :
?>
$("#pdo_sqlite").hide();
<?php
endif;
?>
$("input[name=db_engine]").click(function()
{
if ( $("#mysql").prop('checked')) {
$("#mysql_infos").show();
$("#pg_infos").hide();
$("#pdo_sqlite").hide();
$("#install_button").show();
}
else {
if ( $("#postgresql").prop('checked')) {
if ( $("#postgres").prop('checked')) {
$("#mysql_infos").hide();
$("#pg_infos").show();
$("#pdo_sqlite").hide();
$("#install_button").show();
}
else {
$("#mysql_infos").hide();
$("#pg_infos").hide();
<?php
if (!extension_loaded('pdo_sqlite')) : ?>
$("#pdo_sqlite").show();
$("#install_button").hide();
<?php
endif;
?>
}
}
});

0
install/poche.sqlite Executable file → Normal file
View File

View File

@ -1,10 +1,10 @@
CREATE TABLE config (
CREATE TABLE IF NOT EXISTS config (
id bigserial primary key,
name varchar(255) NOT NULL,
value varchar(255) NOT NULL
);
CREATE TABLE entries (
CREATE TABLE IF NOT EXISTS entries (
id bigserial primary key,
title varchar(255) NOT NULL,
url varchar(255) NOT NULL,
@ -14,7 +14,7 @@ CREATE TABLE entries (
user_id integer NOT NULL
);
CREATE TABLE users (
CREATE TABLE IF NOT EXISTS users (
id bigserial primary key,
username varchar(255) NOT NULL,
password varchar(255) NOT NULL,
@ -22,20 +22,20 @@ CREATE TABLE users (
email varchar(255) NOT NULL
);
CREATE TABLE users_config (
CREATE TABLE IF NOT EXISTS users_config (
id bigserial primary key,
user_id integer NOT NULL,
name varchar(255) NOT NULL,
value varchar(255) NOT NULL
);
CREATE TABLE tags (
CREATE TABLE IF NOT EXISTS tags (
id bigserial primary key,
value varchar(255) NOT NULL
);
CREATE TABLE tags_entries (
CREATE TABLE IF NOT EXISTS tags_entries (
id bigserial primary key,
entry_id integer NOT NULL,
tag_id integer NOT NULL
)
)

View File

@ -4,54 +4,137 @@
msgid ""
msgstr ""
"Project-Id-Version: poche\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2013-10-08 13:25+0100\n"
"Last-Translator: Nicolas Lœuillet <nicolas.loeuillet@gmail.com>\n"
"Language-Team: Czech (http://www.transifex.com/projects/p/poche/language/"
"cs/)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-25 15:28+0300\n"
"PO-Revision-Date: 2014-02-25 15:29+0300\n"
"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
"Language-Team: Czech (http://www.transifex.com/projects/p/poche/language/cs/)\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: cs\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Poedit 1.5.4\n"
"X-Poedit-Language: Czech\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
msgid "wallabag, a read it later open source system"
msgstr ""
msgid "login failed: user doesn't exist"
msgstr ""
msgid "return home"
msgstr ""
msgid "config"
msgstr "nastavení"
msgid "Poching a link"
msgstr "Odkaz se ukládá"
msgid "Saving articles"
msgstr ""
msgid "There are several ways to save an article:"
msgstr ""
msgid "read the documentation"
msgstr "číst dokumentaci"
msgid "by filling this field"
msgid "download the extension"
msgstr ""
msgid "via F-Droid"
msgstr ""
msgid " or "
msgstr ""
msgid "via Google Play"
msgstr ""
msgid "download the application"
msgstr ""
#, fuzzy
msgid "By filling this field"
msgstr "vyplněním tohoto pole"
msgid "poche it!"
msgstr "uložit!"
msgid "bag it!"
msgstr ""
msgid "Updating poche"
msgstr "Poche se aktualizuje"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "vaše verze"
msgid "Upgrading wallabag"
msgstr ""
msgid "latest stable version"
#, fuzzy
msgid "Installed version"
msgstr "poslední stabilní verze"
msgid "a more recent stable version is available."
#, fuzzy
msgid "Latest stable version"
msgstr "poslední stabilní verze"
#, fuzzy
msgid "A more recent stable version is available."
msgstr "je k dispozici novější stabilní verze."
msgid "you are up to date."
#, fuzzy
msgid "You are up to date."
msgstr "je aktuální"
msgid "latest dev version"
#, fuzzy
msgid "Latest dev version"
msgstr "poslední vývojová verze"
msgid "a more recent development version is available."
#, fuzzy
msgid "A more recent development version is available."
msgstr "je k dispozici novější vývojová verze."
msgid "Feeds"
msgstr ""
msgid "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>."
msgstr ""
msgid "Unread feed"
msgstr ""
#, fuzzy
msgid "Favorites feed"
msgstr "oblíbené"
#, fuzzy
msgid "Archive feed"
msgstr "archív"
msgid "Your token:"
msgstr ""
msgid "Your user id:"
msgstr ""
msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgstr ""
#, fuzzy
msgid "Change your theme"
msgstr "Změnit heslo"
msgid "Theme:"
msgstr ""
msgid "Update"
msgstr "Aktualizovat"
#, fuzzy
msgid "Change your language"
msgstr "Změnit heslo"
msgid "Language:"
msgstr ""
msgid "Change your password"
msgstr "Změnit heslo"
@ -64,65 +147,68 @@ msgstr "Heslo"
msgid "Repeat your new password:"
msgstr "Znovu nové heslo:"
msgid "Update"
msgstr "Aktualizovat"
msgid "Import"
msgstr "Importovat"
msgid "Please execute the import script locally, it can take a very long time."
#, fuzzy
msgid "Please execute the import script locally as it can take a very long time."
msgstr "Spusťte importní skript lokálně, může to dlouho trvat."
msgid "More info in the official doc:"
#, fuzzy
msgid "More info in the official documentation:"
msgstr "Více informací v oficiální dokumentaci:"
msgid "import from Pocket"
#, fuzzy
msgid "Import from Pocket"
msgstr "importovat z Pocket"
msgid "import from Readability"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr ""
#, fuzzy
msgid "Import from Readability"
msgstr "importovat z Readability"
msgid "import from Instapaper"
#, fuzzy
msgid "Import from Instapaper"
msgstr "importovat z Instapaper"
msgid "Export your poche data"
#, fuzzy
msgid "Import from wallabag"
msgstr "importovat z Readability"
#, fuzzy
msgid "Export your wallabag data"
msgstr "Export dat"
msgid "Click here"
msgstr "Klikněte zde"
msgid "to export your poche data."
msgid "to download your database."
msgstr ""
#, fuzzy
msgid "to export your wallabag data."
msgstr "pro export vašich dat."
msgid "back to home"
msgstr "zpět na úvod"
msgid "installation"
msgstr "instalace"
msgid "install your poche"
msgstr "instalovat"
msgid ""
"poche is still not installed. Please fill the below form to install it. "
"Don't hesitate to <a href='http://doc.inthepoche.com'>read the documentation "
"on poche website</a>."
msgid "Cache"
msgstr ""
"poche ještě není nainstalováno. Pro instalaci vyplňte níže uvedený formulář. "
"Nezapomeňte <a href='http://doc.inthepoche.com'>si přečíst dokumentaci</a> "
"na stránkách programu."
msgid "Login"
msgstr "Jméno"
msgid "to delete cache."
msgstr ""
msgid "Repeat your password"
msgstr "Zopakujte heslo"
msgid "You can enter multiple tags, separated by commas."
msgstr ""
msgid "Install"
msgstr "Instalovat"
msgid "return to article"
msgstr ""
msgid "back to top"
msgstr "zpět na začátek"
msgid "plop"
msgstr ""
msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgstr ""
msgid "favoris"
msgstr "oblíbené"
@ -151,10 +237,14 @@ msgstr "podle nadpisu"
msgid "by title desc"
msgstr "podle nadpisu sestupně"
msgid "No link available here!"
msgstr "Není k dispozici žádný odkaz!"
msgid "Tag"
msgstr ""
msgid "toggle mark as read"
msgid "No articles found."
msgstr ""
#, fuzzy
msgid "Toggle mark as read"
msgstr "označit jako přečtené"
msgid "toggle favorite"
@ -166,13 +256,95 @@ msgstr "smazat"
msgid "original"
msgstr "originál"
msgid "estimated reading time:"
msgstr ""
msgid "mark all the entries as read"
msgstr ""
msgid "results"
msgstr "výsledky"
msgid "tweet"
msgid "installation"
msgstr "instalace"
#, fuzzy
msgid "install your wallabag"
msgstr "instalovat"
#, fuzzy
msgid "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>."
msgstr "poche ještě není nainstalováno. Pro instalaci vyplňte níže uvedený formulář. Nezapomeňte <a href='http://doc.inthepoche.com'>si přečíst dokumentaci</a> na stránkách programu."
msgid "Login"
msgstr "Jméno"
msgid "Repeat your password"
msgstr "Zopakujte heslo"
msgid "Install"
msgstr "Instalovat"
#, fuzzy
msgid "login to your wallabag"
msgstr "přihlásit se k poche"
msgid "Login to wallabag"
msgstr ""
msgid "you are in demo mode, some features may be disabled."
msgstr "používáte ukázkový mód, některé funkce jsou zakázány."
msgid "Username"
msgstr ""
msgid "Stay signed in"
msgstr "Zůstat přihlášen(a)"
msgid "(Do not check on public computers)"
msgstr "(Nezaškrtávejte na veřejně dostupných počítačích)"
msgid "Sign in"
msgstr "Přihlásit se"
msgid "favorites"
msgstr "oblíbené"
msgid "estimated reading time :"
msgstr ""
msgid "Mark all the entries as read"
msgstr ""
msgid "Return home"
msgstr ""
#, fuzzy
msgid "Back to top"
msgstr "zpět na začátek"
#, fuzzy
msgid "Mark as read"
msgstr "označit jako přečtené"
#, fuzzy
msgid "Favorite"
msgstr "oblíbené"
#, fuzzy
msgid "Toggle favorite"
msgstr "označit jako oblíbené"
#, fuzzy
msgid "Delete"
msgstr "smazat"
#, fuzzy
msgid "Tweet"
msgstr "tweetnout"
msgid "email"
#, fuzzy
msgid "Email"
msgstr "email"
msgid "shaarli"
@ -181,26 +353,24 @@ msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
msgid "this article appears wrong?"
#, fuzzy
msgid "Does this article appear wrong?"
msgstr "vypadá tento článek špatně?"
msgid "create an issue"
msgstr "odeslat požadavek"
msgid "tags:"
msgstr ""
msgid "or"
msgstr "nebo"
msgid "Edit tags"
msgstr ""
msgid "contact us by mail"
msgstr "kontaktovat e-mailem"
msgid "plop"
msgid "save link!"
msgstr ""
msgid "home"
msgstr "domů"
msgid "favorites"
msgstr "oblíbené"
msgid "tags"
msgstr ""
msgid "logout"
msgstr "odhlásit se"
@ -211,23 +381,187 @@ msgstr "běží na"
msgid "debug mode is on so cache is off."
msgstr "je zapnut ladicí mód, proto je keš vypnuta."
msgid "your poche version:"
msgstr "verze:"
#, fuzzy
msgid "your wallabag version:"
msgstr "vaše verze"
msgid "storage:"
msgstr "úložiště:"
msgid "login to your poche"
msgstr "přihlásit se k poche"
msgid "save a link"
msgstr ""
msgid "you are in demo mode, some features may be disabled."
msgstr "používáte ukázkový mód, některé funkce jsou zakázány."
msgid "back to home"
msgstr "zpět na úvod"
msgid "Stay signed in"
msgstr "Zůstat přihlášen(a)"
msgid "toggle mark as read"
msgstr "označit jako přečtené"
msgid "(Do not check on public computers)"
msgstr "(Nezaškrtávejte na veřejně dostupných počítačích)"
msgid "tweet"
msgstr "tweetnout"
msgid "Sign in"
msgstr "Přihlásit se"
msgid "email"
msgstr "email"
msgid "this article appears wrong?"
msgstr "vypadá tento článek špatně?"
msgid "No link available here!"
msgstr "Není k dispozici žádný odkaz!"
msgid "Poching a link"
msgstr "Odkaz se ukládá"
msgid "by filling this field"
msgstr "vyplněním tohoto pole"
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "vaše verze"
msgid "latest stable version"
msgstr "poslední stabilní verze"
msgid "a more recent stable version is available."
msgstr "je k dispozici novější stabilní verze."
msgid "you are up to date."
msgstr "je aktuální"
msgid "latest dev version"
msgstr "poslední vývojová verze"
msgid "a more recent development version is available."
msgstr "je k dispozici novější vývojová verze."
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Spusťte importní skript lokálně, může to dlouho trvat."
#, fuzzy
msgid "More infos in the official doc:"
msgstr "Více informací v oficiální dokumentaci:"
msgid "import from Pocket"
msgstr "importovat z Pocket"
msgid "import from Readability"
msgstr "importovat z Readability"
msgid "import from Instapaper"
msgstr "importovat z Instapaper"
msgid "Tags"
msgstr ""
#, fuzzy
msgid "Untitled"
msgstr "podle nadpisu"
msgid "the link has been added successfully"
msgstr ""
msgid "error during insertion : the link wasn't added"
msgstr ""
msgid "the link has been deleted successfully"
msgstr ""
msgid "the link wasn't deleted"
msgstr ""
msgid "Article not found!"
msgstr ""
msgid "previous"
msgstr ""
msgid "next"
msgstr ""
msgid "in demo mode, you can't update your password"
msgstr ""
msgid "your password has been updated"
msgstr ""
msgid "the two fields have to be filled & the password must be the same in the two fields"
msgstr ""
msgid "still using the \""
msgstr ""
msgid "that theme does not seem to be installed"
msgstr ""
msgid "you have changed your theme preferences"
msgstr ""
msgid "that language does not seem to be installed"
msgstr ""
msgid "you have changed your language preferences"
msgstr ""
msgid "login failed: you have to fill all fields"
msgstr ""
msgid "welcome to your wallabag"
msgstr ""
msgid "login failed: bad login or password"
msgstr ""
#, fuzzy
msgid "import from instapaper completed"
msgstr "importovat z Instapaper"
#, fuzzy
msgid "import from pocket completed"
msgstr "importovat z Pocket"
#, fuzzy
msgid "import from Readability completed. "
msgstr "importovat z Readability"
#, fuzzy
msgid "import from Poche completed. "
msgstr "importovat z Pocket"
msgid "Unknown import provider."
msgstr ""
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr ""
msgid "Could not find required \""
msgstr ""
msgid "Uh, there is a problem while generating feeds."
msgstr ""
#, fuzzy
msgid "Cache deleted."
msgstr "smazat"
msgid "Oops, it seems you don't have PHP 5."
msgstr ""
#~ msgid "poche it!"
#~ msgstr "uložit!"
#~ msgid "Updating poche"
#~ msgstr "Poche se aktualizuje"
#~ msgid "create an issue"
#~ msgstr "odeslat požadavek"
#~ msgid "or"
#~ msgstr "nebo"
#~ msgid "contact us by mail"
#~ msgstr "kontaktovat e-mailem"
#~ msgid "your poche version:"
#~ msgstr "verze:"

View File

@ -1,51 +1,130 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"Project-Id-Version: Wallabag\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-03-27 13:41+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: Square252\n"
"Last-Translator: Kevin Meyer <wallabag@kevin-meyer.de>\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.7\n"
"X-Generator: Poedit 1.6.4\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: /Users/kevinmeyer/Dropbox/dev_web/wallabag-dev\n"
msgid "config"
msgstr "Konfiguration"
msgid "Poching a link"
msgstr "Poche einen Link"
msgid "Saving articles"
msgstr "Artikel speichern"
msgid "There are several ways to save an article:"
msgstr "Es gibt viele Methoden um Artikel zu speichern:"
msgid "read the documentation"
msgstr "Die Dokumentation lesen"
msgid "by filling this field"
msgstr "durch das ausfüllen dieses Feldes:"
msgid "download the extension"
msgstr "installiere die Erweiterung"
msgid "poche it!"
msgstr "Poche es!"
msgid "via F-Droid"
msgstr "via F-Droid"
msgid "Updating poche"
msgstr "Poche aktualisieren"
msgid " or "
msgstr " oder "
msgid "your version"
msgstr "Deine Version"
msgid "via Google Play"
msgstr "via Google Play"
msgid "latest stable version"
msgid "download the application"
msgstr "lade die App"
msgid "By filling this field"
msgstr "Durch Ausfüllen dieses Feldes"
msgid "bag it!"
msgstr "bag it!"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "Bookmarklet: Ziehe diesen Link in deine Lesezeichen-Leiste"
msgid "Upgrading wallabag"
msgstr "wallabag aktualisieren"
msgid "Installed version"
msgstr "Installierte Version"
msgid "Latest stable version"
msgstr "Neuste stabile Version"
msgid "a more recent stable version is available."
msgid "A more recent stable version is available."
msgstr "Eine neuere stabile Version ist verfügbar."
msgid "you are up to date."
msgid "You are up to date."
msgstr "Du bist auf den neuesten Stand."
msgid "latest dev version"
msgid "Last check:"
msgstr "Zuletzt geprüft:"
msgid "Latest dev version"
msgstr "Neuste Entwicklungsversion"
msgid "a more recent development version is available."
msgid "A more recent development version is available."
msgstr "Eine neuere Entwicklungsversion ist verfügbar."
msgid "You can clear cache to check the latest release."
msgstr "Leere den Cache um die neueste Version zu prüfen."
msgid "Feeds"
msgstr "Feeds"
msgid ""
"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>."
msgstr ""
"Dein Feed Token ist noch nicht vorhanden und muss zunächst generiert werden, "
"um deine Feeds zu aktivieren. Klicke <a href='?feed&amp;"
"action=generate'>hier um ihn zu generieren</a>."
msgid "Unread feed"
msgstr "Ungelesen Feed"
msgid "Favorites feed"
msgstr "Favoriten Feed"
msgid "Archive feed"
msgstr "Archiv Feed"
msgid "Your token:"
msgstr "Dein Token:"
msgid "Your user id:"
msgstr "Deine User ID:"
msgid ""
"You can regenerate your token: <a href='?feed&amp;action=generate'>generate!"
"</a>."
msgstr ""
"Hier kannst du dein Token erzeugen: <a href='?feed&amp;"
"action=generate'>Generieren!</a>."
msgid "Change your theme"
msgstr "Theme ändern"
msgid "Theme:"
msgstr "Theme:"
msgid "Update"
msgstr "Aktualisieren"
msgid "Change your language"
msgstr "Sprache ändern"
msgid "Language:"
msgstr "Sprache:"
msgid "Change your password"
msgstr "Passwort ändern"
@ -58,75 +137,86 @@ msgstr "Passwort"
msgid "Repeat your new password:"
msgstr "Neues Passwort wiederholen:"
msgid "Update"
msgstr "Aktualisieren"
msgid "Import"
msgstr "Import"
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Bitte führe das Import Script lokal aus, dies kann eine Weile dauern."
msgid ""
"Importing from other services can be quite long, and webservers default "
"configuration often prevents long scripts execution time, so it must be done "
"in multiple parts."
msgstr ""
"Der Import von anderen Diensten kann sehr lange dauern. Deswegen bricht der "
"Webserver diesen in vielen Konfigurationen ab. Daher muss der Import in "
"mehrere Teile aufgeteilt werden."
msgid "More info in the official doc:"
msgstr "Mehr Informationen in der offiziellen Dokumentation:"
msgid "First, select the export file on your computer and upload it."
msgstr "Wähle eine Datei von deinem Computer aus und lade sie hoch."
msgid "import from Pocket"
msgid "File:"
msgstr "Datei:"
msgid "Upload"
msgstr "Hochladen"
msgid "Then, click on the right link below."
msgstr "Klicke dann unten auf den entsprechenden Link."
msgid "Import from Pocket"
msgstr "Import aus Pocket"
msgid "import from Readability"
#, php-format
msgid "(after uploaded %s file)"
msgstr "(nach Upload der Datei %s)"
msgid "Import from Readability"
msgstr "Import aus Readability"
msgid "import from Instapaper"
msgid "Import from Instapaper"
msgstr "Import aus Instapaper"
msgid "Export your poche data"
msgstr "Exportieren Sie Ihre Poche Daten."
msgid "Import from wallabag"
msgstr "Import aus Readability"
msgid ""
"3. Your feed token is currently empty and must first be generated to fetch "
"content. Click <a href='?feed&amp;action=generate'>here to generate it</a>."
msgstr ""
"3. Dein Feed Token ist noch nicht vorhanden und muss zunächst generiert "
"werden, um Inhalt abrufen zu können. Klicke <a href='?feed&amp;"
"action=generate'>hier um ihn zu generieren</a>."
msgid "Finally, you have to fetch content for imported items."
msgstr "Jetzt musst du den Inhalt der importierten Artikel abrufen."
msgid "Click here"
msgstr "Klicke hier"
msgid "to export your poche data."
msgstr "um deine Daten aus Poche zu exportieren."
msgid "back to home"
msgstr "züruck zur Hauptseite"
msgid "installation"
msgstr "Installieren"
msgid "install your poche"
msgstr "Installiere dein Poche"
msgid "to fetch content for 10 articles"
msgstr "um den Inhalt von 10 Artikeln abzurufen"
msgid ""
"poche is still not installed. Please fill the below form to install it. "
"Don't hesitate to <a href='http://doc.inthepoche.com'>read the documentation "
"on poche website</a>."
"If you have console access to your server, you can also create a cron task:"
msgstr ""
"Poche ist noch nicht installiert. Bitte fülle die Felder unten aus, um die "
"Installation durchzuführen. Zögere nicht, <a href='http://inthepoche.com/"
"doc'>die Dokumentation auf der Website von Poche zu lesen falls du Probleme "
"haben solltest."
"Wenn du Konsolenzugang zu deinem Server hast kannst du auch einen cron "
"erstellen:"
msgid "Login"
msgstr "Benutzername"
msgid "Export your wallabag data"
msgstr "Exportieren deine wallabag Daten"
msgid "Repeat your password"
msgstr "Wiederhole dein Passwort"
msgid "to download your database."
msgstr "um deine Datenbank herunterzuladen"
msgid "Install"
msgstr "Installieren"
msgid "to export your wallabag data."
msgstr "um deine Daten aus wallabag zu exportieren."
msgid "back to top"
msgstr "Nach Oben"
msgid "Cache"
msgstr "Cache"
msgid "favoris"
msgstr ""
msgid "to delete cache."
msgstr "um den Cache zu löschen."
msgid "archive"
msgstr "Archiv"
msgid "unread"
msgstr "ungelesen"
msgid "Tags"
msgstr "Tags"
msgid "by date asc"
msgstr "nach Datum aufsteigend"
@ -146,10 +236,72 @@ msgstr "nach Titel"
msgid "by title desc"
msgstr "nach Titel absteigend"
msgid "No link available here!"
msgstr "Kein Link verfügbar!"
#, fuzzy
msgid "toggle view mode"
msgstr "Favorit"
msgid "toggle mark as read"
msgid "home"
msgstr "Start"
msgid "favorites"
msgstr "Favoriten"
msgid "archive"
msgstr "Archiv"
msgid "tags"
msgstr "Tags"
msgid "save a link"
msgstr "Speichere einen Link"
msgid "search"
msgstr "Suche"
msgid "logout"
msgstr "Logout"
msgid "return home"
msgstr "Zurück zum Start"
#, fuzzy
msgid "Search"
msgstr "Archiv"
msgid "powered by"
msgstr "bereitgestellt von"
msgid "debug mode is on so cache is off."
msgstr "Debug Modus ist aktiviert, das Caching ist somit deaktiviert"
msgid "your wallabag version:"
msgstr "Deine wallabag Version"
msgid "storage:"
msgstr "Speicher:"
msgid "Save a link"
msgstr "Speichere einen Link"
msgid "save link!"
msgstr "Link speichern!"
msgid "unread"
msgstr "ungelesen"
msgid "Tag"
msgstr "Tag"
msgid "No articles found."
msgstr "Keine Artikel gefunden."
msgid "estimated reading time:"
msgstr "geschätzte Lesezeit:"
msgid "estimated reading time :"
msgstr "geschätzte Lesezeit:"
msgid "Toggle mark as read"
msgstr "Als gelesen markieren"
msgid "toggle favorite"
@ -161,69 +313,346 @@ msgstr "Löschen"
msgid "original"
msgstr "Original"
msgid "Mark all the entries as read"
msgstr "Markiere alle als gelesen"
msgid "results"
msgstr "Ergebnisse"
msgid "tweet"
msgstr "Twittern"
msgid "Uh, there is a problem with the cron."
msgstr "Oh, es gab ein Problem mit dem cron."
msgid "email"
msgstr "senden per E-Mail"
msgid "Untitled"
msgstr "Ohne Titel"
msgid "shaarli"
msgstr "Shaarli"
msgid "the link has been added successfully"
msgstr "Speichern des Links erfolgreich"
msgid "flattr"
msgstr "flattr"
msgid "error during insertion : the link wasn't added"
msgstr "Fehler beim Einfügen: Der Link wurde nicht hinzugefügt"
msgid "this article appears wrong?"
msgstr "dieser Artikel erscheint falsch?"
msgid "the link has been deleted successfully"
msgstr "Löschen des Links erfolgreich"
msgid "create an issue"
msgstr "ein Ticket erstellen"
msgid "the link wasn't deleted"
msgstr "Der Link wurde nicht entfernt"
msgid "or"
msgstr "oder"
msgid "Article not found!"
msgstr "Artikel nicht gefunden!"
msgid "contact us by mail"
msgstr "kontaktieren Sie uns per E-Mail"
msgid "previous"
msgstr "vorherige"
msgid "plop"
msgstr "plop"
msgid "next"
msgstr "nächste"
msgid "home"
msgstr "Start"
msgid "in demo mode, you can't update your password"
msgstr "im Demo-Modus kann das Passwort nicht geändert werden"
msgid "favorites"
msgstr "Favoriten"
msgid "your password has been updated"
msgstr "Dein Passwort wurde geändert"
msgid "logout"
msgstr "Logout"
msgid ""
"the two fields have to be filled & the password must be the same in the two "
"fields"
msgstr "Beide Felder müssen mit selbem Inhalt ausgefüllt sein"
msgid "powered by"
msgstr "bereitgestellt von"
msgid "still using the \""
msgstr "nutze immernoch die \""
msgid "debug mode is on so cache is off."
msgstr "Debug Modus ist aktiviert, das Caching ist somit deaktiviert"
msgid "that theme does not seem to be installed"
msgstr "dieses Theme scheint nicht installiert zu sein"
msgid "your poche version:"
msgstr "Deine Poche Version"
msgid "you have changed your theme preferences"
msgstr "Du hast deine Theme Einstellungen geändert"
msgid "storage:"
msgstr "Speicher:"
msgid "that language does not seem to be installed"
msgstr "Diese Sprache scheint nicht installiert zu sein"
msgid "login to your poche"
msgstr "Bei Poche anmelden"
msgid "you have changed your language preferences"
msgstr "Du hast deine Spracheinstellungen geändert"
msgid "you are in demo mode, some features may be disabled."
msgid "login failed: you have to fill all fields"
msgstr "Anmeldung fehlgeschlagen: Alle Felder müssen ausgefüllt werden"
msgid "welcome to your wallabag"
msgstr "Willkommen bei deiner wallabag"
msgid "login failed: bad login or password"
msgstr "Anmeldung fehlgeschlagen: Falscher Benutzername oder Passwort"
msgid ""
"import from instapaper completed. You have to execute the cron to fetch "
"content."
msgstr ""
"Du befindest dich im Demomodus, einige Funktionen könnten deaktiviert sein."
"Import aus Instapaper vollständig. Führe den cronjob aus um den Inhalt "
"abzurufen."
msgid "Stay signed in"
msgstr "Angemeldet bleiben"
msgid ""
"import from pocket completed. You have to execute the cron to fetch content."
msgstr ""
"Import aus Pocket vollständig. Führe den cronjob aus um den Inhalt abzurufen."
msgid "(Do not check on public computers)"
msgstr "(nicht auf einem öffentlichen Computer anhaken)"
msgid ""
"import from Readability completed. You have to execute the cron to fetch "
"content."
msgstr ""
"Import aus Readability vollständig. Führe den cronjob aus um den Inhalt "
"abzurufen."
msgid "Sign in"
msgstr "Einloggen"
msgid ""
"import from Poche completed. You have to execute the cron to fetch content."
msgstr ""
"Import aus Poche vollständig. Führe den cronjob aus um den Inhalt abzurufen."
msgid "Unknown import provider."
msgstr "Unbekannter Import Anbieter."
msgid "Could not find required \""
msgstr "Nicht gefunden: \""
msgid "File uploaded. You can now execute import."
msgstr "Datei hochgeladen. Du kannst nun importieren."
msgid "Error while importing file. Do you have access to upload it?"
msgstr "Fehler beim Importieren. Hast du das Recht zum Hochladen?"
msgid "User with this id ("
msgstr "Nutzer mit dieser id ("
msgid "Uh, there is a problem while generating feeds."
msgstr "Oh, es gab ein Problem beim Erstellen des Feeds."
msgid "Cache deleted."
msgstr "Cache gelöscht"
msgid "Oops, it seems you don't have PHP 5."
msgstr "Oops, es scheint als würde PHP 5 fehlen."
msgid "wallabag, a read it later open source system"
msgstr "wallabag, ein Später-Lesen Open Source System"
msgid "login failed: user doesn't exist"
msgstr "Anmeldung fehlgeschlagen: Benutzer existiert nicht"
#~ msgid "You can enter multiple tags, separated by commas."
#~ msgstr "Du kannst mehrere Tags, durch Kommata getrennt, eingeben."
#~ msgid "return to article"
#~ msgstr "zurück zum Artikel"
#, fuzzy
#~ msgid "favoris"
#~ msgstr "Favoriten"
#~ msgid "mark all the entries as read"
#~ msgstr "Markiere alle als gelesen"
#~ msgid "Back to top"
#~ msgstr "Nach Oben"
#~ msgid "Mark as read"
#~ msgstr "Als gelesen markieren"
#~ msgid "Favorite"
#~ msgstr "Favoriten"
#~ msgid "Toggle favorite"
#~ msgstr "Favorit"
#~ msgid "Delete"
#~ msgstr "Löschen"
#~ msgid "Tweet"
#~ msgstr "Twittern"
#~ msgid "Email"
#~ msgstr "per E-Mail senden"
#~ msgid "shaarli"
#~ msgstr "Shaarli"
#~ msgid "flattr"
#~ msgstr "flattr"
#~ msgid "Does this article appear wrong?"
#~ msgstr "Erscheint dieser Artikel falsch?"
#~ msgid "Edit tags"
#~ msgstr "Tags bearbeiten"
#~ msgid "Start typing for auto complete."
#~ msgstr "Beginne zu tippen für die Autovervollständigung."
#~ msgid "Return home"
#~ msgstr "Zurück zum Start"
#~ msgid "tags:"
#~ msgstr "Tags:"
#~ msgid "login to your wallabag"
#~ msgstr "Bei wallabag anmelden"
#~ msgid "you are in demo mode, some features may be disabled."
#~ msgstr ""
#~ "Du befindest dich im Demomodus, einige Funktionen könnten deaktiviert "
#~ "sein."
#~ msgid "Login"
#~ msgstr "Benutzername"
#~ msgid "Stay signed in"
#~ msgstr "Angemeldet bleiben"
#~ msgid "(Do not check on public computers)"
#~ msgstr "(nicht auf einem öffentlichen Computer anhaken)"
#~ msgid "plop"
#~ msgstr "plop"
#~ msgid "Login to wallabag"
#~ msgstr "Bei wallabag anmelden"
#~ msgid "Username"
#~ msgstr "Benutzername"
#~ msgid "Sign in"
#~ msgstr "Einloggen"
#~ msgid "Enter your search here"
#~ msgstr "Gib hier deine Suchanfrage ein"
#~ msgid "installation"
#~ msgstr "Installieren"
#~ msgid "install your wallabag"
#~ msgstr "Installiere deine wallabag"
#~ msgid ""
#~ "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>."
#~ msgstr ""
#~ "wallabag ist noch nicht installiert. Bitte fülle die Felder unten aus, um "
#~ "die Installation durchzuführen. Zögere nicht, <a href='http://doc."
#~ "wallabag.org/'>die Dokumentation auf der Website von wallabag zu lesen, "
#~ "falls du Probleme haben solltest."
#~ msgid "Repeat your password"
#~ msgstr "Wiederhole dein Passwort"
#~ msgid "Install"
#~ msgstr "Installieren"
#~ msgid "No link available here!"
#~ msgstr "Kein Link verfügbar!"
#~ msgid "toggle mark as read"
#~ msgstr "Als gelesen markieren"
#~ msgid ""
#~ "You can <a href='wallabag_compatibility_test.php'>check your "
#~ "configuration here</a>."
#~ msgstr ""
#~ "Du kannst deine Konfiguration <a href='wallabag_compatibility_test."
#~ "php'>hier testen</a>."
#~ msgid "back to home"
#~ msgstr "züruck zur Hauptseite"
#~ msgid "tweet"
#~ msgstr "Twittern"
#~ msgid "email"
#~ msgstr "senden per E-Mail"
#~ msgid "this article appears wrong?"
#~ msgstr "dieser Artikel erscheint falsch?"
#~ msgid "Poching a link"
#~ msgstr "Poche einen Link"
#~ msgid "by filling this field"
#~ msgstr "durch das ausfüllen dieses Feldes:"
#~ msgid "bookmarklet: drag & drop this link to your bookmarks bar"
#~ msgstr "Bookmarklet: Ziehe diesen Link in deine Lesezeichen-Leiste"
#~ msgid "your version"
#~ msgstr "Deine Version"
#~ msgid "latest stable version"
#~ msgstr "Neuste stabile Version"
#~ msgid "a more recent stable version is available."
#~ msgstr "Eine neuere stabile Version ist verfügbar."
#~ msgid "you are up to date."
#~ msgstr "Du bist auf den neuesten Stand."
#~ msgid "latest dev version"
#~ msgstr "Neuste Entwicklungsversion"
#~ msgid "a more recent development version is available."
#~ msgstr "Eine neuere Entwicklungsversion ist verfügbar."
#~ msgid ""
#~ "Please execute the import script locally, it can take a very long time."
#~ msgstr ""
#~ "Bitte führe das Import Script lokal aus, dies kann eine Weile dauern."
#~ msgid "More infos in the official doc:"
#~ msgstr "Mehr Informationen in der offiziellen Dokumentation:"
#~ msgid "import from Pocket"
#~ msgstr "Import aus Pocket"
#~ msgid "(you must have a %s file on your server)"
#~ msgstr "(du brauchst eine %s Datei auf deinem Server)"
#~ msgid "import from Readability"
#~ msgstr "Import aus Readability"
#~ msgid "import from Instapaper"
#~ msgstr "Import aus Instapaper"
#~ msgid "You can also create a cron task:"
#~ msgstr "Du kannst auch einen cronjob anlegen:"
#~ msgid ""
#~ "Please execute the import script locally as it can take a very long time."
#~ msgstr ""
#~ "Bitte führe das Import Script lokal aus, da dies eine Weile dauern kann."
#~ msgid "More info in the official documentation:"
#~ msgstr "Mehr Informationen in der offiziellen Dokumentation:"
#~ msgid "import from instapaper completed"
#~ msgstr "Import aus Instapaper erfolgreich"
#~ msgid "import from pocket completed"
#~ msgstr "Import aus Pocket erfolgreich"
#~ msgid "import from Poche completed. "
#~ msgstr "Import aus Poche erfolgreich"
#~ msgid "Incomplete inc/poche/define.inc.php file, please define \""
#~ msgstr "Unvollständige inc/poche/define.inc.php Datei, bitte setze \""
#~ msgid "poche it!"
#~ msgstr "Poche es!"
#~ msgid "Updating poche"
#~ msgstr "Poche aktualisieren"
#~ msgid "create an issue"
#~ msgstr "ein Ticket erstellen"
#~ msgid "or"
#~ msgstr "oder"
#~ msgid "contact us by mail"
#~ msgstr "kontaktieren Sie uns per E-Mail"
#~ msgid "your poche version:"
#~ msgstr "Deine Poche Version"

View File

@ -1,50 +1,124 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-25 15:17+0300\n"
"PO-Revision-Date: \n"
"Last-Translator: Nicolas Lœuillet <nicolas.loeuillet@gmail.com>\n"
"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.4\n"
"X-Poedit-Language: English\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
msgid "wallabag, a read it later open source system"
msgstr "wallabag, a read it later open source system"
msgid "login failed: user doesn't exist"
msgstr "login failed: user doesn't exist"
msgid "return home"
msgstr "return home"
msgid "config"
msgstr "config"
msgid "Poching a link"
msgstr "Poching a link"
msgid "Saving articles"
msgstr "Saving articles"
msgid "There are several ways to save an article:"
msgstr "There are several ways to save an article:"
msgid "read the documentation"
msgstr "read the documentation"
msgid "by filling this field"
msgstr "by filling this field"
msgid "download the extension"
msgstr "download the extension"
msgid "poche it!"
msgstr "poche it!"
msgid "via F-Droid"
msgstr "via F-Droid"
msgid "Updating poche"
msgstr "Updating poche"
msgid " or "
msgstr " or "
msgid "your version"
msgstr "your version"
msgid "via Google Play"
msgstr "via Google Play"
msgid "latest stable version"
msgstr "latest stable version"
msgid "download the application"
msgstr "download the application"
msgid "a more recent stable version is available."
msgstr "a more recent stable version is available."
msgid "By filling this field"
msgstr "By filling this field"
msgid "you are up to date."
msgstr "you are up to date."
msgid "bag it!"
msgstr "bag it!"
msgid "latest dev version"
msgstr "latest dev version"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "Bookmarklet: drag & drop this link to your bookmarks bar"
msgid "a more recent development version is available."
msgstr "a more recent development version is available."
msgid "Upgrading wallabag"
msgstr "Upgrading wallabag"
msgid "Installed version"
msgstr "Installed version"
msgid "Latest stable version"
msgstr "Latest stable version"
msgid "A more recent stable version is available."
msgstr "A more recent stable version is available."
msgid "You are up to date."
msgstr "You are up to date."
msgid "Latest dev version"
msgstr "Latest dev version"
msgid "A more recent development version is available."
msgstr "A more recent development version is available."
msgid "Feeds"
msgstr "Feeds"
msgid "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>."
msgstr "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>."
msgid "Unread feed"
msgstr "Unread feed"
msgid "Favorites feed"
msgstr "Favorites feed"
msgid "Archive feed"
msgstr "Archive feed"
msgid "Your token:"
msgstr "Your token:"
msgid "Your user id:"
msgstr "Your user id:"
msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgstr "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgid "Change your theme"
msgstr "Change your theme"
msgid "Theme:"
msgstr "Theme:"
msgid "Update"
msgstr "Update"
msgid "Change your language"
msgstr "Change your language"
msgid "Language:"
msgstr "Language:"
msgid "Change your password"
msgstr "Change your password"
@ -58,66 +132,60 @@ msgstr "Password"
msgid "Repeat your new password:"
msgstr "Repeat your new password:"
msgid "Update"
msgstr "Update"
msgid "Import"
msgstr "Import"
msgid "Please execute the import script locally, it can take a very long time."
msgstr ""
"Please execute the import script locally, it can take a very long time."
msgid "Please execute the import script locally as it can take a very long time."
msgstr "Please execute the import script locally as it can take a very long time."
msgid "More info in the official doc:"
msgstr "More info in the official doc:"
msgid "More info in the official documentation:"
msgstr "More info in the official documentation:"
msgid "import from Pocket"
msgstr "import from Pocket"
msgid "Import from Pocket"
msgstr "Import from Pocket"
msgid "import from Readability"
msgstr "import from Readability"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr "(you must have a %s file on your server)"
msgid "import from Instapaper"
msgstr "import from Instapaper"
msgid "Import from Readability"
msgstr "Import from Readability"
msgid "Export your poche data"
msgstr "Export your poche data"
msgid "Import from Instapaper"
msgstr "Import from Instapaper"
msgid "Import from wallabag"
msgstr "Import from wallabag"
msgid "Export your wallabag data"
msgstr "Export your wallabag data"
msgid "Click here"
msgstr "Click here"
msgid "to export your poche data."
msgstr "to export your poche data."
msgid "to download your database."
msgstr "to download your database."
msgid "back to home"
msgstr "back to home"
msgid "to export your wallabag data."
msgstr "to export your wallabag data."
msgid "installation"
msgstr "installation"
msgid "Cache"
msgstr "Cache"
msgid "install your poche"
msgstr "install your poche"
msgid "to delete cache."
msgstr "to delete cache."
msgid ""
"poche is still not installed. Please fill the below form to install it. "
"Don't hesitate to <a href='http://doc.inthepoche.com'>read the documentation "
"on poche website</a>."
msgstr ""
"poche is still not installed. Please fill the below form to install it. "
"Don't hesitate to <a href='http://doc.inthepoche.com'>read the documentation "
"on poche website</a>."
msgid "You can enter multiple tags, separated by commas."
msgstr "You can enter multiple tags, separated by commas."
msgid "Login"
msgstr "Login"
msgid "return to article"
msgstr "return to article"
msgid "Repeat your password"
msgstr "Repeat your password"
msgid "plop"
msgstr "plop"
msgid "Install"
msgstr "Install"
msgid "back to top"
msgstr "back to top"
msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgstr "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgid "favoris"
msgstr "favoris"
@ -146,11 +214,14 @@ msgstr "by title"
msgid "by title desc"
msgstr "by title desc"
msgid "No link available here!"
msgstr "No link available here!"
msgid "Tag"
msgstr "Tag"
msgid "toggle mark as read"
msgstr "toggle mark as read"
msgid "No articles found."
msgstr "No articles found."
msgid "Toggle mark as read"
msgstr "Toggle mark as read"
msgid "toggle favorite"
msgstr "toggle favorite"
@ -161,14 +232,86 @@ msgstr "delete"
msgid "original"
msgstr "original"
msgid "estimated reading time:"
msgstr "estimated reading time:"
msgid "mark all the entries as read"
msgstr "mark all the entries as read"
msgid "results"
msgstr "results"
msgid "tweet"
msgstr "tweet"
msgid "installation"
msgstr "installation"
msgid "email"
msgstr "email"
msgid "install your wallabag"
msgstr "install your wallabag"
msgid "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>."
msgstr "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>."
msgid "Login"
msgstr "Login"
msgid "Repeat your password"
msgstr "Repeat your password"
msgid "Install"
msgstr "Install"
msgid "login to your wallabag"
msgstr "login to your wallabag"
msgid "Login to wallabag"
msgstr "Login to wallabag"
msgid "you are in demo mode, some features may be disabled."
msgstr "you are in demo mode, some features may be disabled."
msgid "Username"
msgstr "Username"
msgid "Stay signed in"
msgstr "Stay signed in"
msgid "(Do not check on public computers)"
msgstr "(Do not check on public computers)"
msgid "Sign in"
msgstr "Sign in"
msgid "favorites"
msgstr "favorites"
msgid "estimated reading time :"
msgstr "estimated reading time :"
msgid "Mark all the entries as read"
msgstr "Mark all the entries as read"
msgid "Return home"
msgstr "Return home"
msgid "Back to top"
msgstr "Back to top"
msgid "Mark as read"
msgstr "Mark as read"
msgid "Favorite"
msgstr "Favorite"
msgid "Toggle favorite"
msgstr "Toggle favorite"
msgid "Delete"
msgstr "Delete"
msgid "Tweet"
msgstr "Tweet"
msgid "Email"
msgstr "Email"
msgid "shaarli"
msgstr "shaarli"
@ -176,26 +319,23 @@ msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
msgid "this article appears wrong?"
msgstr "this article appears wrong?"
msgid "Does this article appear wrong?"
msgstr "Does this article appear wrong?"
msgid "create an issue"
msgstr "create an issue"
msgid "tags:"
msgstr "tags:"
msgid "or"
msgstr "or"
msgid "Edit tags"
msgstr "Edit tags"
msgid "contact us by mail"
msgstr "contact us by mail"
msgid "plop"
msgstr "plop"
msgid "save link!"
msgstr "save link!"
msgid "home"
msgstr "home"
msgid "favorites"
msgstr "favorites"
msgid "tags"
msgstr "tags"
msgid "logout"
msgstr "logout"
@ -206,23 +346,179 @@ msgstr "powered by"
msgid "debug mode is on so cache is off."
msgstr "debug mode is on so cache is off."
msgid "your poche version:"
msgstr "your poche version:"
msgid "your wallabag version:"
msgstr "your wallabag version:"
msgid "storage:"
msgstr "storage:"
msgid "login to your poche"
msgstr "login to your poche"
msgid "save a link"
msgstr "save a link"
msgid "you are in demo mode, some features may be disabled."
msgstr "you are in demo mode, some features may be disabled."
msgid "back to home"
msgstr "back to home"
msgid "Stay signed in"
msgstr "Stay signed in"
msgid "toggle mark as read"
msgstr "toggle mark as read"
msgid "(Do not check on public computers)"
msgstr "(Do not check on public computers)"
msgid "tweet"
msgstr "tweet"
msgid "Sign in"
msgstr "Sign in"
msgid "email"
msgstr "email"
msgid "this article appears wrong?"
msgstr "this article appears wrong?"
msgid "No link available here!"
msgstr "No link available here!"
msgid "Poching a link"
msgstr "Poching a link"
msgid "by filling this field"
msgstr "by filling this field"
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "bookmarklet: drag & drop this link to your bookmarks bar"
msgid "your version"
msgstr "your version"
msgid "latest stable version"
msgstr "latest stable version"
msgid "a more recent stable version is available."
msgstr "a more recent stable version is available."
msgid "you are up to date."
msgstr "you are up to date."
msgid "latest dev version"
msgstr "latest dev version"
msgid "a more recent development version is available."
msgstr "a more recent development version is available."
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Please execute the import script locally, it can take a very long time."
msgid "More infos in the official doc:"
msgstr "More infos in the official doc:"
msgid "import from Pocket"
msgstr "import from Pocket"
msgid "import from Readability"
msgstr "import from Readability"
msgid "import from Instapaper"
msgstr "import from Instapaper"
msgid "Tags"
msgstr "Tags"
msgid "Untitled"
msgstr "Untitled"
msgid "the link has been added successfully"
msgstr "the link has been added successfully"
msgid "error during insertion : the link wasn't added"
msgstr "error during insertion : the link wasn't added"
msgid "the link has been deleted successfully"
msgstr "the link has been deleted successfully"
msgid "the link wasn't deleted"
msgstr "the link wasn't deleted"
msgid "Article not found!"
msgstr "Article not found!"
msgid "previous"
msgstr "previous"
msgid "next"
msgstr "next"
msgid "in demo mode, you can't update your password"
msgstr "in demo mode, you can't update your password"
msgid "your password has been updated"
msgstr "your password has been updated"
msgid "the two fields have to be filled & the password must be the same in the two fields"
msgstr "the two fields have to be filled & the password must be the same in the two fields"
msgid "still using the \""
msgstr "still using the \""
msgid "that theme does not seem to be installed"
msgstr "that theme does not seem to be installed"
msgid "you have changed your theme preferences"
msgstr "you have changed your theme preferences"
msgid "that language does not seem to be installed"
msgstr "that language does not seem to be installed"
msgid "you have changed your language preferences"
msgstr "you have changed your language preferences"
msgid "login failed: you have to fill all fields"
msgstr "login failed: you have to fill all fields"
msgid "welcome to your wallabag"
msgstr "welcome to your wallabag"
msgid "login failed: bad login or password"
msgstr "login failed: bad login or password"
msgid "import from instapaper completed"
msgstr "import from instapaper completed"
msgid "import from pocket completed"
msgstr "import from pocket completed"
msgid "import from Readability completed. "
msgstr "import from Readability completed. "
msgid "import from Poche completed. "
msgstr "import from Poche completed. "
msgid "Unknown import provider."
msgstr "Unknown import provider."
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr "Incomplete inc/poche/define.inc.php file, please define \""
msgid "Could not find required \""
msgstr "Could not find required \""
msgid "Uh, there is a problem while generating feeds."
msgstr "Uh, there is a problem while generating feeds."
msgid "Cache deleted."
msgstr "Cache deleted."
msgid "Oops, it seems you don't have PHP 5."
msgstr "Oops, it seems you don't have PHP 5."
#~ msgid "poche it!"
#~ msgstr "poche it!"
#~ msgid "Updating poche"
#~ msgstr "Updating poche"
#~ msgid "create an issue"
#~ msgstr "create an issue"
#~ msgid "or"
#~ msgstr "or"
#~ msgid "contact us by mail"
#~ msgstr "contact us by mail"
#~ msgid "your poche version:"
#~ msgstr "your poche version:"

View File

@ -1,51 +1,136 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-25 15:16+0300\n"
"PO-Revision-Date: \n"
"Last-Translator: Nicolas Lœuillet <nicolas.loeuillet@gmail.com>\n"
"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.4\n"
"X-Poedit-Language: Spanish\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
msgid "wallabag, a read it later open source system"
msgstr ""
msgid "login failed: user doesn't exist"
msgstr ""
msgid "return home"
msgstr ""
msgid "config"
msgstr "configuración"
msgid "Poching a link"
msgstr "Pochear un enlace"
msgid "Saving articles"
msgstr ""
msgid "There are several ways to save an article:"
msgstr ""
msgid "read the documentation"
msgstr "leer la documentación"
msgid "by filling this field"
msgid "download the extension"
msgstr ""
msgid "via F-Droid"
msgstr ""
msgid " or "
msgstr ""
msgid "via Google Play"
msgstr ""
msgid "download the application"
msgstr ""
#, fuzzy
msgid "By filling this field"
msgstr "rellenando este campo"
msgid "poche it!"
msgstr "pochéalo!"
msgid "bag it!"
msgstr ""
msgid "Updating poche"
msgstr "Actualizar"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "su versión"
msgid "Upgrading wallabag"
msgstr ""
msgid "latest stable version"
#, fuzzy
msgid "Installed version"
msgstr "ultima versión estable"
msgid "a more recent stable version is available."
#, fuzzy
msgid "Latest stable version"
msgstr "ultima versión estable"
#, fuzzy
msgid "A more recent stable version is available."
msgstr "una versión estable más reciente está disponible."
msgid "you are up to date."
#, fuzzy
msgid "You are up to date."
msgstr "estás actualizado."
msgid "latest dev version"
#, fuzzy
msgid "Latest dev version"
msgstr "ultima versión de desarollo"
msgid "a more recent development version is available."
#, fuzzy
msgid "A more recent development version is available."
msgstr "una versión de desarollo más reciente está disponible."
msgid "Feeds"
msgstr ""
msgid "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>."
msgstr ""
msgid "Unread feed"
msgstr ""
#, fuzzy
msgid "Favorites feed"
msgstr "preferidos"
#, fuzzy
msgid "Archive feed"
msgstr "archivos"
msgid "Your token:"
msgstr ""
msgid "Your user id:"
msgstr ""
msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgstr ""
#, fuzzy
msgid "Change your theme"
msgstr "Modificar tu contraseña"
msgid "Theme:"
msgstr ""
msgid "Update"
msgstr "Actualizar"
#, fuzzy
msgid "Change your language"
msgstr "Modificar tu contraseña"
msgid "Language:"
msgstr ""
msgid "Change your password"
msgstr "Modificar tu contraseña"
@ -58,66 +143,68 @@ msgstr "Contraseña"
msgid "Repeat your new password:"
msgstr "Repetir la nueva contraseña :"
msgid "Update"
msgstr "Actualizar"
msgid "Import"
msgstr "Importar"
msgid "Please execute the import script locally, it can take a very long time."
msgstr ""
"Por favor, ejecute la importación en local, esto puede demorar un tiempo."
#, fuzzy
msgid "Please execute the import script locally as it can take a very long time."
msgstr "Por favor, ejecute la importación en local, esto puede demorar un tiempo."
msgid "More info in the official doc:"
#, fuzzy
msgid "More info in the official documentation:"
msgstr "Más información en la documentación oficial :"
msgid "import from Pocket"
#, fuzzy
msgid "Import from Pocket"
msgstr "importación desde Pocket"
msgid "import from Readability"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr ""
#, fuzzy
msgid "Import from Readability"
msgstr "importación desde Readability"
msgid "import from Instapaper"
#, fuzzy
msgid "Import from Instapaper"
msgstr "importación desde Instapaper"
msgid "Export your poche data"
#, fuzzy
msgid "Import from wallabag"
msgstr "importación desde Readability"
#, fuzzy
msgid "Export your wallabag data"
msgstr "Exportar sus datos de poche"
msgid "Click here"
msgstr "Haga clic aquí"
msgid "to export your poche data."
msgid "to download your database."
msgstr ""
#, fuzzy
msgid "to export your wallabag data."
msgstr "para exportar sus datos de poche."
msgid "back to home"
msgstr "volver a la página de inicio"
msgid "installation"
msgstr "instalación"
msgid "install your poche"
msgstr "instala tu Poche"
msgid ""
"Poche is still not installed. Please fill the below form to install it. "
"Don't hesitate to <a href='http://doc.inthepoche.com'>read the documentation "
"on poche website</a>."
msgid "Cache"
msgstr ""
"Poche todavia no està instalado. Por favor, completa los campos siguientes "
"para instalarlo. No dudes de <a href='http://doc.inthepoche.com'>leer la "
"documentación en el sitio de Poche</a>."
msgid "Login"
msgstr "Nombre de usuario"
msgid "to delete cache."
msgstr ""
msgid "Repeat your password"
msgstr "Repita su contraseña"
msgid "You can enter multiple tags, separated by commas."
msgstr ""
msgid "Install"
msgstr "Instalar"
msgid "return to article"
msgstr ""
msgid "back to top"
msgstr "volver arriba"
msgid "plop"
msgstr "plop"
msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgstr ""
msgid "favoris"
msgstr "preferidos"
@ -146,10 +233,14 @@ msgstr "por título"
msgid "by title desc"
msgstr "por título descendiente"
msgid "No link available here!"
msgstr "¡No hay ningún enlace disponible por aquí!"
msgid "Tag"
msgstr ""
msgid "toggle mark as read"
msgid "No articles found."
msgstr ""
#, fuzzy
msgid "Toggle mark as read"
msgstr "marcar como leído"
msgid "toggle favorite"
@ -161,13 +252,95 @@ msgstr "eliminar"
msgid "original"
msgstr "original"
msgid "estimated reading time:"
msgstr ""
msgid "mark all the entries as read"
msgstr ""
msgid "results"
msgstr "resultados"
msgid "tweet"
msgid "installation"
msgstr "instalación"
#, fuzzy
msgid "install your wallabag"
msgstr "instala tu Poche"
#, fuzzy
msgid "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>."
msgstr "Poche todavia no està instalado. Por favor, completa los campos siguientes para instalarlo. No dudes de <a href='http://doc.inthepoche.com'>leer la documentación en el sitio de Poche</a>."
msgid "Login"
msgstr "Nombre de usuario"
msgid "Repeat your password"
msgstr "Repita su contraseña"
msgid "Install"
msgstr "Instalar"
#, fuzzy
msgid "login to your wallabag"
msgstr "conectarse a tu Poche"
msgid "Login to wallabag"
msgstr ""
msgid "you are in demo mode, some features may be disabled."
msgstr "este es el modo de demostración, algunas funcionalidades pueden estar desactivadas."
msgid "Username"
msgstr ""
msgid "Stay signed in"
msgstr "Seguir conectado"
msgid "(Do not check on public computers)"
msgstr "(no marcar en un ordenador público)"
msgid "Sign in"
msgstr "Iniciar sesión"
msgid "favorites"
msgstr "preferidos"
msgid "estimated reading time :"
msgstr ""
msgid "Mark all the entries as read"
msgstr ""
msgid "Return home"
msgstr ""
#, fuzzy
msgid "Back to top"
msgstr "volver arriba"
#, fuzzy
msgid "Mark as read"
msgstr "marcar como leído"
#, fuzzy
msgid "Favorite"
msgstr "preferidos"
#, fuzzy
msgid "Toggle favorite"
msgstr "preferido"
#, fuzzy
msgid "Delete"
msgstr "eliminar"
#, fuzzy
msgid "Tweet"
msgstr "tweetear"
msgid "email"
#, fuzzy
msgid "Email"
msgstr "enviar por mail"
msgid "shaarli"
@ -176,26 +349,24 @@ msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
msgid "this article appears wrong?"
#, fuzzy
msgid "Does this article appear wrong?"
msgstr "este articulo no se ve bien?"
msgid "create an issue"
msgstr "crear un ticket"
msgid "tags:"
msgstr ""
msgid "or"
msgstr "o"
msgid "Edit tags"
msgstr ""
msgid "contact us by mail"
msgstr "contactarnos por mail"
msgid "plop"
msgstr "plop"
msgid "save link!"
msgstr ""
msgid "home"
msgstr "inicio"
msgid "favorites"
msgstr "preferidos"
msgid "tags"
msgstr ""
msgid "logout"
msgstr "cerrar sesión"
@ -206,25 +377,187 @@ msgstr "hecho con"
msgid "debug mode is on so cache is off."
msgstr "el modo de depuración está activado, así que la cache está desactivada."
msgid "your poche version:"
msgstr "tu versión de Poche:"
#, fuzzy
msgid "your wallabag version:"
msgstr "su versión"
msgid "storage:"
msgstr "almacenamiento:"
msgid "login to your poche"
msgstr "conectarse a tu Poche"
msgid "you are in demo mode, some features may be disabled."
msgid "save a link"
msgstr ""
"este es el modo de demostración, algunas funcionalidades pueden estar "
"desactivadas."
msgid "Stay signed in"
msgstr "Seguir conectado"
msgid "back to home"
msgstr "volver a la página de inicio"
msgid "(Do not check on public computers)"
msgstr "(no marcar en un ordenador público)"
msgid "toggle mark as read"
msgstr "marcar como leído"
msgid "Sign in"
msgstr "Iniciar sesión"
msgid "tweet"
msgstr "tweetear"
msgid "email"
msgstr "enviar por mail"
msgid "this article appears wrong?"
msgstr "este articulo no se ve bien?"
msgid "No link available here!"
msgstr "¡No hay ningún enlace disponible por aquí!"
msgid "Poching a link"
msgstr "Pochear un enlace"
msgid "by filling this field"
msgstr "rellenando este campo"
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "su versión"
msgid "latest stable version"
msgstr "ultima versión estable"
msgid "a more recent stable version is available."
msgstr "una versión estable más reciente está disponible."
msgid "you are up to date."
msgstr "estás actualizado."
msgid "latest dev version"
msgstr "ultima versión de desarollo"
msgid "a more recent development version is available."
msgstr "una versión de desarollo más reciente está disponible."
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Por favor, ejecute la importación en local, esto puede demorar un tiempo."
#, fuzzy
msgid "More infos in the official doc:"
msgstr "Más información en la documentación oficial :"
msgid "import from Pocket"
msgstr "importación desde Pocket"
msgid "import from Readability"
msgstr "importación desde Readability"
msgid "import from Instapaper"
msgstr "importación desde Instapaper"
msgid "Tags"
msgstr ""
#, fuzzy
msgid "Untitled"
msgstr "por título"
msgid "the link has been added successfully"
msgstr ""
msgid "error during insertion : the link wasn't added"
msgstr ""
msgid "the link has been deleted successfully"
msgstr ""
msgid "the link wasn't deleted"
msgstr ""
msgid "Article not found!"
msgstr ""
msgid "previous"
msgstr ""
msgid "next"
msgstr ""
msgid "in demo mode, you can't update your password"
msgstr ""
msgid "your password has been updated"
msgstr ""
msgid "the two fields have to be filled & the password must be the same in the two fields"
msgstr ""
msgid "still using the \""
msgstr ""
msgid "that theme does not seem to be installed"
msgstr ""
msgid "you have changed your theme preferences"
msgstr ""
msgid "that language does not seem to be installed"
msgstr ""
msgid "you have changed your language preferences"
msgstr ""
msgid "login failed: you have to fill all fields"
msgstr ""
msgid "welcome to your wallabag"
msgstr ""
msgid "login failed: bad login or password"
msgstr ""
#, fuzzy
msgid "import from instapaper completed"
msgstr "importación desde Instapaper"
#, fuzzy
msgid "import from pocket completed"
msgstr "importación desde Pocket"
#, fuzzy
msgid "import from Readability completed. "
msgstr "importación desde Readability"
#, fuzzy
msgid "import from Poche completed. "
msgstr "importación desde Pocket"
msgid "Unknown import provider."
msgstr ""
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr ""
msgid "Could not find required \""
msgstr ""
msgid "Uh, there is a problem while generating feeds."
msgstr ""
#, fuzzy
msgid "Cache deleted."
msgstr "eliminar"
msgid "Oops, it seems you don't have PHP 5."
msgstr ""
#~ msgid "poche it!"
#~ msgstr "pochéalo!"
#~ msgid "Updating poche"
#~ msgstr "Actualizar"
#~ msgid "create an issue"
#~ msgstr "crear un ticket"
#~ msgid "or"
#~ msgstr "o"
#~ msgid "contact us by mail"
#~ msgstr "contactarnos por mail"
#~ msgid "your poche version:"
#~ msgstr "tu versión de Poche:"

View File

@ -1,51 +1,136 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-25 15:15+0300\n"
"PO-Revision-Date: \n"
"Last-Translator: Nicolas Lœuillet <nicolas.loeuillet@gmail.com>\n"
"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.4\n"
"X-Poedit-Language: Persian\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
msgid "wallabag, a read it later open source system"
msgstr ""
msgid "login failed: user doesn't exist"
msgstr ""
msgid "return home"
msgstr ""
msgid "config"
msgstr "تنظیمات"
msgid "Poching a link"
msgstr "پیوندی را poche کنید"
msgid "Saving articles"
msgstr ""
msgid "There are several ways to save an article:"
msgstr ""
msgid "read the documentation"
msgstr "راهنما را بخوانید"
msgid "by filling this field"
msgid "download the extension"
msgstr ""
msgid "via F-Droid"
msgstr ""
msgid " or "
msgstr ""
msgid "via Google Play"
msgstr ""
msgid "download the application"
msgstr ""
#, fuzzy
msgid "By filling this field"
msgstr "با پرکردن این بخش"
msgid "poche it!"
msgstr "poche کنید!"
msgid "bag it!"
msgstr ""
msgid "Updating poche"
msgstr "به‌روزرسانی poche"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "نسخهٔ شما"
msgid "Upgrading wallabag"
msgstr ""
msgid "latest stable version"
#, fuzzy
msgid "Installed version"
msgstr "آخرین نسخهٔ پایدار"
msgid "a more recent stable version is available."
#, fuzzy
msgid "Latest stable version"
msgstr "آخرین نسخهٔ پایدار"
#, fuzzy
msgid "A more recent stable version is available."
msgstr "نسخهٔ پایدار تازه‌ای منتشر شده است."
msgid "you are up to date."
#, fuzzy
msgid "You are up to date."
msgstr "شما به‌روز هستید."
msgid "latest dev version"
#, fuzzy
msgid "Latest dev version"
msgstr "آخرین نسخهٔ آزمایشی"
msgid "a more recent development version is available."
#, fuzzy
msgid "A more recent development version is available."
msgstr "نسخهٔ آزمایشی تازه‌ای منتشر شده است."
msgid "Feeds"
msgstr ""
msgid "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>."
msgstr ""
msgid "Unread feed"
msgstr ""
#, fuzzy
msgid "Favorites feed"
msgstr "بهترین‌ها"
#, fuzzy
msgid "Archive feed"
msgstr "بایگانی"
msgid "Your token:"
msgstr ""
msgid "Your user id:"
msgstr ""
msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgstr ""
#, fuzzy
msgid "Change your theme"
msgstr "گذرواژهٔ خود را تغییر دهید"
msgid "Theme:"
msgstr ""
msgid "Update"
msgstr "به‌روزرسانی"
#, fuzzy
msgid "Change your language"
msgstr "گذرواژهٔ خود را تغییر دهید"
msgid "Language:"
msgstr ""
msgid "Change your password"
msgstr "گذرواژهٔ خود را تغییر دهید"
@ -58,64 +143,68 @@ msgstr "گذرواژه"
msgid "Repeat your new password:"
msgstr "گذرواژهٔ تازه را دوباره وارد کنید"
msgid "Update"
msgstr "به‌روزرسانی"
msgid "Import"
msgstr "درون‌ریزی"
msgid "Please execute the import script locally, it can take a very long time."
#, fuzzy
msgid "Please execute the import script locally as it can take a very long time."
msgstr "لطفاً برنامهٔ درون‌ریزی را به‌طور محلی اجرا کنید، شاید خیلی طول بکشد."
msgid "More info in the official doc:"
#, fuzzy
msgid "More info in the official documentation:"
msgstr "اطلاعات بیشتر در راهنمای رسمی:"
msgid "import from Pocket"
#, fuzzy
msgid "Import from Pocket"
msgstr "درون‌ریزی از Pocket"
msgid "import from Readability"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr ""
#, fuzzy
msgid "Import from Readability"
msgstr "درون‌ریزی از Readability"
msgid "import from Instapaper"
#, fuzzy
msgid "Import from Instapaper"
msgstr "درون‌ریزی از Instapaper"
msgid "Export your poche data"
#, fuzzy
msgid "Import from wallabag"
msgstr "درون‌ریزی از Readability"
#, fuzzy
msgid "Export your wallabag data"
msgstr "داده‌های poche خود را برون‌بری کنید"
msgid "Click here"
msgstr "اینجا را کلیک کنید"
msgid "to export your poche data."
msgid "to download your database."
msgstr ""
#, fuzzy
msgid "to export your wallabag data."
msgstr "برای برون‌بری داده‌های poche شما"
msgid "back to home"
msgstr "بازگشت به خانه"
msgid "installation"
msgstr "نصب"
msgid "install your poche"
msgstr "poche خود را نصب کنید"
msgid ""
"poche is still not installed. Please fill the below form to install it. "
"Don't hesitate to <a href='http://doc.inthepoche.com'>read the documentation "
"on poche website</a>."
msgid "Cache"
msgstr ""
"poche هنوز نصب نیست. برای نصب لطفاً فرم زیر را پر کنید. خواندن <a "
"href='http://doc.inthepoche.com'>راهنما در وبگاه poche</a> را از یاد نبرید."
msgid "Login"
msgstr "ورود"
msgid "to delete cache."
msgstr ""
msgid "Repeat your password"
msgstr "گذرواژه را دوباره وارد کنید"
msgid "You can enter multiple tags, separated by commas."
msgstr ""
msgid "Install"
msgstr "نصب"
msgid "return to article"
msgstr ""
msgid "back to top"
msgstr "بازگشت به بالای صفحه"
msgid "plop"
msgstr "plop"
msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgstr ""
msgid "favoris"
msgstr "بهترین‌ها"
@ -144,10 +233,14 @@ msgstr "با عنوان"
msgid "by title desc"
msgstr "با عنوان (الفبایی معکوس)"
msgid "No link available here!"
msgstr "اینجا پیوندی موجود نیست!"
msgid "Tag"
msgstr ""
msgid "toggle mark as read"
msgid "No articles found."
msgstr ""
#, fuzzy
msgid "Toggle mark as read"
msgstr "خوانده‌شده/خوانده‌نشده"
msgid "toggle favorite"
@ -159,13 +252,95 @@ msgstr "پاک‌کردن"
msgid "original"
msgstr "اصلی"
msgid "estimated reading time:"
msgstr ""
msgid "mark all the entries as read"
msgstr ""
msgid "results"
msgstr "نتایج"
msgid "tweet"
msgid "installation"
msgstr "نصب"
#, fuzzy
msgid "install your wallabag"
msgstr "poche خود را نصب کنید"
#, fuzzy
msgid "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>."
msgstr "poche هنوز نصب نیست. برای نصب لطفاً فرم زیر را پر کنید. خواندن <a href='http://doc.inthepoche.com'>راهنما در وبگاه poche</a> را از یاد نبرید."
msgid "Login"
msgstr "ورود"
msgid "Repeat your password"
msgstr "گذرواژه را دوباره وارد کنید"
msgid "Install"
msgstr "نصب"
#, fuzzy
msgid "login to your wallabag"
msgstr "به poche خود وارد شوید"
msgid "Login to wallabag"
msgstr ""
msgid "you are in demo mode, some features may be disabled."
msgstr "این تنها نسخهٔ نمایشی است، برخی از ویژگی‌ها کار نمی‌کنند."
msgid "Username"
msgstr ""
msgid "Stay signed in"
msgstr "مرا به خاطر بسپار"
msgid "(Do not check on public computers)"
msgstr "(روی رایانه‌های عمومی این کار را نکنید)"
msgid "Sign in"
msgstr "ورود"
msgid "favorites"
msgstr "بهترین‌ها"
msgid "estimated reading time :"
msgstr ""
msgid "Mark all the entries as read"
msgstr ""
msgid "Return home"
msgstr ""
#, fuzzy
msgid "Back to top"
msgstr "بازگشت به بالای صفحه"
#, fuzzy
msgid "Mark as read"
msgstr "خوانده‌شده/خوانده‌نشده"
#, fuzzy
msgid "Favorite"
msgstr "بهترین‌ها"
#, fuzzy
msgid "Toggle favorite"
msgstr "جزء بهترین‌ها هست/نیست"
#, fuzzy
msgid "Delete"
msgstr "پاک‌کردن"
#, fuzzy
msgid "Tweet"
msgstr "توییت"
msgid "email"
#, fuzzy
msgid "Email"
msgstr "ایمیل"
msgid "shaarli"
@ -174,26 +349,24 @@ msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
msgid "this article appears wrong?"
#, fuzzy
msgid "Does this article appear wrong?"
msgstr "این مطلب اشتباه نمایش داده شده؟"
msgid "create an issue"
msgstr "یک درخواست رفع‌مشکل بنویسید"
msgid "tags:"
msgstr ""
msgid "or"
msgstr "یا"
msgid "Edit tags"
msgstr ""
msgid "contact us by mail"
msgstr "به ما ایمیل بزنید"
msgid "plop"
msgstr "plop"
msgid "save link!"
msgstr ""
msgid "home"
msgstr "خانه"
msgid "favorites"
msgstr "بهترین‌ها"
msgid "tags"
msgstr ""
msgid "logout"
msgstr "بیرون رفتن"
@ -204,23 +377,187 @@ msgstr "نیروگرفته از"
msgid "debug mode is on so cache is off."
msgstr "حالت عیب‌یابی فعال است، پس کاشه خاموش است."
msgid "your poche version:"
msgstr "نسخهٔ poche شما:"
#, fuzzy
msgid "your wallabag version:"
msgstr "نسخهٔ شما"
msgid "storage:"
msgstr "ذخیره‌سازی:"
msgid "login to your poche"
msgstr "به poche خود وارد شوید"
msgid "save a link"
msgstr ""
msgid "you are in demo mode, some features may be disabled."
msgstr "این تنها نسخهٔ نمایشی است، برخی از ویژگی‌ها کار نمی‌کنند."
msgid "back to home"
msgstr "بازگشت به خانه"
msgid "Stay signed in"
msgstr "مرا به خاطر بسپار"
msgid "toggle mark as read"
msgstr "خوانده‌شده/خوانده‌نشده"
msgid "(Do not check on public computers)"
msgstr "(روی رایانه‌های عمومی این کار را نکنید)"
msgid "tweet"
msgstr "توییت"
msgid "Sign in"
msgstr "ورود"
msgid "email"
msgstr "ایمیل"
msgid "this article appears wrong?"
msgstr "این مطلب اشتباه نمایش داده شده؟"
msgid "No link available here!"
msgstr "اینجا پیوندی موجود نیست!"
msgid "Poching a link"
msgstr "پیوندی را poche کنید"
msgid "by filling this field"
msgstr "با پرکردن این بخش"
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "نسخهٔ شما"
msgid "latest stable version"
msgstr "آخرین نسخهٔ پایدار"
msgid "a more recent stable version is available."
msgstr "نسخهٔ پایدار تازه‌ای منتشر شده است."
msgid "you are up to date."
msgstr "شما به‌روز هستید."
msgid "latest dev version"
msgstr "آخرین نسخهٔ آزمایشی"
msgid "a more recent development version is available."
msgstr "نسخهٔ آزمایشی تازه‌ای منتشر شده است."
msgid "Please execute the import script locally, it can take a very long time."
msgstr "لطفاً برنامهٔ درون‌ریزی را به‌طور محلی اجرا کنید، شاید خیلی طول بکشد."
#, fuzzy
msgid "More infos in the official doc:"
msgstr "اطلاعات بیشتر در راهنمای رسمی:"
msgid "import from Pocket"
msgstr "درون‌ریزی از Pocket"
msgid "import from Readability"
msgstr "درون‌ریزی از Readability"
msgid "import from Instapaper"
msgstr "درون‌ریزی از Instapaper"
msgid "Tags"
msgstr ""
#, fuzzy
msgid "Untitled"
msgstr "با عنوان"
msgid "the link has been added successfully"
msgstr ""
msgid "error during insertion : the link wasn't added"
msgstr ""
msgid "the link has been deleted successfully"
msgstr ""
msgid "the link wasn't deleted"
msgstr ""
msgid "Article not found!"
msgstr ""
msgid "previous"
msgstr ""
msgid "next"
msgstr ""
msgid "in demo mode, you can't update your password"
msgstr ""
msgid "your password has been updated"
msgstr ""
msgid "the two fields have to be filled & the password must be the same in the two fields"
msgstr ""
msgid "still using the \""
msgstr ""
msgid "that theme does not seem to be installed"
msgstr ""
msgid "you have changed your theme preferences"
msgstr ""
msgid "that language does not seem to be installed"
msgstr ""
msgid "you have changed your language preferences"
msgstr ""
msgid "login failed: you have to fill all fields"
msgstr ""
msgid "welcome to your wallabag"
msgstr ""
msgid "login failed: bad login or password"
msgstr ""
#, fuzzy
msgid "import from instapaper completed"
msgstr "درون‌ریزی از Instapaper"
#, fuzzy
msgid "import from pocket completed"
msgstr "درون‌ریزی از Pocket"
#, fuzzy
msgid "import from Readability completed. "
msgstr "درون‌ریزی از Readability"
#, fuzzy
msgid "import from Poche completed. "
msgstr "درون‌ریزی از Pocket"
msgid "Unknown import provider."
msgstr ""
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr ""
msgid "Could not find required \""
msgstr ""
msgid "Uh, there is a problem while generating feeds."
msgstr ""
#, fuzzy
msgid "Cache deleted."
msgstr "پاک‌کردن"
msgid "Oops, it seems you don't have PHP 5."
msgstr ""
#~ msgid "poche it!"
#~ msgstr "poche کنید!"
#~ msgid "Updating poche"
#~ msgstr "به‌روزرسانی poche"
#~ msgid "create an issue"
#~ msgstr "یک درخواست رفع‌مشکل بنویسید"
#~ msgid "or"
#~ msgstr "یا"
#~ msgid "contact us by mail"
#~ msgstr "به ما ایمیل بزنید"
#~ msgid "your poche version:"
#~ msgstr "نسخهٔ poche شما:"

View File

@ -1,32 +1,395 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"Project-Id-Version: wallabag 1.7\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-05-10 20:09+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: Nicolas Lœuillet <nicolas.loeuillet@gmail.com>\n"
"Last-Translator: Gilles Wittezaële <gilles.wittezaele@laposte.net>\n"
"Language-Team: \n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Generator: Poedit 1.5.4\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "wallabag, a read it later open source system"
msgstr "wallabag, un système open source de lecture différé"
msgid "login failed: user doesn't exist"
msgstr "échec de l'identification : cet utilisateur n'existe pas"
msgid "save link!"
msgstr "enregistrer le lien !"
msgid "plop"
msgstr "plop"
msgid "powered by"
msgstr "propulsé par"
msgid "debug mode is on so cache is off."
msgstr "le mode de debug est actif, le cache est donc désactivé."
msgid "your wallabag version:"
msgstr "votre version de wallabag :"
msgid "storage:"
msgstr "stockage :"
msgid "login to your wallabag"
msgstr "se connecter à votre wallabag"
msgid "Login to wallabag"
msgstr "Se connecter à wallabag"
msgid "you are in demo mode, some features may be disabled."
msgstr ""
"vous êtes en mode démo, certaines fonctionnalités peuvent être désactivées."
msgid "Username"
msgstr "Nom d'utilisateur"
msgid "Password"
msgstr "Mot de passe"
msgid "Stay signed in"
msgstr "Rester connecté"
msgid "(Do not check on public computers)"
msgstr "(Ne pas cocher sur un ordinateur public)"
msgid "Sign in"
msgstr "Se connecter"
msgid "back to home"
msgstr "retour à l'accueil"
msgid "favorites"
msgstr "favoris"
msgid "archive"
msgstr "archive"
msgid "unread"
msgstr "non lus"
msgid "Tag"
msgstr "Tag"
msgid "No articles found."
msgstr "Aucun article trouvé."
msgid "estimated reading time:"
msgstr "temps de lecture estimé :"
msgid "estimated reading time :"
msgstr "temps de lecture estimé :"
msgid "Toggle mark as read"
msgstr "Marquer comme lu / non lu"
msgid "toggle favorite"
msgstr "marquer / enlever comme favori"
msgid "delete"
msgstr "supprimer"
msgid "original"
msgstr "original"
msgid "Mark all the entries as read"
msgstr "Marquer tous les articles comme lus"
msgid "results"
msgstr "résultats"
msgid " found for « "
msgstr "trouvé pour « "
msgid "Only one result found for "
msgstr "Seulement un résultat trouvé pour "
msgid "config"
msgstr "configuration"
msgid "Poching a link"
msgstr "Pocher un lien"
msgid "Saving articles"
msgstr "Sauvegarde des articles"
msgid "There are several ways to save an article:"
msgstr "Il y a plusieurs façons d'enregistrer un article :"
msgid "read the documentation"
msgstr "lisez la documentation"
msgid "download the extension"
msgstr "téléchargez l'extension"
msgid "via F-Droid"
msgstr "via F-Droid"
msgid " or "
msgstr " ou "
msgid "via Google Play"
msgstr "via Google PlayStore"
msgid "download the application"
msgstr "téléchargez l'application"
msgid "By filling this field"
msgstr "En remplissant ce champ"
msgid "bag it!"
msgstr "bag it !"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "Bookmarklet : glissez-déposez ce lien dans votre barre de favoris"
msgid "Upgrading wallabag"
msgstr "Mise à jour de wallabag"
msgid "Installed version"
msgstr "Version installée"
msgid "Latest stable version"
msgstr "Dernière version stable"
msgid "A more recent stable version is available."
msgstr "Une version stable plus récente est disponible."
msgid "You are up to date."
msgstr "Vous êtes à jour."
msgid "Last check:"
msgstr "Dernière vérification: "
msgid "Latest dev version"
msgstr "Dernière version de développement"
msgid "A more recent development version is available."
msgstr "Une version de développement plus récente est disponible."
msgid "You can clear cache to check the latest release."
msgstr ""
"Vous pouvez vider le cache pour vérifier que vous avez la dernière version."
msgid "Feeds"
msgstr "Flux"
msgid ""
"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>."
msgstr ""
"Votre jeton de flux est actuellement vide et doit d'abord être généré pour "
"activer les flux. Cliquez <a href='?feed&amp;action=generate'>ici</a> pour "
"le générer."
msgid "Unread feed"
msgstr "Flux des non lus"
msgid "Favorites feed"
msgstr "Flux des favoris"
msgid "Archive feed"
msgstr "Flux des archives"
msgid "Your token:"
msgstr "Votre jeton :"
msgid "Your user id:"
msgstr "Votre ID utilisateur :"
msgid ""
"You can regenerate your token: <a href='?feed&amp;action=generate'>generate!"
"</a>."
msgstr ""
"Vous pouvez regénérer votre jeton : <a href='?feed&amp;"
"action=generate'>génération !</a>."
msgid "Change your theme"
msgstr "Changer votre thème"
msgid "Theme:"
msgstr "Thème :"
msgid "Update"
msgstr "Mettre à jour"
msgid "Change your language"
msgstr "Changer votre langue"
msgid "Language:"
msgstr "Langue :"
msgid "Change your password"
msgstr "Modifier votre mot de passe"
msgid "New password:"
msgstr "Nouveau mot de passe :"
msgid "Repeat your new password:"
msgstr "Répétez votre nouveau mot de passe :"
msgid "Import"
msgstr "Importer"
msgid ""
"You can import your Pocket, Readability, Instapaper, Wallabag or any data in "
"appropriate json or html format."
msgstr ""
"Vous pouvez importer depuis Pocket, Readability, Instapaper, wallabag, ou "
"n'importe quel fichier au format JSON ou HTML approprié."
msgid ""
"Please select export file on your computer and press \"Import\" button below."
"<br>Wallabag will parse your file, insert all URLs and start fetching of "
"articles if required.<br>Fetching process is controlled by two constants in "
"your config file: IMPORT_LIMIT (how many articles are fetched at once) and "
"IMPORT_DELAY (delay between fetch of next batch of articles)."
msgstr ""
"Sélectionner le fichier à importer sur votre disque dur, et pressez la "
"bouton « Importer » ci-dessous.<br />wallabag analysera votre fichier, "
"ajoutera toutes les URL trouvées et commencera à télécharger les contenus si "
"nécessaire.<br />Le processus de téléchargement est contrôlé par deux "
"constantes dans votre fichier de configuration:<wbr /><code>IMPORT_LIMIT</"
"code> (nombre d'éléments téléchargés à la fois) et <code>IMPORT_DELAY</code> "
"(le délai d'attente entre deux séquences de téléchargement)."
msgid "File:"
msgstr "Fichier : "
msgid "You can click here to fetch content for articles with no content."
msgstr ""
"Vous pouvez cliquer ici pour télécharger le contenu des articles vides."
msgid "Export your wallabag data"
msgstr "Exporter vos données de wallabag"
msgid "Click here"
msgstr "Cliquez ici"
msgid "to download your database."
msgstr "pour télécharger votre base de données."
msgid "to export your wallabag data."
msgstr "pour exporter vos données de wallabag."
msgid "Cache"
msgstr "Cache"
msgid "to delete cache."
msgstr "pour effacer le cache."
msgid "Add user"
msgstr "Ajouter un utilisateur"
msgid "Add a new user :"
msgstr "Ajouter un nouvel utilisateur : "
msgid "Login for new user"
msgstr "Identifiant du nouvel utilisateur"
msgid "Login"
msgstr "Nom d'utilisateur"
msgid "Password for new user"
msgstr "Mot de passe du nouvel utilisateur"
msgid "Send"
msgstr "Envoyer"
msgid "Delete account"
msgstr "Supprimer le compte"
msgid "You can delete your account by entering your password and validating."
msgstr ""
"Vous pouvez supprimer votre compte en entrant votre mot de passe et en "
"validant."
msgid "Be careful, data will be erased forever (that is a very long time)."
msgstr "Attention, les données seront perdues pour toujours."
msgid "Type here your password"
msgstr "Entrez votre mot de passe ici"
msgid "You are the only user, you cannot delete your own account."
msgstr ""
"Vous êtes l'unique utilisateur, vous ne pouvez pas supprimer votre compte."
msgid ""
"To completely remove wallabag, delete the wallabag folder on your web server."
msgstr ""
"Pour désinstaller complètement wallabag, supprimez le répertoire "
"<code>wallabag</code> de votre serveur Web."
msgid "Save a link"
msgstr "Ajouter un lien"
msgid "Return home"
msgstr "Retour accueil"
msgid "Back to top"
msgstr "Haut de page"
msgid "Mark as read"
msgstr "Marquer comme lu"
msgid "Favorite"
msgstr "Favoris"
msgid "Toggle favorite"
msgstr "Marquer / enlever comme favori"
msgid "Delete"
msgstr "Effacer"
msgid "Tweet"
msgstr "Tweet"
msgid "Email"
msgstr "E-mail"
msgid "shaarli"
msgstr "Shaarli"
msgid "flattr"
msgstr "Flattr"
msgid "Print"
msgstr "Imprimer"
msgid "Does this article appear wrong?"
msgstr "Cet article s'affiche mal ?"
msgid "tags:"
msgstr "tags :"
msgid "Edit tags"
msgstr "Modifier les tags"
msgid "favoris"
msgstr "favoris"
msgid "mark all the entries as read"
msgstr "marquer tous les articles comme lus"
msgid "toggle view mode"
msgstr "changer de mode de visualisation"
msgid "return home"
msgstr "retour à l'accueil"
msgid "Poching a link"
msgstr "Enregistrer un lien"
msgid "by filling this field"
msgstr "en remplissant ce champ"
msgid "poche it!"
msgstr "pochez-le !"
msgid "Updating poche"
msgstr "Mettre à jour poche"
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "bookmarklet : glissez-déposez ce lien dans votre barre de favoris"
msgid "your version"
msgstr "votre version"
@ -46,86 +409,35 @@ msgstr "dernière version de développement"
msgid "a more recent development version is available."
msgstr "une version de développement plus récente est disponible."
msgid "Change your password"
msgstr "Modifier votre mot de passe"
msgid "New password:"
msgstr "Nouveau mot de passe :"
msgid "Password"
msgstr "Mot de passe"
msgid "Repeat your new password:"
msgstr "Répétez votre nouveau mot de passe :"
msgid "Update"
msgstr "Mettre à jour"
msgid "Import"
msgstr "Importer"
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Merci d'exécuter l'import en local, cela peut prendre du temps."
msgstr ""
"Merci d'exécuter le script d'importation en local car cela peut prendre du "
"temps."
msgid "More info in the official doc:"
msgstr "Plus d'infos sur la documentation officielle"
msgid "More infos in the official doc:"
msgstr "Plus d'infos dans la documentation officielle :"
msgid "import from Pocket"
msgstr "import depuis Pocket"
msgstr "importer depuis Pocket"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr "(le fichier %s doit être présent sur le serveur)"
msgid "import from Readability"
msgstr "import depuis Readability"
msgstr "importer depuis Readability"
msgid "import from Instapaper"
msgstr "import depuis Instapaper"
msgstr "importer depuis Instapaper"
msgid "Export your poche data"
msgstr "Exporter vos données de poche"
msgid "Start typing for auto complete."
msgstr "Commencez à taper pour activer l'auto-complétion."
msgid "Click here"
msgstr "Cliquez-ici"
msgid "You can enter multiple tags, separated by commas."
msgstr "Vous pouvez entrer plusieurs tags, séparés par des virgules."
msgid "to export your poche data."
msgstr "pour exporter vos données de poche."
msgid "back to home"
msgstr "retour à l'accueil"
msgid "installation"
msgstr "installation"
msgid "install your poche"
msgstr "installez votre poche"
msgid ""
"poche is still not installed. Please fill the below form to install it. "
"Don't hesitate to <a href='http://doc.inthepoche.com'>read the documentation "
"on poche website</a>."
msgstr ""
"poche n'est pas encore installé. Merci de remplir le formulaire suivant pour "
"l'installer. N'hésitez pas à <a href='http://doc.inthepoche.com'>lire la "
"documentation sur le site de poche</a>."
msgid "Login"
msgstr "Nom d'utilisateur"
msgid "Repeat your password"
msgstr "Répétez votre mot de passe"
msgid "Install"
msgstr "Installer"
msgid "back to top"
msgstr "retour en haut de page"
msgid "favoris"
msgstr "favoris"
msgid "archive"
msgstr "archive"
msgid "unread"
msgstr "non lus"
msgid "return to article"
msgstr "retourner à l'article"
msgid "by date asc"
msgstr "par date asc"
@ -145,84 +457,196 @@ msgstr "par titre"
msgid "by title desc"
msgstr "par titre desc"
msgid "home"
msgstr "accueil"
msgid "tags"
msgstr "tags"
msgid "save a link"
msgstr "sauver un lien"
msgid "search"
msgstr "rechercher"
msgid "logout"
msgstr "déconnexion"
msgid "installation"
msgstr "installation"
msgid "install your wallabag"
msgstr "installez votre wallabag"
msgid ""
"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>."
msgstr ""
"wallabag n'est pas encore installé. Merci de remplir le formulaire suivant "
"pour l'installer. N'hésitez pas à <a href='http://doc.wallabag.org'>lire la "
"documentation sur le site de wallabag</a>."
msgid "Repeat your password"
msgstr "Répétez votre mot de passe"
msgid "Install"
msgstr "Installer"
msgid ""
"You can <a href='wallabag_compatibility_test.php'>check your configuration "
"here</a>."
msgstr ""
"Vous pouvez vérifier votre configuration <a "
"href='wallabag_compatibility_test.php'>ici</a>."
msgid "Tags"
msgstr "Tags"
msgid "No link available here!"
msgstr "Aucun lien n'est disponible ici !"
msgid "toggle mark as read"
msgstr "marquer comme lu / non lu"
msgid "toggle favorite"
msgstr "marquer comme favori"
msgid "delete"
msgstr "supprimer"
msgid "original"
msgstr "original"
msgid "results"
msgstr "résultats"
msgid "tweet"
msgstr "tweet"
msgid "email"
msgstr "email"
msgid "shaarli"
msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
msgstr "e-mail"
msgid "this article appears wrong?"
msgstr "cet article s'affiche mal ?"
msgid "create an issue"
msgstr "créez un ticket"
msgid "Search"
msgstr "Rechercher"
msgid "or"
msgstr "ou"
msgid "Download required for "
msgstr "Téléchargement requis pour "
msgid "contact us by mail"
msgstr "contactez-nous par email"
msgid "records"
msgstr " articles"
msgid "plop"
msgstr "plop"
msgid "Downloading next "
msgstr "Téléchargement des "
msgid "home"
msgstr "accueil"
msgid "articles, please wait"
msgstr " articles suivants, veuillez patienter..."
msgid "favorites"
msgstr "favoris"
msgid "Enter your search here"
msgstr "Entrez votre recherche ici"
msgid "logout"
msgstr "déconnexion"
msgid "powered by"
msgstr "propulsé par"
msgid "debug mode is on so cache is off."
msgstr "le mode de debug est actif, le cache est donc désactivé."
msgid "your poche version:"
msgstr "votre version de poche :"
msgid "storage:"
msgstr "stockage :"
msgid "login to your poche"
msgstr "se connecter à votre poche"
msgid "you are in demo mode, some features may be disabled."
#, php-format
msgid ""
"The new user %s has been installed. Do you want to <a href=\"?logout"
"\">logout ?</a>"
msgstr ""
"vous êtes en mode démo, certaines fonctionnalités peuvent être désactivées."
"Le nouvel utilisateur « %s » a été ajouté. Voulez-vous vous <a href=\"?"
"logout\">déconnecter ?</a>"
msgid "Stay signed in"
msgstr "Rester connecté"
#, php-format
msgid "Error : An user with the name %s already exists !"
msgstr "Erreur : Un utilisateur avec le nom « %s » existe déjà !"
msgid "(Do not check on public computers)"
msgstr "(ne pas cocher sur un ordinateur public)"
#, php-format
msgid "User %s has been successfully deleted !"
msgstr "L'utilisateur « %s » a été supprimé avec succès !"
msgid "Sign in"
msgstr "Se connecter"
msgid "Error : The password is wrong !"
msgstr "Erreur : le mot de passe est incorrect !"
msgid "Error : You are the only user, you cannot delete your account !"
msgstr ""
"Erreur : Vous êtes l'unique utilisateur, vous ne pouvez pas supprimer votre "
"compte !"
msgid "Untitled"
msgstr "Sans titre"
msgid "the link has been added successfully"
msgstr "le lien a été ajouté avec succès"
msgid "error during insertion : the link wasn't added"
msgstr "erreur pendant l'insertion : le lien n'a pas été ajouté"
msgid "the link has been deleted successfully"
msgstr "le lien a été effacé avec succès"
msgid "the link wasn't deleted"
msgstr "le lien n'a pas été effacé"
msgid "Article not found!"
msgstr "Article non trouvé !"
msgid "previous"
msgstr "précédent"
msgid "next"
msgstr "suivant"
msgid "in demo mode, you can't update your password"
msgstr "en mode démo, vous ne pouvez pas mettre à jour votre mot de passe"
msgid "your password has been updated"
msgstr "votre mot de passe a été mis à jour"
msgid ""
"the two fields have to be filled & the password must be the same in the two "
"fields"
msgstr ""
"les deux champs doivent être remplis & le mot de passe doit être le même "
"dans les deux"
msgid "still using the \""
msgstr "vous utilisez toujours \""
msgid "that theme does not seem to be installed"
msgstr "ce thème ne semble pas installé"
msgid "you have changed your theme preferences"
msgstr "vous avez changé vos préférences de thème"
msgid "that language does not seem to be installed"
msgstr "cette langue ne semble pas être installée"
msgid "you have changed your language preferences"
msgstr "vous avez changé vos préférences de langue"
msgid "login failed: you have to fill all fields"
msgstr "échec de l'identification : vous devez remplir tous les champs"
msgid "welcome to your wallabag"
msgstr "bienvenue dans votre wallabag"
msgid "login failed: bad login or password"
msgstr "échec de l'identification : mauvais identifiant ou mot de passe"
msgid "Untitled - Import - "
msgstr "Sans titre - Importer - "
msgid "click to finish import"
msgstr "cliquez pour terminer l'importation"
msgid "Articles inserted: "
msgstr "Articles ajoutés : "
msgid ". Please note, that some may be marked as \"read\"."
msgstr ". Notez que certains pourraient être marqués comme \"lus\"."
msgid "Import finished."
msgstr "Importation terminée."
msgid "Undefined"
msgstr "Non défini"
msgid "User with this id ("
msgstr "Utilisateur avec cet identifiant ("
msgid "Uh, there is a problem while generating feeds."
msgstr "Hum, il y a un problème lors de la génération des flux."
msgid "Cache deleted."
msgstr "Cache effacé."
msgid "Oops, it seems you don't have PHP 5."
msgstr "Oups, vous ne semblez pas avoir PHP 5."

View File

@ -4,54 +4,138 @@
msgid ""
msgstr ""
"Project-Id-Version: poche\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2013-11-25 09:47+0100\n"
"Last-Translator: Nicolas Lœuillet <nicolas.loeuillet@gmail.com>\n"
"Language-Team: Italian (http://www.transifex.com/projects/p/poche/language/"
"it/)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-25 15:13+0300\n"
"PO-Revision-Date: 2014-02-25 15:13+0300\n"
"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
"Language-Team: Italian (http://www.transifex.com/projects/p/poche/language/it/)\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.5.4\n"
"X-Poedit-Language: Italian\n"
"X-Poedit-Country: ITALY\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
msgid "wallabag, a read it later open source system"
msgstr ""
msgid "login failed: user doesn't exist"
msgstr ""
msgid "return home"
msgstr ""
msgid "config"
msgstr "configurazione"
msgid "Poching a link"
msgstr "Pochare un link"
msgid "Saving articles"
msgstr ""
msgid "There are several ways to save an article:"
msgstr ""
msgid "read the documentation"
msgstr "leggi la documentazione"
msgid "by filling this field"
msgid "download the extension"
msgstr ""
msgid "via F-Droid"
msgstr ""
msgid " or "
msgstr ""
msgid "via Google Play"
msgstr ""
msgid "download the application"
msgstr ""
#, fuzzy
msgid "By filling this field"
msgstr "compilando questo campo"
msgid "poche it!"
msgstr "pochalo!"
msgid "bag it!"
msgstr ""
msgid "Updating poche"
msgstr "Aggiornamento poche"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "la tua versione"
msgid "Upgrading wallabag"
msgstr ""
msgid "latest stable version"
#, fuzzy
msgid "Installed version"
msgstr "ultima versione stabile"
msgid "a more recent stable version is available."
#, fuzzy
msgid "Latest stable version"
msgstr "ultima versione stabile"
#, fuzzy
msgid "A more recent stable version is available."
msgstr "è disponibile una versione stabile più recente."
msgid "you are up to date."
#, fuzzy
msgid "You are up to date."
msgstr "sei aggiornato."
msgid "latest dev version"
#, fuzzy
msgid "Latest dev version"
msgstr "ultima versione di sviluppo"
msgid "a more recent development version is available."
#, fuzzy
msgid "A more recent development version is available."
msgstr "è disponibile una versione di sviluppo più recente."
msgid "Feeds"
msgstr ""
msgid "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>."
msgstr ""
msgid "Unread feed"
msgstr ""
#, fuzzy
msgid "Favorites feed"
msgstr "preferiti"
#, fuzzy
msgid "Archive feed"
msgstr "archivio"
msgid "Your token:"
msgstr ""
msgid "Your user id:"
msgstr ""
msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgstr ""
#, fuzzy
msgid "Change your theme"
msgstr "Cambia la tua password"
msgid "Theme:"
msgstr ""
msgid "Update"
msgstr "Aggiorna"
#, fuzzy
msgid "Change your language"
msgstr "Cambia la tua password"
msgid "Language:"
msgstr ""
msgid "Change your password"
msgstr "Cambia la tua password"
@ -64,67 +148,68 @@ msgstr "Password"
msgid "Repeat your new password:"
msgstr "Ripeti la nuova password:"
msgid "Update"
msgstr "Aggiorna"
msgid "Import"
msgstr "Importa"
msgid "Please execute the import script locally, it can take a very long time."
msgstr ""
"Si prega di eseguire lo script di importazione a livello locale, può "
"richiedere un tempo molto lungo."
#, fuzzy
msgid "Please execute the import script locally as it can take a very long time."
msgstr "Si prega di eseguire lo script di importazione a livello locale, può richiedere un tempo molto lungo."
msgid "More info in the official doc:"
#, fuzzy
msgid "More info in the official documentation:"
msgstr "Maggiori info nella documentazione ufficiale"
msgid "import from Pocket"
#, fuzzy
msgid "Import from Pocket"
msgstr "Importa da Pocket"
msgid "import from Readability"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr ""
#, fuzzy
msgid "Import from Readability"
msgstr "Importa da Readability"
msgid "import from Instapaper"
#, fuzzy
msgid "Import from Instapaper"
msgstr "Importa da Instapaper"
msgid "Export your poche data"
#, fuzzy
msgid "Import from wallabag"
msgstr "Importa da Readability"
#, fuzzy
msgid "Export your wallabag data"
msgstr "Esporta i tuoi dati di poche"
msgid "Click here"
msgstr "Fai clic qui"
msgid "to export your poche data."
msgid "to download your database."
msgstr ""
#, fuzzy
msgid "to export your wallabag data."
msgstr "per esportare i tuoi dati di poche."
msgid "back to home"
msgstr "torna alla home"
msgid "installation"
msgstr "installazione"
msgid "install your poche"
msgstr "installa il tuo poche"
msgid ""
"poche is still not installed. Please fill the below form to install it. "
"Don't hesitate to <a href='http://doc.inthepoche.com'>read the documentation "
"on poche website</a>."
msgid "Cache"
msgstr ""
"poche non è ancora installato. Si prega di riempire il modulo sottostante "
"per completare l'installazione. <a href='http://doc.inthepoche.com'>Leggere "
"la documentazione sul sito di poche</a>."
msgid "Login"
msgstr "Nome utente"
msgid "to delete cache."
msgstr ""
msgid "Repeat your password"
msgstr "Ripeti la tua password"
msgid "You can enter multiple tags, separated by commas."
msgstr ""
msgid "Install"
msgstr "Installa"
msgid "return to article"
msgstr ""
msgid "back to top"
msgstr "torna a inizio pagina"
msgid "plop"
msgstr "plop"
msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgstr ""
msgid "favoris"
msgstr "preferiti"
@ -153,10 +238,14 @@ msgstr "per titolo"
msgid "by title desc"
msgstr "per titolo decr"
msgid "No link available here!"
msgstr "Nessun link disponibile!"
msgid "Tag"
msgstr ""
msgid "toggle mark as read"
msgid "No articles found."
msgstr ""
#, fuzzy
msgid "Toggle mark as read"
msgstr "segna come letto / non letto"
msgid "toggle favorite"
@ -168,13 +257,95 @@ msgstr "elimina"
msgid "original"
msgstr "originale"
msgid "estimated reading time:"
msgstr ""
msgid "mark all the entries as read"
msgstr ""
msgid "results"
msgstr "risultati"
msgid "tweet"
msgid "installation"
msgstr "installazione"
#, fuzzy
msgid "install your wallabag"
msgstr "installa il tuo poche"
#, fuzzy
msgid "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>."
msgstr "poche non è ancora installato. Si prega di riempire il modulo sottostante per completare l'installazione. <a href='http://doc.inthepoche.com'>Leggere la documentazione sul sito di poche</a>."
msgid "Login"
msgstr "Nome utente"
msgid "Repeat your password"
msgstr "Ripeti la tua password"
msgid "Install"
msgstr "Installa"
#, fuzzy
msgid "login to your wallabag"
msgstr "accedi al tuo poche"
msgid "Login to wallabag"
msgstr ""
msgid "you are in demo mode, some features may be disabled."
msgstr "sei in modalità dimostrazione, alcune funzionalità potrebbero essere disattivate."
msgid "Username"
msgstr ""
msgid "Stay signed in"
msgstr "Resta connesso"
msgid "(Do not check on public computers)"
msgstr "(non selezionare su computer pubblici)"
msgid "Sign in"
msgstr "Accedi"
msgid "favorites"
msgstr "preferiti"
msgid "estimated reading time :"
msgstr ""
msgid "Mark all the entries as read"
msgstr ""
msgid "Return home"
msgstr ""
#, fuzzy
msgid "Back to top"
msgstr "torna a inizio pagina"
#, fuzzy
msgid "Mark as read"
msgstr "segna come letto / non letto"
#, fuzzy
msgid "Favorite"
msgstr "preferiti"
#, fuzzy
msgid "Toggle favorite"
msgstr "segna come preferito"
#, fuzzy
msgid "Delete"
msgstr "elimina"
#, fuzzy
msgid "Tweet"
msgstr "twitta"
msgid "email"
#, fuzzy
msgid "Email"
msgstr "email"
msgid "shaarli"
@ -183,26 +354,24 @@ msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
msgid "this article appears wrong?"
#, fuzzy
msgid "Does this article appear wrong?"
msgstr "articolo non visualizzato correttamente?"
msgid "create an issue"
msgstr "crea una segnalazione"
msgid "tags:"
msgstr ""
msgid "or"
msgstr "oppure"
msgid "Edit tags"
msgstr ""
msgid "contact us by mail"
msgstr "contattaci via email"
msgid "plop"
msgstr "plop"
msgid "save link!"
msgstr ""
msgid "home"
msgstr "home"
msgid "favorites"
msgstr "preferiti"
msgid "tags"
msgstr ""
msgid "logout"
msgstr "esci"
@ -213,25 +382,187 @@ msgstr "realizzato con"
msgid "debug mode is on so cache is off."
msgstr "modalità di debug attiva, cache disattivata."
msgid "your poche version:"
msgstr "la tua versione di poche:"
#, fuzzy
msgid "your wallabag version:"
msgstr "la tua versione"
msgid "storage:"
msgstr "memoria:"
msgid "login to your poche"
msgstr "accedi al tuo poche"
msgid "you are in demo mode, some features may be disabled."
msgid "save a link"
msgstr ""
"sei in modalità dimostrazione, alcune funzionalità potrebbero essere "
"disattivate."
msgid "Stay signed in"
msgstr "Resta connesso"
msgid "back to home"
msgstr "torna alla home"
msgid "(Do not check on public computers)"
msgstr "(non selezionare su computer pubblici)"
msgid "toggle mark as read"
msgstr "segna come letto / non letto"
msgid "Sign in"
msgstr "Accedi"
msgid "tweet"
msgstr "twitta"
msgid "email"
msgstr "email"
msgid "this article appears wrong?"
msgstr "articolo non visualizzato correttamente?"
msgid "No link available here!"
msgstr "Nessun link disponibile!"
msgid "Poching a link"
msgstr "Pochare un link"
msgid "by filling this field"
msgstr "compilando questo campo"
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "la tua versione"
msgid "latest stable version"
msgstr "ultima versione stabile"
msgid "a more recent stable version is available."
msgstr "è disponibile una versione stabile più recente."
msgid "you are up to date."
msgstr "sei aggiornato."
msgid "latest dev version"
msgstr "ultima versione di sviluppo"
msgid "a more recent development version is available."
msgstr "è disponibile una versione di sviluppo più recente."
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Si prega di eseguire lo script di importazione a livello locale, può richiedere un tempo molto lungo."
#, fuzzy
msgid "More infos in the official doc:"
msgstr "Maggiori info nella documentazione ufficiale"
msgid "import from Pocket"
msgstr "Importa da Pocket"
msgid "import from Readability"
msgstr "Importa da Readability"
msgid "import from Instapaper"
msgstr "Importa da Instapaper"
msgid "Tags"
msgstr ""
#, fuzzy
msgid "Untitled"
msgstr "per titolo"
msgid "the link has been added successfully"
msgstr ""
msgid "error during insertion : the link wasn't added"
msgstr ""
msgid "the link has been deleted successfully"
msgstr ""
msgid "the link wasn't deleted"
msgstr ""
msgid "Article not found!"
msgstr ""
msgid "previous"
msgstr ""
msgid "next"
msgstr ""
msgid "in demo mode, you can't update your password"
msgstr ""
msgid "your password has been updated"
msgstr ""
msgid "the two fields have to be filled & the password must be the same in the two fields"
msgstr ""
msgid "still using the \""
msgstr ""
msgid "that theme does not seem to be installed"
msgstr ""
msgid "you have changed your theme preferences"
msgstr ""
msgid "that language does not seem to be installed"
msgstr ""
msgid "you have changed your language preferences"
msgstr ""
msgid "login failed: you have to fill all fields"
msgstr ""
msgid "welcome to your wallabag"
msgstr ""
msgid "login failed: bad login or password"
msgstr ""
#, fuzzy
msgid "import from instapaper completed"
msgstr "Importa da Instapaper"
#, fuzzy
msgid "import from pocket completed"
msgstr "Importa da Pocket"
#, fuzzy
msgid "import from Readability completed. "
msgstr "Importa da Readability"
#, fuzzy
msgid "import from Poche completed. "
msgstr "Importa da Pocket"
msgid "Unknown import provider."
msgstr ""
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr ""
msgid "Could not find required \""
msgstr ""
msgid "Uh, there is a problem while generating feeds."
msgstr ""
#, fuzzy
msgid "Cache deleted."
msgstr "elimina"
msgid "Oops, it seems you don't have PHP 5."
msgstr ""
#~ msgid "poche it!"
#~ msgstr "pochalo!"
#~ msgid "Updating poche"
#~ msgstr "Aggiornamento poche"
#~ msgid "create an issue"
#~ msgstr "crea una segnalazione"
#~ msgid "or"
#~ msgstr "oppure"
#~ msgid "contact us by mail"
#~ msgstr "contattaci via email"
#~ msgid "your poche version:"
#~ msgstr "la tua versione di poche:"

View File

@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: wballabag\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-07 17:38+0300\n"
"PO-Revision-Date: 2014-02-07 17:43+0300\n"
"POT-Creation-Date: 2014-02-24 15:19+0300\n"
"PO-Revision-Date: 2014-02-24 15:29+0300\n"
"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
"Language-Team: \n"
"Language: \n"
@ -15,7 +15,7 @@ msgstr ""
"X-Poedit-Language: Polish\n"
"X-Poedit-Country: POLAND\n"
"X-Poedit-SourceCharset: utf-8\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
msgid "poche, a read it later open source system"
msgstr "poche, serwis odrocznego czytania open source"
@ -23,114 +23,15 @@ msgstr "poche, serwis odrocznego czytania open source"
msgid "login failed: user doesn't exist"
msgstr "logowanie nie udało się: użytkownik nie istnieje"
msgid "Return home"
msgstr "Wrocic do głównej"
msgid "home"
msgstr "strona domowa"
msgid "Back to top"
msgstr "Wrócić na górę"
msgid "original"
msgstr "oryginal"
msgid "Mark as read"
msgstr "Zaznacz jako przeczytane"
msgid "Toggle mark as read"
msgstr "Przełącz jako przeczytane"
msgid "Favorite"
msgstr "Ulubiony"
msgid "Toggle favorite"
msgstr "Zaznacz jako ulubione"
msgid "Delete"
msgstr "Usuń"
msgid "Tweet"
msgstr "Tweet"
msgid "Email"
msgstr "Wyslij email"
msgid "shaarli"
msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
msgid "Does this article appear wrong?"
msgstr "Czy ten artykuł wygląda nieprawidłowo?"
msgid "tags:"
msgstr "tegi:"
msgid "Edit tags"
msgstr "Redagowac tegi"
msgid "return home"
msgstr "wrócić do głównej"
msgid "powered by"
msgstr "zasilany przez"
msgid "debug mode is on so cache is off."
msgstr "tryb debugowania jest włączony, więc cash jest wyłączony."
msgid "your poche version:"
msgstr "twoja wersja poche:"
msgid "storage:"
msgstr "magazyn:"
msgid "favoris"
msgid "favorites"
msgstr "ulubione"
msgid "archive"
msgstr "archiwum"
msgid "unread"
msgstr "nieprzeczytane"
msgid "by date asc"
msgstr "według daty rosnąco"
msgid "by date"
msgstr "wg daty"
msgid "by date desc"
msgstr "według daty spadająco"
msgid "by title asc"
msgstr "według tytułu rosnąco"
msgid "by title"
msgstr "wg tytułu"
msgid "by title desc"
msgstr "według tytułu malejąco"
msgid "No articles found."
msgstr "Nie znaleziono artykułów."
msgid "toggle favorite"
msgstr "przełączyc ulubione"
msgid "delete"
msgstr "usunąć"
msgid "estimated reading time:"
msgstr "szacowany czas odczytu:"
msgid "results"
msgstr "wyniki"
msgid "home"
msgstr "główna"
msgid "favorites"
msgstr "ulubione"
msgid "tags"
msgstr "tagi"
@ -140,89 +41,64 @@ msgstr "ustawienia"
msgid "logout"
msgstr "wyloguj"
msgid "Poching links"
msgid "back to home"
msgstr "wróć do strony domowej"
msgid "Tags"
msgstr "Tagi"
#, fuzzy
msgid "Poching a link"
msgstr "Zapisywanie linków"
msgid "There are several ways to poche a link:"
msgid "You can poche a link by several methods:"
msgstr "Istnieje kilka sposobów aby zapisać link:"
msgid "read the documentation"
msgstr "zapoznać się z dokumentacją"
msgstr "przeczytaj dokumentację"
msgid "download the extension"
msgstr "pobrać rozszerzenie"
msgid "via F-Droid"
msgstr "przez F-Droid"
msgid " or "
msgstr "albo"
msgid "via Google Play"
msgstr "przez Google Play"
msgstr "pobierz rozszerzenie"
msgid "download the application"
msgstr "pobrać aplikację"
msgstr "pobierz aplikację"
msgid "By filling this field"
#, fuzzy
msgid "by filling this field"
msgstr "Poprzez wypełnienie tego pola"
msgid "poche it!"
msgstr "zapis!"
msgstr "zapisz!"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
#, fuzzy
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "Bookmarklet: przeciągnij i upucs ten link na pasek zakladek"
msgid "Updating poche"
msgstr "Aktualizacja poche"
msgid "Installed version"
msgstr "Zainstalowana wersja "
msgid "your version"
msgstr "twoja wersja"
msgid "Latest stable version"
#, fuzzy
msgid "latest stable version"
msgstr "Najnowsza stabilna wersja"
msgid "A more recent stable version is available."
#, fuzzy
msgid "a more recent stable version is available."
msgstr "Nowsza stabilna wersja jest dostępna."
msgid "You are up to date."
msgstr "Masz wszystko najnowsze."
msgid "you are up to date."
msgstr "brak nowych aktualizacji."
msgid "latest dev version"
msgstr "najnowsza wersja dev"
msgstr "najnowsza wersja rozwojowa"
msgid "a more recent development version is available."
msgstr "Nowsza wersja rozwojowa jest dostępna."
msgid "you are up to date."
msgstr "masz wszystko najnowsze."
msgid "Feeds"
msgstr "Kanały (feeds)"
msgid "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>."
msgstr "Twój znak kanału jest pusty i musi najpierw zostac wygenerowany. Kliknij <a href='?feed&action=generate'>tu dla jego generacji</a>."
msgid "Unread feed"
msgstr "Kanał nieprzeczytanego"
msgid "Favorites feed"
msgstr "Kanał ulubionego"
msgid "Archive feed"
msgstr "Kanał archiwum"
msgid "Your token:"
msgstr "Twój znak (token): "
msgid "Your user id:"
msgstr "Twój id użytkownika (user id):"
msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgstr "Mozna zgenerowac nowy znak: kliknij <a href='?feed&amp;action=generate'>zgenerowac!</a>."
msgid "Change your theme"
msgstr "Zmienic motyw"
msgstr "Zmień motyw"
msgid "Theme:"
msgstr "Motyw:"
@ -230,12 +106,6 @@ msgstr "Motyw:"
msgid "Update"
msgstr "Aktualizacja"
msgid "Change your language"
msgstr "Zmienić język"
msgid "Language:"
msgstr "Język:"
msgid "Change your password"
msgstr "Zmień hasło"
@ -251,69 +121,47 @@ msgstr "Powtórz hasło jeszcze raz:"
msgid "Import"
msgstr "Import"
msgid "Please execute the import script locally as it can take a very long time."
msgstr "Proszę wykonać skrypt import lokalnie, gdyż moze to trwać bardzo długo."
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Proszę wykonać skrypt importu lokalnie, ponieważ moze to trwać bardzo długo."
msgid "More info in the official docs:"
msgstr "Więcej informacji w oficjalnej dokumentacji:"
msgid "More infos in the official doc:"
msgstr "Więcej informacji znajduje się w oficjalnej dokumentacji:"
msgid "Import from Pocket"
msgstr "Іmport z Pocket'a"
msgid "import from Pocket"
msgstr "Importuj z Pocket'a"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr "(musisz mieć plik %s na serwerze)"
msgid "Import from Readability"
msgstr "Import z Readability"
msgid "import from Readability"
msgstr "Importuj z Readability"
msgid "Import from Instapaper"
msgstr "Import z Instapaper"
msgid "import from Instapaper"
msgstr "Importuj z Instapaper"
msgid "Import from poche"
msgstr "Import z poche"
msgid "Export your poche data"
msgstr "Eksportowac dane poche"
#, fuzzy
msgid "Export your poche datas"
msgstr "Exportuj dane poche"
msgid "Click here"
msgstr "Kliknij tu"
msgid "to download your database."
msgstr "aby pobrac bazę danych."
msgid "to export your poche data."
msgstr "aby eksportować dane poche."
msgid "Tag"
msgstr "Teg"
msgid "No link available here!"
msgstr "Brak dostępnych linków!"
msgid "toggle mark as read"
msgstr "przełączyć znak jako przeczytane"
msgid "You can enter multiple tags, separated by commas."
msgstr "Mozna wprowadzić wiele tagów rozdzielajac je przecinkami."
msgid "return to article"
msgstr "wrócić do artykułu"
#, fuzzy
msgid "to export your poche datas."
msgstr "aby wyeksportować dane poche."
msgid "plop"
msgstr "plop"
msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgstr "Można <a href='wallabag_compatibility_test.php'>sprawdzić swoją konfigurację tu</a>."
msgid "installation"
msgstr "instalacja"
msgid "install your wallabag"
msgstr "zainstalować wallabag"
msgstr "zainstaluj wallabag"
msgid "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>."
msgstr "wallabag nie jest jeszcze zainstalowany. Proszę wypełnić poniższy formularz, aby go zainstalowac. Nie wahaj się <a href='http://doc.wallabag.org/'>zapoznac się z dokumentacja na stronie wallabag</a>."
msgstr "wallabag nie jest jeszcze zainstalowany. Proszę wypełnić poniższy formularz, aby go zainstalować. Nie wahaj się <a href='http://doc.wallabag.org/'>zapoznać się z dokumentacją na stronie wallabag</a>."
msgid "Login"
msgstr "Login"
@ -322,34 +170,291 @@ msgid "Repeat your password"
msgstr "Powtórz hasło"
msgid "Install"
msgstr "Instalowac"
msgstr "Instaluj"
msgid "favoris"
msgstr "ulubione"
msgid "unread"
msgstr "nieprzeczytane"
msgid "by date asc"
msgstr "według daty rosnąco"
msgid "by date"
msgstr "wg daty"
msgid "by date desc"
msgstr "według daty malejąco"
msgid "by title asc"
msgstr "według tytułu rosnąco"
msgid "by title"
msgstr "wg tytułu"
msgid "by title desc"
msgstr "według tytułu malejąco"
msgid "No link available here!"
msgstr "Brak dostępnych linków!"
msgid "toggle mark as read"
msgstr "przełącz jako przeczytane"
msgid "toggle favorite"
msgstr "przełącz ulubione"
msgid "delete"
msgstr "usuń"
msgid "original"
msgstr "oryginał"
msgid "estimated reading time:"
msgstr "szacowany czas odczytu:"
msgid "results"
msgstr "wyniki"
msgid "login to your wallabag"
msgstr "zalogować się do swojego wallabag"
msgid "Login to wallabag"
msgstr "Zalogować się do wallabag"
msgstr "zaloguj się do swojego wallabag"
msgid "you are in demo mode, some features may be disabled."
msgstr "jesteś w trybie demo, niektóre funkcje mogą być niedostępne."
msgid "Username"
msgstr "Imię użytkownika"
msgstr "jesteś w trybie demo, niektóre funkcje mogą być wyłączone."
msgid "Stay signed in"
msgstr "Pozostań zalogowany"
msgid "(Do not check on public computers)"
msgstr "(Nie sprawdzaj na publicznych komputerach"
msgstr "(Nie sprawdzaj na publicznych komputerach)"
msgid "Saving articles"
msgstr "Zapisywanie artykułów"
msgid "There are several ways to save an article:"
msgstr "Istnieje kilka sposobów aby zapisać artykuł:"
msgid "via F-Droid"
msgstr "przez F-Droid"
msgid " or "
msgstr "albo"
msgid "via Google Play"
msgstr "przez Google Play"
msgid "By filling this field"
msgstr "Poprzez wypełnienie tego pola"
msgid "bag it!"
msgstr "zapisz!"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "Bookmarklet: przeciągnij i upuść ten link na pasek zakladek"
msgid "Upgrading wallabag"
msgstr "Aktualizacja wallabag"
msgid "Installed version"
msgstr "Zainstalowana wersja "
msgid "Latest stable version"
msgstr "Najnowsza stabilna wersja"
msgid "A more recent stable version is available."
msgstr "Nowsza stabilna wersja jest dostępna."
msgid "You are up to date."
msgstr "Brak nowych aktualizacji."
msgid "Latest dev version"
msgstr "Najnowsza wersja rozwojowa"
#, fuzzy
msgid "A more recent development version is available."
msgstr "Nowsza wersja rozwojowa jest dostępna."
msgid "Feeds"
msgstr "Kanały (feeds)"
msgid "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>."
msgstr "Twój token kanału jest pusty i musi najpierw zostać wygenerowany. Kliknij <a href='?feed&action=generate'>tu aby go wygenerować</a>."
msgid "Unread feed"
msgstr "Kanał nieprzeczytanych"
msgid "Favorites feed"
msgstr "Kanał ulubionych"
msgid "Archive feed"
msgstr "Kanał archiwum"
msgid "Your token:"
msgstr "Twój token: "
msgid "Your user id:"
msgstr "Twój identyfikator użytkownika:"
msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgstr "Możesz wygenerować token ponownie: kliknij <a href='?feed&amp;action=generate'>generuj!</a>."
msgid "Change your language"
msgstr "Zmień język"
msgid "Language:"
msgstr "Język:"
msgid "Please execute the import script locally as it can take a very long time."
msgstr "Proszę wykonać skrypt importu lokalnie, gdyż moze to trwać bardzo długo."
#, fuzzy
msgid "More info in the official documentation:"
msgstr "Więcej informacji znajduje się w oficjalnej dokumentacji:"
msgid "Import from Pocket"
msgstr "Іmport z Pocket'a"
msgid "Import from Readability"
msgstr "Import z Readability"
msgid "Import from Instapaper"
msgstr "Import z Instapaper"
msgid "Import from wallabag"
msgstr "Import z wallabag"
msgid "Export your wallabag data"
msgstr "Eksportowac dane wallabag"
msgid "to download your database."
msgstr "aby pobrac bazę danych."
msgid "to export your wallabag data."
msgstr "aby eksportować dane wallabag."
msgid "Cache"
msgstr "Cache"
msgid "to delete cache."
msgstr "aby wyczyścić cache."
msgid "tweet"
msgstr "tweet"
#, fuzzy
msgid "email"
msgstr "Wyślij email"
msgid "shaarli"
msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
msgid "this article appears wrong?"
msgstr "Czy ten artykuł wyświetla się nieprawidłowo?"
msgid "You can enter multiple tags, separated by commas."
msgstr "Możesz wprowadzić wiele tagów, rozdzielając je przecinkami."
msgid "return to article"
msgstr "wróć do artykułu"
#, fuzzy
msgid "powered by"
msgstr "zasilany przez"
msgid "debug mode is on so cache is off."
msgstr "tryb debugowania jest włączony, więc cashe jest wyłączony."
msgid "your wallabag version:"
msgstr "twoja wersja wallabag:"
msgid "storage:"
msgstr "magazyn:"
msgid "save a link"
msgstr "zapisz link"
msgid "return home"
msgstr "wróć do strony domowej"
msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgstr "Możesz <a href='wallabag_compatibility_test.php'>sprawdzić swoją konfigurację tu</a>."
msgid "Tag"
msgstr "Tag"
msgid "No articles found."
msgstr "Nie znaleziono artykułów."
msgid "Toggle mark as read"
msgstr "Przełącz jako przeczytane"
msgid "mark all the entries as read"
msgstr "zaznacz wszystko jako przeczytane"
msgid "Login to wallabag"
msgstr "Zaloguj się do wallabag"
msgid "Username"
msgstr "Nazwa użytkownika"
msgid "Sign in"
msgstr "Login"
msgid "Return home"
msgstr "Wróć do strony domowej"
msgid "Back to top"
msgstr "Wróć na górę"
msgid "Mark as read"
msgstr "Zaznacz jako przeczytane"
msgid "Favorite"
msgstr "Ulubione"
msgid "Toggle favorite"
msgstr "Zaznacz jako ulubione"
msgid "Delete"
msgstr "Usuń"
msgid "Tweet"
msgstr "Tweet"
msgid "Email"
msgstr "Wyślij email"
msgid "Does this article appear wrong?"
msgstr "Czy ten artykuł wyświetla się nieprawidłowo?"
msgid "tags:"
msgstr "tegi:"
msgid "Edit tags"
msgstr "Edytuj tagi"
msgid "save link!"
msgstr "zapisz link!"
#, fuzzy
msgid "estimated reading time :"
msgstr "szacowany czas odczytu:"
msgid "Mark all the entries as read"
msgstr "Oznacz wszystko jako przeczytane"
msgid "Untitled"
msgstr "Bez nazwy"
msgid "the link has been added successfully"
msgstr "link pozostał pomyślnie dodany"
msgstr "link został pomyślnie dodany"
msgid "error during insertion : the link wasn't added"
msgstr "błąd podczas wprowadzania: link nie zostal dodany"
msgstr "błąd podczas wprowadzania: link nie został dodany"
msgid "the link has been deleted successfully"
msgstr "link zostal pomyślnie usunięty"
@ -357,6 +462,9 @@ msgstr "link zostal pomyślnie usunięty"
msgid "the link wasn't deleted"
msgstr "link nie został usunięty"
msgid "Article not found!"
msgstr "Nie znaleziono artykułu."
msgid "previous"
msgstr "poprzednia"
@ -367,7 +475,7 @@ msgid "in demo mode, you can't update your password"
msgstr "w trybie demo, nie można zmieniać hasła"
msgid "your password has been updated"
msgstr "twoje hasło zmienione"
msgstr "twoje hasło zostało zmienione"
msgid "the two fields have to be filled & the password must be the same in the two fields"
msgstr "oba pola muszą być wypełnione i hasła muszę być takie same w obu polach"
@ -376,31 +484,28 @@ msgid "still using the \""
msgstr "nadal w użyciu \""
msgid "that theme does not seem to be installed"
msgstr "wydaje się że motyw nie był zainstalowany"
msgstr "wydaje się że ten motyw nie jest zainstalowany"
msgid "you have changed your theme preferences"
msgstr "ustawienia motywu zostałe zmienione"
msgstr "ustawienia motywu zostały zmienione"
msgid "that language does not seem to be installed"
msgstr "wydaje się że język nie był zainstalowany"
msgstr "wydaje się że ten język nie jest zainstalowany"
msgid "you have changed your language preferences"
msgstr "ustawienia języka zostałe zmienione"
msgstr "ustawienia języka zostały zmienione"
msgid "login failed: you have to fill all fields"
msgstr "logowanie nie powiodlo się: musisz wypełnić wszystkie pola"
msgid "welcome to your poche"
msgstr "witamy w poche"
msgid "welcome to your wallabag"
msgstr "Witamy w wallabag"
msgid "login failed: bad login or password"
msgstr "logowanie nie powiodlo się: zly login lub hasło"
msgid "see you soon!"
msgstr "do zobaczenia wkrótce!"
msgstr "logowanie nie powiodlo się: niepoprawny login lub hasło"
msgid "import from instapaper completed"
msgstr "import з instapaper'a zakończony"
msgstr "import z instapaper'a zakończony"
msgid "import from pocket completed"
msgstr "import z pocket'a zakończony"
@ -415,14 +520,25 @@ msgid "Unknown import provider."
msgstr "Nieznany dostawca importu."
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr "Niekompletny plik inc/poche/define.inc.php, proszę definiować \""
msgstr "Niekompletny plik inc/poche/define.inc.php, proszę zdefiniować \""
msgid "Could not find required \""
msgstr "Nie znaleziono potrzebnego \""
msgid "Uh, there is a problem while generating feeds."
msgstr "Uh, jest problem podczas generowania kanałów (feeds)."
msgstr "Uh, jest problem podczas generowania kanałów."
msgid "Cache deleted."
msgstr "Cache wyczyszczony."
msgid "Oops, it seems you don't have PHP 5."
msgstr "Oops, wygląda ze u was niema PHP 5."
msgstr "Oops, wygląda ze nie masz PHP 5."
#~ msgid "Import from poche"
#~ msgstr "Import z poche"
#~ msgid "welcome to your poche"
#~ msgstr "witamy w poche"
#~ msgid "see you soon!"
#~ msgstr "do zobaczenia wkrótce!"

Binary file not shown.

View File

@ -0,0 +1,549 @@
msgid ""
msgstr ""
"Project-Id-Version: wallabag\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-25 15:17+0300\n"
"PO-Revision-Date: \n"
"Last-Translator: @iancamporez <ian@camporez.com>\n"
"Language-Team: @iancamporez <ian@camporez.com>\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.6.4\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: /home/ian/Projetos/wallabag/locale/en_EN.utf8/"
"LC_MESSAGES\n"
msgid "wallabag, a read it later open source system"
msgstr "wallabag, um \"read it later\" de código aberto"
msgid "login failed: user doesn't exist"
msgstr "falha ao entrar: o usuário não existe"
msgid "return home"
msgstr "retornar à página inicial"
msgid "config"
msgstr "configurar"
msgid "Saving articles"
msgstr "Salvando artigos"
msgid "There are several ways to save an article:"
msgstr "Existem várias maneiras de salvar um artigo:"
msgid "read the documentation"
msgstr "ler a documentação"
msgid "download the extension"
msgstr "baixar a extensão"
msgid "via F-Droid"
msgstr "via F-Droid"
msgid " or "
msgstr "ou "
msgid "via Google Play"
msgstr "via Google Play"
msgid "download the application"
msgstr "baixar o aplicativo"
msgid "By filling this field"
msgstr "Preenchendo esse campo"
msgid "bag it!"
msgstr "adicionar ao wallabag"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "Bookmarklet: arraste esse link para sua barra de favoritos"
msgid "Upgrading wallabag"
msgstr "Atualizando o wallabag"
msgid "Installed version"
msgstr "Versão instalada"
msgid "Latest stable version"
msgstr "Última versão estável"
msgid "A more recent stable version is available."
msgstr "Uma versão estável mais nova está disponível"
msgid "You are up to date."
msgstr "Você está atualizado."
msgid "Latest dev version"
msgstr "Última versão em desenvolvimento"
msgid "A more recent development version is available."
msgstr "Uma versão em desenvolvimento mais recente está disponível"
msgid "Feeds"
msgstr "Feeds"
msgid ""
"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>."
msgstr ""
"Seu token do feed e precisa ser gerado para ativar os feeds. Clique <a "
"href='?feed&amp;action=generate'>aqui para gerar um token</a>."
msgid "Unread feed"
msgstr "Feed de artigos não lidos"
msgid "Favorites feed"
msgstr "Feed dos favoritos"
msgid "Archive feed"
msgstr "Feed de arquivados"
msgid "Your token:"
msgstr "Seu token:"
msgid "Your user id:"
msgstr "Seu código de usuário:"
msgid ""
"You can regenerate your token: <a href='?feed&amp;action=generate'>generate!"
"</a>."
msgstr ""
"Você pode regerar seu token: <a href='?feed&amp;action=generate'>gerar!</a>."
msgid "Change your theme"
msgstr "Mudar seu tema"
msgid "Theme:"
msgstr "Tema:"
msgid "Update"
msgstr "Atualizar"
msgid "Change your language"
msgstr "Alterar seu idioma"
msgid "Language:"
msgstr "Idioma:"
msgid "Change your password"
msgstr "Alterar sua senha"
msgid "New password:"
msgstr "Nova senha:"
msgid "Password"
msgstr "Senha"
msgid "Repeat your new password:"
msgstr "Repetir sua nova senha:"
msgid "Import"
msgstr "Importar"
msgid ""
"Please execute the import script locally as it can take a very long time."
msgstr ""
"Por favor, execute o script de importação localmente, pois pode demorar "
"muito tempo."
msgid "More info in the official documentation:"
msgstr "Mais informações na documentação oficial:"
msgid "Import from Pocket"
msgstr "Importar do Pocket"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr "(você deve ter um arquivo %s no seu servidor)"
msgid "Import from Readability"
msgstr "Importar do Readability"
msgid "Import from Instapaper"
msgstr "Importar do Instapaper"
msgid "Import from wallabag"
msgstr "Importar do wallabag"
msgid "Export your wallabag data"
msgstr "Exportar seus dados do wallabag"
msgid "Click here"
msgstr "Clique aqui"
msgid "to download your database."
msgstr "para baixar seu banco de dados."
msgid "to export your wallabag data."
msgstr "para exportar seus dados do wallabag."
msgid "Cache"
msgstr "Cache"
msgid "to delete cache."
msgstr "para apagar o cache."
msgid "You can enter multiple tags, separated by commas."
msgstr "Você pode inserir várias tags, separadas por vírgulas."
msgid "return to article"
msgstr "retornar ao artigo"
msgid "plop"
msgstr "plop"
msgid ""
"You can <a href='wallabag_compatibility_test.php'>check your configuration "
"here</a>."
msgstr ""
"Você pode <a href='wallabag_compatibility_test.php'>checar suas "
"configurações aqui</a>."
msgid "favoris"
msgstr "favoritos"
msgid "archive"
msgstr "arquivo"
msgid "unread"
msgstr "não lidos"
msgid "by date asc"
msgstr "por data (cresc.)"
msgid "by date"
msgstr "por data"
msgid "by date desc"
msgstr "por data (decr.)"
msgid "by title asc"
msgstr "por título (cresc.)"
msgid "by title"
msgstr "por título"
msgid "by title desc"
msgstr "por título (decr.)"
msgid "Tag"
msgstr "Tag"
msgid "No articles found."
msgstr "Nenhum artigo encontrado."
msgid "Toggle mark as read"
msgstr "Alterar \"marcar como lido\""
msgid "toggle favorite"
msgstr "alterar \"favorito\""
msgid "delete"
msgstr "deletar"
msgid "original"
msgstr "original"
msgid "estimated reading time:"
msgstr "tempo estimado de leitura:"
msgid "mark all the entries as read"
msgstr "marcar todas as entradas como lidas"
msgid "results"
msgstr "resultados"
msgid "installation"
msgstr "instalação"
msgid "install your wallabag"
msgstr "instalar seu wallabag"
msgid ""
"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>."
msgstr ""
"O wallabag ainda não está instalado. Preencha o formulário abaixo para "
"instalá-lo. Não hesite em <a href='http://doc.wallabag.org/'>ler a "
"documentação no site do wallabag</a>."
msgid "Login"
msgstr "Login"
msgid "Repeat your password"
msgstr "Repetir sua senha"
msgid "Install"
msgstr "Instalar"
msgid "login to your wallabag"
msgstr "entrar no seu wallabag"
msgid "Login to wallabag"
msgstr "Entrar no wallabag"
msgid "you are in demo mode, some features may be disabled."
msgstr "você está no modo demo, alguns recursos podem estar desativados."
msgid "Username"
msgstr "Nome de usuário"
msgid "Stay signed in"
msgstr "Continuar conectado"
msgid "(Do not check on public computers)"
msgstr "(Não marque em computadores públicos)"
msgid "Sign in"
msgstr "Entrar"
msgid "favorites"
msgstr "favoritos"
msgid "estimated reading time :"
msgstr "tempo estimado de leitura :"
msgid "Mark all the entries as read"
msgstr "Marcar todas as entradas como lidas"
msgid "Return home"
msgstr "Retornar à página inicial"
msgid "Back to top"
msgstr "Voltar ao topo"
msgid "Mark as read"
msgstr "Marcar como lido"
msgid "Favorite"
msgstr "Favoritar"
msgid "Toggle favorite"
msgstr "Alterar \"favorito\""
msgid "Delete"
msgstr "Deletar"
msgid "Tweet"
msgstr "Tweetar"
msgid "Email"
msgstr "Email"
msgid "shaarli"
msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
msgid "Does this article appear wrong?"
msgstr "Esse artigo está sendo exibido incorretamente?"
msgid "tags:"
msgstr "tags:"
msgid "Edit tags"
msgstr "Editar tags"
msgid "save link!"
msgstr "salvar link!"
msgid "home"
msgstr "início"
msgid "tags"
msgstr "tags"
msgid "logout"
msgstr "sair"
msgid "powered by"
msgstr "powered by"
msgid "debug mode is on so cache is off."
msgstr "o modo debug está ativo, então o cache foi desativado."
msgid "your wallabag version:"
msgstr "sua versão do wallabag:"
msgid "storage:"
msgstr "armazenamento:"
msgid "save a link"
msgstr "salvar link"
msgid "back to home"
msgstr "voltar à página inicial"
msgid "toggle mark as read"
msgstr "alterar \"marcar como lido\""
msgid "tweet"
msgstr "tweetar"
msgid "email"
msgstr "email"
msgid "this article appears wrong?"
msgstr "esse artigo está sendo mostrado incorretamente?"
msgid "No link available here!"
msgstr "Nenhum link disponível aqui!"
msgid "Poching a link"
msgstr "Pocheando um link"
msgid "by filling this field"
msgstr "preenchendo esse campo"
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "bookmarklet: arraste esse link para a sua barra de favoritos"
msgid "your version"
msgstr "sua versão"
msgid "latest stable version"
msgstr "última versão estável"
msgid "a more recent stable version is available."
msgstr "uma versão estável mais nova está disponível"
msgid "you are up to date."
msgstr "você está atualizado."
msgid "latest dev version"
msgstr "última versão em desenvolvimento"
msgid "a more recent development version is available."
msgstr "uma versão em desenvolvimento mais nova está disponível"
msgid "Please execute the import script locally, it can take a very long time."
msgstr ""
"Por favor, execute o script de importação localmente, pois pode demorar "
"muito tempo."
msgid "More infos in the official doc:"
msgstr "Mais informações na documentação oficial:"
msgid "import from Pocket"
msgstr "importar do Pocket"
msgid "import from Readability"
msgstr "importar do Readability"
msgid "import from Instapaper"
msgstr "importar do Instapaper"
msgid "Tags"
msgstr "Tags"
msgid "Untitled"
msgstr "Sem título"
msgid "the link has been added successfully"
msgstr "o link foi adicionado com sucesso"
msgid "error during insertion : the link wasn't added"
msgstr "erro durante a inserção: o link não foi adicionado"
msgid "the link has been deleted successfully"
msgstr "o link foi deletado com sucesso"
msgid "the link wasn't deleted"
msgstr "o link não foi deletado"
msgid "Article not found!"
msgstr "Artigo não encontrado!"
msgid "previous"
msgstr "anterior"
msgid "next"
msgstr "próximo"
msgid "in demo mode, you can't update your password"
msgstr "você não pode alterar a senha no modo demo"
msgid "your password has been updated"
msgstr "sua senha foi atualizada"
msgid ""
"the two fields have to be filled & the password must be the same in the two "
"fields"
msgstr ""
"os dois campos devem estar preenchidos e as senhas devem ser iguais em ambos"
msgid "still using the \""
msgstr "ainda usando o \""
msgid "that theme does not seem to be installed"
msgstr "esse tema aparentemente não está instalado"
msgid "you have changed your theme preferences"
msgstr "você alterou suas preferências de tema"
msgid "that language does not seem to be installed"
msgstr "esse idioma aparentemente não está instalado"
msgid "you have changed your language preferences"
msgstr "você alterou suas preferências de idioma"
msgid "login failed: you have to fill all fields"
msgstr "falha ao entrar: você deve preencher todos os campos"
msgid "welcome to your wallabag"
msgstr "bem-vindo ao seu wallabag"
msgid "login failed: bad login or password"
msgstr "falha ao entrar: login ou senha incorretos"
msgid "import from instapaper completed"
msgstr "importação do instapaper completa"
msgid "import from pocket completed"
msgstr "importação do pocket completa"
msgid "import from Readability completed. "
msgstr "importação do Readability completa. "
msgid "import from Poche completed. "
msgstr "importação do Poche completa. "
msgid "Unknown import provider."
msgstr "Serviço de importação desconhecido."
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr "Arquivo inc/poche/define.inc.php incompleto, por favor defina \""
msgid "Could not find required \""
msgstr "Não foi possível encontrar o requerido \""
msgid "Uh, there is a problem while generating feeds."
msgstr "Uh, houve um problema ao gerar os feeds."
msgid "Cache deleted."
msgstr "Cache deletado."
msgid "Oops, it seems you don't have PHP 5."
msgstr "Oops, parece que você não tem o PHP 5."
#~ msgid "poche it!"
#~ msgstr "poche it!"
#~ msgid "Updating poche"
#~ msgstr "Updating poche"
#~ msgid "create an issue"
#~ msgstr "create an issue"
#~ msgid "or"
#~ msgstr "or"
#~ msgid "contact us by mail"
#~ msgstr "contact us by mail"
#~ msgid "your poche version:"
#~ msgstr "your poche version:"

View File

@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-07 12:40+0300\n"
"POT-Creation-Date: 2014-02-25 15:09+0300\n"
"PO-Revision-Date: \n"
"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
"Language-Team: \n"
@ -14,135 +14,25 @@ msgstr ""
"X-Poedit-Language: Russian\n"
"X-Poedit-Country: RUSSIA\n"
"X-Poedit-SourceCharset: utf-8\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
msgid "poche, a read it later open source system"
msgstr "poche, сервис отложенного чтения с открытым исходным кодом"
msgid "wallabag, a read it later open source system"
msgstr "wallabag, сервис отложенного чтения с открытым исходным кодом"
msgid "login failed: user doesn't exist"
msgstr "войти не удалось: пользователь не существует"
msgid "Return home"
msgstr "На главную"
msgid "Back to top"
msgstr "Наверх"
msgid "original"
msgstr "источник"
msgid "Mark as read"
msgstr "Отметить как прочитанное"
msgid "Toggle mark as read"
msgstr "Изменить отметку 'прочитано'"
msgid "Favorite"
msgstr "Избранное"
msgid "Toggle favorite"
msgstr "Изменить метку избранного"
msgid "Delete"
msgstr "Удалить"
msgid "Tweet"
msgstr "Твитнуть"
msgid "Email"
msgstr "Отправить по почте"
msgid "shaarli"
msgstr "shaarli"
msgid "flattr"
msgstr "проспонсировать"
msgid "Does this article appear wrong?"
msgstr "Статья выглядит криво?"
msgid "tags:"
msgstr "теги:"
msgid "Edit tags"
msgstr "Редактировать теги"
msgid "return home"
msgstr "на главную"
msgid "powered by"
msgstr "при поддержке"
msgid "debug mode is on so cache is off."
msgstr "включён режим отладки - кеш выключен."
msgid "your poche version:"
msgstr "ваша версия poche:"
msgid "storage:"
msgstr "хранилище:"
msgid "favoris"
msgstr "избранное"
msgid "archive"
msgstr "архив"
msgid "unread"
msgstr "непрочитанное"
msgid "by date asc"
msgstr "по дате, сперва старые"
msgid "by date"
msgstr "по дате"
msgid "by date desc"
msgstr "по дате, сперва новые"
msgid "by title asc"
msgstr "по заголовку (прямой)"
msgid "by title"
msgstr "по заголовку"
msgid "by title desc"
msgstr "по заголовку (обратный)"
msgid "No articles found."
msgstr "Статей не найдено."
msgid "toggle favorite"
msgstr "изменить метку избранного"
msgid "delete"
msgstr "удалить"
msgid "estimated reading time:"
msgstr "ориентировочное время чтения:"
msgid "results"
msgstr "найдено"
msgid "home"
msgstr "главная"
msgid "favorites"
msgstr "избранное"
msgid "tags"
msgstr "теги"
msgid "config"
msgstr "настройки"
msgid "logout"
msgstr "выход"
msgid "Saving articles"
msgstr "Сохранение статей"
msgid "Poching links"
msgstr "Сохранение ссылок"
msgid "There are several ways to poche a link:"
#, fuzzy
msgid "There are several ways to save an article:"
msgstr "Существует несколько способов сохранить ссылку:"
msgid "read the documentation"
@ -166,14 +56,14 @@ msgstr "скачать приложение"
msgid "By filling this field"
msgstr "Заполнением этого поля"
msgid "poche it!"
msgid "bag it!"
msgstr "прикарманить!"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "Закладка: перетащите и опустите ссылку на панель закладок"
msgid "Updating poche"
msgstr "Обновления poche"
msgid "Upgrading wallabag"
msgstr "Обновление wallabag"
msgid "Installed version"
msgstr "Установленная версия"
@ -187,15 +77,14 @@ msgstr "Доступна новая стабильная версия."
msgid "You are up to date."
msgstr "У вас всё самое новое."
msgid "latest dev version"
#, fuzzy
msgid "Latest dev version"
msgstr "последняя версия в разработке"
msgid "a more recent development version is available."
#, fuzzy
msgid "A more recent development version is available."
msgstr "есть более свежая версия в разработке."
msgid "you are up to date."
msgstr "у вас всё самое новое."
msgid "Feeds"
msgstr "Ленты (feeds)"
@ -253,7 +142,8 @@ msgstr "Импортировать"
msgid "Please execute the import script locally as it can take a very long time."
msgstr "Пожалуйста, выполните сценарий импорта локально - это может занять слишком много времени."
msgid "More info in the official docs:"
#, fuzzy
msgid "More info in the official documentation:"
msgstr "Больше сведений в официальной документации:"
msgid "Import from Pocket"
@ -269,11 +159,11 @@ msgstr "Импортировать из Readability"
msgid "Import from Instapaper"
msgstr "Импортировать из Instapaper"
msgid "Import from poche"
msgstr "Импортировать из poche"
msgid "Import from wallabag"
msgstr "Импортировать из wallabag"
msgid "Export your poche data"
msgstr "Экспортировать данные poche"
msgid "Export your wallabag data"
msgstr "Экспортировать данные wallabag"
msgid "Click here"
msgstr "Кликните здесь"
@ -281,17 +171,14 @@ msgstr "Кликните здесь"
msgid "to download your database."
msgstr "чтобы скачать вашу базу данных"
msgid "to export your poche data."
msgstr "чтобы экспортировать свои записи из poche."
msgid "to export your wallabag data."
msgstr "чтобы экспортировать свои записи из wallabag."
msgid "Tag"
msgstr "Тег"
msgid "Cache"
msgstr "Кэш"
msgid "No link available here!"
msgstr "Здесь нет ссылки!"
msgid "toggle mark as read"
msgstr "изменить отметку 'прочитано'"
msgid "to delete cache."
msgstr "чтобы сбросить кэш."
msgid "You can enter multiple tags, separated by commas."
msgstr "Вы можете ввести несколько тегов, разделяя их запятой."
@ -305,6 +192,60 @@ msgstr "plop"
msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgstr "Вы можете <a href='wallabag_compatibility_test.php'>проверить конфигурацию здесь</a>."
msgid "favoris"
msgstr "избранное"
msgid "archive"
msgstr "архив"
msgid "unread"
msgstr "непрочитанное"
msgid "by date asc"
msgstr "по дате, сперва старые"
msgid "by date"
msgstr "по дате"
msgid "by date desc"
msgstr "по дате, сперва новые"
msgid "by title asc"
msgstr "по заголовку (прямой)"
msgid "by title"
msgstr "по заголовку"
msgid "by title desc"
msgstr "по заголовку (обратный)"
msgid "Tag"
msgstr "Тег"
msgid "No articles found."
msgstr "Статей не найдено."
msgid "Toggle mark as read"
msgstr "Изменить отметку 'прочитано'"
msgid "toggle favorite"
msgstr "изменить метку избранного"
msgid "delete"
msgstr "удалить"
msgid "original"
msgstr "источник"
msgid "estimated reading time:"
msgstr "ориентировочное время чтения:"
msgid "mark all the entries as read"
msgstr "отметить все статьи как прочитанные "
msgid "results"
msgstr "найдено"
msgid "installation"
msgstr "установка"
@ -341,6 +282,159 @@ msgstr "Запомнить меня"
msgid "(Do not check on public computers)"
msgstr "(Не отмечайте на чужих компьютерах)"
msgid "Sign in"
msgstr "Зарегистрироваться"
msgid "favorites"
msgstr "избранное"
#, fuzzy
msgid "estimated reading time :"
msgstr "ориентировочное время чтения:"
msgid "Mark all the entries as read"
msgstr "Отметить все как прочитанное"
msgid "Return home"
msgstr "На главную"
msgid "Back to top"
msgstr "Наверх"
msgid "Mark as read"
msgstr "Отметить как прочитанное"
msgid "Favorite"
msgstr "Избранное"
msgid "Toggle favorite"
msgstr "Изменить метку избранного"
msgid "Delete"
msgstr "Удалить"
msgid "Tweet"
msgstr "Твитнуть"
msgid "Email"
msgstr "Отправить по почте"
msgid "shaarli"
msgstr "shaarli"
msgid "flattr"
msgstr "проспонсировать"
msgid "Does this article appear wrong?"
msgstr "Статья выглядит криво?"
msgid "tags:"
msgstr "теги:"
msgid "Edit tags"
msgstr "Редактировать теги"
msgid "save link!"
msgstr "сохранить ссылку!"
msgid "home"
msgstr "главная"
msgid "tags"
msgstr "теги"
msgid "logout"
msgstr "выход"
msgid "powered by"
msgstr "при поддержке"
msgid "debug mode is on so cache is off."
msgstr "включён режим отладки - кеш выключен."
msgid "your wallabag version:"
msgstr "Ваша версия wallabag:"
msgid "storage:"
msgstr "хранилище:"
msgid "save a link"
msgstr "сохранить ссылку"
msgid "back to home"
msgstr "домой"
msgid "toggle mark as read"
msgstr "изменить отметку 'прочитано'"
msgid "tweet"
msgstr "твитнуть"
msgid "email"
msgstr "email"
#, fuzzy
msgid "this article appears wrong?"
msgstr "Статья выглядит криво?"
msgid "No link available here!"
msgstr "Здесь нет ссылки!"
#, fuzzy
msgid "Poching a link"
msgstr "Сохранение ссылок"
#, fuzzy
msgid "by filling this field"
msgstr "Заполнением этого поля"
#, fuzzy
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "Закладка: перетащите и опустите ссылку на панель закладок"
msgid "your version"
msgstr "Ваша версия"
#, fuzzy
msgid "latest stable version"
msgstr "Последняя стабильная версия"
#, fuzzy
msgid "a more recent stable version is available."
msgstr "Доступна новая стабильная версия."
msgid "you are up to date."
msgstr "у вас всё самое новое."
msgid "latest dev version"
msgstr "последняя версия в разработке"
msgid "a more recent development version is available."
msgstr "есть более свежая версия в разработке."
#, fuzzy
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Пожалуйста, выполните сценарий импорта локально - это может занять слишком много времени."
#, fuzzy
msgid "More infos in the official doc:"
msgstr "Больше сведений в официальной документации:"
#, fuzzy
msgid "import from Pocket"
msgstr "Импортировать из Pocket"
#, fuzzy
msgid "import from Readability"
msgstr "Импортировать из Readability"
#, fuzzy
msgid "import from Instapaper"
msgstr "Импортировать из Instapaper"
msgid "Tags"
msgstr "Теги"
msgid "Untitled"
msgstr "Без названия"
@ -356,6 +450,9 @@ msgstr "ссылка успешно удалена"
msgid "the link wasn't deleted"
msgstr "ссылка не удалена"
msgid "Article not found!"
msgstr "Статью не найдено."
msgid "previous"
msgstr "предыдущая"
@ -389,15 +486,12 @@ msgstr "вы изменили свои настройки языка"
msgid "login failed: you have to fill all fields"
msgstr "войти не удалось: вы должны заполнить все поля"
msgid "welcome to your poche"
msgstr "добро пожаловать в ваш poche"
msgid "welcome to your wallabag"
msgstr "добро пожаловать в wallabag"
msgid "login failed: bad login or password"
msgstr "войти не удалось: неправильное имя пользователя или пароль"
msgid "see you soon!"
msgstr "увидимся!"
msgid "import from instapaper completed"
msgstr "импорт из instapaper завершен"
@ -422,14 +516,40 @@ msgstr "Не удалось найти требуемый \""
msgid "Uh, there is a problem while generating feeds."
msgstr "Ох, возникла проблема при создании ленты."
msgid "Cache deleted."
msgstr "Кэш очищен. "
msgid "Oops, it seems you don't have PHP 5."
msgstr "Упс, кажется у вас не установлен PHP 5."
#~ msgid "your version"
#~ msgstr "Ваша версия"
#~ msgid "You can poche a link by several methods:"
#~ msgstr "Вы можете сохранить ссылку несколькими путями:"
#~ msgid "back to home"
#~ msgstr "домой"
#~ msgid "poche it!"
#~ msgstr "прикарманить!"
#~ msgid "Updating poche"
#~ msgstr "Обновления poche"
#, fuzzy
#~ msgid "Export your poche datas"
#~ msgstr "Экспортировать данные poche"
#, fuzzy
#~ msgid "to export your poche datas."
#~ msgstr "чтобы экспортировать свои записи из poche."
#~ msgid "your poche version:"
#~ msgstr "ваша версия poche:"
#~ msgid "Import from poche"
#~ msgstr "Импортировать из poche"
#~ msgid "welcome to your poche"
#~ msgstr "добро пожаловать в ваш poche"
#~ msgid "see you soon!"
#~ msgstr "увидимся!"
#~ msgid "create an issue"
#~ msgstr "оповестить об ошибке"
@ -439,6 +559,3 @@ msgstr "Упс, кажется у вас не установлен PHP 5."
#~ msgid "contact us by mail"
#~ msgstr "связаться по почте"
#~ msgid "Sign in"
#~ msgstr "Зарегистрироваться"

View File

@ -4,55 +4,138 @@
msgid ""
msgstr ""
"Project-Id-Version: wallabag\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2014-02-21 15:09+0100\n"
"Last-Translator: Nicolas Lœuillet <nicolas.loeuillet@gmail.com>\n"
"Language-Team: Slovenian (Slovenia) (http://www.transifex.com/projects/p/"
"wallabag/language/sl_SI/)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-25 15:12+0300\n"
"PO-Revision-Date: 2014-02-25 15:12+0300\n"
"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
"Language-Team: Slovenian (Slovenia) (http://www.transifex.com/projects/p/wallabag/language/sl_SI/)\n"
"Language: sl_SI\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: sl_SI\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
"%100==4 ? 2 : 3);\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
"X-Generator: Poedit 1.5.4\n"
"X-Poedit-Language: Slovenian\n"
"X-Poedit-Country: SLOVENIA\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
msgid "wallabag, a read it later open source system"
msgstr ""
msgid "login failed: user doesn't exist"
msgstr ""
msgid "return home"
msgstr ""
msgid "config"
msgstr "nastavitve"
msgid "Poching a link"
msgstr "Shrani povezavo"
msgid "Saving articles"
msgstr ""
msgid "There are several ways to save an article:"
msgstr ""
msgid "read the documentation"
msgstr "preberite dokumentacijo"
msgid "by filling this field"
msgid "download the extension"
msgstr ""
msgid "via F-Droid"
msgstr ""
msgid " or "
msgstr ""
msgid "via Google Play"
msgstr ""
msgid "download the application"
msgstr ""
#, fuzzy
msgid "By filling this field"
msgstr "z vnosom v to polje"
msgid "poche it!"
msgstr "shrani!"
msgid "bag it!"
msgstr ""
msgid "Updating poche"
msgstr "Posodabljam Poche"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "vaša različica"
msgid "Upgrading wallabag"
msgstr ""
msgid "latest stable version"
#, fuzzy
msgid "Installed version"
msgstr "zadnja stabilna različica"
msgid "a more recent stable version is available."
#, fuzzy
msgid "Latest stable version"
msgstr "zadnja stabilna različica"
#, fuzzy
msgid "A more recent stable version is available."
msgstr "na voljo je nova stabilna različica."
msgid "you are up to date."
#, fuzzy
msgid "You are up to date."
msgstr "imate najnovejšo različico."
msgid "latest dev version"
#, fuzzy
msgid "Latest dev version"
msgstr "zadnja razvojna različica"
msgid "a more recent development version is available."
#, fuzzy
msgid "A more recent development version is available."
msgstr "na voljo je nova razvojna različica."
msgid "Feeds"
msgstr ""
msgid "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>."
msgstr ""
msgid "Unread feed"
msgstr ""
#, fuzzy
msgid "Favorites feed"
msgstr "priljubljeni"
#, fuzzy
msgid "Archive feed"
msgstr "arhiv"
msgid "Your token:"
msgstr ""
msgid "Your user id:"
msgstr ""
msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgstr ""
#, fuzzy
msgid "Change your theme"
msgstr "Zamenjava gesla"
msgid "Theme:"
msgstr ""
msgid "Update"
msgstr "Posodobi"
#, fuzzy
msgid "Change your language"
msgstr "Zamenjava gesla"
msgid "Language:"
msgstr ""
msgid "Change your password"
msgstr "Zamenjava gesla"
@ -65,67 +148,69 @@ msgstr "Geslo"
msgid "Repeat your new password:"
msgstr "Ponovite novo geslo:"
msgid "Update"
msgstr "Posodobi"
msgid "Import"
msgstr "Uvozi"
msgid "Please execute the import script locally, it can take a very long time."
msgstr ""
"Prosimo poženite skripto za uvoz lokalno, saj lahko postopek traja precej "
"časa."
#, fuzzy
msgid "Please execute the import script locally as it can take a very long time."
msgstr "Prosimo poženite skripto za uvoz lokalno, saj lahko postopek traja precej časa."
msgid "More infos in the official doc:"
#, fuzzy
msgid "More info in the official documentation:"
msgstr "Več informacij v uradni dokumentaciji:"
msgid "import from Pocket"
#, fuzzy
msgid "Import from Pocket"
msgstr "Uvoz iz aplikacije Pocket"
msgid "import from Readability"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr ""
#, fuzzy
msgid "Import from Readability"
msgstr "Uvoz iz aplikacije Readability"
msgid "import from Instapaper"
#, fuzzy
msgid "Import from Instapaper"
msgstr "Uvoz iz aplikacije Instapaper"
msgid "Export your poche datas"
#, fuzzy
msgid "Import from wallabag"
msgstr "Uvoz iz aplikacije Readability"
#, fuzzy
msgid "Export your wallabag data"
msgstr "Izvoz vsebine"
msgid "Click here"
msgstr "Kliknite tukaj"
msgid "to export your poche datas."
#, fuzzy
msgid "to download your database."
msgstr "za izvoz vsebine aplikacije Poche."
msgid "back to home"
msgstr "Nazaj domov"
#, fuzzy
msgid "to export your wallabag data."
msgstr "za izvoz vsebine aplikacije Poche."
msgid "installation"
msgstr "Namestitev"
msgid "install your poche"
msgstr "Namestitev aplikacije Poche"
msgid ""
"poche is still not installed. Please fill the below form to install it. "
"Don't hesitate to <a href='http://inthepoche.com/doc'>read the documentation "
"on poche website</a>."
msgid "Cache"
msgstr ""
"Poche še vedno ni nameščen. Za namestitev izpolnite spodnji obrazec. Za več "
"informacij <a href='http://inthepoche.com/doc'>preberite dokumentacijo na "
"spletni strani</a>."
msgid "Login"
msgstr "Prijava"
msgid "to delete cache."
msgstr ""
msgid "Repeat your password"
msgstr "Ponovite geslo"
msgid "You can enter multiple tags, separated by commas."
msgstr ""
msgid "Install"
msgstr "Namesti"
msgid "return to article"
msgstr ""
msgid "back to top"
msgstr "nazaj na vrh"
msgid "plop"
msgstr "štrbunk"
msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
msgstr ""
msgid "favoris"
msgstr "priljubljeni"
@ -154,10 +239,14 @@ msgstr "po naslovu"
msgid "by title desc"
msgstr "po naslovu - padajoče"
msgid "No link available here!"
msgstr "Povezava ni na voljo!"
msgid "Tag"
msgstr ""
msgid "toggle mark as read"
msgid "No articles found."
msgstr ""
#, fuzzy
msgid "Toggle mark as read"
msgstr "označi kot prebrano"
msgid "toggle favorite"
@ -169,65 +258,47 @@ msgstr "zavrzi"
msgid "original"
msgstr "izvirnik"
msgid "estimated reading time:"
msgstr ""
msgid "mark all the entries as read"
msgstr ""
msgid "results"
msgstr "rezultati"
msgid "tweet"
msgstr "tvitni"
msgid "installation"
msgstr "Namestitev"
msgid "email"
msgstr "pošlji po e-pošti"
#, fuzzy
msgid "install your wallabag"
msgstr "Namestitev aplikacije Poche"
msgid "shaarli"
msgstr "shaarli"
#, fuzzy
msgid "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>."
msgstr "Poche še vedno ni nameščen. Za namestitev izpolnite spodnji obrazec. Za več informacij <a href='http://inthepoche.com/doc'>preberite dokumentacijo na spletni strani</a>."
msgid "flattr"
msgstr "flattr"
msgid "Login"
msgstr "Prijava"
msgid "this article appears wrong?"
msgstr "napaka?"
msgid "Repeat your password"
msgstr "Ponovite geslo"
msgid "create an issue"
msgstr "prijavi napako"
msgid "Install"
msgstr "Namesti"
msgid "or"
msgstr "ali"
msgid "contact us by mail"
msgstr "pošlji e-pošto razvijalcem"
msgid "plop"
msgstr "štrbunk"
msgid "home"
msgstr "domov"
msgid "favorites"
msgstr "priljubljeni"
msgid "logout"
msgstr "odjava"
msgid "powered by"
msgstr "stran poganja"
msgid "debug mode is on so cache is off."
msgstr ""
"vklopljen je način odpravljanja napak, zato je predpomnilnik izključen."
msgid "your poche version:"
msgstr "vaša verzija Poche:"
msgid "storage:"
msgstr "pomnilnik:"
msgid "login to your poche"
#, fuzzy
msgid "login to your wallabag"
msgstr "prijavite se v svoj Poche"
msgid "you are in demo mode, some features may be disabled."
msgid "Login to wallabag"
msgstr ""
msgid "you are in demo mode, some features may be disabled."
msgstr "uporabljate vzorčno različico programa, zato so lahko nekatere funkcije izklopljene."
msgid "Username"
msgstr ""
"uporabljate vzorčno različico programa, zato so lahko nekatere funkcije "
"izklopljene."
msgid "Stay signed in"
msgstr "Ostani prijavljen"
@ -237,3 +308,261 @@ msgstr "(Ne označi na javnih napravah)"
msgid "Sign in"
msgstr "Prijava"
msgid "favorites"
msgstr "priljubljeni"
msgid "estimated reading time :"
msgstr ""
msgid "Mark all the entries as read"
msgstr ""
msgid "Return home"
msgstr ""
#, fuzzy
msgid "Back to top"
msgstr "nazaj na vrh"
#, fuzzy
msgid "Mark as read"
msgstr "označi kot prebrano"
#, fuzzy
msgid "Favorite"
msgstr "priljubljeni"
#, fuzzy
msgid "Toggle favorite"
msgstr "označi kot priljubljeno"
#, fuzzy
msgid "Delete"
msgstr "zavrzi"
#, fuzzy
msgid "Tweet"
msgstr "tvitni"
#, fuzzy
msgid "Email"
msgstr "pošlji po e-pošti"
msgid "shaarli"
msgstr "shaarli"
msgid "flattr"
msgstr "flattr"
#, fuzzy
msgid "Does this article appear wrong?"
msgstr "napaka?"
msgid "tags:"
msgstr ""
msgid "Edit tags"
msgstr ""
msgid "save link!"
msgstr ""
msgid "home"
msgstr "domov"
msgid "tags"
msgstr ""
msgid "logout"
msgstr "odjava"
msgid "powered by"
msgstr "stran poganja"
msgid "debug mode is on so cache is off."
msgstr "vklopljen je način odpravljanja napak, zato je predpomnilnik izključen."
#, fuzzy
msgid "your wallabag version:"
msgstr "vaša različica"
msgid "storage:"
msgstr "pomnilnik:"
msgid "save a link"
msgstr ""
msgid "back to home"
msgstr "Nazaj domov"
msgid "toggle mark as read"
msgstr "označi kot prebrano"
msgid "tweet"
msgstr "tvitni"
msgid "email"
msgstr "pošlji po e-pošti"
msgid "this article appears wrong?"
msgstr "napaka?"
msgid "No link available here!"
msgstr "Povezava ni na voljo!"
msgid "Poching a link"
msgstr "Shrani povezavo"
msgid "by filling this field"
msgstr "z vnosom v to polje"
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr ""
msgid "your version"
msgstr "vaša različica"
msgid "latest stable version"
msgstr "zadnja stabilna različica"
msgid "a more recent stable version is available."
msgstr "na voljo je nova stabilna različica."
msgid "you are up to date."
msgstr "imate najnovejšo različico."
msgid "latest dev version"
msgstr "zadnja razvojna različica"
msgid "a more recent development version is available."
msgstr "na voljo je nova razvojna različica."
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Prosimo poženite skripto za uvoz lokalno, saj lahko postopek traja precej časa."
msgid "More infos in the official doc:"
msgstr "Več informacij v uradni dokumentaciji:"
msgid "import from Pocket"
msgstr "Uvoz iz aplikacije Pocket"
msgid "import from Readability"
msgstr "Uvoz iz aplikacije Readability"
msgid "import from Instapaper"
msgstr "Uvoz iz aplikacije Instapaper"
msgid "Tags"
msgstr ""
#, fuzzy
msgid "Untitled"
msgstr "po naslovu"
msgid "the link has been added successfully"
msgstr ""
msgid "error during insertion : the link wasn't added"
msgstr ""
msgid "the link has been deleted successfully"
msgstr ""
msgid "the link wasn't deleted"
msgstr ""
msgid "Article not found!"
msgstr ""
msgid "previous"
msgstr ""
msgid "next"
msgstr ""
msgid "in demo mode, you can't update your password"
msgstr ""
msgid "your password has been updated"
msgstr ""
msgid "the two fields have to be filled & the password must be the same in the two fields"
msgstr ""
msgid "still using the \""
msgstr ""
msgid "that theme does not seem to be installed"
msgstr ""
msgid "you have changed your theme preferences"
msgstr ""
msgid "that language does not seem to be installed"
msgstr ""
msgid "you have changed your language preferences"
msgstr ""
msgid "login failed: you have to fill all fields"
msgstr ""
msgid "welcome to your wallabag"
msgstr ""
msgid "login failed: bad login or password"
msgstr ""
#, fuzzy
msgid "import from instapaper completed"
msgstr "Uvoz iz aplikacije Instapaper"
#, fuzzy
msgid "import from pocket completed"
msgstr "Uvoz iz aplikacije Pocket"
#, fuzzy
msgid "import from Readability completed. "
msgstr "Uvoz iz aplikacije Readability"
#, fuzzy
msgid "import from Poche completed. "
msgstr "Uvoz iz aplikacije Pocket"
msgid "Unknown import provider."
msgstr ""
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr ""
msgid "Could not find required \""
msgstr ""
msgid "Uh, there is a problem while generating feeds."
msgstr ""
#, fuzzy
msgid "Cache deleted."
msgstr "zavrzi"
msgid "Oops, it seems you don't have PHP 5."
msgstr ""
#~ msgid "poche it!"
#~ msgstr "shrani!"
#~ msgid "Updating poche"
#~ msgstr "Posodabljam Poche"
#~ msgid "create an issue"
#~ msgstr "prijavi napako"
#~ msgid "or"
#~ msgstr "ali"
#~ msgid "contact us by mail"
#~ msgstr "pošlji e-pošto razvijalcem"
#~ msgid "your poche version:"
#~ msgstr "vaša verzija Poche:"

59
locale/tools/fillCache.php Executable file
View File

@ -0,0 +1,59 @@
<?php
// this script compile all twig templates and put it in cahce to get Poedit (or xgettext) to extract phrases fron chached templates.
// gettext command line tools:
// msgunfmt - get po from mo
// msgfmt - get mo from po
// xgettext - extract phrases from files
$siteRoot = dirname(__FILE__) . '/../..';
require_once $siteRoot . '/vendor/twig/twig/lib/Twig/Autoloader.php';
Twig_Autoloader::register();
require_once $siteRoot . '/vendor/twig/extensions/lib/Twig/Extensions/Autoloader.php';
Twig_Extensions_Autoloader::register();
//$tplDir = $siteRoot.'/themes/default';
$tplDirRoot = $siteRoot.'/themes/';
$tmpDir = $siteRoot. '/cache/';
foreach (new IteratorIterator(new DirectoryIterator($tplDirRoot)) as $tplDir) {
if ($tplDir->isDir() and $tplDir!='.' and $tplDir!='..') {
echo "\n$tplDir\n";
$loader = new Twig_Loader_Filesystem($tplDirRoot.$tplDir);
// force auto-reload to always have the latest version of the template
$twig = new Twig_Environment($loader, array(
'cache' => $tmpDir,
'auto_reload' => true
));
$twig->addExtension(new Twig_Extensions_Extension_I18n());
$filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain');
$twig->addFilter($filter);
$filter = new Twig_SimpleFilter('getReadingTime', 'Tools::getReadingTime');
$twig->addFilter($filter);
$filter = new Twig_SimpleFilter('getPrettyFilename', function($string) { return str_replace($siteRoot, '', $string); });
$twig->addFilter($filter);
// // iterate over all your templates
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tplDirRoot.$tplDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
// force compilation
if ($file->isFile() and pathinfo($file, PATHINFO_EXTENSION)=='twig') {
echo "\t$file\n";
$twig->loadTemplate(str_replace($tplDirRoot.$tplDir.'/', '', $file));
}
}
}
}

View File

@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: wballabag\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-06 19:23+0300\n"
"PO-Revision-Date: 2014-02-06 19:24+0300\n"
"POT-Creation-Date: 2014-02-25 15:06+0300\n"
"PO-Revision-Date: 2014-02-25 15:08+0300\n"
"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
"Language-Team: \n"
"Language: \n"
@ -15,52 +15,25 @@ msgstr ""
"X-Poedit-Language: Ukrainian\n"
"X-Poedit-Country: UKRAINE\n"
"X-Poedit-SourceCharset: utf-8\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag\n"
"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
msgid "poche, a read it later open source system"
msgstr "poche, сервіс відкладеного читання з відкритим кодом"
msgid "wallabag, a read it later open source system"
msgstr "wallabag, сервіс відкладеного читання з відкритим кодом"
msgid "login failed: user doesn't exist"
msgstr "увійти не вдалося: користувач не існує"
msgid "powered by"
msgstr "за підтримки"
msgid "debug mode is on so cache is off."
msgstr "режим відладки включено, отже кеш виключено."
msgid "your poche version:"
msgstr "версія вашої poche:"
msgid "storage:"
msgstr "сховище:"
msgid "home"
msgstr "головна"
msgid "favorites"
msgstr "вибране"
msgid "archive"
msgstr "архів"
msgid "tags"
msgstr "теги"
msgid "return home"
msgstr "повернутися на головну"
msgid "config"
msgstr "налаштування"
msgid "logout"
msgstr "вихід"
msgid "return home"
msgstr "повернутися на головну"
msgid "Poching links"
msgid "Saving articles"
msgstr "Зберігання посилань"
msgid "There are several ways to poche a link:"
msgstr "Є кілька способів зберегти посилання:"
msgid "There are several ways to save an article:"
msgstr "Є кілька способів зберегти статтю:"
msgid "read the documentation"
msgstr "читати документацію"
@ -83,14 +56,14 @@ msgstr "завантажити додаток"
msgid "By filling this field"
msgstr "Заповнивши це поле"
msgid "poche it!"
msgid "bag it!"
msgstr "зберегти!"
msgid "Bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "З допомогою закладки: перетягніть і відпустіть посилання на панель закладок"
msgid "Updating poche"
msgstr "Оновлення poche"
msgid "Upgrading wallabag"
msgstr "Оновлення wallabag"
msgid "Installed version"
msgstr "Встановлено ​​версію"
@ -104,14 +77,11 @@ msgstr "Є новіша стабільна версія."
msgid "You are up to date."
msgstr "У вас остання версія."
msgid "latest dev version"
msgstr "остання версія в розробці"
msgid "Latest dev version"
msgstr "Остання версія в розробці"
msgid "a more recent development version is available."
msgstr "доступна новіша версія в розробці."
msgid "you are up to date."
msgstr "у вас остання версія."
msgid "A more recent development version is available."
msgstr "Доступна новіша версія в розробці."
msgid "Feeds"
msgstr "Завантаження (feeds)"
@ -170,8 +140,8 @@ msgstr "Імпортування"
msgid "Please execute the import script locally as it can take a very long time."
msgstr "Будь ласка, виконайте сценарій імпорту локально, оскільки це може тривати досить довго."
msgid "More info in the official docs:"
msgstr "Більш детальна інформація в офіційній документації:"
msgid "More info in the official documentation:"
msgstr "Більше інформації в офіційній документації:"
msgid "Import from Pocket"
msgstr "Імпорт з Pocket-а"
@ -186,11 +156,11 @@ msgstr "Імпорт з Readability"
msgid "Import from Instapaper"
msgstr "Імпорт з Instapaper"
msgid "Import from poche"
msgstr "Імпорт з poche"
msgid "Import from wallabag"
msgstr "Імпорт з wallabag"
msgid "Export your poche data"
msgstr "Експортувати ваші дані з poche"
msgid "Export your wallabag data"
msgstr "Експортувати ваші дані з wallabag"
msgid "Click here"
msgstr "Клікніть тут"
@ -198,32 +168,14 @@ msgstr "Клікніть тут"
msgid "to download your database."
msgstr "щоб завантажити вашу базу даних."
msgid "to export your poche data."
msgstr "щоб експортувати ваші дані poche."
msgid "to export your wallabag data."
msgstr "щоб експортувати ваші дані wallabag."
msgid "Tag"
msgstr "Тег"
msgid "Cache"
msgstr "Кеш"
msgid "No link available here!"
msgstr "Немає доступних посилань!"
msgid "toggle mark as read"
msgstr "змінити мітку на прочитано"
msgid "toggle favorite"
msgstr "змінити мітку вибраного"
msgid "delete"
msgstr "видалити"
msgid "original"
msgstr "оригінал"
msgid "estimated reading time:"
msgstr "приблизний час читання:"
msgid "results"
msgstr "результат(ів)"
msgid "to delete cache."
msgstr "щоб очистити кеш."
msgid "You can enter multiple tags, separated by commas."
msgstr "Ви можете ввести декілька тегів, розділених комами."
@ -240,6 +192,9 @@ msgstr "Ви можете <a href='wallabag_compatibility_test.php'>переві
msgid "favoris"
msgstr "вибране"
msgid "archive"
msgstr "архів"
msgid "unread"
msgstr "непрочитане"
@ -261,12 +216,33 @@ msgstr "за назвою"
msgid "by title desc"
msgstr "за назвою по спаданню"
msgid "Tag"
msgstr "Тег"
msgid "No articles found."
msgstr "Статей не знайдено."
msgid "Toggle mark as read"
msgstr "змінити мітку прочитаного"
msgid "toggle favorite"
msgstr "змінити мітку вибраного"
msgid "delete"
msgstr "видалити"
msgid "original"
msgstr "оригінал"
msgid "estimated reading time:"
msgstr "приблизний час читання:"
msgid "mark all the entries as read"
msgstr "відмітити всі статті як прочитані"
msgid "results"
msgstr "результат(ів)"
msgid "installation"
msgstr "інсталяція"
@ -303,6 +279,18 @@ msgstr "Запам'ятати мене"
msgid "(Do not check on public computers)"
msgstr "(Не відмічайте на загальнодоступних комп'ютерах)"
msgid "Sign in"
msgstr "Увійти"
msgid "favorites"
msgstr "вибране"
msgid "estimated reading time :"
msgstr "приблизний час читання:"
msgid "Mark all the entries as read"
msgstr "Відмітити все як прочитане"
msgid "Return home"
msgstr "Повернутися на головну"
@ -342,11 +330,95 @@ msgstr "теги:"
msgid "Edit tags"
msgstr "Редагувати теги"
msgid "previous"
msgstr "попередня"
msgid "save link!"
msgstr "зберегти лінк!"
msgid "next"
msgstr "наступна"
msgid "home"
msgstr "головна"
msgid "tags"
msgstr "теги"
msgid "logout"
msgstr "вихід"
msgid "powered by"
msgstr "за підтримки"
msgid "debug mode is on so cache is off."
msgstr "режим відладки включено, отже кеш виключено."
msgid "your wallabag version:"
msgstr "версія вашого wallabag:"
msgid "storage:"
msgstr "сховище:"
msgid "save a link"
msgstr "зберегти лінк"
msgid "back to home"
msgstr "назад на головну"
msgid "toggle mark as read"
msgstr "змінити мітку на прочитано"
msgid "tweet"
msgstr "твітнути"
msgid "email"
msgstr "email"
msgid "this article appears wrong?"
msgstr "ця стаття виглядає не так, як треба?"
msgid "No link available here!"
msgstr "Немає доступних посилань!"
msgid "Poching a link"
msgstr "Зберігання посилання"
msgid "by filling this field"
msgstr "заповнивши це поле"
msgid "bookmarklet: drag & drop this link to your bookmarks bar"
msgstr "з допомогою закладки: перетягніть і відпустіть посилання на панель закладок"
msgid "your version"
msgstr "ваша версія:"
msgid "latest stable version"
msgstr "остання стабільна версія"
msgid "a more recent stable version is available."
msgstr "є новіша стабільна версія."
msgid "you are up to date."
msgstr "у вас остання версія."
msgid "latest dev version"
msgstr "остання версія в розробці"
msgid "a more recent development version is available."
msgstr "доступна новіша версія в розробці."
msgid "Please execute the import script locally, it can take a very long time."
msgstr "Будь ласка, виконайте сценарій імпорту локально, оскільки це може тривати досить довго."
msgid "More infos in the official doc:"
msgstr "Більше інформації в офіційній документації:"
msgid "import from Pocket"
msgstr "імпорт з Pocket-а"
msgid "import from Readability"
msgstr "імпорт з Readability"
msgid "import from Instapaper"
msgstr "імпорт з Instapaper"
msgid "Tags"
msgstr "Теги"
msgid "Untitled"
msgstr "Без назви"
@ -363,6 +435,15 @@ msgstr "посилання успішно видалено"
msgid "the link wasn't deleted"
msgstr "посилання не було видалено"
msgid "Article not found!"
msgstr "Статтю не знайдено!"
msgid "previous"
msgstr "попередня"
msgid "next"
msgstr "наступна"
msgid "in demo mode, you can't update your password"
msgstr "в демонстраційному режимі ви не можете змінювати свій пароль"
@ -390,15 +471,12 @@ msgstr "ви змінили свої налаштування мови"
msgid "login failed: you have to fill all fields"
msgstr "увійти не вдалося: ви повинні заповнити всі поля"
msgid "welcome to your poche"
msgstr "ласкаво просимо до вашого poche"
msgid "welcome to your wallabag"
msgstr "ласкаво просимо до вашого wallabag"
msgid "login failed: bad login or password"
msgstr "увійти не вдалося: не вірний логін або пароль"
msgid "see you soon!"
msgstr "бувайте, ще побачимось!"
msgid "import from instapaper completed"
msgstr "імпорт з instapaper-а завершено"
@ -423,6 +501,34 @@ msgstr "Не вдалося знайти потрібний \""
msgid "Uh, there is a problem while generating feeds."
msgstr "Ох, є проблема при створенні завантажень (feeds)."
msgid "Cache deleted."
msgstr "Кеш очищено."
msgid "Oops, it seems you don't have PHP 5."
msgstr "Упс, здається, у вас немає PHP 5."
#~ msgid "You can poche a link by several methods:"
#~ msgstr "Ви можете зберегти посилання кількома способами:"
#~ msgid "poche it!"
#~ msgstr "зберегти!"
#~ msgid "Updating poche"
#~ msgstr "Оновлення poche"
#, fuzzy
#~ msgid "Export your poche datas"
#~ msgstr "Експортувати ваші дані з poche"
#, fuzzy
#~ msgid "to export your poche datas."
#~ msgstr "щоб експортувати ваші дані poche."
#~ msgid "Import from poche"
#~ msgstr "Імпорт з poche"
#~ msgid "welcome to your poche"
#~ msgstr "ласкаво просимо до вашого poche"
#~ msgid "see you soon!"
#~ msgstr "бувайте, ще побачимось!"

View File

@ -0,0 +1,5 @@
<div id="display-mode">
<a href="javascript: void(null);" id="listmode" class="listmode">
<img src="{{ poche_url }}themes/{{ theme }}/img/{{ theme }}/blank.png" alt="{% trans "toggle view mode" %}" title="{% trans "toggle view mode" %}" width="16" height="16">
</a>
</div>

28
themes/baggy/_head.twig Normal file → Executable file
View File

@ -1,12 +1,16 @@
<link rel="shortcut icon" type="image/x-icon" href="{{ poche_url }}/themes/{{theme}}/img/favicon.ico" />
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="{{ poche_url }}/themes/{{theme}}/img/apple-touch-icon-144x144-precomposed.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="{{ poche_url }}/themes/{{theme}}/img/apple-touch-icon-72x72-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="{{ poche_url }}/themes/{{theme}}/img/apple-touch-icon-precomposed.png">
<link rel="stylesheet" href="{{ poche_url }}/themes/{{theme}}/css/ratatouille.css" media="all">
<link rel="stylesheet" href="{{ poche_url }}/themes/{{theme}}/css/font.css" media="all">
<link rel="stylesheet" href="{{ poche_url }}/themes/{{theme}}/css/main.css" media="all">
<link rel="stylesheet" href="{{ poche_url }}/themes/{{theme}}/css/messages.css" media="all">
<link rel="stylesheet" href="{{ poche_url }}/themes/{{theme}}/css/print.css" media="print">
<script src="{{ poche_url }}/themes/{{theme}}/js/jquery-2.0.3.min.js"></script>
<script src="{{ poche_url }}/themes/{{theme}}/js/init.js"></script>
<script src="{{ poche_url }}/themes/{{ constant('DEFAULT_THEME') }}/js/closeMessage.js"></script>
<link rel="shortcut icon" type="image/x-icon" href="{{ poche_url }}themes/{{theme}}/img/favicon.ico" />
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="{{ poche_url }}themes/{{theme}}/img/apple-touch-icon-144x144-precomposed.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="{{ poche_url }}themes/{{theme}}/img/apple-touch-icon-72x72-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="{{ poche_url }}themes/{{theme}}/img/apple-touch-icon-precomposed.png">
<link rel="stylesheet" href="{{ poche_url }}themes/{{theme}}/css/ratatouille.css" media="all">
<link rel="stylesheet" href="{{ poche_url }}themes/{{theme}}/css/font.css" media="all">
<link rel="stylesheet" href="{{ poche_url }}themes/{{theme}}/css/main.css" media="all">
<link rel="stylesheet" href="{{ poche_url }}themes/{{theme}}/css/messages.css" media="all">
<link rel="stylesheet" href="{{ poche_url }}themes/{{theme}}/css/print.css" media="print">
<script src="{{ poche_url }}themes/default/js/jquery-2.0.3.min.js"></script>
<script src="{{ poche_url }}themes/default/js/autoClose.js"></script>
<script src="{{ poche_url }}themes/{{theme}}/js/jquery.cookie.js"></script>
<script src="{{ poche_url }}themes/{{theme}}/js/init.js"></script>
<script src="{{ poche_url }}themes/default/js/saveLink.js"></script>
<script src="{{ poche_url }}themes/default/js/popupForm.js"></script>
<script src="{{ poche_url }}themes/{{theme}}/js/closeMessage.js"></script>

View File

@ -4,9 +4,13 @@
<li><a href="./?view=fav" {% if view == 'fav' %}class="current"{% endif %}>{% trans "favorites" %}</a></li>
<li><a href="./?view=archive" {% if view == 'archive' %}class="current"{% endif %}>{% trans "archive" %}</a></li>
<li><a href="./?view=tags" {% if view == 'tags' %}class="current"{% endif %}>{% trans "tags" %}</a></li>
<li><a href="javascript: void(null);" id="pocheit">{% trans "save a link" %}</a></li>
<li style="position: relative;"><a href="javascript: void(null);" id="bagit">{% trans "save a link" %}</a>
{% include '_pocheit-form.twig' %}
</li>
<li style="position: relative;"><a href="javascript: void(null);" id="search">{% trans "search" %}</a>
{% include '_search-form.twig' %}
</li>
<li><a href="./?view=config" {% if view == 'config' %}class="current"{% endif %}>{% trans "config" %}</a></li>
<li><a class="icon icon-power" href="./?logout" title="{% trans "logout" %}">{% trans "logout" %}</a></li>
</ul>
{% include '_pocheit-form.twig' %}

10
themes/baggy/_pocheit-form.twig Executable file
View File

@ -0,0 +1,10 @@
<div id="bagit-form" class="messages info">
<form method="get" action="index.php" target="_blank" id="bagit-form-form">
<h2><a href="javascript: void(null);" id="bagit-form-close">X</a>
{% trans "Save a link" %}</h2>
<input type="hidden" name="autoclose" value="1" />
<input required placeholder="example.com/article" class="addurl" id="plainurl" name="plainurl" type="url" />
<input type="submit" value="{% trans "save link!" %}" />
<div id="add-link-result"></div>
</form>
</div>

View File

@ -0,0 +1,7 @@
<div id="search-form" class="messages info">
<form method="get" action="index.php">
<input type="hidden" name="view" value="search"></input>
<label><a href="javascript: void(null);" id="search-form-close">X</a>{% trans "Search" %}</label> : <input type="text" name="search" />
<input id="submit-search" type="submit" value="{% trans "Search" %} !"></input>
</form>
</div>

2
themes/baggy/_top.twig Normal file → Executable file
View File

@ -1,6 +1,6 @@
<header class="w600p center mbm">
<h1 class="logo">
{% if view == 'home' %}{% block logo %}<img width="100" height="100" src="{{ poche_url }}/themes/{{theme}}/img/logo-w.png" alt="logo poche" />{% endblock %}
{% if view == 'home' %}{% block logo %}<img width="100" height="100" src="{{ poche_url }}themes/{{theme}}/img/logo-w.png" alt="wallabag logo" />{% endblock %}
{% else %}<a href="./" title="{% trans "return home" %}" >{{ block('logo') }}</a>
{% endif %}
</h1>

74
themes/baggy/config.twig Normal file → Executable file
View File

@ -8,10 +8,11 @@
<h2>{% trans "Saving articles" %}</h2>
<p>{% trans "There are several ways to save an article:" %} (<a href="http://doc.wallabag.org/" title="{% trans "read the documentation" %}">?</a>)</p>
<ul>
<li>Firefox: <a href="https://addons.mozilla.org/firefox/addon/poche/" title="download the firefox extension">{% trans "download the extension" %}</a></li>
<li>Firefox: <a href="https://addons.mozilla.org/firefox/addon/wallabag/" title="download the firefox extension">{% trans "download the extension" %}</a></li>
<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>
<li>Android: <a href="https://f-droid.org/repository/browse/?fdid=fr.gaulupeau.apps.Poche" 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>
<li>Windows Phone: <a href="https://www.windowsphone.com/en-us/store/app/poche/334de2f0-51b5-4826-8549-a3d805a37e83" title="download the window phone application">{% trans "download the application" %}</a></li>
<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>
<li>iOS: <a href="https://itunes.apple.com/app/wallabag/id828331015?mt=8" title="download the iOS application">{% trans "download the application" %}</a></li>
<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>
<li>
<form method="get" action="index.php">
<label class="addurl" for="config_plainurl">{% trans "By filling this field" %}:</label>
@ -25,9 +26,10 @@
<h2>{% trans "Upgrading wallabag" %}</h2>
<ul>
<li>{% trans "Installed version" %} : <strong>{{ constant('POCHE') }}</strong></li>
<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>
{% 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 %}
<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 %} ({% trans "Last check:" %} {{ check_time_prod }})</li>
{% 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 %} ({% trans "Last check:" %} {{ check_time_dev }}){% endif %}</li>
</ul>
<p>{% trans "You can clear cache to check the latest release." %}</p>
<h2>{% trans "Feeds" %}</h2>
{% if token == '' %}
@ -42,7 +44,7 @@
<p>{% trans "Your user id:" %} <strong>{{user_id}}</strong></p>
<p>{% trans "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>." %}</p>
{% endif %}
<h2>{% trans "Change your theme" %}</h2>
<form method="post" action="?updatetheme" name="changethemeform">
<fieldset class="w500p inline">
@ -103,21 +105,63 @@
{% endif %}
<h2>{% trans "Import" %}</h2>
<p>{% trans "Please execute the import script locally as it can take a very long time." %}</p>
<p>{% trans "More info in the official documentation:" %} <a href="http://doc.wallabag.org/doku.php?id=users:migrate">wallabag.org</a></p>
<ul>
<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>
<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>
<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>
<li><a href="./?import&amp;from=poche">{% trans "Import from wallabag" %}</a> {{ '(you must have a %s file on your server)'|trans|format(constant('POCHE_FILE')) }}</li>
</ul>
<p>{% trans "You can import your Pocket, Readability, Instapaper, Wallabag or any data in appropriate json or html format." %}</p>
<p>{% trans "Please select export file on your computer and press \"Import\" button below.<br>Wallabag will parse your file, insert all URLs and start fetching of articles if required.<br>Fetching process is controlled by two constants in your config file: IMPORT_LIMIT (how many articles are fetched at once) and IMPORT_DELAY (delay between fetch of next batch of articles)." %}</p>
<form method="post" action="?import" name="uploadfile" enctype="multipart/form-data">
<fieldset class="w500p">
<div class="row">
<label class="col w150p" for="file">{% trans "File:" %}</label>
<input class="col" type="file" id="file" name="file" tabindex="4">
</div>
<div class="row mts txtcenter">
<button class="bouton" type="submit" tabindex="4">{% trans "Import" %}</button>
</div>
</fieldset>
</form>
<p><a href="?import">{% trans "You can click here to fetch content for articles with no content." %}</a></p>
<h2>{% trans "Export your wallabag data" %}</h2>
{% if constant('STORAGE') == 'sqlite' %}
<p><a href="?download" target="_blank">{% trans "Click here" %}</a> {% trans "to download your database." %}</p>{% endif %}
<p><a href="?export" target="_blank">{% trans "Click here" %}</a> {% trans "to export your wallabag data." %}</p>
<h2>{% trans "Fancy an E-Book ?" %}</h2>
<p>{% trans "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)." %}
<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>
<h2>{% trans "Cache" %}</h2>
<p><a href="?empty-cache">{% trans "Click here" %}</a> {% trans "to delete cache." %}</p>
<h2>{% trans 'Add user' %}</h2>
<p>{% trans 'Add a new user :' %}</p>
<form method="post" action="?newuser">
<fieldset class="w500p">
<div class="row">
<label class="col w150p" for="newusername">{% trans 'Login for new user' %}</label>
<input class="col" type="text" id="newusername" name="newusername" placeholder="{% trans 'Login' %}">
</div>
<div class="row">
<label class="col w150p" for="password4newuser">{% trans "Password for new user" %}</label>
<input class="col" type="password" id="password4newuser" name="password4newuser" placeholder="{% trans "Password" %}">
</div>
<div class="row mts txtcenter">
<button type="submit">{% trans "Send" %}</button>
</div>
</fieldset>
</form>
<h2>{% trans "Delete account" %}</h2>
{% if not only_user %}<form method="post" action="?deluser">
<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>
<fieldset class="w500p">
<div class="row">
<label class="col w150p" for="password4deletinguser">{% trans "Type here your password" %}</label>
<input class="col" type="password" id="password4deletinguser" name="password4deletinguser" placeholder="{% trans "Password" %}">
</div>
<div class="row mts txtcenter">
<button type="submit">{% trans "Send" %}</button>
</div>
</form>
{% else %}<p>{% trans "You are the only user, you cannot delete your own account." %}<br />
{% trans "To completely remove wallabag, delete the wallabag folder on your web server." %}</p>{% endif %}
{% endblock %}

View File

@ -173,21 +173,22 @@ h2:after {
#links {
position: fixed;
top: 0;
width: 9em;
width: 10em;
left: 0;
text-align: right;
background: #333;
padding-top: 9em;
padding-top: 9.5em;
height: 100%;
box-shadow:inset -4px 0 20px rgba(0,0,0,0.6);
z-index: 10;
}
#main {
margin-left: 12em;
margin-left: 13em;
position: relative;
z-index: 10;
padding-right: 5%;
padding-bottom: 1em;
}
#links a {
@ -227,7 +228,7 @@ h2:after {
#links li:last-child {
position: fixed;
bottom: 1em;
width: 10%;
width: 10em;
}
#links li:last-child a:before {
@ -237,6 +238,61 @@ h2:after {
}
#sort {
padding: 0;
list-style-type: none;
opacity: 0.5;
display: inline-block;
}
#sort li {
display: inline;
font-size: 0.9em;
}
#sort li + li {
margin-left: 10px;
}
#sort a {
padding: 2px 2px 0;
vertical-align: middle;
}
#sort img {
vertical-align: baseline;
}
#sort img:hover {
cursor: pointer;
}
#display-mode {
float: right;
vertical-align: middle;
margin-top: 10px;
margin-bottom: 10px;
opacity: 0.5;
}
#listmode {
width: 16px;
display: inline-block;
text-decoration: none;
}
#listmode a:hover {
opacity: 1;
}
.tablemode {
background-image: url("../img/baggy/table.png");
background-repeat: no-repeat;
background-position: bottom;
}
.listmode {
background-image: url("../img/baggy/list.png");
background-repeat: no-repeat;
background-position: bottom;
}
/* ==========================================================================
2 = Layout
========================================================================== */
@ -248,7 +304,7 @@ h2:after {
footer {
text-align: right;
position: fixed;
position: relative;
bottom: 0;
right: 5em;
color: #999;
@ -266,6 +322,15 @@ footer a {
letter-spacing:-5px;
}
.listmode .entrie {
width: 100%!important;
margin-left: 0!important;
}
.listmode .entrie p {
display: none;
}
.list-entries + .results {
margin-bottom: 2em;
}
@ -359,6 +424,7 @@ footer a {
content: none;
}
.entrie h2 a {
display: block;
text-decoration: none;
@ -370,7 +436,7 @@ footer a {
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
/*
.entrie h2 a:after {
content: "";
position: absolute;
@ -379,6 +445,7 @@ footer a {
height: 100%;
left: 0;
}
*/
.entrie p {
color: #666;
@ -442,6 +509,7 @@ footer a {
.pagination {
text-align: right;
margin-bottom:50px;
}
.nb-results {
@ -468,6 +536,153 @@ footer a {
display: none;
}
/* ==========================================================================
2.1 = "save a link" related styles
========================================================================== */
#bagit-form, #search-form {
background: rgba(0,0,0,0.5);
position: absolute;
top: 0;
left: 10em;
z-index: 20;
height: 100%;
width: 100%;
margin: 0;
margin-top: -30%;
padding: 2em;
display: none;
border-left: 1px #EEE solid;
}
#bagit-form form, #search-form form {
background: #FFF;
position: absolute;
top: 0;
left: 0;
z-index: 20;
border: 10px solid #000;
width: 400px;
height: 200px;
/* margin: -150px 0 0 -300px; */
padding: 2em;
}
a#bagit-form-close, a#search-form-close {
background: #000;
color: #FFF;
padding: 0.2em 0.5em;
text-decoration: none;
display: inline-block;
float: right;
font-size: 0.6em;
}
a#bagit-form-close:hover, a#search-form-close:hover {
background: #999;
color: #000;
}
.active-current {
background-color: #999;
}
.active-current:after {
content: "";
width: 0;
height: 0;
position: absolute;
border-style: solid;
border-width: 10px;
border-color: transparent #EEE transparent transparent;
right: 0;
top: 50%;
margin-top: -10px;
}
.opacity03 {
opacity: 0.3;
}
.add-to-wallabag-link-after {
background-color: #000;
color: #fff;
padding: 0 3px 2px 3px;
}
a.add-to-wallabag-link-after {
visibility: hidden;
position: absolute;
opacity: 0;
transition-duration: 2s;
transition-timing-function: ease-out;
}
#article article a:hover + a.add-to-wallabag-link-after, a.add-to-wallabag-link-after:hover {
opacity: 1;
visibility: visible;
transition-duration: .3s;
transition-timing-function: ease-in;
}
a.add-to-wallabag-link-after:after {
content: "w";
}
#add-link-result {
font-weight: bold;
margin-top: 10px;
}
/* ==========================================================================
2.2 = "search for articles" popup div related styles
========================================================================== */
#search-form {
background: rgba(0,0,0,0.5);
position: absolute;
top: 0;
left: 10em;
z-index: 20;
height: 100%;
width: 100%;
margin: 0;
margin-top: -30%;
padding: 2em;
display: none;
border-left: 1px #EEE solid;
}
#search-form form {
background: #FFF;
position: absolute;
top: 0;
left: 0;
z-index: 20;
border: 10px solid #000;
width: 400px;
height: 200px;
/* margin: -150px 0 0 -300px; */
padding: 2em;
}
a#search-form-close {
background: #000;
color: #FFF;
padding: 0.2em 0.5em;
text-decoration: none;
display: inline-block;
float: right;
font-size: 1.2em;
}
a#search-form-close:hover {
background: #999;
color: #000;
}
#submit-search{
margin-left: 4em;
margin-top:1em;
}
/* ==========================================================================
3 = Pictos
========================================================================== */
@ -550,6 +765,9 @@ footer a {
.icon-rss:before {
content: "\e808";
}
.icon-print:before {
content: "\e80d";
}
/* ==========================================================================
Icon selected
@ -583,7 +801,7 @@ footer a {
}
.warning {
font-size: 3em;
/* font-size: 3em;
color: #999;
font-style: italic;
position: absolute;
@ -592,7 +810,10 @@ footer a {
width: 100%;
text-align: center;
padding-right: 5%;
margin-top: -2em;
margin-top: -2em;*/
font-weight: bold;
display: block;
width: 100%;
}
/* ==========================================================================
@ -602,6 +823,7 @@ footer a {
#article {
width: 70%;
margin-bottom: 3em;
text-align: justify;
}
#article .tags {
@ -731,6 +953,9 @@ blockquote {
width: 100%;
margin-left: 0;
}
#display-mode {
display: none;
}
}
@media screen and (max-width: 500px) {
@ -754,8 +979,8 @@ blockquote {
content: none;
}
.logo {
width: 1.5em;
height: 1.5em;
width: 1.25em;
height: 1.25em;
left: 0;
top: 0;
}
@ -805,6 +1030,7 @@ blockquote {
margin-left: 1.5em;
padding-right: 1.5em;
position: static;
margin-top: 3em;
}
#article_toolbar .topPosF {
display: none;
@ -820,4 +1046,12 @@ blockquote {
#article_toolbar a {
padding: 0.3em 0.4em 0.2em;
}
#display-mode {
display: none;
}
#bagit-form, #search-form {
left: 0;
}
}

View File

@ -17,6 +17,7 @@ img {
/* Hide useless blocks */
body > header,
#article_toolbar,
#links,
#sort,
body > footer,
@ -46,3 +47,16 @@ abbr[title]:after {
.pagination span.current {
border-style: dashed;
}
#main {
width: 100%;
padding: 0;
margin: 0;
margin-left: 0;
padding-right: 0;
padding-bottom: 0;
}
#article {
width: 100%;
}

8
themes/baggy/edit-tags.twig Normal file → Executable file
View File

@ -4,6 +4,11 @@
{% include '_menu.twig' %}
{% endblock %}
{% block content %}
<script src="{{ poche_url }}themes/default/js/jquery-ui-1.10.4.custom.min.js"></script>
<script src="{{ poche_url }}themes/default/js/autoCompleteTags.js"></script>
<link rel="stylesheet" href="{{ poche_url }}themes/default/css/jquery-ui-1.10.4.custom.min.css" media="all">
<div id="article">
<h2>{{ entry.title|raw }}</21>
</div>
@ -17,7 +22,8 @@
<input type="hidden" name="entry_id" value="{{ entry_id }}" />
<label for="value">Add tags: </label><input type="text" placeholder="interview, editorial, video" id="value" name="value" required="required" />
<input type="submit" value="Tag" />
<p>{% trans "You can enter multiple tags, separated by commas." %}</p>
<p>{% trans "Start typing for auto complete." %}<br>
{% trans "You can enter multiple tags, separated by commas." %}</p>
</form>
<a class="icon icon-reply return" href="./?view=view&id={{ entry_id }}">{% trans "return to article" %}</a>
{% endblock %}

BIN
themes/baggy/fonts/icomoon.eot Executable file → Normal file

Binary file not shown.

17
themes/baggy/fonts/icomoon.svg Executable file → Normal file
View File

@ -1,7 +1,21 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<metadata>
<json>
{
"fontFamily": "icomoon",
"majorVersion": 1,
"minorVersion": 0,
"version": "Version 1.0",
"fontId": "icomoon",
"psName": "icomoon",
"subFamily": "Regular",
"fullName": "icomoon",
"description": "Generated by IcoMoon"
}
</json>
</metadata>
<defs>
<font id="icomoon" horiz-adv-x="512">
<font-face units-per-em="512" ascent="480" descent="-32" />
@ -23,4 +37,5 @@
<glyph unicode="&#xe80a;" d="M475.648 50.432v219.136q-9.216-10.24-19.968-18.944-76.288-58.368-121.856-96.256-14.336-12.288-23.552-19.456t-24.576-13.824-29.184-6.656h-1.024q-13.312 0-29.184 6.656t-24.576 13.824-23.552 19.456q-45.056 37.888-121.856 96.256-10.752 8.704-19.968 18.944v-219.136q0-4.096 3.072-6.656t6.144-2.56h420.864q3.584 0 6.144 2.56t3.072 6.656zM475.648 350.464v7.168t-0.512 3.584-0.512 3.584-1.536 2.56-2.56 2.048-4.096 1.024h-420.864q-3.584 0-6.144-3.072t-3.072-6.144q0-48.128 41.984-81.408 55.296-43.52 114.688-90.624 2.048-1.024 10.24-8.192t12.8-10.752 12.8-9.216 14.336-7.68 12.288-2.56h1.024q5.632 0 12.288 2.56t14.336 7.68 12.8 9.216 12.8 10.752 10.24 8.192q59.392 47.104 114.688 90.624 15.36 12.288 28.672 33.28t13.312 37.376zM512 361.216v-310.784q0-18.944-13.312-32.256t-32.256-13.824h-420.864q-18.432 0-32.256 13.824t-13.312 32.256v310.784q0 18.944 13.312 32.256t32.256 13.312h420.864q18.944 0 32.256-13.312t13.312-32.256z" />
<glyph unicode="&#xe80b;" d="M0 133.888l256 256 256-256-75.776-75.776-180.224 179.712-180.224-179.712z" />
<glyph unicode="&#xe80c;" d="M25.6 279.296q62.464-35.84 168.96-35.84t168.96 35.84l-27.648-248.832q-1.024-7.168-17.92-18.432t-51.2-22.016-72.192-10.752-71.68 10.752-51.2 22.016-18.432 18.432zM275.456 432.896q48.128-9.216 80.896-28.16t32.768-36.352v-5.12q0-29.696-57.344-50.688t-137.216-20.992-137.216 20.992-57.344 50.688v5.12q0 17.408 32.768 36.352t80.896 28.16l21.504 24.576q11.264 13.312 35.84 13.312h47.104q26.624 0 35.84-13.312zM247.808 375.552h43.008q-47.104 56.32-53.248 64.512-7.168 8.192-16.384 8.192h-52.224q-11.264 0-16.384-8.192l-54.272-64.512h43.008l32.768 33.792h41.984z" horiz-adv-x="389" />
<glyph unicode="&#xe80d;" d="M128 448h256v-64h-256zM480 352h-448c-17.6 0-32-14.4-32-32v-160c0-17.6 14.398-32 32-32h96v-128h256v128h96c17.6 0 32 14.4 32 32v160c0 17.6-14.4 32-32 32zM352 32h-192v160h192v-160zM487.2 304c0-12.813-10.387-23.2-23.199-23.2-12.813 0-23.201 10.387-23.201 23.2s10.388 23.2 23.201 23.2c12.813 0 23.199-10.387 23.199-23.2z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
themes/baggy/fonts/icomoon.ttf Executable file → Normal file

Binary file not shown.

BIN
themes/baggy/fonts/icomoon.woff Executable file → Normal file

Binary file not shown.

27
themes/baggy/home.twig Normal file → Executable file
View File

@ -18,17 +18,27 @@
{% if entries is empty %}
<div class="messages warning"><p>{% trans "No articles found." %}</p></div>
{% else %}
<div>
{% include '_display-mode.twig' %}
{% include '_sorting.twig' %}
</div>
{% block pager %}
{% if nb_results > 1 %}
<div class="results">
<div class="nb-results">{{ nb_results }} {% trans "results" %}</div>
<div class="nb-results">{{ nb_results }} {% trans "results" %}{% if search_term is defined %} {% trans %}found for « {{ search_term }} »{% endtrans %}{% endif %}</div>
{{ page_links | raw }}
</div>
{% elseif nb_results == 1 %}
{% if search_term is defined %}
<div class="results">
<div class="nb-results">{% trans "Only one result found for " %} « {{ search_term }} »</div>
</div>
{% endif %}
{% endif %}
{% endblock %}
<div class="list-entries">
<div id="list-entries" class="list-entries">
{% for entry in entries %}
<div id="entry-{{ entry.id|e }}" class="entrie">
<div id="entry-{{ entry.id|e }}" class="entrie"{% if listmode %} style="width:100%; margin-left:0;"{% endif %}>
<h2><a href="index.php?view=view&amp;id={{ entry.id|e }}">{{ entry.title|raw }}</a></h2>
{% if entry.content| getReadingTime > 0 %}
<div class="estimatedTime"><a target="_blank" title="{% trans "estimated reading time:" %} {{ entry.content| getReadingTime }} min" class="tool reading-time"><span>{% trans "estimated reading time :" %} {{ entry.content| getReadingTime }} min</span></div>
@ -46,7 +56,14 @@
{% endfor %}
</div>
{% if view == 'home' %}{% if nb_results > 1 %}<a title="{% trans "Mark all the entries as read" %}" href="./?action=archive_all">{{ "Mark all the entries as read" }}</a>{% endif %}{% endif %}
{% endif %}
{{ block('pager') }}
{% if view == 'home' %}{% if nb_results > 1 %}<a title="{% trans "Mark all the entries as read" %}" href="./?action=archive_all">{{ "Mark all the entries as read" }}</a>{% endif %}{% endif %}
{% if search_term is defined %}<a title="{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}" href="./?action=add_tag&search={{ search_term }}">{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}</a>{% endif %}
{% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;tag={{ tag.value }}">{% trans "Download the articles from this tag in an epub" %}</a>
{% elseif search_term is defined %}<a title="{% trans "Download the articles from this search in an epub" %}" href="./?epub&amp;method=search&amp;search={{ search_term }}">{% trans "Download the articles from this search in an epub" %}</a>
{% else %}<a title="{% trans "Download the articles from this category in an epub" %}" href="./?epub&amp;method=category&amp;category={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %}
{% endif %}
{% endblock %}

BIN
themes/baggy/img/baggy/blank.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

BIN
themes/baggy/img/baggy/list.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

BIN
themes/baggy/img/baggy/table.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,6 +0,0 @@
$(document).ready(function() {
current_url = window.location.href
if (current_url.match("&closewin=true")) {
window.close();
}
});

View File

@ -1,12 +1,48 @@
document.addEventListener('DOMContentLoaded', function() {
var menu = document.getElementById('menu');
$.fn.ready(function() {
menu.addEventListener('click', function(){
if(this.nextElementSibling.style.display === "block") {
this.nextElementSibling.style.display = "none";
}else {
this.nextElementSibling.style.display = "block";
}
var $listmode = $('#listmode'),
$listentries = $("#list-entries");
/* ==========================================================================
Menu
========================================================================== */
$("#menu").click(function(){
$("#links").toggle();
});
});
/* ==========================================================================
List mode or Table Mode
========================================================================== */
$listmode.click(function(){
if ( $.cookie("listmode") == 1 ) {
// Cookie
$.removeCookie("listmode");
$listentries.removeClass("listmode");
$listmode.removeClass("tablemode");
$listmode.addClass("listmode");
}
else {
// Cookie
$.cookie("listmode", 1, {expires: 365});
$listentries.addClass("listmode");
$listmode.removeClass("listmode");
$listmode.addClass("tablemode");
}
});
/* ==========================================================================
Cookie listmode
========================================================================== */
if ( $.cookie("listmode") == 1 ) {
$listentries.addClass("listmode");
$listmode.removeClass("listmode");
$listmode.addClass("tablemode");
}
});

File diff suppressed because one or more lines are too long

117
themes/baggy/js/jquery.cookie.js Executable file
View File

@ -0,0 +1,117 @@
/*!
* jQuery Cookie Plugin v1.4.0
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2013 Klaus Hartl
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as anonymous module.
define(['jquery'], factory);
} else {
// Browser globals.
factory(jQuery);
}
}(function ($) {
var pluses = /\+/g;
function encode(s) {
return config.raw ? s : encodeURIComponent(s);
}
function decode(s) {
return config.raw ? s : decodeURIComponent(s);
}
function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
}
function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
} catch(e) {
return;
}
try {
// If we can't parse the cookie, ignore it, it's unusable.
return config.json ? JSON.parse(s) : s;
} catch(e) {}
}
function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
}
var config = $.cookie = function (key, value, options) {
// Write
if (value !== undefined && !$.isFunction(value)) {
options = $.extend({}, config.defaults, options);
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setDate(t.getDate() + days);
}
return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// Read
var result = key ? undefined : {};
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
var cookies = document.cookie ? document.cookie.split('; ') : [];
for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
var name = decode(parts.shift());
var cookie = parts.join('=');
if (key && key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
}
// Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
}
return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
if ($.cookie(key) !== undefined) {
// Must not alter options, thus extending a fresh object...
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return true;
}
return false;
};
}));

3
themes/baggy/layout.twig Normal file → Executable file
View File

@ -21,6 +21,9 @@
{% block precontent %}{% endblock %}
{% block messages %}
{% include '_messages.twig' %}
{% if includeImport %}
{% include '_import.twig' %}
{% endif %}
{% endblock %}
<div id="content" class="w600p center">
{% block content %}{% endblock %}

Some files were not shown because too many files have changed in this diff Show More