Compare commits

...
2316 Commits
Author SHA1 Message Date
Veloman Yunkan 091e9370e9 Automatic wombatization in case of updated test data 2026-03-17 14:43:49 +04:00
Veloman Yunkan e8dcf14fad Testing of an inter-page link with a hash
Added testing of an internal inter-page link with a fragment component.

Existing references to entries in issues.html served as such links
(which is how the bug was noticed), however it is better to have
a dedicated row in the test matrix for such a case.
2026-03-17 14:43:49 +04:00
Veloman Yunkan 755da7c255 Testing of links on a dynamic page
Note that the test dynamic page uses assignment to innerHTML (the method
of DOM manipulation is important in the context of interaction with
wombat.js which may not fully and correctly handle all the possible ways
in which dynamic content may appear).
2026-03-17 14:43:49 +04:00
Veloman Yunkan cb15d155f6 Added testing results for wombatized pages 2026-03-17 14:43:49 +04:00
Veloman Yunkan 75f98b88ef Wombatization of test pages
Added a script for wombatization of test pages
2026-03-17 14:43:49 +04:00
Veloman Yunkan db423a5ba9 Added a nested iframe test page
Also added a column to the test matrix table corresponding to this
additional dimension of testing.
2026-03-17 14:43:49 +04:00
Veloman Yunkan 75e34fa6e2 Enter test data for viewer testing
Added test data for centralized manual testing of various corner cases
of the kiwix-serve frontend.
2026-03-17 14:43:49 +04:00
Kelson 30adab7337 Merge pull request #1279 from kiwix/release-14.2.0
Release 14.2.0
2026-03-02 08:18:56 +01:00
Emmanuel Engelhart d2d9cdf044 Add 14.2.0 Changelog 2026-03-02 08:17:20 +01:00
Emmanuel Engelhart a833fde211 Bump-up version to 14.2.0 2026-03-02 07:58:28 +01:00
Kelson a4720363a8 Merge pull request #1276 from kiwix/faster_removeAccents
Optimized removeAccents() for ASCII-only input
2026-02-27 17:26:13 +01:00
Veloman Yunkan 15e1194c63 Optimized removeAccents() for ASCII-only input 2026-02-27 19:40:57 +04:00
Veloman Yunkan 0021f2b336 A unit test for removeAccents() 2026-02-27 19:35:42 +04:00
Kelson 52f2de8a26 Merge pull request #1272 from kiwix/support_for_ipv4only_systems
Made kiwix-serve friendly to IPv4-only systems
2026-02-24 18:55:18 +01:00
Veloman Yunkan 34fc831c13 Documentation of a subset of Server API
Documentation of libkiwix API has been largely neglected. This commit
documents the Server API having to do with the functionality fixed in
the previous commit.
2026-02-24 16:10:57 +04:00
Veloman Yunkan 47f1a61443 Made kiwix-serve friendly to IPv4-only systems
kiwix-serve without an explicitly supplied -i option can henceforth run
on IPv4-only systems. Before this fix, an "Unable to instantiate the
HTTP daemon." error was being reported.
2026-02-23 20:04:04 +04:00
Veloman Yunkan a3b246fd6d Extracted InternalServer::startMHD(flags, sockaddr) 2026-02-23 19:50:38 +04:00
Veloman Yunkan 75ff043476 Moved some code into InSockAddr::setAnyAddress() 2026-02-23 19:22:03 +04:00
Veloman Yunkan 0f7458c693 Extracted getMHDFlags() 2026-02-23 19:11:43 +04:00
Veloman Yunkan add7c4cc3a Moved some code into InSockAddr::setAddress() 2026-02-23 19:11:43 +04:00
Veloman Yunkan fcdc3a7eaf Extracted InSockAddr 2026-02-23 19:09:22 +04:00
Veloman Yunkan db3705dd23 Errors in InternalServer::startMHD() as exceptions 2026-02-23 18:58:55 +04:00
Veloman Yunkan 3b34130cfc Extracted InternalServer::startMHD() 2026-02-23 18:14:09 +04:00
Veloman Yunkan b773e93a95 Negative unit tests for starting the server 2026-02-23 18:14:09 +04:00
Veloman Yunkan e481164258 Extracted test/testing_tools.h 2026-02-23 18:09:33 +04:00
Kelson 32cd7661ff Merge pull request #1274 from kiwix/no-pagination-atom-feed
No pagination for Atom feed URL
2026-02-23 10:14:07 +01:00
Emmanuel Engelhart f29c69aac6 No pagination for Atom feed URL
New cache busting id for skin/index.js
2026-02-23 10:13:10 +01:00
Kelson 3fe9be88d4 Merge pull request #1273 from kiwix/add-10.211-to-known-loca-ip-range
Add 10.211 IPv4 range to known local ranges
2026-02-23 10:11:09 +01:00
Emmanuel Engelhart 910ad614c4 Add 10.211 IPv4 range to known local ranges 2026-02-23 10:10:59 +01:00
Kelson 724b6cc0cc Merge pull request #1220 from kiwix/dirScan
Introduce Manager::addBooksFromDirectory()
2026-02-22 20:01:34 +01:00
Nikhil Tanwar c5ec7651a6 Introduce Manager::addBooksFromDirectory()
Added a function to load books from a directory. Requires rootPath to iterate over.
2026-02-22 19:35:07 +01:00
Kelson 949a612fd4 Merge pull request #1261 from shbhmexe/fix/stability-and-correctness-fixes
Fix core stability, correctness, and memory issues
2026-02-22 19:01:31 +01:00
shbhmexe 974a5ff87f Fix infinite loop and memory leak in getNetworkInterfacesWin
- Increment the iteration counter to prevent infinite loops when GetAdaptersAddresses returns ERROR_BUFFER_OVERFLOW.
- Free the previously allocated buffer before re-allocating to prevent memory leaks on retry.

Signed-off-by: shbhmexe <shubhushukla586@gmail.com>
2026-02-22 18:37:36 +01:00
shbhmexe 503e55c87e Fix various stability and correctness issues in libkiwix
- Fix infinite loop and memory leak in Windows network tools (networkTools.cpp)
- Improve exception safety in removeAccents using RAII (stringTools.cpp)
- Change getBookById to return by value to avoid dangling references (library.cpp)
- Use proper constant for HTTP 416 instead of magic number (response.cpp)
- Fix exception slicing in getDownload re-throw (downloader.cpp)

Signed-off-by: shbhmexe <shubhushukla586@gmail.com>
2026-02-22 18:37:36 +01:00
Veloman Yunkan fb6448011b Merge pull request #1256 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2026-02-12 17:39:01 +04:00
Veloman Yunkan 9493c092ad Updated/regenerated static/skin/languages.js 2026-02-12 17:32:41 +04:00
translatewiki.net 52b02b964d Localisation updates from https://translatewiki.net. 2026-02-12 13:07:56 +01:00
Kelson 78124833b3 Merge pull request #1269 from kiwix/windows-2025-ci
Windows 2025 ci
2026-02-11 11:12:36 +01:00
Emmanuel Engelhart 0d9bab12b9 use windows-2025 runner for CI 2026-02-11 11:05:22 +01:00
Veloman Yunkan 650f2d0027 Merge pull request #1255 from pippotadde/fix-empty-pattern-737
Fix: avoid error on empty search pattern (#1255)
2026-01-12 12:38:07 +04:00
Veloman Yunkan b6a13d9b03 Minor cosmetic clean-up
Performed minor cosmetic clean-up in the ServerSearchTest.searchResults
unit-test:

1. Fixed alignment in test data
2. Moved the test point for search query "yellow submarine" out of the
   set of test points for search query "jazz"
2026-01-12 12:21:56 +04:00
pippotadde 86f125f8fb Fix: avoid error on empty search pattern 2026-01-12 12:18:53 +04:00
pippotadde 3cd8554733 Tools: Add kiwix::trim() helper and unit tests 2025-12-28 20:31:51 +01:00
Kelson a10f0f287f Merge pull request #1262 from kiwix/carriage-return-after-error
Carriage return after error
2025-12-27 11:55:07 +01:00
Emmanuel Engelhart cdf48fc987 Add carriage return after error 2025-12-27 11:40:28 +01:00
Veloman Yunkan ba598bda9b Merge pull request #1259 from pippotadde/pr_yellow_tests
Testing of a search pattern containing a space
2025-12-23 21:36:58 +04:00
pippotadde 0ad2710884 Tests: add yellow submarine search case 2025-12-23 17:02:52 +01:00
pippotadde ab31ed9ca5 Tests: deduplicate yellow search results 2025-12-23 17:01:13 +01:00
Veloman Yunkan 86cbc303cb Merge pull request #1258 from pippotadde/pr_viewerjs
Frontend: guard empty search input
2025-12-23 17:50:25 +04:00
pippotadde 19d9bc36c8 Frontend: guard empty search input 2025-12-23 14:30:42 +01:00
Kelson f82bfc068f Merge pull request #1252 from kiwix/release-14.1.1
Release 14.1.1
2025-11-30 16:37:21 +01:00
Emmanuel Engelhart e6335be897 14.1.1 changelog 2025-11-30 16:34:37 +01:00
Emmanuel Engelhart 1074e833b7 Bump-up version to 14.1.1 2025-11-30 16:30:36 +01:00
Kelson 9da5fbad1e Merge pull request #1248 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2025-11-30 16:29:27 +01:00
translatewiki.net 1869fb4e8e Localisation updates from https://translatewiki.net. 2025-11-30 16:29:19 +01:00
Kelson 536198fa38 Merge pull request #1250 from kiwix/kiwix-serve_nosearchbar_fix
Fix for kiwix-serve --nosearchbar
2025-11-30 15:51:19 +01:00
Veloman Yunkan ca808718f7 Fix for kiwix-serve --nosearchbar
In kiwix-serve --nosearchbar mode the viewer is still engaged and
its setup must completed appropriately, otherwise the content requested
via the URL is not loaded.
2025-11-28 17:16:24 +04:00
Veloman Yunkan b65074f961 Got rid of an unused variable
This should have been done in commit "Viewer iframe location is checked
every 0.1s"
2025-11-28 17:10:13 +04:00
Kelson 8b7d1ef9ec Merge pull request #1249 from kiwix/fix_for_intermittent_content_blank.html_errors
Fix for intermittent /content/blank.html errors
2025-11-27 16:38:54 +01:00
Veloman Yunkan 8b0f01fa9b Fix for intermittent /content/blank.html errors
Monitoring of the iframe content URL could result in the check being
performed while the iframe placeholder page /skin/blank.html was still
loaded (a slow connection increased the odds of it happening). This was
contrary to the assumptions behind the logic of that procedure and the
outcome was an attempt to load the /content/blank.html page with a
subsequent 404 error.

Now that situation is taken into account.
2025-11-27 17:55:14 +04:00
Kelson 33f22eb966 Merge pull request #1241 from vighnesh-sawant/mustache-tag-escaping
Avoid interpretation of content coming from zim by mustache
2025-11-10 20:10:16 +01:00
Vighnesh 55c13c3d24 Avoid interpretation of content coming from zim by mustache 2025-11-10 20:10:06 +01:00
Veloman Yunkan 2b1f556c20 Merge pull request #1239 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2025-11-10 18:41:03 +04:00
translatewiki.net e0cd5a1642 Localisation updates from https://translatewiki.net. 2025-11-10 13:13:07 +01:00
Kelson 0a9ba9b678 Merge pull request #1237 from kiwix/release-14.1.0
Release 14.1.0
2025-10-31 15:17:48 +01:00
Emmanuel Engelhart db9607e55e 14.1.0 changelog 2025-10-31 15:12:00 +01:00
Emmanuel Engelhart 592e22732e Bump-up version to 14.1.0 2025-10-31 15:12:00 +01:00
Kelson 17f0ad2cf4 Merge pull request #1234 from vighnesh-sawant/standard-port-enhancment
Add functions which return displayable addresses
2025-10-31 14:55:35 +01:00
Vighnesh 4928509991 Implement a function which returns server access url 2025-10-31 18:11:22 +05:30
Vighnesh c2df0a99fe Normalize m_root in Server itself 2025-10-31 18:11:22 +05:30
Vighnesh cffca3ad85 Sync m_addr of Server and InternalServer 2025-10-31 18:11:22 +05:30
Kelson 0a2bebe7a3 Merge pull request #1218 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2025-10-31 12:44:38 +01:00
translatewiki.net bdb1f09884 Localisation updates from https://translatewiki.net. 2025-10-30 13:12:50 +01:00
Kelson f98b79348b Merge pull request #1235 from kiwix/macos-15
Use macos-15 in CI
2025-10-29 13:00:13 +01:00
Emmanuel Engelhart 2b8927e66e Use macos-15 in CI 2025-10-27 18:00:23 +01:00
Kelson d0fb8214c3 Merge pull request #1233 from kiwix/fix-compilation-libicu76
Fix build with ICU 76+
2025-10-27 18:00:05 +01:00
Emmanuel Engelhart d5894092fd Fix build with ICU 76+ 2025-10-27 15:45:27 +01:00
Kelson dd09e3ce5f Merge pull request #1231 from kiwix/requires-libzim-9.4.0
Requires now libzim 9.4.0
2025-10-24 13:16:20 +02:00
Emmanuel Engelhart 92954bbbe4 Requires now libzim 9.4.0 2025-10-24 12:46:09 +02:00
Kelson 7a9edccbc5 Merge pull request #1200 from kiwix/kiwix-serve-pagination-fix
Fix kiwix-serve pagination
2025-10-24 12:35:29 +02:00
Emmanuel Engelhart e9e76e0901 Adapt tests to results offset starting at 0 2025-10-24 12:24:20 +02:00
Emmanuel Engelhart ad9377083f Add search template variable 'startLabel' 2025-10-24 12:24:20 +02:00
Emmanuel Engelhart d857b0f8f6 Fix kiwix-serve pagination 2025-10-24 12:24:20 +02:00
Kelson 759d430232 Merge pull request #1230 from kiwix/spelling_correction
Spelling correction of full titles
2025-10-14 11:24:52 +02:00
Veloman Yunkan e402dcabcb Another way of testing that an existing spellings DB is reused
Under Windows and Packages CI workflows the previous approach to testing
that an existing spellings DB file is reused didn't work since it relied
on an auxiliary test ensuring that a spellings database cannot be
created in a read-only directory, whereas

1. under Windows a temporary directory couldn't be made read-only
   (leading to the failure of the auxiliary test)

2. in the Packages workflow the build was run with root privileges
   and the read-onliness of the target directory was ignored
   (leading to the same failure).

So the test was rewritten to actually check the content of the target
directory as well as the modifications times of the target directory and
the database file.
2025-10-09 17:15:17 +04:00
Veloman Yunkan 54bd29e3ed A more portable spelling correction unit-test
Packages workflow jobs run under Ubuntu 22.04 Jammy and 24.04 Noble with
different versions of libxapian.so. So the spelling correction unit test
must adapt accordingly.
2025-10-09 15:08:04 +04:00
Veloman Yunkan 5c8aa240ad SpellingsDB is created in a cache directory
The path parameter of the SpellingsDB constructor has been changed to
denote the path of the cache directory where spellings databases for
different ZIM archive should be stored. The filename of the spellings
database is generated from the ZIM archive UUID and the current version
of the spellings database implementation.
2025-10-06 17:20:22 +04:00
Veloman Yunkan 39672f0532 SpellingsDB reuses an existing database
Also the underlying Xapian database is now in a single-file format.
2025-10-06 17:20:13 +04:00
Veloman Yunkan e0491adc85 Extracted testSpellingCorrections()
... so that it can be reused in a test where an existing spellings
database is opened.
2025-10-06 17:19:42 +04:00
Veloman Yunkan 286649e8c3 Enter SpellingsDB 2025-10-06 17:19:32 +04:00
Veloman Yunkan b799c0648b ZIM file for testing spelling correction
The ZIM file test/data/spelling_correction_test.zim was generated using
the script test/data/create_zim_file_for_testing_spelling_correction
included in this commit.
2025-10-02 20:02:08 +04:00
Kelson 050906c1b2 Merge pull request #1226 from kiwix/new_illustrations_api
Switched to the new illustrations API
2025-09-25 19:53:14 +02:00
Veloman Yunkan f5e35b4c5d Switched to the new illustrations API 2025-09-25 12:21:07 +04:00
Kelson 2a858dcc82 Merge pull request #1224 from kiwix/previewable_books_for_empty_root
Empty urlRootLocation doesn't disable book preview links
2025-09-13 21:48:33 +02:00
Veloman Yunkan ac9be80369 InternalServer::setContentAccessUrl(LibraryDumper&)
Code deduplication
2025-09-13 18:34:54 +04:00
Veloman Yunkan d0a48cc9cc LibraryDumper::content{Server -> Access}Url
Renamed contentServerUrl in LibraryDumper to contentAccessUrl to avoid
confusion with contentServerUrl concept at Server/InternalServer level
(roughly, contentAccessUrl = contentServerUrl + "/content").
2025-09-13 18:34:54 +04:00
Veloman Yunkan 67b7e25494 Empty root isn't confused with missing contentServerURL
Running kiwix-serve without --catalogOnly and
--urlRootLocation resulted in non-clickable book tiles since
empty root was confused with empty contentServerURL which controlled
whether book preview links should be activated.

This commit fixes that bug and adds respective unit-tests.
2025-09-13 18:34:02 +04:00
Kelson 2b4b90f8a3 Merge pull request #1219 from kiwix/catalog_only_mode
Support for catalog only mode of kiwix-serve
2025-09-11 13:45:32 +02:00
Veloman Yunkan 208dd96edd Catalog-only mode of nojs welcome page 2025-09-08 18:52:50 +04:00
Veloman Yunkan 51ffa31037 Book preview link is derived from the content URL
Now the book preview link is derived from the content URL link found in
the OPDS entry for a book.  If no content URL is present in the OPDS
entry for a book, then preview link is disabled.
2025-09-08 18:39:48 +04:00
Veloman Yunkan 968d1c1067 Support for setting the content server URL 2025-09-08 18:39:48 +04:00
Veloman Yunkan c205a4703b Welcome page no longer depends on viewer_settings.js
The dependence of the welcome page on viewer_settings.js was added
in commit cc6aa9b162 as a hack which
stayed there after the need for it was removed by PR#1044.
2025-09-08 18:39:48 +04:00
Veloman Yunkan 8bff8d5891 Fixed indentation 2025-09-08 18:39:48 +04:00
Veloman Yunkan 94e51e363c Illustrations are not suppressed for ZIM-less books 2025-09-08 18:39:48 +04:00
Veloman Yunkan 25e03ce597 Support for catalog-only mode 2025-09-08 18:39:48 +04:00
Veloman Yunkan 8a3c4c92e0 Enhanced test library.xml with an entry not backed by a ZIM file
The test data was modified so that support for catalog only mode
of kiwix-serve can be properly tested.

The effect of this change in the test data on the library_server unit
test demonstrates that although the new entry does not appear in the
catalog (for example, no catalog_v2_entries* test cases were affected)
the category and language of this ghost entry slipped into the
observable output.
2025-09-08 18:39:48 +04:00
Kelson 95fc478e37 Merge pull request #1213 from kiwix/anchorage_2025.08.15
Viewer detects & tracks intrapage navigation too
2025-09-08 13:51:03 +02:00
Veloman Yunkan 26253ebf8f Viewer iframe location is checked every 0.1s
The only way to detect change of the iframe location performed via
`History.pushState()` or `History.replaceState()` is to constantly
monitor it, since those methods don't trigger any events.
2025-09-08 12:51:10 +04:00
Veloman Yunkan 34c6a3bfab Viewer detects & tracks intrapage navigation too
Clicking intrapage links (of the form <a href="#anchor">) inside the
viewer iframe is detected by the viewer and reflected in the URL in the
address bar.

The solution only works if following the link is performed by the
browser as a default action. It doesn't work if the changed URL in the
address bar after clicking a link is a result of `History.pushState()`
or `History.replaceState()` being called by javascript code installed as
an event handled on the link (which is the case in single page
applications).
2025-09-01 16:37:38 +04:00
Veloman Yunkan 5c1f8de891 Merge pull request #1212 from kiwix/viewer_chaperon_mode
Viewer chaperon mode
2025-09-01 13:22:33 +04:00
Veloman Yunkan 334ca0295e Viewer chaperon mode
Viewer now rewrites internal links so that opening them in a new
tab/window keeps the viewer around. Thus the viewer acts as a chaperon
for the users preventing them from finding themselves out of the
viewer's supervision. Of course there are ways to circumvent such
oversight, however it has always been the case with chaperons in all
cultures in all epochs.
2025-09-01 12:31:41 +04:00
Kelson e2186cfb7b Merge pull request #1215 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2025-08-29 20:25:25 +02:00
translatewiki.net a4985c62c7 Localisation updates from https://translatewiki.net. 2025-08-28 14:09:22 +02:00
Veloman Yunkan 2f9deb0eaa Merge pull request #1197 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2025-08-15 12:22:03 +04:00
Veloman Yunkan b8d975068e Updated/regenerated static/skin/languages.js 2025-08-15 12:00:10 +04:00
translatewiki.net 222327586e Localisation updates from https://translatewiki.net. 2025-08-14 14:07:56 +02:00
Kelson 699cbccf38 Merge pull request #1209 from kiwix/focal-to-jammy-ci
Use Ubuntu 22.04 in place of 20.04 for CI
2025-06-22 20:54:17 +02:00
Emmanuel Engelhart fdc3a715c4 Use macOS 14 in place of macOS 13 for the CI 2025-06-22 20:15:05 +02:00
Emmanuel Engelhart 3bfcc5108f Use Ubuntu 22.04 in place of 20.04 for CI 2025-06-22 20:09:39 +02:00
Kelson 6225b4608a Merge pull request #1208 from kiwix/allow-popups-to-escape-sandbox
Popups are allowed to escape the browser sandbox
2025-06-15 19:44:42 +02:00
Veloman Yunkan 0bc9a25179 Popups are allowed to escape the browser sandbox
... so that Chrome doesn't block attempts to open PDF links in a new
tab/window.
2025-06-15 19:07:48 +04:00
Kelson 9433f7cef9 Merge pull request #1207 from kiwix/remove-ubuntu-20.04-ci-cd
Stop publishing on Ubuntu 20.04 PPA
2025-06-13 10:58:02 +02:00
Emmanuel Engelhart eba66a391f Stop publishing on Ubuntu 20.04 PPA 2025-06-13 10:40:20 +02:00
Kelson fa6c93950c Merge pull request #1202 from kiwix/print-css
First kiwix-serve print.css
2025-06-13 10:21:33 +02:00
Emmanuel Engelhart 850e330461 First kiwix-serve print.css 2025-06-13 10:21:00 +02:00
Kelson eccb8db7b7 Merge pull request #1205 from kiwix/default-white-background-iframe
Default (real) white background for kiwix-serve iframe/body
2025-06-10 16:55:13 +02:00
Emmanuel Engelhart 33bb0141c0 Default white background for kiwix-serve iframe/body 2025-06-10 16:45:36 +02:00
Kelson b3b4064ad6 Merge pull request #1204 from kiwix/fix-book-title-js-encoding
Stop HTML encoding by mustache.js
2025-06-09 16:31:29 +02:00
Emmanuel Engelhart 2fdd2066cd Avoid ZIM title double HTML encoding 2025-06-09 16:30:29 +02:00
Emmanuel Engelhart 4dfcfbe1fa Stop HTML encoding by mustache.js 2025-06-09 16:30:29 +02:00
Kelson e912f0520e Merge pull request #1201 from kiwix/default-kiwix-serve-iframe-background
Default kiwix serve iframe background
2025-06-09 13:33:49 +02:00
Emmanuel Engelhart c4ced73f7c Update cacheid for kiwix.css 2025-06-08 09:35:21 +02:00
Emmanuel Engelhart c244d95a94 Add kiwix-serve homepage background color 2025-06-08 09:35:21 +02:00
Emmanuel Engelhart 04d301d024 Add default iframe background color 2025-06-08 09:35:21 +02:00
Kelson e415958ae9 Merge pull request #1203 from kiwix/fix-readme-ci-badge
Fix Readme CI badge
2025-06-08 09:33:08 +02:00
Emmanuel Engelhart f9b8789723 Fix Readme CI badge 2025-06-08 09:15:16 +02:00
Veloman Yunkan fe806396f9 Merge pull request #1185 from aditii2712/overflow-fix
Fix Search Bar Placeholder Text Overflow.
2025-06-02 12:07:18 +04:00
aditii2712 5729b6540c Fixing placeholder text in search bar input field. 2025-06-02 11:56:40 +04:00
Kelson 33c83eec4b Merge pull request #1196 from kiwix/nicer_internal_server_error_page
Nicer Internal Server Error page
2025-05-22 20:41:49 +02:00
Veloman Yunkan be69584637 Additional error info on the HTTP 500 error page
Additional error info (text of the exception thrown by low level C++
code) is shown inside a text box of the same style as used for the
advice on the 404 error page (we either need to change the name of the
CSS style, or introduce a separate style for this piece of information).
2025-05-22 15:29:09 +04:00
Veloman Yunkan 2ba29f76e1 Nicer Internal Server Error page
Updated the Internal Server Error page to match the 404 (Content Not
Found) error page.
2025-05-22 15:29:05 +04:00
Kelson 222e4396c7 Merge pull request #1195 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2025-05-19 14:26:47 +02:00
translatewiki.net 4c480952d1 Localisation updates from https://translatewiki.net. 2025-05-19 14:07:14 +02:00
Kelson 79479788f9 Merge pull request #1178 from kiwix/nicer_error_pages
Nicer 404 error and external link blocker pages
2025-05-17 13:56:46 +02:00
Veloman Yunkan 3cd1f7854a Fully translated external link blocker page 2025-05-14 21:40:23 +04:00
Veloman Yunkan 58a211d01d Renamed a parameter in external link blocker template 2025-05-14 21:37:52 +04:00
Veloman Yunkan 07fc40da5a Translation works on external link blocker
This comes at the cost of broken support for SeaMonkey (due to usage of
import.meta in i18n.js)
2025-05-14 21:36:43 +04:00
Veloman Yunkan d961447e1e Started translating the external link blocker page
The external link blocker page isn't actually translated since it is not
managed by the viewer. Will port the translation code from the viewer.js
in next commit.
2025-05-14 21:35:29 +04:00
Veloman Yunkan c9ebeb7b96 New external link blocker page
The page doesn't support translation yet.
2025-05-14 21:34:14 +04:00
Veloman Yunkan 2d73ed31a9 Handling translation in ServerTest.HttpSexy404HtmlError
The failing test point in the ServerTest.Http404HtmlError unit-test
has been superseded by the enhanced ServerTest.HttpSexy404HtmlError
unit-test, resulting in a clean test-suite.
2025-05-14 21:30:05 +04:00
Veloman Yunkan 6a0349e575 Preparing ServerTest.HttpSexy404HtmlError for translation 2025-05-14 21:30:02 +04:00
Veloman Yunkan 6d80edc04a Translated the advice on the new 404 error page
Translation of the multi-line/multi-paragraph advice is done under the
assumption that its structure  (5 paragraphs, two of which serve as
entries in a bulleted list) can be preserved in the translations by
proper phrasing, i.e. the advice must be translated as a whole rather
than each of its sentences (which act as units of translation) separately.
2025-05-14 21:27:56 +04:00
Veloman Yunkan b3a33747f0 More simple translations on the new 404 error page 2025-05-14 21:25:59 +04:00
Veloman Yunkan f47490e1bc Started translation of the new 404 error page
- Enabled translation on the new 404 error page
- Translated its title & heading

This commit also fixes the failure of the ServerTest.UserLanguageControl
unit-test.

The only remaining failing test case is ServerTest.Http404HtmlError
(only for url=/ROOT%23%3F/content/zimfile/invalid-article?userlang=test).
2025-05-14 21:23:34 +04:00
Veloman Yunkan 1ce909ae68 ServerTest.HttpSexy404HtmlError unit-test
Converted a few failing test points of the ServerTest.Http404HtmlError
unit-test into a new unit-test ServerTest.HttpSexy404HtmlError.

Some broken test cases still remain.
2025-05-14 21:20:00 +04:00
Veloman Yunkan 5eb31d7286 New 404 error page
The page doesn't support translation, yet.

The new 404 error page is used only when accessing ZIM file content
(i.e. as a response from the `/content` API endpoint).

One notable difference from the previous error page is that now no hint
is provided about whether the error is due to trying to access a
non-existent book/ZIM-file or non-existent resource inside a valid
book/ZIM-file (previously such a hint was present in the suggested
search URL). However, when displayed in the viewer this difference can
be seen in the viewer toolbar - book related buttons are hidden if the
URL points to a non-existent book.

This change breaks some unit tests. They will be fixed in a separate
commit.
2025-05-14 21:18:36 +04:00
Veloman Yunkan 107421cdab Merge pull request #1179 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2025-05-10 17:21:29 +04:00
Veloman Yunkan bd474b9720 Updated/regenerated static/skin/languages.js 2025-05-10 17:12:19 +04:00
translatewiki.net e66ba1a532 Localisation updates from https://translatewiki.net. 2025-05-10 17:12:19 +04:00
Veloman Yunkan c1e58331d7 Merge pull request #1194 from kiwix/linux_ci_runner_upgrade
Upgraded Linux CI runner to ubuntu-22.04
2025-05-10 17:11:57 +04:00
Veloman Yunkan d776077c5f Upgraded Linux CI runner to ubuntu-22.04
We are quite late with this change and were simply forced to make it
because ubuntu-20.04 has been phased out in GitHub Workflows.
2025-05-10 17:00:52 +04:00
Kelson b8e997f805 Merge pull request #1190 from kiwix/pastproof_atomics_check
Made atomics check work with old compilers
2025-04-02 18:47:21 +02:00
Veloman Yunkan b7421d7dae Made atomics check work with old compilers
In our CI a quite old version of gcc (6.3.0) is used for the aarch64
configs and it was confused by the (previous) code of the test program
intended to find out if libatomics must be explicitly passed to the
linker.
2025-04-02 15:10:46 +04:00
Kelson a0c99f879b Merge pull request #1183 from Optimus-NP/kiwix-tools-issue_731
Show spinner while loading ZIM content in viewer iframe
2025-03-30 19:51:09 +02:00
Naman Pahwa c7e86c9dbb Show spinner while loading ZIM content in viewer iframe
- Implemented a spinner to improve user experience while ZIM content is loading in the viewer iframe.
- Added .loader and .spinner styles in kiwix.css.
- The iframe content is initially hidden (visibility: hidden) and will be displayed once loading completes.
- Used CSS animations (@keyframes spin) for a smooth rotating effect.
2025-03-26 21:51:43 +05:30
Kelson ad58a501b0 Merge pull request #1181 from Optimus-NP/kiwix-tools_issues_724
Replace multiple comma-separated languages with 'mul'
2025-03-17 18:55:07 +01:00
Naman Pahwa a55e8565d1 Replace multiple comma-separated languages with 'mul'
- Refactored language code handling to replace multiple comma-separated values with 'mul'.
- Single-language entries remain unchanged.
- created the helper function to get the lang tag
- ensured the consistent behaviour for js and nojs version for the kiwix library view
2025-03-17 21:10:53 +05:30
Kelson 610b8cbb2a Merge pull request #1177 from kiwix/handling_of_pdf_links_under_chrome_on_android
If PDF viewer is not enabled PDFs are downloaded instead
2025-02-07 05:35:53 +01:00
Veloman Yunkan e087f1c82f If PDF viewer is not enabled, PDFs are downloaded
Chrome on Android doesn't support displaying PDF documents inline so an
attempt to load a PDF into the Kiwix viewer iframe fails in a way that
may be confusing to the users. In such situations it is better to offer
to the users to download the PDF file so that they can view it with a
dedicated application. Making the clicked PDF link to open in a new
tab/window achieves exactly that effect.
2025-02-07 05:32:30 +01:00
Kelson e5d3e6ff07 Merge pull request #1170 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2025-02-07 05:32:01 +01:00
translatewiki.net d0aeac64d0 Localisation updates from https://translatewiki.net. 2025-02-06 13:05:48 +01:00
Kelson 5da88c0ad7 Merge pull request #1176 from kiwix/handling_of_target_blank_external_links
Handling of external links with target="_blank"
2025-02-03 14:44:15 +01:00
Veloman Yunkan c7d3a38a3e Handling of external links with target="_blank"
External links with target="_blank" attribute are opened in a new tab/window.

Also included metaKey (Command key under Mac) in the list of click
modifiers that make the link to be opened in a new tab.
2025-02-03 17:11:29 +04:00
Kelson 6b74395455 Merge pull request #1175 from kiwix/fully_visible_suggestions
Autocompleter box size matches the content width
2025-02-03 13:25:35 +01:00
Veloman Yunkan 2eea6136d6 Full suggestion text is shown on hover
The width of the suggestion box is capped at 600 pixels. The full
text of a suggestion is shown on hover (doesn't work on mobile).
2025-02-03 16:11:53 +04:00
Veloman Yunkan 64eb0d10d6 Autocompleter box size matches the content width
Note however that no upper limit is set on the width of the
autocompleter box - it is possible, but I don't see how we could
come up with a good value for it.
2025-01-27 17:20:39 +04:00
Kelson 664944f16c Merge pull request #1174 from OlCe2/main
meson.build: Comment on 'threads' dependency required for FreeBSD
2025-01-15 17:51:23 +01:00
Olivier Certner d34a0c5bf0 meson.build: Comment on 'threads' dependency required for FreeBSD
While here, wrap the long test line.
2025-01-13 18:43:28 +01:00
Kelson bb65d77229 Merge pull request #1169 from kiwix/wait-1s-to-aria2c
Wait up to 1s to le aria2c to start
2025-01-12 12:17:56 +01:00
Emmanuel Engelhart 98849831da Wait up to 1s to le aria2c to start 2025-01-12 12:17:10 +01:00
Kelson 2e3eae5615 Merge pull request #1173 from OlCe2/main
Two compilation fixes for FreeBSD
2025-01-08 16:47:14 +01:00
Olivier Certner 93ace5cf45 networkTools: Fix compilation on FreeBSD
Header <netinet/in.h> should be included (as per POSIX) to get a definition for
'struct sockaddr_in'.  Fixes commit "add ipv6 support to HTTP daemon".
2025-01-08 15:07:30 +01:00
Olivier Certner cb777ed836 meson.build: Test whether linking with 'libatomic' is necessary
See the added comments for more details.

While here, initialize 'extra_deps' once and for all at the top and append to it
when needed.
2025-01-08 15:07:00 +01:00
Kelson 27e7840cce Merge pull request #1158 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-12-20 10:18:53 +01:00
translatewiki.net 99c28b72b5 Localisation updates from https://translatewiki.net. 2024-12-20 10:11:36 +01:00
Kelson 81b579cdcb Merge pull request #1168 from kiwix/remove-set-output-in-workflows
Update a few dependencies in the workflows
2024-12-20 10:08:08 +01:00
Emmanuel Engelhart f693f700bc Remove HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 2024-12-20 09:13:26 +01:00
Emmanuel Engelhart 50f04d7060 'pkg-config' is already installed with proper version 2024-12-20 09:08:35 +01:00
Emmanuel Engelhart 8fdaa5f4db Bump-up to actions/checkout@v4 2024-12-20 08:31:44 +01:00
Emmanuel Engelhart 297627fbc7 Bump-up to actions/upload-artifact@v4 2024-12-20 08:31:44 +01:00
Emmanuel Engelhart a3708c68ce Replace deprecated 'set-output' in workflows 2024-12-20 08:31:43 +01:00
Kelson a809c671fd Merge pull request #1167 from kiwix/better-deb-control-version-checking
Check versus minor version of dependencies
2024-12-20 08:29:03 +01:00
Emmanuel Engelhart 31477bc99b Check versus minor version of dependencies 2024-12-20 08:19:45 +01:00
Kelson 6c37e2827e Merge pull request #1165 from kiwix/kelson42-patch-1
Stop building Windows with DEBUG symbols in CI
2024-11-26 08:37:20 +00:00
Kelson 9138f91c31 Stop building Windows with DEBUG symbols in CI 2024-11-26 09:35:55 +01:00
rgaudin 9bd568fe0e Merge pull request #1160 from kiwix/1157_fixmagnet
magnetLink queryString to start with ? and not ?&
2024-11-08 16:27:46 +00:00
rgaudin eca7cf86e6 fixup! Fixed #1157: magnetLink queryString to start with ? and not ?& 2024-11-08 15:56:58 +00:00
rgaudin 77f4fd7447 Fixed #1157: magnetLink queryString to start with ? and not ?& 2024-11-08 14:58:28 +00:00
Kelson 84ebee899c Merge pull request #1154 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-10-31 11:37:34 +01:00
translatewiki.net 9eed5da3be Localisation updates from https://translatewiki.net. 2024-10-28 13:07:08 +01:00
Kelson 20abebd623 Merge pull request #1152 from kiwix/macos13
removed temp hack
2024-10-09 17:18:52 +00:00
rgaudin 58a1af85b9 removed temp hack and unlink 2024-10-09 14:38:25 +00:00
Kelson 585f55d885 Merge pull request #1151 from kiwix/feature/fix-server-set-addr
Fix Server::setAddress
2024-10-09 14:24:46 +00:00
sgourdas 8b00c2eb22 Fix Server::setAddress 2024-10-09 12:17:01 +03:00
Kelson c8bddd6cf4 Merge pull request #1149 from kiwix/feature/remove-ip-prefix
Remove 169.254 prefix
2024-10-09 05:25:16 +00:00
sgourdas 5d1b6274a8 Remove 169.254 prefix 2024-10-08 21:39:12 +03:00
Kelson 0de9bd0a99 Merge pull request #1141 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-10-08 16:15:40 +00:00
translatewiki.net b62274efdd Localisation updates from https://translatewiki.net. 2024-10-07 14:06:39 +02:00
Kelson 4a1498d8df Merge pull request #1145 from kiwix/ci_fix
Fix broken CI on Linux (aarch64, focal)
2024-10-03 16:48:21 +00:00
Veloman Yunkan f6df2342cf Fix broken CI on Linux (aarch64, focal) 2024-10-03 17:13:34 +04:00
Kelson 8bbda99cab Merge pull request #1132 from kiwix/feature/best-public-ip
Refactor getBestPublicIp for all valid ips
2024-10-02 19:31:17 +00:00
sgourdas 95529d2c0a Add ip availability check in server start 2024-10-02 20:55:13 +03:00
sgourdas b80699916d Refactor getBestPublicIp for both protocols 2024-10-02 20:55:11 +03:00
sgourdas 534916929d Line cleanup 2024-09-30 19:39:40 +03:00
sgourdas 02ab2ce5a5 Make server getters const 2024-09-30 19:39:40 +03:00
sgourdas 8930095c52 Make IpMode members uppercase 2024-09-30 19:39:40 +03:00
Kelson bef3ec7694 Merge pull request #1140 from kiwix/release-14.0.0
libkiwix 14.0.0 Changelog
2024-09-28 14:36:36 +00:00
Emmanuel Engelhart 9057686a25 libkiwix 14.0.0 Changelog 2024-09-28 14:29:07 +00:00
Kelson 723dd977fe Merge pull request #1126 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-09-28 14:28:07 +00:00
translatewiki.net 0b87d4fe04 Localisation updates from https://translatewiki.net. 2024-09-26 14:07:55 +02:00
Kelson ea31e2f42f Merge pull request #1137 from kiwix/catalog_search_without_boolean_operators
Catalog search without support for Xapian boolean operators
2024-09-25 15:16:53 +00:00
Veloman Yunkan 01bda6b2c0 Disabled Xapian boolean operators in catalog query 2024-09-25 17:42:50 +04:00
Veloman Yunkan de64a5a724 Testing of Xapian query operators in catalog search 2024-09-25 17:42:50 +04:00
Veloman Yunkan 90dd1cb3f0 Enhanced test book descriptions with xapian keywords
Added to test book descriptions words that serve as keywords
for query syntax with boolean operators (or, and, not, xor, near, adj) enabled.

Note that the change in indexed text has lead to the change in the order
of returned results.
2024-09-25 16:41:38 +04:00
Kelson 0b14fda94d Merge pull request #1135 from kiwix/fix-deb-package-deps
Fix deb package dependencies
2024-09-18 12:39:34 +00:00
Emmanuel Engelhart fe965faf1b Fix deb package dependencies 2024-09-18 14:21:42 +02:00
Kelson 6ad1776242 Merge pull request #1133 from kiwix/pkgconfig
Generation of libkiwix.pc via meson's pkgconfig module
2024-09-17 10:35:29 +02:00
Veloman Yunkan cbfd3ec7c4 Dropped generation of kiwix.pc
Below are the contents of libkiwix.pc and kiwix.pc files generated using
the new and old approaches, respectively, for native_dyn and
native_static configurations:

```
$ cat BUILD_native_dyn/INSTALL/lib/x86_64-linux-gnu/pkgconfig/libkiwix.pc
prefix=<REDACTED>
includedir=${prefix}/include
libdir=${prefix}/lib/x86_64-linux-gnu

Name: libkiwix
Description: A library that contains useful primitives that Kiwix readers have in common
Version: 14.0.0
Requires.private: icu-i18n, libzim < 10.0.0, libzim >= 9.0.0, pugixml, libcurl, libmicrohttpd, zlib, xapian-core
Libs: -L${prefix}/lib/x86_64-linux-gnu -lkiwix
Libs.private: -pthread
Cflags: -I${includedir}

$ cat BUILD_native_dyn/INSTALL/lib/x86_64-linux-gnu/pkgconfig/kiwix.pc
prefix=<REDACTED>
libdir=${prefix}/lib64
includedir=${prefix}/include

Name: libkiwix
Description: A library that contains a lot of things used by used by other kiwix programs
Version: 14.0.0
Requires: libzim icu-i18n pugixml libcurl libmicrohttpd xapian-core
Libs: -L${libdir} -lkiwix
Cflags: -I${includedir}/

$ cat BUILD_native_static/INSTALL/lib/x86_64-linux-gnu/pkgconfig/libkiwix.pc
prefix=<REDACTED>
includedir=${prefix}/include
libdir=${prefix}/lib/x86_64-linux-gnu

Name: libkiwix
Description: A library that contains useful primitives that Kiwix readers have in common
Version: 14.0.0
Requires: icu-i18n, libzim < 10.0.0, libzim >= 9.0.0, pugixml, libcurl, libmicrohttpd, zlib, xapian-core
Libs: -L${prefix}/lib/x86_64-linux-gnu -lkiwix -pthread
Cflags: -I${includedir} -pthread

$ cat BUILD_native_static/INSTALL/lib/x86_64-linux-gnu/pkgconfig/kiwix.pc
prefix=<REDACTED>
libdir=${prefix}/lib64
includedir=${prefix}/include

Name: libkiwix
Description: A library that contains a lot of things used by used by other kiwix programs
Version: 14.0.0
Requires: libzim icu-i18n pugixml libcurl libmicrohttpd xapian-core
Libs: -L${libdir} -lkiwix
Cflags: -I${includedir}/
```

The notable differences are:

- libdir changed from `${prefix}/lib64` to `${prefix}/lib/x86_64-linux-gnu`

- for native_dyn configuration Requires.private is used

- pthread has appeared in Libs/Libs.private and/or Cflags

- version information was added to the libzim requirement
2024-09-17 12:26:14 +04:00
Veloman Yunkan f6765137e7 Fixed the libzim version requirement
Also fixed capitalization in an error message
2024-09-16 17:26:28 +04:00
Veloman Yunkan c24e04c8da Generation of libkiwix.pc via meson's pkgconfig module
Generation of kiwix.pc using the previous approach still stays in place.
2024-09-16 17:25:42 +04:00
Kelson 327fec1877 Merge pull request #1131 from kiwix/ungarbled_binary_resources
Ungarbled binary resources
2024-09-14 14:43:23 +02:00
Veloman Yunkan c8524b95bc Protection against adding resources of new types
Now if a static resource of a new type is added the build will
fail unless the list of known file type extensions is updated.
2024-09-12 17:39:49 +04:00
Veloman Yunkan 0ac3130b0d Added an extension to an extensionless resource
... so that all resources have extensions and can be automatically
categorized as binary or text based on extension (coming next).
2024-09-12 17:18:16 +04:00
Veloman Yunkan 425ae1efae Disabled dos2unix conversion for binary resources 2024-09-11 17:52:11 +04:00
Veloman Yunkan 920d603a89 Validation of resource content against cacheid
Added a test that checks that the static resources returned by the
server have content that matches their cacheid. This test currently
fails because some binary resources (e.g. png images) are garbled by the
dos2unix conversion.
2024-09-11 17:46:40 +04:00
Kelson f5c91cc272 Merge pull request #1094 from kiwix/downloadBtn
More conspicuous download button
2024-09-11 11:42:59 +02:00
Veloman Yunkan 3cdc036858 Updated nojs library page
... to keep it in sync with the JSful library page that has been
modified in the previous commit.
2024-09-11 13:17:27 +04:00
Nikhil Tanwar 29bfaa5c5b Move download button to end of tile
- Changed the position of download button to the end of tile and
  added a proper download icon to it. When the button is hovered it
  becomes darker.

- Also internationalized the "Download" text on the modal download widget
  and added download size information to it.
2024-09-11 11:02:08 +04:00
Kelson bec80e8091 Merge pull request #1123 from kiwix/handling_of_external_app_links
Handling of external app links in the viewer
2024-09-10 13:45:50 +00:00
Veloman Yunkan 2da9801bac Fixed ctrl-clicking of links for Zimit2 ZIMs
Zimit2 ZIMs employ Wombat for client-side rewriting of URLs. The latter
interferes with our approach of handling in the viewer CTRL/SHIFT-clicks
on links inside articles. This commit disables Wombat temporarily while
changing the href attribute of the clicked link.
2024-09-10 17:03:04 +04:00
Veloman Yunkan 16ebc6611b Handling of external app links in the viewer
Links that should be handled/opened by external applications - such as email
addresses (mailto:), phone numbers (tel:), etc - are opened by the
viewer in a new tab/window, thus avoiding any issues with content
security policy.
2024-09-10 16:28:28 +04:00
Kelson d5a44b913e Merge pull request #1127 from kiwix/crisp_illustration_on_book_tile
Illustration size on book tile is fixed to 48x48
2024-09-09 18:03:57 +00:00
Veloman Yunkan a63a162c58 Illustration size on book tile is fixed to 48x48 2024-09-09 17:47:55 +00:00
Kelson c29cd8cf3b Merge pull request #1128 from kiwix/mul_as_mul
Deprived pseudolang mul of a self-name
2024-09-09 15:03:47 +00:00
Veloman Yunkan 04bf1be9d6 Deprived pseudolang mul of a self-name
ICU package contains a special code "mul" with a self-name of "multiple
languages". libkiwix now suppresses that. As a result the self-name of
"mul" (like for any other unknown language code) is the code itself
(i.e. "mul").

The most prominent user-visible effect of this change is that the
language filter in the library page no longer contains a "Multiple
languages" entry if there is a legacy ZIM file with the language set to
"mul" - that entry now shows up as "Mul".
2024-09-09 16:57:07 +04:00
Kelson 59054aa5ad Merge pull request #1109 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-09-08 20:49:31 +00:00
translatewiki.net 1b8dde0115 Localisation updates from https://translatewiki.net. 2024-09-08 19:34:42 +00:00
Kelson 9d0f6a3170 Merge pull request #1125 from kiwix/remove-windows-cross-compile
Remove Windows cross-compilation from CI
2024-09-08 19:34:27 +00:00
Emmanuel Engelhart c16ed0aa4c Remove Windows cross-compilation from CI 2024-09-08 21:18:16 +02:00
Kelson 3d95b386c6 Merge pull request #1124 from kiwix/better-libzim-version-check
Better check libzim version
2024-09-07 13:43:37 +00:00
Emmanuel Engelhart a3f5a654f2 Better check libzim version 2024-09-07 15:35:30 +02:00
Kelson 801b1df304 Merge pull request #1121 from kiwix/safe_tags_without_makeup
Untransformed (but HTML-safe) tags in the kiwix-serve frontend
2024-09-05 04:43:29 +00:00
Veloman Yunkan 2b8a071c6f Fixed cacheids in unit-tests 2024-09-04 19:13:41 +04:00
Veloman Yunkan 00fae37f2d Fixed vertical alignment of the tag filter indicator 2024-09-04 19:09:35 +04:00
Veloman Yunkan 846404e959 Proper HTML encoding/decoding of tags in the frontend
- Tags in the OPDS feed are HTML encoded and must be decoded.

- Tag values must be HTML encoded when injected into the DOM:

  * When the injection is done by setting the innerHTML attribute of a
    DOM element, HTML encoding must be done explicitly (since that text
    is going to be parsed as HTML).

  * When the tag value is expanded into a string that is then set as an
    attribute of a DOM element via the setAttribute() method, no HTML
    encoding must be done (since Element.setAttribute() directly sets
    that value and no HTML decoding is involved in that operation).
2024-09-04 18:43:24 +04:00
Veloman Yunkan fbcd160efd Disabled beautification of tags in the frontend 2024-09-04 18:15:01 +04:00
Kelson 196185dd73 Merge pull request #1119 from kiwix/fix-debian-control-file-for-v14
Fix deb control file for 14.0.0
2024-09-02 18:14:23 +00:00
Emmanuel Engelhart affb996769 Fix deb control file for 14.0.0 2024-09-02 19:59:27 +02:00
Kelson 418abbcefa Merge pull request #1116 from kiwix/bump-up-to-version-14.0.0
Bump-up version to 14.0.0
2024-09-01 12:47:13 +00:00
Emmanuel Engelhart 00867a13f6 Rename deb .install file 2024-09-01 14:39:45 +02:00
Emmanuel Engelhart e096c7e2fd Bump-up version to 14.0.0 2024-09-01 10:48:49 +02:00
Kelson 69341eab47 Merge pull request #1114 from kiwix/update-deb-packages-ci-cd
Update deb packages CI/CD
2024-09-01 08:41:30 +00:00
Emmanuel Engelhart 082727ebb6 Comment out Debian related CI/CD 2024-09-01 10:31:19 +02:00
Emmanuel Engelhart 75a4f8b806 Requires libzim9 2024-09-01 10:14:03 +02:00
Emmanuel Engelhart 2eaa1c4649 Refresh deb packages CI/CD 2024-09-01 10:06:31 +02:00
Matthieu Gautier 199a10d093 Merge pull request #1113 from kiwix/ci_windows 2024-08-27 13:25:40 +02:00
Matthieu Gautier 4812fb18f6 Ensure resources use \n as newline and not \r\n
It appears that git on Windows replace `\n` with `\r\n` in the working
tree.

So compiled resources contain a extra `\r` and our tests are failing.
2024-08-27 13:17:53 +02:00
Matthieu Gautier 940818d801 Do not do iterator underflow in urlDecode
`value.end() - 3` may be "before start of string" if string length is < 3.
On Windows debug, is throw an exception.
On other platform it is probably an undefined behavior.

Rewrite the test to avoid such invalid substraction.
2024-08-27 13:17:53 +02:00
Matthieu Gautier 5182a66b19 Update test to have Windows paths on Windows 2024-08-27 13:17:53 +02:00
Matthieu Gautier b688aa294a [CI] Build libkiwix on Windows CI
As kiwix-build now publish deps archive for libkiwix on Windows (github actions),
we can now start compiling (and test !!) libkiwix on Windows CI.
2024-08-22 17:04:54 +02:00
Kelson 27ad77c566 Merge pull request #1111 from kiwix/revert-1110-revert-1107-feature/data-directory
"Removed getDataDirectory()" again
2024-08-21 23:50:24 +02:00
Matthieu Gautier 7677f76854 Revert "Revert "Removed getDataDirectory()"" 2024-08-21 22:58:42 +02:00
Kelson 513a8d1383 Merge pull request #1105 from kiwix/string_slugification
Add String Slugification for Generating File Name
2024-08-14 20:24:08 +00:00
ShaopengLin be464a5986 Introduce getSlugifiedFileName in tools.h
The function sanitizes file names depending on OS.
2024-08-14 20:11:11 +00:00
Kelson c2042c3be8 Merge pull request #1112 from kiwix/public_i18n_api
Public i18n API
2024-08-14 11:18:29 +00:00
Veloman Yunkan 8d480c8b6d Introduced translateBookCategory() 2024-08-14 12:45:37 +04:00
Veloman Yunkan 82ff88f5d8 Made some i18n API public 2024-08-14 12:45:37 +04:00
Veloman Yunkan 2535f210b3 Renamed src/server/{i18n -> i18n_utils}.h
... so that i18n.h can be introduced in include/
2024-08-14 12:44:20 +04:00
Matthieu Gautier cb0a2c234a Merge pull request #1110 from kiwix/revert-1107-feature/data-directory 2024-08-12 16:32:21 +02:00
Matthieu Gautier 5a73a75798 Revert "Removed getDataDirectory()" 2024-08-12 16:22:01 +02:00
Matthieu Gautier 0ea756c42a Merge pull request #1107 from kiwix/feature/data-directory 2024-08-12 14:41:33 +02:00
sgourdas 7108dfa9c2 Remove makeDirectory 2024-08-11 23:46:48 +03:00
sgourdas 9fd8e81de2 Remove getDataDirectory 2024-08-11 23:46:34 +03:00
sgourdas 566b40a2f8 Pass download directory directly to startDownload 2024-08-11 23:45:27 +03:00
Kelson ff6d8a4b30 Merge pull request #1108 from kiwix/pkgconf
Replace pkg-config by pkgconf package in deb
2024-08-07 05:03:38 +00:00
Emmanuel Engelhart f456ce3e93 Replace pkg-config by pkgconf 2024-08-07 06:53:25 +02:00
Veloman Yunkan ece40966f1 Merge pull request #1097 from kiwix/robust_download_management
kiwix::Downloader's constructor pauses all downloads found in the aria session file
2024-07-08 20:26:24 +04:00
Veloman Yunkan 65a777d4ed Active downloads are paused before starting aria2c
The aria session file is edited before starting aria2c. This ensures
responsive aria2c RPC server even after a crash.
2024-07-08 20:17:07 +04:00
Veloman Yunkan 42295c9010 Defense against non-responsive aria RPC on startup
Downloader constructor may get stuck if the check for the aria2c RPC
being up gets stuck due to curl_easy_perform() never returning (or, at
least, taking longer than I was willing to wait). Currently it may
happen, for example, after an application crashes with active downloads
being saved to slow media. Then the next creation of a Downloader object
will deal with aria2c immediately resuming those downloads and becoming
unresponsive as it struggles flushing incoming data to slow storage (or
because of some other unfortunate timing of the RPC request being
received while it cannot yet be served).
2024-07-08 20:17:07 +04:00
Veloman Yunkan e8afcbe6ae Downloader::close() is called in destructor 2024-07-08 20:17:07 +04:00
Veloman Yunkan c46cd403ae Downloader::close() pauses all downloads
Otherwise, creating a Downloader object next time may take very long (or
that operation may get stuck) if an active download is being saved to slow
media.
2024-07-08 20:17:07 +04:00
Kelson af96b19bd1 Merge pull request #1091 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-06-30 13:38:26 +02:00
translatewiki.net 8a00e9383d Localisation updates from https://translatewiki.net. 2024-06-27 14:07:38 +02:00
Veloman Yunkan 964131ce47 Merge pull request #1096 from harsha-mangena/i1095-consistancy-issue
[fixes]ZIM size being advertized inconsistently between MB and MiB
2024-06-24 12:50:29 +04:00
harsha-mangena 97832c8436 Book sizes are shown in binary (MiB, etc) units
Switched display of ZIM sizes from decimal (MB) to binary (MiB) units.

Also made the size value to be formatted in a more human friendly way
(fractional part is shown only to provide at least three significant
digits).
2024-06-24 12:40:49 +04:00
Kelson beab8d7041 Merge pull request #1093 from kiwix/network_tools_backward_compatibility
Backward compatible support for IPv6
2024-06-11 11:27:05 +02:00
Veloman Yunkan 75bddbf725 "Unittests" for getBestPublicIp() & getNetworkInterfaces()
The unit-tests only call the said functions and print their output
which should then be examined by the maintainer.
2024-06-11 11:19:49 +02:00
Veloman Yunkan 5927550a36 kiwix::getNetworkInterfacesIPv4Or6()
- Restored kiwix::getNetworkInterfaces() API to the version before
  support for IPv6 was introduced

- Renamed the new API method to kiwix::getNetworkInterfacesIPv4Or6()
2024-06-11 11:19:49 +02:00
Veloman Yunkan 135c6f875d Hid some symbols in unnamed namespace 2024-06-11 11:19:49 +02:00
Veloman Yunkan 83101679a0 Backward compatible overload of getBestPublicIp() 2024-06-11 11:19:49 +02:00
Matthieu Gautier ae4b652fb2 Merge pull request #1092 from kiwix/fix_extra_lib_args 2024-06-03 16:06:43 +02:00
Matthieu Gautier 01b94418eb Fix wrong usage of extra_link_args variable. 2024-06-03 14:44:31 +02:00
Kelson a1ce3d10b1 Merge pull request #1074 from aryanA101a/main
Add IPv6 support to HTTP daemon
2024-05-29 21:10:13 +02:00
Aryan Arora b7eadf95bf handle ip modes & add compilation flags for windows build 2024-05-29 21:05:01 +02:00
Aryan Arora a6cf161341 add ipv6 support to HTTP daemon 2024-05-29 21:05:01 +02:00
Veloman Yunkan 618a718645 Merge pull request #1073 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-05-27 18:01:00 +04:00
Veloman Yunkan c2cc4c39f1 Registered i18n resources for new languages 2024-05-27 17:41:29 +04:00
translatewiki.net 8477e04ffa Localisation updates from https://translatewiki.net. 2024-05-27 14:07:46 +02:00
Kelson 5345d43017 Merge pull request #1086 from kiwix/getdatadirectory-doc
Improve  documentation
2024-05-20 15:43:33 +02:00
Emmanuel Engelhart 843adb3397 Improve documentation 2024-05-20 15:41:31 +02:00
Kelson 4fe4a88574 Merge pull request #1088 from kiwix/better-kiwix-server-home-buttom-width
Better Kiwix Server taskbar home button max-width
2024-05-20 14:22:28 +02:00
Emmanuel Engelhart 6ee09114eb Better Kiwix Server taskbar home button max-width 2024-05-19 20:54:36 +02:00
Kelson 7366938785 Merge pull request #1079 from kiwix/raw-tag-displayed
Revert humanfriendly tag display in Kiwix Server
2024-05-12 17:59:06 +02:00
Emmanuel Engelhart 84405b1318 Revert humanfriendly tag disply in Kiwix Server 2024-05-12 17:54:34 +02:00
Kelson a0c4118fd3 Merge pull request #1080 from kiwix/improve-custom-lang-mapping
Complete custom language mapping
2024-05-12 15:02:58 +02:00
Emmanuel Engelhart 72147aec5b Complete custom language mapping 2024-05-11 16:42:43 +02:00
Kelson 016072292c Merge pull request #1075 from kiwix/kiwix-server-accesskeys
Add Kiwix server a few accesskeys
2024-05-11 11:23:35 +02:00
Emmanuel Engelhart 2964cc5e92 Updates tests 2024-05-11 11:23:27 +02:00
Emmanuel Engelhart 8d766335b4 Add accesskey to Kiwix Server home button 2024-05-11 11:23:27 +02:00
Emmanuel Engelhart 5450bcd3c2 Add accesskey to Kiwix Server library button 2024-05-11 11:23:27 +02:00
Emmanuel Engelhart a0b66eae0c Add accesskey to Kiwix Server random button 2024-05-11 11:23:27 +02:00
Emmanuel Engelhart 22c75245a5 Add accesskey to Kiwix Server multiple search inputs 2024-05-11 11:23:27 +02:00
Kelson f40c3426a5 Merge pull request #1077 from kiwix/better-kiwix-server-download-overlay
Better labels/hints for Kiwix Server download overlay
2024-05-11 11:23:05 +02:00
Emmanuel Engelhart 8e6569362c Better labels/hints for Kiwix Server download overlay 2024-05-11 11:21:39 +02:00
Matthieu Gautier eb328ed73d Merge pull request #1071 from kiwix/build_dir 2024-04-09 14:16:39 +02:00
Matthieu Gautier 21e3c5c19f New version of dl_deps_archive action doesn't need os_name. 2024-04-09 11:36:55 +02:00
Matthieu Gautier f0927fec49 Build libkiwix with new archive from kiwix-build 2024-04-08 16:46:14 +02:00
Matthieu Gautier 66693cd73e Merge pull request #1070 from kiwix/new-kiwix-serve-head-link 2024-03-20 17:50:32 +01:00
Emmanuel Engelhart be8a60c330 Add OpenSearch description in Kiwix Server homepage 2024-03-20 16:11:00 +01:00
Matthieu Gautier 8009edd349 Merge pull request #1066 from kiwix/smarter_startDownload 2024-03-20 10:52:56 +01:00
Veloman Yunkan 3733e506c1 More reasonable criteria for reusing a download 2024-03-20 11:26:18 +04:00
Veloman Yunkan 9fe81e9bce Introduced downloadCanBeReused() helper
The dubious logic of when an existing download can be reused by
Downloader::startDownload() is preserved.
2024-03-20 11:23:00 +04:00
Veloman Yunkan 4ab6215046 Downloader::Options typedef 2024-03-20 11:23:00 +04:00
Veloman Yunkan ff88430227 Documented the problem with startDownload() 2024-03-20 11:23:00 +04:00
Veloman Yunkan 922c138809 Merge pull request #1064 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-03-09 16:08:48 +04:00
Veloman Yunkan fa9ebf55fc Updated languages.js 2024-03-09 15:59:44 +04:00
translatewiki.net bc9b5a0354 Localisation updates from https://translatewiki.net. 2024-03-07 13:07:14 +01:00
Matthieu Gautier 719e947ddf Merge pull request #1068 from kiwix/zim_name_vs_book_name 2024-03-06 15:09:39 +01:00
Veloman Yunkan e3fffd9b23 Negative tests for books selection during search 2024-03-06 14:39:09 +01:00
Veloman Yunkan 6ef4f6396e Testing of filtering during search by books.filter.name 2024-03-06 14:39:09 +01:00
Veloman Yunkan d8b4c1584c Testing of filtering during search by books.name 2024-03-06 14:39:09 +01:00
Veloman Yunkan 1fc006f639 Deduplicated test data in two test points
This was mainly done to prevent further duplication of test data as more
test points around the same query are added next but is also useful on
its own.
2024-03-06 14:39:09 +01:00
Matthieu Gautier a8368b3a0d Merge pull request #1067 from kiwix/stricter_namemapper 2024-03-06 14:24:41 +01:00
Veloman Yunkan 068555de38 Paths in the error are put in single quotes 2024-03-06 11:43:43 +01:00
Veloman Yunkan 0168764f4c NameMapper detects all naming conflicts
Also this change leads to the change in the mapping (since conflicts
that previously went undetected and just overwrote the existing entry
are now rejected).
2024-03-06 11:43:43 +01:00
Veloman Yunkan 181893d31a Cleanup after previous change
- Got rid of the continue statement
- Renamed the function parameter
- Fixed indentation
2024-03-06 11:43:43 +01:00
Veloman Yunkan 5b9daf0d9d Extracted HumanReadableNameMapper::mapName()
No cleanup of the new function was performed to keep the diff minimal.
2024-03-06 11:43:43 +01:00
Veloman Yunkan 4e64d26ede Added more name conflicts to NameMapper unit test
The extended setup of the NameMapper unit test demonstrates (by the fact
that this change doesn't break the tests that check the stderr) that
certain naming conflicts escape NameMapper's attention.
2024-03-06 11:43:43 +01:00
Veloman Yunkan 5e669cd65c Deduplicated test output data 2024-03-06 11:43:43 +01:00
Veloman Yunkan 2749564424 Made entries in test library point to "different" files
Two entries in test library.xml used to point to the same file path.
Note that though the third entry pointed to a different file name
it is a symbolic link to the same file.

Now all three entries point to pseudo-different files (having the
same content behind them).

This change is needed so that tests don't break when detection of
conflicting book names is made stricter.
2024-03-06 11:43:43 +01:00
Kelson ddde6db16f Merge pull request #1061 from kiwix/release-3.1.0
Release 3.1.0
2024-02-25 15:11:31 +01:00
Emmanuel Engelhart 50d1394a0a Add 13.1.0 Changelog 2024-02-25 15:11:13 +01:00
Emmanuel Engelhart a6040b2ecd Bump-up version to 13.1.0 2024-02-25 15:11:13 +01:00
Kelson 4e755bc949 Merge pull request #1062 from kiwix/compilation_warnings
Fixed compilation warnings
2024-02-25 15:01:17 +01:00
Veloman Yunkan cfab4c946a Fixed compilation warnings 2024-02-25 16:15:29 +04:00
Kelson 57a265f73c Merge pull request #1059 from kiwix/translatewiki 2024-02-22 19:23:34 +01:00
translatewiki.net 3f945813f2 Localisation updates from https://translatewiki.net. 2024-02-22 13:07:51 +01:00
Veloman Yunkan 86100b39ed Merge pull request #1047 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-02-20 14:40:42 +04:00
Matthieu Gautier b2ae6d1fca Update i18n translation files. 2024-02-20 10:40:44 +01:00
translatewiki.net e82b62c552 Localisation updates from https://translatewiki.net. 2024-02-19 13:07:49 +01:00
Kelson 5fba3f434e Merge pull request #1054 from kiwix/polyfilljs
Enter polyfills.js
2024-02-15 16:04:45 +01:00
Veloman Yunkan 3ac36e8ebd Enter polyfills.js
The `String.replaceAll` polyfill was borrowed (at 0% annual intereset
rate) from https://github.com/kiwix/kiwix-js/pull/1190/files.
2024-02-15 16:03:29 +01:00
Kelson 1babbc0e4a Merge pull request #1043 from kiwix/bookmarks_migrations
Migrate bookmarks between books
2024-02-15 16:01:46 +01:00
Matthieu Gautier 6b05eeb24b Add a small test on getBestTargetBookId and flavour. 2024-02-15 14:52:57 +01:00
Matthieu Gautier 73b855ce6b Add a getBestTargetBookId directly taking bookName, flavour and date. 2024-02-15 14:52:57 +01:00
Matthieu Gautier eaca7010bc Fix definition of UPGRADE_ONLY and ALLOW_DOWNGRADE.
`MigrationMode` was kind of defined in the context of an internal mode
used by `migrateBookmark(...)`.
But now, with `getBestTargetBookId`, it is broken.

This commit fix that and the associated implementation.
Now `UPGRADE_ONLY` will make `getBestTargetBookId` return only newer books.
and `ALLOW_DOWNGRADE` will return older books only if current book is
invalid.
2024-02-15 14:52:57 +01:00
Matthieu Gautier 6efdc43964 Correcly search for book's title with double quote (").
At indexation time, double quote are ignored, so a title as
`TED "talks" - Business` is indexed as `ted talks business`.

By removing the quotes, we ensure that our title "phrase" is not closed
too early and we correctly search for `ted PHRASE talks PHRASE business`
instead of `ted AND talks AND business`.
2024-02-15 14:52:57 +01:00
Matthieu Gautier 7a0ab3a429 Update tests to check book's title with double quotes (")
On top of modifying the existing test, the commit also make
`MigrateBookmark` test fails as `migrateBookmarks` now migrates
from `wrong-book-id-noname` to `Dummy id`.

Fix will be provided in next commit.
2024-02-15 14:52:57 +01:00
Matthieu Gautier 3e9d50fecb Make getBestTargetBookId public. 2024-02-15 14:52:57 +01:00
Matthieu Gautier f3a604380c Do not migrate bookmarks to an older book.
At least, it must be explicitly asked by the user.
2024-02-15 14:52:57 +01:00
Matthieu Gautier 167e0dc4b3 Only migrate bookmarks to books with the same flavour.
If there is no book with the same flavour, but book with same name and
different flavour, we do the migration to the other book.
2024-02-15 14:52:57 +01:00
Matthieu Gautier 14c9530afa [Test] Introduce variant books in sample library.
We will need them to test flavour/date bookmarks migration.
2024-02-15 14:52:57 +01:00
Matthieu Gautier 8d97686b81 Introduce migrateBookmarks to move (invalid) bookmarks to new books. 2024-02-15 14:52:57 +01:00
Matthieu Gautier b16f6b9561 Allow to filter books by flavour. 2024-02-15 14:52:57 +01:00
Matthieu Gautier a546effa15 Allow bookmark to be created from a Book and url/title. 2024-02-15 14:52:57 +01:00
Matthieu Gautier 699f96ca0d Add book's flavour in bookmark. 2024-02-15 14:52:57 +01:00
Matthieu Gautier 5a0644d32b Also store book's name in bookmark. 2024-02-15 14:52:57 +01:00
Matthieu Gautier 903f476f77 Test bookmarks serializations. 2024-02-15 14:52:57 +01:00
Matthieu Gautier bf1ab03332 [Test] Add missing flavour in books. 2024-02-15 14:52:57 +01:00
Matthieu Gautier 82cb1133e5 [Test] Add missing name in sample library.xml 2024-02-15 14:52:57 +01:00
Matthieu Gautier 9b9c61a194 Use a recursive_mutex instead of a mutex.
This allow us to internally call thread_safe function from already
locked context.
2024-02-15 14:52:57 +01:00
Matthieu Gautier c768d05b5b Merge pull request #1056 from kiwix/fix_macos_build
[CI] Fix macos python installation.
2024-02-15 14:52:19 +01:00
Matthieu Gautier fe018efc70 Update to new macos' python 3.12
Brew update its receipe about python and now use python 3.12 instead of
python 3.11.
2024-02-15 14:16:29 +01:00
Matthieu Gautier e625c25ef1 Merge pull request #1048 from Begasus/haiku
Haiku
2024-02-08 15:10:42 +01:00
Begasus b2ae1d66f5 Fix for getifaddrs on Haiku 2024-02-08 11:52:37 +01:00
Begasus 2818dd3151 Fix undeclared SIOCGIFCONF for Haiku 2024-02-08 11:51:12 +01:00
Kelson 09eec822c1 Merge pull request #1046 from kiwix/translation_of_search_results_page
Translation of search results page
2024-02-01 21:33:25 +01:00
Veloman Yunkan 34cd553642 Updated languages.js 2024-02-01 18:33:34 +04:00
Veloman Yunkan 70dd738801 Front-end calls the /search endpoint with userlang 2024-02-01 18:31:32 +04:00
Veloman Yunkan 958067d94d Backend translates the search results page
Now the search results page is presented by the backend in the language
controlled by the value of the `userlang` URL query parameter (or, if
the latter is missing, the value of the `Accept-Language:` HTTP header).

Note that the front-end doesn't yet take advantage of this
functionality.
2024-02-01 18:27:54 +04:00
Veloman Yunkan 33a3277400 Search result info as translatable text
However it is NOT actually translated by the backend yet
2024-02-01 18:27:33 +04:00
Veloman Yunkan 8f5714be07 Search results page header as translatable text
However it is NOT actually translated by the backend yet
2024-02-01 18:27:11 +04:00
Veloman Yunkan c4fa42f20b Search results page title as translatable text
However it is NOT actually translated by the backend yet
2024-02-01 18:22:36 +04:00
Matthieu Gautier 795fcb9de4 Merge pull request #1044 from kiwix/default_ui_language_is_resolved_in_the_frontend
Default UI language is resolved in the frontend
2024-01-31 17:54:56 +01:00
Veloman Yunkan c697611064 Dropped defaultUserLanguage from viewer_settings.js 2024-01-31 17:55:17 +04:00
Veloman Yunkan e5dab19844 Default UI language is resolved in the frontend
This change eliminates any need for defaultUserLanguage in
viewer_settings.js.
2024-01-31 17:55:09 +04:00
Veloman Yunkan 1f44465d09 Added translation counts to skin/languages.js
Note that static/skin/languages.js must be generated/updated manually
by running the static/generate_i18n_resources_list.py script. Previously
it had to be done only when new languages were added. Now the
translation counts will also need to be updated when new entries are
added to static/skin/i18n/en.json or upon merging a few translatewiki PRs.
2024-01-31 17:52:56 +04:00
Veloman Yunkan 258a6d029f Changed the format of skin/languages.js
... so that extra info about the count of translated strings can be
added.

Note that due to increased size skin/languages.js lost its
too-small-to-be-worth-compressing status.
2024-01-31 17:47:41 +04:00
Veloman Yunkan fc211d9a2e Cleaned up traces of userlang control via cookie 2024-01-31 17:41:37 +04:00
Veloman Yunkan aff801e6cc Merge pull request #1033 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2024-01-30 14:22:44 +04:00
translatewiki.net 3479589d53 Localisation updates from https://translatewiki.net. 2024-01-29 13:09:38 +01:00
Matthieu Gautier d2f20dba66 Merge pull request #1032 from kiwix/error_response_i18n
Translation of error pages
2024-01-29 10:58:55 +01:00
Veloman Yunkan dc3960c5f8 Fix against a malicious "</script>" in KIWIX_RESPONSE_DATA 2024-01-29 10:53:36 +01:00
Veloman Yunkan 1f9026f295 "</script>" inside KIWIX_RESPONSE_DATA is bad
Added a test case demonstrating how a bad error response could be
generated if </script> appears inside KIWIX_RESPONSE_DATA. That seems to
be the only problematic interaction between HTML-like syntax inside
javascript code (hence the deleted XXX comments on the other two test
cases).
2024-01-29 10:53:36 +01:00
Veloman Yunkan 30b3f05497 All kiwix-serve errors are now frontend-translatable
But the question is do we need all of them to be translatable in the
frontend? Maybe only responses to /random, /content and /search endpoints (that
are displayed in the viewer) should be translatable?

Also, the test cases against vulnerabilities in kiwix-serve seem to suggest
that KIWIX_RESPONSE_DATA should be HTML-encoded too.
2024-01-29 10:53:36 +01:00
Veloman Yunkan 13a6863183 Enabled frontend-side translation of 500 error page 2024-01-29 10:53:36 +01:00
Veloman Yunkan bb1a730253 Workaround for missing support for of std::variant
std::variant is not supported by the old version of gcc used under
aarch64.
2024-01-29 10:53:36 +01:00
Veloman Yunkan e1f067c086 Undid the demo of frontend-side error page translation
This undoes frontend-side translation of the demo case with the purpose
of having "clean" unit tests to support further work on this PR.
2024-01-29 10:53:36 +01:00
Veloman Yunkan 103a4516db Demo of error page translation
This commit demonstrates front-end-side translation of an error page
for a URL like /viewer#INVALIDBOOK/whatever (where INVALIDBOOK should
be a book name NOT present in the library).

Known issues:

- This change breaks a couple of subtests in the
  ServerTest.Http404HtmlError unit test.

- Changing the UI language while an error page is displayed in the
  viewer doesn't retranslate it.
2024-01-29 10:53:36 +01:00
Veloman Yunkan bceba4da06 HTML-template data is HTML-encoded
Non-HTML-encoded HTML-template data causes problems in HTML
even when it appears inside JS string (resulting in the <script> tag being
closed by a </script> appearing inside a JS string).

Besides, the KIWIX_RESPONSE_DATA and KIWIX_RESPONSE_TEMPLATE variables
are set on the window object so that they can be accessed from the top
context.

This commit eliminates the need for the `escapeQuote` parameter in
`escapeForJSON()` (that was introduced earlier in this PR) since now it
is set to false in all call contexts. However from the consistency point
of view, the default and intuitive behaviour of `escapeForJSON()` should
be to escape the quote symbols, which justifies the existence of that
parameter.
2024-01-10 00:28:37 +04:00
Veloman Yunkan e14de69271 The page template is embedded in the error response
This is a shortcut change since it doesn't make sense to send the error
page template with every error response (the viewer can fetch it from
the server once but that's slightly more work).
2024-01-10 00:28:37 +04:00
Veloman Yunkan d2fedf9123 Added error details in testing of error responses 2024-01-10 00:28:37 +04:00
Veloman Yunkan b151a2a480 Added KIWIX_RESPONSE_DATA to error response
Now the data used to generate an error response can be made to be
embedded in the response as a JS object KIWIX_RESPONSE_DATA.
2024-01-10 00:26:13 +04:00
Veloman Yunkan 8b8a2eede7 Slight enhancement of escapeForJSON()
- More familiar escape sequences for tab, newline and carriage return
  symbols.

- Quote symbol is escaped by default too, however that behaviour can
  be disabled for uses in HTML-related contexts where quotes should then
  be replaced with the character entity &quot;
2024-01-10 00:26:13 +04:00
Veloman Yunkan f3d3ab13cb Exposed escapeForJSON() in kiwix namespace
Note that it is declared in stringTools.h but its definition remains in
otherTools.cpp (to minimize the diff).
2024-01-10 00:26:13 +04:00
Veloman Yunkan 1553d52593 Lazy translation during error response generation
Now when parameterized messages are added to an error response, they are
not immediately instantiated (translated). Instead the message id and
the parameters of the message are recorded. The instantiation of the
messages happens right before generating the final content of the
response.
2024-01-10 00:26:13 +04:00
Veloman Yunkan f298acd45f Unmustached i18n::Parameters 2024-01-10 00:26:13 +04:00
Veloman Yunkan 0b542fe66d New implementation of ContentResponseBlueprint::Data 2024-01-10 00:25:18 +04:00
Veloman Yunkan e72fc2391d Enter ContentResponseBlueprint::Data
ContentResponseBlueprint::m_data is now an opaque data member
implemented in the .cpp and ready to be switched from
kainjow::mustache::data to a different implementation.
2024-01-09 22:50:34 +04:00
Veloman Yunkan d39e91f6bc Moved constructor into .cpp 2024-01-09 22:46:06 +04:00
Veloman Yunkan 0b7cd614c6 Fixed an encapsulation breach 2024-01-09 20:44:44 +04:00
Veloman Yunkan 54191bcfab Retired HTTP500Response::generateResponseObject()
... whereupon `ContentResponseBlueprint::generateResponseObject()` (and
`ContentResponseBlueprint` as a whole) no longer needs to be
polymorphic.
2024-01-09 20:44:44 +04:00
Veloman Yunkan 797f4c432c Testing of MIME-type of HTTP 500 response 2024-01-09 20:44:44 +04:00
Veloman Yunkan c57b8a0c7c Testing of HTTPErrorResponse translation 2024-01-09 20:44:44 +04:00
Veloman Yunkan aee6c23082 Decoupled RequestContext from MHD_Connection
This will simplify testing of Response utilities.
2024-01-09 20:44:44 +04:00
Veloman Yunkan af228bf45f Dropped cookies from RequestContext
This should have been done in PR#997 in order to better guarantee
a lasting solution to issue#995.
2024-01-09 20:44:44 +04:00
Veloman Yunkan b9323f17bb Introduced testing of HTTP response utils 2024-01-09 20:44:44 +04:00
Veloman Yunkan 8993f99587 ParameterizedMessage is actually a class 2024-01-09 20:44:44 +04:00
Veloman Yunkan 96b6f41244 Added i18n unit test 2024-01-09 20:25:59 +04:00
Veloman Yunkan 3f0ea083e6 Moved microhttpd_wrapper.h under server/ 2024-01-09 20:20:51 +04:00
Matthieu Gautier 9c5f5c7be0 Merge pull request #1036 from kiwix/fix_viewer_href
Get correct href value on `onClick` for "warc2zim" files.
2024-01-04 17:18:14 +01:00
Matthieu Gautier 9375f97b60 Get correct href value on onClick for "warc2zim" files.
Next to come warc2zim archive will come with "wombat" embedded.
The purpose of wombat is to be an interface with js code to mask that
we are in a scrapped/zim context to the js.

So it rewrite the `.href` attributes to the original url (ie, an
absolute url to the original website), even if the local relative url
is valid.

Let's ask to wombat to not rewrite href in our special case.
2024-01-04 17:03:40 +01:00
Matthieu Gautier 2ad5e510c6 Merge pull request #1035 from kiwix/ghaction
Use kiwix-build's github action to download dependencies.
2023-12-20 11:53:26 +01:00
Matthieu Gautier a2e56e2422 Make homebrew don't try to update installed dependencies. 2023-12-20 11:45:28 +01:00
Matthieu Gautier 8cc724b4a4 Use kiwix-build's github action to download dependencies. 2023-12-20 11:45:28 +01:00
Kelson fa212fd6ae Merge pull request #1027 from kiwix/polish-apple-ci
Better use GitHub action .env directive
2023-12-04 22:39:45 +01:00
Emmanuel Engelhart c0073b3bc7 Better use GitHub action .env directive 2023-12-04 20:51:46 +01:00
Matthieu Gautier 0d2b6b3344 Merge pull request #1030 from kiwix/cleanup_of_error_response_generation 2023-12-04 10:59:55 +01:00
Veloman Yunkan 5f27b4b651 Taking advantage of std::make_unique() 2023-11-29 21:32:16 +04:00
Veloman Yunkan 7a85c92025 Dropped root from HTTPErrorResponse & friends 2023-11-29 21:32:16 +04:00
Veloman Yunkan 6e2be481fd Dropped the root param from ItemResponse::build() 2023-11-29 21:32:16 +04:00
Veloman Yunkan db3b76247f Last step of removing root from ContentResponse 2023-11-29 21:32:16 +04:00
Veloman Yunkan 6a651e04e5 1st step in removing root from ContentResponse
It turned out that ContentResponse::m_root is no longer used.

At this point, the root parameter is dropped only from the 3-ary variant
of ContentResponse::build(), so that its all call sites are
automatically discovered by the compiler (and updated manually).
Including the other (4-ary) variant of ContentResponse::build() in this
change might result in the semantic change of expressions like
`ContentResponse::build(x, y, z)` and failure to update them.
2023-11-29 21:32:16 +04:00
Veloman Yunkan 22ea3106c5 Passing only root location instead of the entire server 2023-11-29 21:32:16 +04:00
Veloman Yunkan 2d132d701e Dropped the server param from Response::build*() 2023-11-29 21:32:16 +04:00
Veloman Yunkan f81a5a1a4b Moved verbosity control to Response::send()
It makes little sense to pass the verbosity control to the `Response`
constructor if it is used only in `Response::send()`.
2023-11-29 21:32:12 +04:00
Veloman Yunkan 3dce025f47 Deleted an unused function 2023-11-29 17:16:23 +04:00
Veloman Yunkan e470c97f74 Got rid of InvalidUrlMsg 2023-11-29 15:42:21 +04:00
Veloman Yunkan a7ea908bcd HTTPErrorResponse no longer accepts std::strings 2023-11-29 15:35:53 +04:00
Veloman Yunkan 41f25083da Replaced UrlNotFoundMsg with UrlNotFoundResponse 2023-11-29 14:31:38 +04:00
Veloman Yunkan 3188b0afe6 Translated a hard-coded error message 2023-11-29 14:18:06 +04:00
Kelson f8aae395f3 Merge pull request #1018 from kiwix/ci-ios
Test iOS cross-compile in CI
2023-11-23 08:32:30 +01:00
renaud gaudin c5088aad7b fixed typo in deps filename to fetch 2023-11-23 07:33:51 +01:00
Emmanuel Engelhart 269a659160 Download proper deps file 2023-11-23 07:33:51 +01:00
Emmanuel Engelhart 7161df9e4c Test iOS cross-compile in CI 2023-11-23 07:33:51 +01:00
Kelson 24faf84163 Merge pull request #1023 from kiwix/suggestions_with_control_characters
Control characters are escaped in suggestions JSON
2023-11-17 15:12:13 +01:00
Veloman Yunkan 571c09e00a Control characters are escaped in suggestions JSON
According to the JSON spec, control characters from U+0000 through U+001F
must NOT appear in strings unescaped.
2023-11-17 14:55:01 +01:00
Kelson a959800173 Merge pull request #1024 from kiwix/release-13.0.0
Release 13.0.0
2023-11-17 14:13:31 +01:00
Emmanuel Engelhart b2196ee7a9 13.0.0 Changelog 2023-11-17 14:11:20 +01:00
Emmanuel Engelhart aea51c21ff Bump-up version to 13.0.0 2023-11-17 13:52:03 +01:00
Kelson 95d627afa1 Merge pull request #1022 from kiwix/viewer_toolbar_tweaks
Viewer toolbar improvements
2023-11-15 21:41:55 +01:00
Veloman Yunkan 183bdcf2c0 Updated tests depending on kiwix-serve resources 2023-11-15 16:35:06 +04:00
Veloman Yunkan e1cf16ddea Better behavior on narrow screens
On media (screens) narrower than 420 pixels, the toolbar buttons
are hidden. Before this change, when made visible they were laid out
in two rows. This change places them in a single row and provides
some vertical spacing from the search-box.
2023-11-15 16:08:41 +04:00
Veloman Yunkan a74df86fcf Continuity in responsive layout of the toolbar
Without this change, in the media width range [416, 420) the searchbox is
narrow while the toolbars button space is empty which doesn't look nice.
2023-11-15 15:45:28 +04:00
Veloman Yunkan 605c7f71e0 Right-aligned UI language selector button 2023-11-15 15:31:22 +04:00
Veloman Yunkan f58d4a93e1 Viewer toolbar controls are now of the same height 2023-11-15 13:00:12 +04:00
Kelson 00032adce2 Merge pull request #1017 from kiwix/macos_13
Switch to macos-13.
2023-11-11 19:33:53 +01:00
Matthieu Gautier f5e6502e04 Switch to macos-13. 2023-11-09 17:53:33 +01:00
Kelson 37274f7882 Merge pull request #1016 from kiwix/fix_query_with_dot
Do not index book's name as a phrase.
2023-11-08 17:31:15 +01:00
Matthieu Gautier 07ff4eab43 Do not index book's name as a phrase.
Fix #1004
2023-11-08 10:29:31 +01:00
Kelson e89f4e2ac7 Merge pull request #1008 from kiwix/autocomplete_no_min
Add a non minified version of autoComplete.js
2023-11-07 20:41:59 +01:00
Matthieu Gautier bcbdce6a9a Add a small comment on autoComplete.css telling where it comes from. 2023-11-07 11:13:09 +01:00
Matthieu Gautier 0effcdb23f Add unminified autoComplete.js and LICENSE file.
- LICENSE is the copy of LICENSE file in TarekRaafat/autoComplete.js
- autoComplete.js is
  `https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.6/dist/autoComplete.js`
2023-11-07 11:07:56 +01:00
Matthieu Gautier 5c8dd0e8d3 Move autoComplete.min.js and autoComplete.css in a subdirectory.
This way we can easily identify which files is part of other project.
2023-11-07 11:04:27 +01:00
Matthieu Gautier d2c031e047 Merge pull request #1013 from kiwix/add-fon-language-support 2023-11-07 08:29:25 +01:00
Emmanuel Engelhart 733b027c2f Add support of Fon language (no supported in libicu) 2023-11-04 15:34:42 +01:00
Kelson e8b8c18297 Merge pull request #1009 from kiwix/kiwix_frontend_style_cleanup
Kiwix frontend style cleanup
2023-11-04 15:20:45 +01:00
Veloman Yunkan 29c33a7ad6 More economic use of vertical space on the library page 2023-10-28 21:20:33 +04:00
Veloman Yunkan fd504c1166 Matched viewer toolbar color to that of the library page
Attempts to use the same color for buttons yielded poor results: viewer
toolbar buttons don't look nice on the dark background used for the
filter controls on the library page, whereas the light background of the
viewer toolbar buttons doesn't play well with the filters on the library
page which seem to be designed around the contrast effect.
2023-10-28 21:20:33 +04:00
Veloman Yunkan 0c05af658d Deduplicated styling of UI language selector
There was a slight difference (between index.css and taskbar.css) in the
margin values of the UI language selector button, however the values
taken from taskbar.css don't seem to have any visible impact on the
welcome/library page (controlled by index.css).
2023-10-28 21:20:33 +04:00
Veloman Yunkan 0c0b1f5971 Moved to kiwix.css some CSS with global effect
Moved from index.css into kiwix.css some CSS with global effect thus
making it apply to the viewer too.

Extra font-size directives in taskbar.css are needed to undo the effect
of 'font-size: 62.5%' now applied to the 'html' element type.
2023-10-28 21:20:33 +04:00
Veloman Yunkan a65681d6f4 Shared styling of modal dialogs goes into kiwix.css 2023-10-28 21:20:33 +04:00
Veloman Yunkan af27141320 Enter kiwix.css
The new file kiwix.css is intended to host the intersection of index.css
and taskbar.css. In this commit only font definitions have been moved
into it.
2023-10-28 21:20:33 +04:00
Veloman Yunkan d2bb3d198c Moved font definition from template to CSS 2023-10-28 21:20:33 +04:00
Matthieu Gautier a5db4a1fd5 Merge pull request #1006 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2023-10-24 15:33:21 +02:00
Matthieu Gautier 59f0070ecc Add new translations to resource files. 2023-10-24 15:13:07 +02:00
translatewiki.net bd818d33af Localisation updates from https://translatewiki.net. 2023-10-23 13:10:04 +02:00
Kelson 16fbf15938 Merge pull request #1007 from computerscienceiscool/patch-1 2023-10-20 10:21:51 +02:00
JJ 8383265ac4 Update README.md
Fixed a couple of spelling errors
2023-10-20 00:58:52 -07:00
Kelson 0eb9a06736 Merge pull request #1003 from kiwix/nodiscard_aarch64
Do not use `[[nodiscard]]` attribute on compiler not supporting it.
2023-10-16 15:19:53 +02:00
Matthieu Gautier 01aa190c38 Do not use [[nodiscard]] attribute on compiler not supporting it.
On aarch64, we use gcc version 6.3.0 which doesn't support the
`[[nodiscard]]` attribute
(see https://en.cppreference.com/w/cpp/compiler_support/17)

So don't set the attribute if the attribute is not present.
2023-10-16 14:41:30 +02:00
Kelson da891699ac Merge pull request #1005 from kiwix/language_selector_font_fix
Fixed the fonts in the viewer UI language selector
2023-10-16 11:34:38 +02:00
Veloman Yunkan f9be9f98ce Fixed the fonts in the viewer UI language selector 2023-10-15 16:37:28 +04:00
Veloman Yunkan 22b55d36c6 Merge pull request #990 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2023-10-15 15:04:00 +04:00
Veloman Yunkan 2d86927e17 Registered new translations in the resource list 2023-10-15 14:47:32 +04:00
translatewiki.net 86be66a2d8 Localisation updates from https://translatewiki.net. 2023-10-12 13:09:48 +02:00
Matthieu Gautier 4425cd2122 Merge pull request #1001 from kiwix/magnet 2023-10-09 18:16:39 +02:00
renaud gaudin ab0d7b6e80 updated index.js cacheid 2023-10-09 16:08:24 +00:00
renaud gaudin cfc91b0967 Fixed #938: added hack for mirrobrain magnet URIs
Missing parameters are added to the magnet link for it to work properly
given it is mainly based on webseeds.
Each mirror serving the file is added as a webseed.
Params that requires URIEncoding are now encoded.

Introduces `makeURLSearchString()` to turn SearchParams into a string but only
URIEncoding some specific params.
2023-10-08 16:52:02 +02:00
Kelson 2650cdd7da Merge pull request #983 from kiwix/multiple-ci-cd-fixes
Multiple CI/CD fixes
2023-10-08 16:47:29 +02:00
Emmanuel Engelhart efdb596561 Add Debian package building in CI 2023-10-08 16:43:10 +02:00
Emmanuel Engelhart 177e1d5da6 Use latest base image_variant v38 2023-10-08 16:43:10 +02:00
Emmanuel Engelhart b861dfc9dd Use pinned version of Ubuntu for workflow 2023-10-08 16:43:10 +02:00
Emmanuel Engelhart 3fdbb5a990 Push on 'release' PPA triggered by 'release' event 2023-10-08 16:43:10 +02:00
Matthieu Gautier e49abc1df1 Merge pull request #991 from kiwix/no_raw_pointer 2023-10-05 17:47:44 +02:00
Matthieu Gautier 9166b67c47 Do not allow SearchRendered to work on a delete nameMapper/Library.
By moving the nameMapper/library arguments in `getHtml`/`getXml` we avoid
any potential "use after free" of name mapper or library as they are not
stored.
2023-10-05 16:37:22 +02:00
Matthieu Gautier 1dc9705597 Introduce LibraryPtr and ConstLibraryPtr.
As we enforce the use of Library through a shared_ptr, let's simplify
user life (and code) with new "type".
2023-10-05 16:37:22 +02:00
Matthieu Gautier 5292f06fff Move back Library::Impl in Library.
As we now always use Library through a shared_ptr, we can make `Library`
not copiable and not movable.
So we can move back the data in `Library`, we don't care about move
constructor.
2023-10-05 16:37:22 +02:00
Matthieu Gautier f8e7c3d476 Move the Library mutex in Library::Impl.
The why of this mutex is in `Library` is a bit complex.
It has been introduced in c2927ce when there was only `Library` and no
`std::unique_ptr<Impl>`.
As introducing the mutex imply implementing the move constructor, we have
split all data in `LibraryBase` (and keep a default move constructor here)
and add the mutex in `Library` (and implement a simple move constructor).

Later, in 090c2fd, we have move the `LibraryBase` to `Library::Impl`
(which should have been `Library::Data`).

So at the end, `Library::Impl` is never moved. We can move the `mutex` in
it and still simply implement move constructor for `Library`.
2023-10-05 16:37:22 +02:00
Matthieu Gautier ead1474ead Make SearchRendered taking a const pointer. 2023-10-05 16:37:22 +02:00
Matthieu Gautier 1316dec37c Make the Server keep a shared_ptr instead of a raw NameMapper pointer.
Same as for `Library`, we want to be sure that the `NameMapper`
actually exists when the server is using it.
2023-10-05 16:37:22 +02:00
Matthieu Gautier a5557eeb25 Make the Server keep a shared_ptr instead of a raw Library pointer.
We want to be sure that `Library` actually exists when we use it.
While it is not a silver bullet (user can still create a shared_ptr on
a raw pointer), making the `Server` keep `shared_ptr` on the library
help us a lot here.
2023-10-05 16:36:18 +02:00
Matthieu Gautier efcbf6ef1e Make the UpdatableNameMapper keep a shared_ptr.
Same as `Manager`, we want to be sure that `Library` actually exists
when we use it.
2023-09-25 16:31:55 +02:00
Matthieu Gautier 139b561253 Make the Manager keep a shared_ptr instead of a raw Library reference.
We want to be sure that `Library` actually exists when we modify it.
While it is not a silver bullet (user can still create a shared_ptr on
a raw pointer), making the `Manager` keep `shared_ptr` on the library
help us a lot here.
2023-09-25 16:30:56 +02:00
Matthieu Gautier c203e07ee9 Make the library creatable only within a shared_ptr. 2023-09-25 16:28:25 +02:00
Matthieu Gautier 49e99e7c22 Remove dumpers from the public API.
All those dumper were not used by any of our other projects.
They are only used internally, either by `Library::writeToFile` or the
server.
2023-09-19 16:46:58 +02:00
Kelson e13324fbba Merge pull request #996 from kiwix/cpp17
Move to c++17.
2023-09-14 17:21:18 +02:00
Matthieu Gautier c38ab3e5d7 Move to c++17.
All our compilers should handle c++17. Let's move on.
2023-09-14 17:21:02 +02:00
Matthieu Gautier bde737f63b Merge pull request #997 from kiwix/cookieless_user_language_control 2023-09-11 14:04:48 +02:00
Veloman Yunkan cc6aa9b162 Fixed userlang control on the library page too
This fix contains a small hack - in order to detect the default language
from browser language preference during the first visit, the library
page has to load /viewer_settings.js which contains that information.
2023-09-09 19:39:16 +04:00
Veloman Yunkan 9063450b5a Fixed userlang control in the viewer
Now the viewer stores the userlang preference in window.localStorage.
2023-09-09 19:39:16 +04:00
Veloman Yunkan f8c3a1fd2e Added default user language to viewer_settings.js
The default user language determined from the value of "Accept-Language"
header is communicated to the client via the /viewer_settings.js
endpoint.
2023-09-09 19:37:49 +04:00
Veloman Yunkan b5b98e7a61 RIP userlang cookie
This commit drops the usage of the userlang cookie in the backend but
not in the frontend. UI language control should be broken at this point
and will be fixed in the next few commits.
2023-09-09 19:37:49 +04:00
Veloman Yunkan e7e8275a31 Made the language selector button visible
After upgrading my OS to Ubuntu 22.04 the language selector button
didn't show up in the viewer taskbar. Investigation shows that the id
used in the CSS was applied to the wrong HTML element (the enclosing
<a> rather than <img>).
2023-09-09 19:37:49 +04:00
Kelson c6456cac42 Merge pull request #993 from kiwix/no_kinetic_package
Remove Ubuntu Kinetic from CI/CD (deprecated)
2023-08-24 17:15:22 +07:00
Emmanuel Engelhart f0c0400485 Remove Ubuntu Kinetic from CI/CD (deprecated) 2023-08-24 11:15:19 +02:00
Matthieu Gautier ccbeb154a5 Merge pull request #992 from kiwix/fix_rtd 2023-08-24 10:55:57 +02:00
Matthieu Gautier 0e8a2952d5 Always set html_theme in doc configuration.
Lat version of read the doc do not set a html_theme for us.
So we have to always set it.

See readthedocs/readthedocs.org#10638
2023-08-24 10:46:46 +02:00
Kelson fe5e6c451d Merge pull request #977 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2023-08-18 10:37:54 +08:00
translatewiki.net 3966e8544b Localisation updates from https://translatewiki.net. 2023-08-17 13:10:24 +02:00
Matthieu Gautier 09476ededb Merge pull request #974 from kiwix/multipleCategories 2023-07-26 14:57:29 +02:00
Nikhil Tanwar d47c4fa72f Unit tests for OPDS filtering by category
Added tests for multiple category filtering for zims
Added new test: catalog_v2_entries_filtered_by_category for entry filtering by category.
2023-07-26 18:15:47 +05:30
Nikhil Tanwar c938101c70 Allow multiple category support
Created a generic function multipleQuery which takes:
1. string (representing a comma separated list)
2. param (the value to query on using Xapian).

Category and language query will use this function.
2023-07-26 18:15:45 +05:30
Matthieu Gautier 9c91fc7369 Merge pull request #967 from kiwix/opdsFilters 2023-07-26 14:00:06 +02:00
Nikhil Tanwar 385931f229 Move getLanguageSelfName to tools.h
This is a general utility which other ports can get use of.
Added tests
2023-07-26 16:02:32 +05:30
Nikhil Tanwar 8726de494c Tests for readLanguagesFromFeed and readCategoriesFromFeed
Added tests on a sample OPDS language and categories stream
2023-07-26 16:02:32 +05:30
Nikhil Tanwar 94d6bef402 Introduce readCategoriesFromFeed()
Added a function to load categories stored in an OPDS stream
2023-07-26 16:02:32 +05:30
Nikhil Tanwar a28c2973e9 Introduce readLanguagesFromFeed()
Added a new function to read languages stored in an OPDS feed
2023-07-26 16:02:32 +05:30
Nikhil Tanwar 7feb89c30e Add remaining include files to meson.build
These files were overlooked during a merge of another PR
2023-07-26 16:02:32 +05:30
Matthieu Gautier 903dcd46d6 Merge pull request #978 from kiwix/fix_missing_includes 2023-07-25 16:32:26 +02:00
Matthieu Gautier 1be5424711 Add missing include.
`uint64_t` type (used by `beautifyFileSize`) need to be declared.
2023-07-25 13:37:31 +02:00
Matthieu Gautier de517330f6 Merge pull request #971 from kiwix/beautifyPublic
Make beautifyFileSize public
2023-07-21 19:10:26 +02:00
Nikhil Tanwar 5c3a997de4 make beautifyFileSize public
This general function will be useful in other kiwix apps
2023-07-21 22:19:45 +05:30
Matthieu Gautier cb74c9c7c7 Merge pull request #972 from kiwix/version_12.1.0 2023-07-20 16:01:30 +02:00
Matthieu Gautier 312cecf5f2 New version 12.1.0 2023-07-20 15:54:55 +02:00
Matthieu Gautier a4d207a03a Merge pull request #964 from kiwix/translatewiki 2023-07-17 13:16:40 +02:00
translatewiki.net 7e36dd5ddb Localisation updates from https://translatewiki.net. 2023-07-17 13:08:18 +02:00
Matthieu Gautier 8ca809f8d9 Merge pull request #970 from kiwix/fix_macos_deps_name 2023-07-13 12:12:53 +02:00
Matthieu Gautier fd22e34d58 Fix the name of the deps archive on macos. 2023-07-13 12:04:41 +02:00
Matthieu Gautier 3be1ddd8a9 Merge pull request #966 from kiwix/gungbe 2023-07-11 18:50:51 +02:00
Veloman Yunkan e9d9d85427 Added Gungbe language code 2023-07-10 23:28:04 +04:00
Kelson 9599a31d2f Merge pull request #963 from kiwix/quasiuriencoded_suggestion_links
Quasi-URI-encoded suggestion links
2023-07-10 14:36:46 +02:00
Veloman Yunkan 4d60b106a2 Quasi-URI-encoded suggestion links
Before this fix suggestion links were built out of fully URI-encoded
book name and article path components despite the fact that this measure
was taken against only a few dangerous symbols such as '#', '?', '"' and
'\'.  However, URI-encoding the slash symbols in the path has some
undesirable side-effects (see #958).

Henceforth only the problematic symbols are encoded in the article path
component. The book name is still fully URI-encoded since I don't see
any counter-arguments.
2023-07-01 17:52:11 +04:00
Kelson 60cce602a3 Merge pull request #957 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2023-07-01 15:12:42 +02:00
translatewiki.net abb81e7798 Localisation updates from https://translatewiki.net. 2023-07-01 15:12:24 +02:00
Kelson 1808857173 Merge pull request #954 from kiwix/search_remove_accent
Add a new test, showing accents is not properly handle in search endpoint.
2023-07-01 15:11:54 +02:00
Matthieu Gautier 556b94daae Fix server_search test.
The pattern (given as a query string) must be url decoded.
2023-06-30 12:04:42 +02:00
Matthieu Gautier 5f4dad60b9 Add a new test, showing accents is not properly handle in search endpoint. 2023-06-30 12:04:42 +02:00
Matthieu Gautier 820ffa8134 Merge pull request #962 from kiwix/fix_macos_build 2023-06-30 12:04:11 +02:00
renaud gaudin f6f7214c99 Unlink and remove some linked python3 files
meson and ninja both depends on python3 which received an update.
This python3 update fails to install when linking.

This temp fix removes those files. Hopefully a future update will remove the need
for this hack
2023-06-30 11:26:55 +02:00
Matthieu Gautier 1f5a160d3d Merge pull request #961 from kiwix/issue950 2023-06-28 15:21:23 +02:00
Veloman Yunkan f41007989b Fool-proof checking of book illustration presence
Now (in a library.xml flow) a book is considered to contain an
illustration only if both "faviconMimeType" and "favicon" attributes
are set to non-empty values.
2023-06-24 20:10:41 +04:00
Veloman Yunkan f25d287afa Enhanced the test data to demonstrate issue#950
Presence of the "faviconMimeType" attribute in a book entry in library.xml
file is enough for libkiwix to assume that the book contains an illustration
(even if the "favicon" attribute is missing).
2023-06-24 20:03:54 +04:00
Kelson 550fc2fcf9 Merge pull request #959 from kiwix/clickable_external_links4
Fixed external links in the viewer iframe (final version)
2023-06-21 17:32:02 +02:00
Veloman Yunkan 96fb65f560 Guaranteed activation of external link blocking
This is a quickfix for the problem observed with external link blocking
during certain history navigation actions (when the cached iframe content is
loaded/restored before the viewer setup is completed).

Since external link blocking doesn't depend on the translations (that
are asynchronously loaded during the viewer setup) it can be performed
unconditionally. However, the current dependence of `on_content_load()`
on viewer setup has to be addressed too.
2023-06-18 19:49:47 +04:00
Veloman Yunkan 93197f8175 Mostly fixed external links in the viewer iframe
Before this fix clicking an external link in the viewer iframe had no
effect (other than an error being reported in the browser dev tools
console) because the attempt to navigate the top browser context was
suppressed due to sandboxing - the click handling code changed the
target of the link but navigating to that target was blocked. Now the
click handler works as follows:

1. Changes the target of the link to the catch page only if the
   link is going to be opened in a new tab or window (in this case
   sandboxing restrictions do not apply).

2. Otherwise directly navigates the viewer window to external URL
   or the catch page.

An unhandled scenario is opening an external link in a new tab/window
via a middle click or context menu - such events cannot be intercepted
and therefore there is no way of blocking external links accessed in
the said way.
2023-06-18 19:41:10 +04:00
Kelson 144945cfe0 Merge pull request #940 from kiwix/fix_for_issue912
PDF-friendly book home button in the viewer
2023-06-08 15:48:11 +02:00
Veloman Yunkan c1ad65d515 PDF-friendly book home button in the viewer
In firefox, when PDF content is displayed in the viewer, changing the
viewer URL in the address bar had no effect. The most prominent
manifestation of this bug was the broken book home button but the same
issue was present even if the fragment component of the viewer URL was
edited manually. The bug was a result of

1. an optimization preventing any actions if the new content URL is the
   same as the old content URL (this was needed to break the infinite loop
   of mutual updates of the top-window and content window/iframe URLs when
   any one of them changes).

2. sandboxing of the iframe and inability to access the content URL in
   iframe because of cross-origin restrictions when the content is a PDF
   displayed by the builtin viewer.

Now that issue is fixed. A slight remaining defect is that the
addressbar URL is still not updated when a PDF file is loaded/displayed
in the viewer.
2023-06-08 17:32:50 +04:00
Matthieu Gautier af2dfdccbc Merge pull request #956 from kiwix/no_bionic_package 2023-06-07 11:45:42 +02:00
Matthieu Gautier f2072d87a0 [CI] Remove creation of package for bionic. 2023-06-07 11:26:55 +02:00
Matthieu Gautier e9c3a7ff45 Merge pull request #955 from kiwix/fix_doc 2023-06-07 11:12:46 +02:00
Matthieu Gautier a715203d3e Add readthedoc configuration file. 2023-06-07 10:54:51 +02:00
Kelson 552717b9ce Merge pull request #951 from OlCe2/oc-xapian_libzim_fix 2023-05-27 15:23:42 +03:00
Olivier Certner 0ed805ae6b meson.build: Fix detection of libzim built with Xapian
The dependency on libzim must be specified in compiler.has_header_symbol() for
it to find the header in all cases.

Fixes a configure error on FreeBSD:
"""
Header "zim/zim.h" has symbol "LIBZIM_WITH_XAPIAN" : NO

meson.build:33:2: ERROR: Problem encountered: Libzim seems to be compiled without xapian. Xapian support is mandatory.
"""
2023-05-27 12:53:57 +03:00
Kelson b45cfd767a Merge pull request #949 from bentley/openbsd
Include netinet/in.h everywhere except Windows
2023-05-27 12:53:21 +03:00
Anthony J. Bentley df164aefe5 Include netinet/in.h everywhere except Windows
According to POSIX, sockaddr_in is declared in netinet/in.h.
Some POSIX systems (notably OpenBSD and FreeBSD) declare it in
only this header, so including it is required. Others, like Linux,
are are more lax in exposing symbols to the namespace, providing
sockaddr_in via additional headers, but it does no harm to include
the standard header on such systems.
2023-05-27 12:42:29 +03:00
Kelson 58890a3f97 Merge pull request #952 from kiwix/use-focal-ci
Few CI changes (mostly Linux Bionic to Focal)
2023-05-27 12:42:12 +03:00
Emmanuel Engelhart 2d58142c58 No need anymore to change directory 2023-05-26 14:09:02 +02:00
Emmanuel Engelhart 0afa5e569c Ubuntu 20.04 & macos 11 as OS in CI 2023-05-26 14:07:03 +02:00
Emmanuel Engelhart ae605dc26d Use latest version 27 of docker base image 2023-05-26 14:05:31 +02:00
Emmanuel Engelhart d8f02ac225 Uses actions/checkout 2023-05-26 14:00:46 +02:00
Emmanuel Engelhart e4595f357d Use Ubuntu Focal as CI base image 2023-05-26 13:54:52 +02:00
Veloman Yunkan 881c121142 Merge pull request #918 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2023-05-20 16:36:20 +04:00
Veloman Yunkan 2d51e1f0c6 Updated the list of translations 2023-05-20 16:18:12 +04:00
translatewiki.net b24f681c24 Localisation updates from https://translatewiki.net. 2023-05-18 13:06:38 +02:00
Matthieu Gautier deb02d92e2 Merge pull request #942 from kiwix/opds_response_charset_info 2023-04-25 16:56:06 +02:00
Veloman Yunkan dc58e278c7 git mv src/server/internalServer_catalog{_v2,}.cpp 2023-04-25 12:48:49 +04:00
Veloman Yunkan 9994302312 Explicit charset in OPDS response MIME types 2023-04-25 12:48:29 +04:00
Veloman Yunkan 8c190cf34f Moved InternalServer::handle_catalog() 2023-04-25 12:48:10 +04:00
Veloman Yunkan 1273570e01 Deduplication of OPDS MIME type strings 2023-04-25 12:47:02 +04:00
Veloman Yunkan 9bd2df2327 ServerTest.MimeTypes tests all OPDS endpoints 2023-04-25 12:46:24 +04:00
Kelson 08834d6f17 Merge pull request #939 from kiwix/welcome_page_opds_api_upgrade
Got rid of legacy OPDS API usage in kiwix-serve
2023-04-21 20:19:07 +02:00
Veloman Yunkan 47950f132e Got rid of legacy OPDS API usage in kiwix-serve 2023-04-21 17:03:13 +04:00
Kelson 1a92d4a0b5 Merge pull request #934 from kiwix/mulNames
Display MUL on tile when multiple languages are available
2023-04-18 16:58:27 +02:00
Nikhil Tanwar 272dc142c5 Display MUL on tile when multiple languages are available
If a book contains multiple languages, the language label now shows "MUL".
On hover, it displays the list of all languages available in the ZIM.
2023-04-18 18:53:07 +05:30
Matthieu Gautier bf1d207651 Merge pull request #936 from kiwix/opds_xml_fix 2023-04-18 14:07:31 +02:00
Veloman Yunkan 6f0e55d603 A slight simplification of the mustache template
Got rid of the partial vs full entries logic in the mustache template -
now it is entirely contained in `OPDSDumper::dumpOPDSFeedV2()`.
2023-04-18 14:45:51 +04:00
Veloman Yunkan ebe16f92a5 Fixed OPDS XML output for multiple filters
In XML any & symbols acting as parameter separators in URL search
components must be HTML-escaped.
2023-04-18 14:33:40 +04:00
Veloman Yunkan 4f6a5759aa LibraryServerTest.catalog_v2_entries_multiple_filters 2023-04-18 14:24:00 +04:00
Kelson d85eb1b747 Merge pull request #935 from kiwix/revert-macos-ci-fix
Revert "Unlink and remove some linked python3 files"
2023-04-18 07:37:59 +02:00
Emmanuel Engelhart 41a1124585 Revert "Unlink and remove some linked python3 files"
This reverts commit 95bde675ef.
2023-04-18 07:29:29 +02:00
Kelson 98853a0708 Merge pull request #931 from kiwix/brew-overwrite
Fix macOS CI python dependency install
2023-04-11 17:30:05 +02:00
renaud gaudin 95bde675ef Unlink and remove some linked python3 files
meson and ninja both depends on python3 which received an update.
This python3 update fails to install when linking.

This temp fix removes those files. Hopefully a future update will remove the need
for this hack
2023-04-11 17:04:24 +02:00
Matthieu Gautier fcde243117 Merge pull request #930 from kiwix/pdf-friendly-kiwix-serve 2023-04-11 17:01:30 +02:00
Veloman Yunkan 9fd7f7da34 Really enable Chromium to display PDFs in the viewer iframe
The previous "fix" (merged PR #924) was buggy. It not only didn't work
in Chromium v90, but in more recent versions too.

I verified that this fix works in Firefox (v111) and Chromium (v90):

- Attempts by the ZIM content to break out of the viewer iframe are
blocked.
- PDFs are displayed in the viewer.
2023-04-10 16:42:21 +04:00
Matthieu Gautier 453f02cc85 Merge pull request #924 from kiwix/pdf-friendly-kiwix-serve 2023-04-05 15:41:37 +02:00
Veloman Yunkan a6659cbe96 Enable Chromium to display PDFs in the viewer iframe
This fix requires Chromium version above 90.
2023-04-05 15:08:29 +02:00
Kelson e13fed8670 Merge pull request #897 from kiwix/nojs
A gift to javascript naysayers
2023-03-29 16:15:43 +02:00
Nikhil Tanwar 25f589ee73 noscript text on welcome page
Added a <noscript> elements which hides everything on the welcome page if javascript is not enabled.
It displays a text to tell the user to navigate to /nojs endpoint
2023-03-29 19:03:30 +05:30
Nikhil Tanwar 208f0f5f69 Tests for /nojs
Added 4 tests for /nojs endpoint

Test 1: no_js_default - Without any filters
Test 2: no_js_eng_lang - With lang=eng as filter
Test 3: no_js_no_books - For 0 results case
Test 4: no_js_download - To test download page
2023-03-29 19:03:30 +05:30
Nikhil Tanwar 951e15c665 No results display in /nojs
Shows a link to reset filter if there are no books.
2023-03-29 19:03:30 +05:30
Nikhil Tanwar cc35fe503f Translations for /nojs endpoint
Uses the string from #846 for translations.
A couple new translations are also added for <title> tag.
2023-03-29 19:03:29 +05:30
Nikhil Tanwar 37aadb86fb language/category filtering in /nojs endpoint
Adds language and category filter in /nojs.
Unlike the main page, the filtering is only done after user submits the form.
2023-03-29 19:02:58 +05:30
Nikhil Tanwar f843ea48f0 Add Results label
Shows "x results" label where x = number of books based on filters
2023-03-29 19:02:58 +05:30
Nikhil Tanwar a48e2e6f06 Add search form for /nojs endpoint
Adds an html form to search books by the q= parameter
2023-03-29 19:02:58 +05:30
Nikhil Tanwar 0f7e11bd86 Add download-links to tiles in /nojs
The download-link links to /nojs/download/<bookname> for all 4 types of downloads.
2023-03-29 19:02:56 +05:30
Nikhil Tanwar dbded6eee2 Add links to content for tiles in /nojs
If the tiles are now clicked, they redirect to main page of book.
2023-03-28 21:50:47 +05:30
Nikhil Tanwar c1d7cc37fd Add tags in tiles for /nojs endpoint
Adds span elements for tags
2023-03-28 21:49:31 +05:30
Nikhil Tanwar 6071b98fb7 Import book tiles
Tries to copy the same design of tiles as main page with javascript enabled
2023-03-28 21:49:31 +05:30
Nikhil Tanwar dca47d35f7 Introduce /nojs endpoint
Adds /nojs endpoint for fallback.
Currently, it serves an HTML with book names in library
2023-03-28 20:25:44 +05:30
Nikhil Tanwar d8656ec149 Introduce HTMLDumper
HTMLDumper class will be used to dump library in HTML format. It inherits from LibraryDumper
2023-03-28 20:25:44 +05:30
Nikhil Tanwar f1873876b2 Extract LibraryDumper from OPDSDumper
This change creates a new common class for dumping the library into various formats: LibraryDumper
2023-03-28 20:25:44 +05:30
Kelson cb20317047 Merge pull request #920 from kiwix/iconFeedToolTip
Parameterised feed tool tip
2023-03-27 22:26:44 +02:00
Nikhil Tanwar ae58f009fb Feed tooltip based on filters
The feed logo tooltip text is now based on filters.
If no filters are set, it shows "All entries"
2023-03-27 23:59:15 +05:30
Nikhil Tanwar d7a3a417e1 Use SVG files for feed logo & ui language selector
Added new, better proportioned SVG files.
2023-03-26 19:58:50 +05:30
Kelson 68c6c93945 Merge pull request #910 from kiwix/minor_ui_language_selection_improvements
Minor UI language selection improvements
2023-03-20 17:29:37 +01:00
Veloman Yunkan 4c256e97c7 Minor UI language selection improvements
Added cursor type and hints to the UI language selection button. The
hints are always in English since seeing a hint in an unfamiliar language
doesn't help and English is the current lingua franca.
2023-03-19 17:00:28 +01:00
Kelson 7478217ad4 Merge pull request #909 from Bigguysahaj/main
Changed word "language" to "category" in README.mdS
2023-03-18 06:55:46 +01:00
bigguysahaj ea33a3b65e Changed word "language" to "category" in README.mdS 2023-03-18 06:55:12 +01:00
Kelson f4e8f688ad Merge pull request #919 from kiwix/new-ci-container-images
Bump-up CI base container images to r36
2023-03-16 17:23:20 +01:00
Emmanuel Engelhart 4c4969d95a Use Codecov action 2023-03-16 14:35:20 +01:00
Emmanuel Engelhart 676a5d11f5 Bump-up CI base container images to r36 2023-03-16 13:44:07 +01:00
Matthieu Gautier 6b57ad89b7 Merge pull request #907 from kiwix/hash 2023-03-15 17:13:24 +01:00
Nikhil Tanwar 174deddf35 Use fragment value instead of search query for filters
The filters are now taken from window.location.hash (instead of window.location.search).
This change will help in caching of the page better.
2023-03-15 17:05:27 +01:00
Veloman Yunkan 782a25bba8 Merge pull request #905 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2023-03-13 16:28:27 +04:00
translatewiki.net 24ed5491fd Localisation updates from https://translatewiki.net. 2023-03-13 13:06:23 +01:00
Matthieu Gautier 88de978a9c Merge pull request #904 from kiwix/support_for_multilang_zims 2023-03-08 15:30:59 +01:00
Veloman Yunkan eb002ae306 Deprecated Book::getLanguage()
Introduced `Book::getCommaSeparatedLanguages()` instead.
2023-03-08 15:24:53 +01:00
Veloman Yunkan 2550306052 One more usage of Book::getLanguages()
`Book::getLanguages()` is used instead of `Book::getLanguage()` when
determining the set of languages for a collection of books.
2023-03-08 15:24:53 +01:00
Veloman Yunkan 51fcb90dc0 Library::updateBookDB() uses Book::getLanguages() 2023-03-08 15:24:53 +01:00
Veloman Yunkan b1ad319d52 Enter Book::getLanguages() 2023-03-08 15:24:53 +01:00
Veloman Yunkan 12826a57bd Less verbose book creation in unit-tests 2023-03-08 15:24:53 +01:00
Veloman Yunkan 5bda7fd45c Support for multilang ZIMs 2023-03-08 15:24:53 +01:00
Matthieu Gautier 30725136c8 Merge pull request #906 from kiwix/pseudosafe_iframe 2023-03-07 17:06:54 +01:00
Veloman Yunkan 571b6089a4 A pseudosafe iframe
This prevents scripts running inside an iframe from inadvertently
manipulating the top browsing context. However a malicious script could
still remove the sandboxing imposed on it (because the combination of
"allow-same-origin" and "allow-scripts" is vulnerable).
2023-03-06 18:17:52 +04:00
Veloman Yunkan 32b4bca745 Merge pull request #896 from kiwix/stickyNav
Stick kiwixNav on top
2023-03-06 15:56:42 +04:00
Nikhil Tanwar f838314435 Auto hiding of kiwixNav on scroll for mobile devices
Since kiwixNav is sticky for larger screens now, the tiles area on mobile devices is incredibly low.
This change hides kiwixNav if the screen is scrolled.
2023-03-03 02:47:18 +05:30
Nikhil Tanwar 08d6376eed Economical space usage in search form
No pre defined height for devices with with max-width 590px now. The previous height took a good amount of space on some devices.
2023-03-02 12:45:25 +05:30
Nikhil Tanwar 3cdc6c41c4 Stick kiwixNav on top
The filters menu will always stay on top now.
2023-03-02 12:45:25 +05:30
Veloman Yunkan 973ac28dcb Merge pull request #901 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2023-03-01 19:26:40 +04:00
Veloman Yunkan a855b422c7 Updated the list of translations 2023-03-01 19:16:30 +04:00
Veloman Yunkan 28673c1bb8 Handling of translation jsons w/o the language name
If a translation JSON file doesn't contain the 'name' (self-name)
attribute of the translation language then that language is not included
in the list of languages available in the UI language selector.
2023-03-01 19:16:06 +04:00
translatewiki.net df4b16e485 Localisation updates from https://translatewiki.net. 2023-02-27 13:05:55 +01:00
Matthieu Gautier 936707f73b Merge pull request #846 from kiwix/frontend_i18n 2023-02-22 15:44:56 +01:00
Veloman Yunkan 9e2a601d52 Translated filter-by-tag messages 2023-02-22 18:02:48 +04:00
Veloman Yunkan 1d074cda40 Changed the UI language selector in ZIM viewer
The UI language selector in the viewer is now the same as on the welcome
page. This comes with some (mostly CSS) code duplication.
2023-02-22 18:02:41 +04:00
Veloman Yunkan 5850e0d489 The OPDS feed icon is never hidden 2023-02-22 18:01:28 +04:00
Veloman Yunkan 904615a51a Modal language selector on the welcome page
The language selector on the welcome page has been replaced with
a smaller button that opens a modal language selector. Though the
code for introducing such a modal language selector has been added
in i18n.js, its appearance relies on styles defined in index.css.

Once this new UI for changing the UI language is approved, it must be
used in the ZIM viewer too.

Known issues:

- selecting the language with arrow keys (using the keyboard only,
  without pressing space first, so that the full list of languages is
  shown) doesn't work because as soon as the current language is changed
  the modal language selector disappears.
2023-02-22 18:01:21 +04:00
Veloman Yunkan 763fb86ad0 userlang query param is removed from the URL
If the userlang query param is present in the URL it is used to set the
UI language and then is removed from the URL.

Unlike the ZIM viewer, changing the UI language on the welcome page
isn't recorded in the navigation history (and probably it should work
the same way in the ZIM viewer where the appearance of the web page is
affected by the UI language changes to a significantly smaller extent).
2023-02-22 17:59:37 +04:00
Veloman Yunkan fbf6d97f5e Translation of the library OPDS feed link hints 2023-02-22 17:59:18 +04:00
Veloman Yunkan c85466995d Added a TTL parameter to setCookie() 2023-02-22 17:58:57 +04:00
Veloman Yunkan 514d6e6514 Added UI language selector on the welcome page
Also:

- Moved the language selector to the right hand side on the ZIM viewer
  page (to be consistent with the welcome page)
2023-02-22 17:58:46 +04:00
Veloman Yunkan 351bc87231 Moved initUILanguageSelector() into i18n.js 2023-02-22 17:56:28 +04:00
Veloman Yunkan ac742e9da2 Redirection of slashless root URL
With non-empty root location, the canonic form of the root URL for a
kiwix server is now required to end with a slash (to match the situation
for an empty root location). This requirement enables usage of relative
URLs on the welcome page and resources/scripts loaded through that page.

A slashless root URL is redirected to the slashful version.
2023-02-22 17:54:20 +04:00
Veloman Yunkan 0581da44fe Internationalization of download options 2023-02-22 17:54:01 +04:00
Veloman Yunkan 2825c4c63d Fixed links to various download option icons 2023-02-22 17:53:42 +04:00
Veloman Yunkan fa7d044037 One more translation on the welcome page
This translation has to deal with handling of plural forms which is a
tricky part of internationalization, but we are not going to complicate
things in our code and will offload the headache to translators (they
will have to invent a single message for all numbers).
2023-02-22 17:53:23 +04:00
Veloman Yunkan d42fa22450 Translation of static text on the welcome page
Note that i18n/test.json overgrew the non-compressible size limit, that
is why it had to move to a richer neighbourhood.
2023-02-22 17:53:03 +04:00
Veloman Yunkan 7307a9a1b7 First translation on the welcome page 2023-02-22 17:50:22 +04:00
Kelson bf80367b5a Merge pull request #898 from kiwix/improve-macos-ci
Improve macOS Ci workflow
2023-02-20 16:49:22 +01:00
Emmanuel Engelhart a04646b7b2 Simplify ninja and meson calls 2023-02-20 16:36:30 +01:00
Emmanuel Engelhart cfe3f8e3d9 Better use HTTPS in place of HTTP 2023-02-19 17:10:08 +01:00
Emmanuel Engelhart 2d0cff2dc1 Better definition of env variables 2023-02-19 17:10:04 +01:00
Emmanuel Engelhart b24157ddf9 Not necessary to specify bash, already the default 2023-02-19 16:42:37 +01:00
Emmanuel Engelhart c57b5ba1ad Install meson using Homebrew 2023-02-19 16:36:28 +01:00
Emmanuel Engelhart fe646511d1 Python3 is already available 2023-02-19 16:29:31 +01:00
Emmanuel Engelhart cc31846152 Don't install unused packages 2023-02-19 16:22:23 +01:00
Emmanuel Engelhart cb4938c5f8 Improve a bit the readability of the workflow 2023-02-19 16:21:30 +01:00
Emmanuel Engelhart b1055e814a Use fix macOS version in CI 2023-02-19 16:12:21 +01:00
Kelson 13951c13df Merge pull request #895 from kiwix/better-package-ci-triggers
Better triggers for packages builds
2023-02-16 16:28:46 +01:00
Emmanuel Engelhart 60fbe7f714 Better triggers for packages builds 2023-02-11 16:55:45 +01:00
Matthieu Gautier 595817852d Merge pull request #894 from kiwix/zerocount_catalog_query 2023-02-10 19:28:53 +01:00
Veloman Yunkan 2e0124710a ?count=0 OPDS catalog queries return 0 results
... which is a useful way of finding out the total number of results
with the least consumption of resources.
2023-02-10 19:15:29 +01:00
Veloman Yunkan 340fadd9be Testing of /catalog/search?count=-1 2023-02-10 19:13:33 +01:00
Veloman Yunkan 4bdc1d76c6 Testing of /catalog/v2/entries for count={0,-1} 2023-02-10 19:11:39 +01:00
Veloman Yunkan 738c06ada6 Merge pull request #892 from kiwix/jsonico_mimetypes
A better favicon.ico with correct MIME-type
2023-02-10 18:13:28 +04:00
Veloman Yunkan 93bb0f098b A slightly better favicon.ico
Replaced the favicon embedded in kiwix-serve with a slightly better one
(taken from https://www.kiwix.org/favicon.ico).
2023-02-10 15:07:00 +01:00
Veloman Yunkan e8c8a297b5 Registered MIME-types for .ico and .json
As a result, favicon.ico stopped being considered a compressible resource.
2023-02-10 15:07:00 +01:00
Veloman Yunkan f4f7879ff3 New unit test ServerTest.MimeTypes
The new unit test demonstrates that for embedded resources with .ico and
.json extensions MIME-types are incorrect.
2023-02-10 15:07:00 +01:00
Kelson 706108256b Merge pull request #891 from kiwix/hbsLang
Add Serbo-croate language name
2023-02-10 09:33:34 +01:00
Nikhil Tanwar 12f0614350 Add Serbo-croate language name
Adds "srpskohrvatski" as name for "hbs" language tag.
2023-02-10 09:20:23 +05:30
Matthieu Gautier 29519df906 Merge pull request #882 from kiwix/rssFeed 2023-02-09 16:43:52 +01:00
Nikhil Tanwar 6b8f9aa6ab Add specific link for Kiwix RSS Feed
Added an image of rss logo on the welcome page which links to the RSS feed with current filters
2023-02-09 20:50:52 +05:30
Nikhil Tanwar e3a211e41c Add RSS Feed extension in head
This change adds a <link> element in the head node of welcome page.
Browsers with extensions for RSS will show a sign to navigate to the feed.
The link changes based on current set filters.
2023-02-09 20:47:32 +05:30
Matthieu Gautier fa80be87be Merge pull request #890 from kiwix/url_encoding_of_redirects 2023-02-09 11:22:21 +01:00
Veloman Yunkan 51206f4037 fixup! URI-encoding when redirecting legacy URLs to /content
The alleged bug seems rather an issue with httplib which seems to
URI-encode any + present in query parameters.
2023-02-09 11:10:37 +01:00
Veloman Yunkan c2fffacbbd Renamed a data member 2023-02-09 10:40:23 +01:00
Veloman Yunkan 02f631fdb6 Got rid of RequestContext::full_url 2023-02-09 10:40:23 +01:00
Veloman Yunkan 05a66ead6e URI-encoding of the root location part
Now the root location is URI-encoded too.

In order to properly test this change the root location in the tests was
changed from "/ROOT" to "/ROOT#?" (or "/ROOT%23%3F" in URI-encoded form),
which is why this commit is so big.
2023-02-09 10:40:07 +01:00
Veloman Yunkan 97f0314fe6 Saving a few CPU cycles
This silly optimization in fact helps to avoid a somewhat more serious
waste of CPU cycles that would otherwise result in the next commit.
2023-02-08 22:16:27 +01:00
Veloman Yunkan a7fe4193e3 Preparing to save a few CPU cycles 2023-02-08 22:16:27 +01:00
Veloman Yunkan 2c5e84b6b3 Simpler fullURL2LocalURL() 2023-02-08 22:16:27 +01:00
Veloman Yunkan 71a66e0528 Passing of unrooted URL into RequestContext()
This change doesn't make much sense on its own - the real goal is to
prepare some ground for easier implementation of URI-encoding of the root
location.
2023-02-08 22:16:27 +01:00
Veloman Yunkan a807ce27f1 URI-encoding when redirecting legacy URLs to /content
Testing of this functionality revealed that the query part containing +
symbols (as replacement for spaces in the parameter values) isn't
forwarded properly as the + symbols are URI-encoded (this is a bug on
the part of the `RequestContext::get_query()` the result of which
already contains URI-encoded +'s).
2023-02-08 22:16:27 +01:00
Veloman Yunkan 58bb8b9843 ServerTest.RandomPageRedirectionsAreUrlEncoded 2023-02-08 22:16:27 +01:00
Veloman Yunkan 2e9bec95b0 Proper URI-encoding in InternalServer::build_redirect()
- Before this change `InternalServer::build_redirect()` only URI-encoded the
  article path, ignoring the book name and/or the root location components of
  the URL.

- In order to be able to test this fix, corner_cases.zim was renamed to
  contain a couple of special URL symbols in its filename. The
  `create_corner_cases_zim_file` script was updated accordingly.
2023-02-08 22:16:09 +01:00
Matthieu Gautier 2f419996ab Merge pull request #886 from kiwix/thread_aria 2023-02-08 16:21:52 +01:00
Matthieu Gautier 1ba588272c Get Waiting downloads before Active ones.
`Waiting` can become `Active` while we are getting the downloads.
We may have rare case where we miss a download if we get `Active` before
`Waiting`.
2023-02-08 15:42:17 +01:00
Matthieu Gautier 2c3b7409aa Remove the default value of follow parameter in updateStatus.
`false` is a pretty bad default value as most user want to track
the real download.

By removing the default value, we force user to make a choice.
We could have change the default value to true but it would have been
a silent API change and we don't want that.
2023-02-08 15:42:17 +01:00
Matthieu Gautier f239f2de18 Add documentation. 2023-02-08 15:42:17 +01:00
Matthieu Gautier 18b7b5f277 Mark constant methods as const. 2023-02-08 15:42:17 +01:00
Matthieu Gautier 0e612de4d1 Make Downloader return shared_ptr instead of raw pointer.
This is dangerous by nature to return raw pointer on internal data.
2023-02-08 15:42:17 +01:00
Matthieu Gautier 52ae5c3a5f Make Downloader thread safe. 2023-02-08 15:42:17 +01:00
Matthieu Gautier d1fe1b89ae Do not automatically update the status of existing Download.
User may already have a pointer to the `Download` and it is not protected
against concurrent access.

We could update the status of new created `Download` as by definition,
no one have a pointer on it.
But it better to not do it neither :
- For consistency
- Because the first call on update status may be long on windows (because
  of file preallocation). It is better to not block the downloader for that.
2023-02-08 15:42:17 +01:00
Matthieu Gautier 1aa8521e15 Remove the lock.
As we now build a new request handle for every request, we don't need
a lock.

libcurl itself is thread safe as long as we don't share a handle.
2023-02-08 15:42:17 +01:00
Matthieu Gautier 95ebb6a492 Build a new curl "handle" at everyrequest instead of reusing the same one. 2023-02-08 15:42:17 +01:00
Matthieu Gautier a74aaa5b13 Merge pull request #887 from kiwix/seamonkey 2023-02-08 15:41:59 +01:00
Veloman Yunkan 4bf4b66b27 Explicitly styled UI language selector
The recently introduced ZIM viewer UI language selector looked
adequately nice under Firefox without any explicit styling applied.
Under SeaMonkey, however, its default look and feel was intolerable, so
I used this opportunity to make the UI language selector comply with the
current fashion of the ZIM viewer toolbar.
2023-02-08 15:36:04 +01:00
Veloman Yunkan 57484fd63d Fixed ZIM viewer iframe height under SeaMonkey
SeaMonkey doesn't yet support [Window.visualViewport][1]. As a result the
height of the content iframe element was initialized to the default 150
pixels and never changed. Fortunately there is [Window.innerHeight][2]
which is supported from the very first days of the Gecko layout engine.
The difference between `Window.visualViewport.height` and
`Window.innerHeight` is that the latter also includes

- the height of the horizontal scroll bar, if present (but in a correctly
  implemented ZIM viewer there shouldn't be a horizontal scroll bar for the
  full web-page, so it's OK)

- the height of the on-screen keyboard (which is mostly used on mobile
  devices where SeaMonkey doesn't run). And it is also arguable if the
  appearing on-screen keyboard should squeeze the iframe or slide over
  it (in which latter case it may make more sense to always use `innerHeight`
  instead of `visualViewport.height`).

[1]: https://developer.mozilla.org/en-US/docs/Web/API/Window/visualViewport
[2]: https://developer.mozilla.org/en-US/docs/Web/API/Window/innerHeight
2023-02-08 15:36:04 +01:00
Veloman Yunkan 3a40b6b6d7 Fixed broken ZIM viewer under SeaMonkey
SeaMonkey doesn't yet support ['import.meta'][1].

This change requires that a function `setPermanentGlobalCookie(name, value)`
is defined before `setUserLanguage()` (exported by i18n.js) can be called.

[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta
2023-02-08 15:36:04 +01:00
Matthieu Gautier 2781da3221 Merge pull request #888 from kiwix/meson_bionic 2023-02-08 15:35:41 +01:00
Matthieu Gautier 4629673161 Don't use check keyword argument on old meson.
Ubuntu bionic still use meson 0.45.1.

On bionic we don't check if the command is successful or not but we don't
have choice, the feature is not there.
2023-02-08 15:19:59 +01:00
Matthieu Gautier fe30438854 Merge pull request #884 from kiwix/remove-android-publisher 2023-02-07 09:36:35 +01:00
Emmanuel Engelhart 291fca2b17 Remove libkiwix Android publisher 2023-02-06 19:05:21 +01:00
Kelson 6fd54c7e6e Merge pull request #881 from kiwix/update-workflow-versions
Bump-up GitHub action workflows to latest version
2023-02-06 18:04:30 +01:00
Emmanuel Engelhart a9e4d8a0a1 Bump-up GitHub action workflows to latest version 2023-02-06 17:54:08 +01:00
Veloman Yunkan f3c0d5d422 Merge pull request #871 from kiwix/zim_viewer_i18n
Internationalization of ZIM viewer
2023-02-06 20:50:09 +04:00
Veloman Yunkan a620c8658b UI language setting is preserved in a cookie 2023-02-06 17:39:55 +01:00
Veloman Yunkan d59cfb1fa2 Hiding the userlang query parameter
Now that we have proper UI for user language selection, we don't need
the `?userlang=` query parameter present in the URL. If `?userlang=` is
explicitly provided in the URL, it sets the requested language and
disappears.
2023-02-06 17:39:55 +01:00
Veloman Yunkan ca65dd9000 Navigation history tracks UI language changes 2023-02-06 17:39:55 +01:00
Veloman Yunkan 6c2f229d31 Added prototype UI language selector
Known issues

- styling / placement

- language changes via the selector UI are not recorded in the
  navigation history

- changing the language via the UI doesn't update the `?userlang=` URL
  query parameter
2023-02-06 17:39:55 +01:00
Veloman Yunkan eba7e15358 ZIM viewer i18n via userlang query parameter
ZIM viewer is now internally internationalized but the UI language
can only be set by providing the `userlang` query parameter in the URL:

Example:

  /viewer?userlang=fr#wikipedia_en_climate_change_mini_2021-03/A/index
         ^^^^^^^^^^^^
2023-02-06 17:39:55 +01:00
Veloman Yunkan e42719c9df Frontend i18n utilities 2023-02-06 17:39:55 +01:00
Veloman Yunkan 2995a00cd0 /skin/languages.js
Serving the language list as a JS file rather than JSON simplifies
a few things:

- cacheid management;
- having to manually delay the UI initialization until the JSON file
  is loaded.

static/skin/languages.js must be generated/updated manually by running
the static/generate_i18n_resources_list.py script.
2023-02-06 17:39:55 +01:00
Veloman Yunkan 9f34613473 Added mustache.js (v4.2.0)
mustache.js was obtained from the following location:

- https://github.com/janl/mustache.js/raw/v4.2.0/mustache.js

mustache.min.js which is a build artifact was taken from

- https://cdnjs.cloudflare.com/ajax/libs/mustache.js/4.2.0/mustache.min.js

Note that mustache.js is included in order to comply with Debian packaging
requirements but will not be used in any other way (hence it is not
added to resources_list.txt).
2023-02-06 17:39:55 +01:00
Veloman Yunkan 430bcb17c2 All of viewer initialization is done by setupViewer()
Before this change, some of the actions related to the initialization of
the viewer were run in the global scope as a side effect of loading
/skin/viewer.js. This change moves those actions into setupViewer().
2023-02-06 17:39:55 +01:00
Veloman Yunkan 37bf993759 Fixed indentation 2023-02-06 17:39:55 +01:00
Veloman Yunkan 886a92a795 Included i18n resources in compilation of static resources
Did it by making the kiwix-compile-resources script take multiple
arguments.
2023-02-06 17:39:55 +01:00
Veloman Yunkan 2b01b8168f Moved i18n resources under skin/
This is a quick workaround (at the expense of data duplication) for
having to generate the i18n data in JSON format from the embedded i18n
resource data.

Note, however, that at this point i18n resources are not included in
the list of regular static resources. This will change in the next
commit.
2023-02-06 17:39:55 +01:00
Veloman Yunkan 35aacf7a48 Merge pull request #876 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2023-02-06 20:35:47 +04:00
translatewiki.net 0e0044f840 Localisation updates from https://translatewiki.net. 2023-02-06 13:07:51 +01:00
Matthieu Gautier 76dfc03751 Merge pull request #870 from kiwix/urlEncode_quickfix 2023-01-25 16:41:24 +01:00
Veloman Yunkan ca079a72cc Some clean-up 2023-01-25 19:15:12 +04:00
Veloman Yunkan 471c5b89f4 Dropped the 2nd param of urlEncode()
`urlEncode(str)` is now equivalent to the previous `urlEncode(str, true)`.
2023-01-25 19:15:12 +04:00
Veloman Yunkan 3bf8211b70 Made 2nd param of urlEncode() mandatory
This is a precautionary step before dropping the said parameter.
2023-01-25 19:15:12 +04:00
Veloman Yunkan ec81d5904d Proper URI-encoding in kiwix::getSearchUrl() 2023-01-25 19:15:12 +04:00
Veloman Yunkan 82dcba542a Demonstrating bugs of kiwix::getSearchUrl() 2023-01-25 19:15:12 +04:00
Veloman Yunkan 63e0d5c7c2 RequestContext::get_query() is fully URI-encoded 2023-01-25 19:15:12 +04:00
Veloman Yunkan 772243e832 Category name is fully URI-encoded 2023-01-25 19:15:12 +04:00
Veloman Yunkan bad13d76b4 Removed unused code 2023-01-25 19:15:12 +04:00
Veloman Yunkan 0bde4d9412 Properly URI-encoded links in search results
Special URI symbols occurring in the item path part of the search result
link were NOT encoded, because that would also encode the path separator (/)
symbol. Now that `urlEncode()` never encodes the / symbol, it is safe to
encode all other URI-special symbols in the path.
2023-01-25 19:15:12 +04:00
Veloman Yunkan 239b108fa7 / is no longer a reserved char for urlEncode()
This change is a quick hack solving known issues with URI-encoding in
libkiwix.

This change removes the slash character from the list of URL separator
symbols in URL encoding/decoding utilities, and makes it a symbol that
is safe to leave unencoded.

Effects:

- `urlEncode()` never encodes the '/' symbol (even when it is requested
  to encode the URL separator symbols too).

- `urlDecode(str)`/`urlDecode(..., false)` will now decode %2F to '/';
  other encoded URL separator symbols are NOT decoded when the second
  argument of `urlDecode()` is set to false (which is the default).
2023-01-25 19:15:12 +04:00
Veloman Yunkan c5ccbd37e2 Extracted isHarmlessUriChar() 2023-01-25 19:15:12 +04:00
Veloman Yunkan 822fb3748a Added a unit-test for urlDecode() 2023-01-25 19:15:12 +04:00
Veloman Yunkan aa2e443eb8 Fixed indentation
Replaced tabs with spaces.
2023-01-25 19:15:11 +04:00
Veloman Yunkan 82d477009d '#' is a URI delimiter symbol 2023-01-25 19:15:11 +04:00
Veloman Yunkan e49081da80 Fixed urlEncode() for chars below 0x10 2023-01-25 19:15:11 +04:00
Veloman Yunkan 07c7d3931d Added a unit-test of buggy urlEncode()
Added a unit-test for urlEncode() that passes for its current
implementation despite the two bugs that were revealed while creating
the unit-test.
2023-01-25 19:15:11 +04:00
Matthieu Gautier cf59a93cf1 Merge pull request #869 from kiwix/userlang_cookie_fixes 2023-01-24 19:16:08 +01:00
Veloman Yunkan e35e7585e0 Server sets userlang cookie as global and permanent
Without specifying the "Path" attribute of the cookie in the "Set-Cookie" header
we end up with multiple instances of the cookie for different URLs. We
want a single "global" cookie for kiwix-serve. Besides we want it to be
"permanent" rather than a session cookie, hence the large (1-year-long)
TTL value for the "Max-Age" attribute.
2023-01-24 19:01:32 +01:00
Veloman Yunkan fcb97c3c06 Sparing use of "Set-Cookie: userlang=..." header
Server adds the "Set-Cookie: userlang=..." header to the response only
if the "userlang" cookie is not already present with the same value.
2023-01-24 19:01:32 +01:00
Veloman Yunkan 0edee4d066 Improved ServerTest.UserLanguageControl unittest
- Description of a test point was not updated in an earlier commit
  that added proper handling of the Accept-Language header. Also
  after enhancing the limited implementation it made sense to
  add another test point demonstrating that the most suitable language
  (rather than just the first one in the list) is selected.

- Now failures of the test case because of a missing Set-Cookie header
  are more informative.
2023-01-24 19:01:32 +01:00
Kelson b9937e6859 Merge pull request #868 from adamlamar/windows-git-clone
Fix git clone on Windows
2023-01-19 08:44:36 +01:00
Adam Lamar 59012c50b4 Fix git clone on Windows
The question mark (?) is not a valid filename character on Windows.
Changing to a the pound sign (#) so that this repository can still be
cloned on Windows.
2023-01-18 23:01:14 +01:00
Matthieu Gautier 7a98878273 Merge pull request #866 from kiwix/uri_encoded_redirections 2023-01-10 15:06:18 +01:00
Veloman Yunkan 8eb527389e URI-encoding of redirections to URLs with special symbols 2023-01-10 17:41:59 +04:00
Veloman Yunkan 78b2c1a273 Testing of redirection to URLs with special symbols 2023-01-10 17:41:59 +04:00
Veloman Yunkan 497c0700b5 Fixed metadata options in create_corner_cases_zim_file
Specifying the = symbol with single-character options makes that
character included in the option value (e.g. -l=en results in the
language of the ZIM file being set to =en).
2023-01-10 17:41:59 +04:00
Veloman Yunkan bac12010aa Updated create_corner_cases_zim_file script
Updated the create_corner_cases_zim_file to work with the latest (v3.1.3)
release of zimwriterfs.
2023-01-10 17:41:59 +04:00
Veloman Yunkan dad33a850c Merge pull request #857 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2023-01-09 15:20:52 +04:00
Veloman Yunkan 0968fc98ee Added new translations to i18n_resources_list.txt 2023-01-09 15:04:51 +04:00
translatewiki.net ff44d88f21 Localisation updates from https://translatewiki.net. 2023-01-05 13:10:37 +01:00
Matthieu Gautier 1e7baee9d7 Merge pull request #862 from kiwix/suggestion_link_fix 2023-01-03 11:07:14 +01:00
Veloman Yunkan d9342acf5b Suggestion link points to /content endpoint
Directly pointing the suggestion link to a /content/... URL avoids
an unnecessary redirection by the server (and an associated bug
related to redirection of URLs with URI-encoded special symbols in
them that - in the current implementation - go into the target URL
in decoded form).
2023-01-03 10:57:59 +01:00
Kelson b3f1ab6579 Merge pull request #863 from kiwix/update-workflows-new-default-branch
New git default branch is 'main'
2022-12-27 14:28:13 +01:00
Emmanuel Engelhart f5c9b2404a New git default branch is 'main' 2022-12-27 14:27:43 +01:00
Kelson 8b1fe21e4e Delete move.yml 2022-12-27 14:25:28 +01:00
Kelson 815c59ff6d "main" is the new git default branch 2022-12-27 14:23:14 +01:00
Matthieu Gautier 90318dfb6b Merge pull request #860 from kiwix/handling_of_suggestion_links_with_single_quotes 2022-12-21 12:02:58 +01:00
Veloman Yunkan f3d2f474a7 Handling of suggestions containing special symbols
This change fixes two issues:

1. Presence of URL-specific special symbols (such as ? or #) in the book
   and/or article name resulted in a wrong suggestion link. This is
   fixed by URI-encoding the book name and the path, too.

2. Presence of a single quote symbol in the book and/or article name
   resulted in invalid javascript code in the href attribute of the
   suggestion link.

   The single quote (') symbol is not URL-encoded (unlike its double quote
   counterpart). As a result, enclosing a URL-encoded string in single
   quotes may result in invalid javascript. Using double quotes instead is
   safe, since both double quote (") and backslash (\) symbols (which are
   the only special symbols for such quoting) undergo URL-encoding.
2022-12-17 18:39:17 +04:00
Veloman Yunkan 12140098e6 Extracted makeJSLink() 2022-12-15 18:53:32 +04:00
Veloman Yunkan c7d8081e9a gotoUrl() takes URLs relative to root location 2022-12-15 18:21:22 +04:00
Matthieu Gautier a10067e6b6 Merge pull request #849 from kiwix/backend_userlang_control 2022-12-14 15:39:31 +01:00
Veloman Yunkan 28e9fb48b6 Properly implemented parseUserLanguagePreferences() 2022-12-14 15:34:46 +01:00
Veloman Yunkan 634f3fcf14 Properly implemented selectMostSuitableLanguage() 2022-12-14 15:34:46 +01:00
Veloman Yunkan 88597e1834 Enter selectMostSuitableLanguage() 2022-12-14 15:34:46 +01:00
Veloman Yunkan 69b3e1f8a7 Moved user language preferences into i18n.{h,cpp} 2022-12-14 15:34:46 +01:00
Veloman Yunkan 669d8898ac Enter UserLangPreferences 2022-12-14 15:34:46 +01:00
Veloman Yunkan 14f0f79061 User language control via userlang cookie 2022-12-14 15:34:46 +01:00
Veloman Yunkan 600ff07986 Test descriptions in ServerTest.UserLanguageControl 2022-12-14 15:34:46 +01:00
Veloman Yunkan 1d74b5e311 Server sets the userlang cookie on every response 2022-12-14 15:34:46 +01:00
Veloman Yunkan c0fe6f4aee Added cookies to ServerTest.UserLanguageControl 2022-12-14 15:34:46 +01:00
Matthieu Gautier aa7053bbe8 Merge pull request #859 from kiwix/safe_href_in_suggestion_links 2022-12-14 15:31:56 +01:00
Veloman Yunkan 99f24eb598 Safe href in suggestion links 2022-12-12 17:15:46 +04:00
Kelson 6790a144a1 Merge pull request #856 from kiwix/compress-web-fonts
Gzip compress HTTP response for Web fonts
2022-12-08 14:36:32 +01:00
Emmanuel Engelhart cd3d2110d9 Error if run_command() fails, remove meson warning 2022-12-08 13:03:33 +01:00
Emmanuel Engelhart b404241d0b Fix font compression tests 2022-12-08 12:55:28 +01:00
Emmanuel Engelhart 2d42d6dc60 Gzip compress HTTP response for Web fonts 2022-12-07 19:21:27 +01:00
Matthieu Gautier e65c9c41d8 Merge pull request #850 from kiwix/version_12.0.0 2022-11-30 18:10:19 +01:00
Matthieu Gautier 0ae31bd181 New version 12.0.0
* [API Break] Remove wrapper around libzim (@mgautierfr #789)
* Allow kiwix-serve to use custom resource files (@veloman-yunkan #779)
* Properly handle searchProtocolPrefix when rendering search result (@veloman-yunkan #823)
* Prevent search on multi language content (@veloman-yunkan #838)
* Use new `zim::Archive::getMediaCount` from libzim (@mgautierfr #836)
* Catalog:
 - Include tags in free text catalog search (@veloman-yunkan #802)
 - Illustration's url is based on book's uuid (@veloman-yunkan #804)
 - Cleanup of the opds-dumper (@veloman-yunkan #829)
 - Allow filtering of catalog content using multiple languages (@veloman-yunkan #841)
 - Make opds-dumper respect the namemapper (@mgautierfr #837)
* Server:
 - Correctly handle `\` in suggestion json generation (@veloman-yunkan #843)
 - Better http caching (@veloman-yunkan #833)
 - Make `/suggest` endpoint thread-safe (@veloman-yunkan #834)
 - Better redirection of main page (@veloman-yunkan #827)
 - Remove jquery (@mgautierfr @juuz0 #796)
 - Better Viewer of zim content :
   . Introduce `/content` endpoints (@veloman-yunkan #806)
   . Switch to iframe based content viewer (@veloman-yunkan #716)
 - Optimised design of the welcome page:
   . Alignement (@juuz0 @kelson42 #786)
   . Exit download modal on pressing escape key (@juzz0 #800)
   . Add favicon for different devices (@juzz0 #805)
   . Fix auto hidding of the toolbar (@veloman-yunkan #821)
   . Allow user to filter books by tags in the front page (@juuz0 #711)
* CI :
  - Trigger CI on pull_request (@kelson42 #791)
  - Drop Ubuntu Impish packaging (@legoktm #825)
  - Add Ubuntu Kinetic packaging (@legoktm #801)
* Testing:
  - Test ICULanguageInfo (@veloman-yunkan #795)
  - Introduce fake `test` language to test i18n (@veloman-yunkan #848)
* Fix documentation (@kelson42 #816)
* Udpate translation (#787 #839 #847)
2022-11-30 18:01:13 +01:00
Matthieu Gautier 0d8971ef88 Merge pull request #847 from kiwix/translatewiki 2022-11-30 17:59:15 +01:00
translatewiki.net 2812b5ca5c Localisation updates from https://translatewiki.net. 2022-11-30 14:50:14 +01:00
Matthieu Gautier 4dc8973cdc Merge pull request #848 from kiwix/fake_language_for_i18n_testing 2022-11-29 16:19:35 +01:00
Veloman Yunkan 160c95e317 Fake language for testing is now based on English
Usage of non-latin scripts in unit-tests creates unnecessary problems
for maintainers.
2022-11-26 11:59:04 +04:00
Veloman Yunkan 956289d9f8 Introduced a fake language for i18n testing
We need a fake language for tests that won't be affected by
modifications made by 3rd party translators (see kiwix/libkiwix#749).

- static/i18n/hy.json was cloned as static/i18n/test.json
- usage of "hy" in unit-tests was replaced with "test"
2022-11-26 11:58:27 +04:00
Kelson 3568ccd511 Merge pull request #843 from kiwix/backslash_handling_in_suggestions
Backslash handling in suggestions
2022-11-17 11:48:37 +01:00
Emmanuel Engelhart d66cc6286c Fix broken macOS CI (change Python version) 2022-11-17 11:42:42 +01:00
Veloman Yunkan 7743e73ede All non-alphanumeric symbols deserve a test 2022-11-17 11:51:53 +04:00
Veloman Yunkan 4966f4155d Fixed handling of backslashes in suggestions 2022-11-17 11:51:53 +04:00
Veloman Yunkan c727de6591 Unit-testing of kiwix::Suggestions
The new unit test fails because of a buggy mishandling of backslashes
in suggestions. The fix is coming next.
2022-11-17 11:51:53 +04:00
Veloman Yunkan 0f0ae1cfed A small refactoring 2022-11-17 11:51:53 +04:00
Veloman Yunkan da78aae62b kiwix::Suggestions gives up its temporary pedigree 2022-11-17 11:51:53 +04:00
Veloman Yunkan abcd4ade99 kiwix::Suggestions::getJSON() 2022-11-17 11:51:53 +04:00
Veloman Yunkan 7a9780eb90 kiwix::Suggestions::addFTSearchSuggestion() 2022-11-17 11:51:53 +04:00
Veloman Yunkan 51bd881211 kiwix::Suggestions::add() 2022-11-17 11:51:53 +04:00
Veloman Yunkan f36f1661d5 Got rid of result count tracker variable 2022-11-17 11:51:53 +04:00
Veloman Yunkan 18f4a58237 Conception of kiwix::Suggestions 2022-11-17 11:51:53 +04:00
Veloman Yunkan 6285599b7c Merge pull request #839 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2022-11-17 11:29:21 +04:00
Veloman Yunkan 764f68f7d8 Updated i18n_resources_list 2022-11-17 11:10:07 +04:00
translatewiki.net 777c5e1f7a Localisation updates from https://translatewiki.net. 2022-11-14 13:06:22 +01:00
Kelson 8031ffa447 Merge pull request #801 from kiwix/legoktm-patch-1
PPA: Add kinetic
2022-11-13 21:03:46 +01:00
Kunal Mehta 0c8ceac117 PPA: Add kinetic 2022-11-13 21:02:32 +01:00
Kelson ec31882e94 Merge pull request #836 from kiwix/media_count_libzim
Use new `zim::Archive::getMediaCount` from libzim.
2022-11-07 12:52:55 +01:00
Matthieu Gautier 8cec014691 Use new zim::Archive::getMediaCount from libzim.
As libzim also changed the behavior of `zim::Archive::getArticleCount`,
we don't need the hack, and we don't need the code to parse `M/Counter`.
2022-11-02 13:15:47 +01:00
Matthieu Gautier bf9aeffbfa Merge pull request #841 from kiwix/catalog_filtering_by_multiple_languages 2022-11-01 19:23:36 +01:00
Veloman Yunkan 7765769e6f Beautification (better alignment) 2022-11-01 19:16:30 +01:00
Veloman Yunkan 7d69ece27d OPDS can be filtered using more than one language
From now on, the `lang` parameter of the /catalog/search,
/catalog/v2/entries, and /catalog/v2/partial_entries endpoints is
interpreted as a comma-separated list of languages.
2022-11-01 19:16:30 +01:00
Veloman Yunkan c0d027e8a4 Unittests for OPDS filtering by language 2022-11-01 19:16:30 +01:00
Veloman Yunkan c87add1419 Removed an unused variable 2022-11-01 19:16:30 +01:00
Matthieu Gautier a52138e5ba Merge pull request #838 from kiwix/language_handling_during_search 2022-11-01 18:28:02 +01:00
Veloman Yunkan d1b85192c0 ServerSearchTest.searchInMultilanguageBookSetIsDenied 2022-10-31 13:30:11 +04:00
Veloman Yunkan cb02dbd92a RequestContext preserves the exact query string
Before this change RequestContext::get_query() returned a reordered
query string (alphabetically sorted by the parameter names).

This fix facilitiates testing of responses where the request URL appears
in the response.
2022-10-31 13:28:21 +04:00
Veloman Yunkan 9409e8bd91 Preventing confusion of tongues in multizim search
Multizim search requires that all selected books be in the same
language.

No new URL query parameter was introduced for specifying the intended
search language - `books.filter.lang` can be used for that purpose.

The server_search unit-test was updated to use a slightly cheating
library xml file where the language of example.zim was tweaked from "en"
to "eng" in order to match that of zimfile.zim. Note that this change
drops from the tested server two other goofy ZIM files corner_cases.zim
and poor.zim that have been/are included in ServerTest.
2022-10-31 13:27:57 +04:00
Veloman Yunkan cd62b5dd91 Some clean-up 2022-10-31 13:22:15 +04:00
Veloman Yunkan 414d7ae4fe Fixed indentation 2022-10-31 13:22:15 +04:00
Veloman Yunkan 9d2cc35447 Extracted InternalServer::handle_search_request() 2022-10-31 13:22:15 +04:00
Veloman Yunkan 7167ca1e6a Adios kiwix::getArchiveId() 2022-10-31 13:22:15 +04:00
Kelson 8cc1c47133 Merge pull request #837 from kiwix/opds_name_mapper_bis
Make OPDSDumper respect the NameMapper of the server.
2022-10-31 09:14:55 +01:00
Matthieu Gautier e5b94fa1bb Make the opds_dumper respect the provided nameMapper used in the server.
Fix #828
2022-10-30 19:21:01 +01:00
Matthieu Gautier b0d719431d Use a macro to define catalog's entries in test. 2022-10-26 17:37:45 +02:00
Matthieu Gautier 0e20f50443 Merge pull request #833 from kiwix/http_caching 2022-10-20 16:17:43 +02:00
Veloman Yunkan 18a18c17a9 Applied KIWIXCACHEID to skin/search-icon.svg 2022-10-19 19:27:21 +04:00
Veloman Yunkan 602c20f160 Removed unused resource skin/css/images/search.svg 2022-10-19 19:27:21 +04:00
Veloman Yunkan 415ec41099 Cacheids are computed for all static resources
Before this change cacheids were computed only for those static
resources that were referenced from other resources via KIWIXCACHEID.

A few static resources without such references existed.

Now all resources under skin/ have their cacheids computed.
2022-10-19 19:26:04 +04:00
Veloman Yunkan b9f60ecfe9 Handling of cacheid when serving static resources
During static resource preprocessing and compilation their cacheid
values are embedded into libkiwix and can be accessed at runtime.

If a static resource is requsted without specifying any cacheid
it is served as dynamic content (with short TTL and the library id
used for the ETag, though using the cacheid for the ETag would
be better).

If a cacheid is supplied in the request it must match the cacheid of the
resource (otherwise a 404 Not Found error is returned) whereupon the
resource is served as immutable content.

Known issues:

- One issue is caused by the fact that some static resources don't get a
  cacheid; this is resolved in the next commit.

- Interaction of this change with the support for dynamically customizing
  static resources (via KIWIX_SERVE_CUSTOMIZED_RESOURCES env var) was
  not addressed.
2022-10-19 19:26:04 +04:00
Veloman Yunkan 12a638750e Fixed URLs to static resources without cacheids
One (hopefully, last) remaining relative URL to a static resource
is the reference to ./search-icon.svg found in skin/index.css to which
KIWIXCACHEID could not be applied because of the limitations of the
resource preprocessing script `kiwix-resources`.
2022-10-19 19:26:04 +04:00
Veloman Yunkan b62486c2f9 Added /catalog URLs to general purpose server tests 2022-10-19 19:26:04 +04:00
Veloman Yunkan 6bc7e0178d Added all static resources to the server unit-test 2022-10-19 19:26:04 +04:00
Veloman Yunkan ce8b2bf9d9 Library::removeBookById() updates the revision 2022-10-19 19:26:04 +04:00
Veloman Yunkan 9fd1423100 Small clean-up 2022-10-19 19:26:04 +04:00
Veloman Yunkan 6b8d6232f0 InternalServer::getLibraryId() 2022-10-19 19:26:02 +04:00
Veloman Yunkan c91df1cb26 Two private funcs of InternalServer became free 2022-10-19 19:21:28 +04:00
Veloman Yunkan b249edee60 ETags for ZIM content use the ZIM file UUID 2022-10-19 19:21:28 +04:00
Veloman Yunkan a31ccb6588 Decoupling ETags from the server id 2022-10-19 19:21:28 +04:00
Veloman Yunkan 43c8da9b04 Testing of cache control 2022-10-19 19:21:28 +04:00
Veloman Yunkan 190156e095 Setting Cache-Control: for three types of content
At this point the ETag value for ZIM content is still generated from the
timestamp of the server start-up time.
2022-10-19 19:21:28 +04:00
Veloman Yunkan 5471819021 Finer categorization of URLs in the server unit-test
Preparing the server unit-test for the more elaborate handling of HTTP
caching.
2022-10-19 19:21:28 +04:00
Matthieu Gautier 7feef320d9 Merge pull request #834 from kiwix/concurrency_safe_suggestion_endpoint 2022-10-18 17:00:02 +02:00
Veloman Yunkan 73191fb8f8 Made the /suggest endpoint concurrency-safe 2022-10-13 13:39:25 +04:00
Matthieu Gautier a844bc4000 Merge pull request #829 from kiwix/opds_dumper_cleanup
OPDS dumper cleanup
2022-10-06 14:11:47 +02:00
Veloman Yunkan f13ca55ef6 Eliminated the endpointRoot parameter 2022-10-06 14:02:50 +04:00
Veloman Yunkan dc194683bb Split XML generation code for full & partial entries 2022-10-06 13:48:58 +04:00
Veloman Yunkan 0841472004 Separate templates for full & partial OPDS entries 2022-10-06 13:44:39 +04:00
Veloman Yunkan ebb713cb85 Got rid of an unjustified parameter
The XML header is injected in a more straightforward way in the single
location where it is needed.
2022-10-06 12:49:51 +04:00
Matthieu Gautier cd6cbe3655 Merge pull request #827 from kiwix/http_redirect_new_logic
New logic for generating HTTP-redirects
2022-10-04 16:04:20 +02:00
Veloman Yunkan 582c8d868a New logic for generating HTTP-redirects
Before this fix the root URL for a book was assumed to resolve to the
main page.  This was not true for ZIM files containing an entry at an
empty path or with a path equal to "/", resulting in issue #826. The
logic behind this behaviour is found in `kiwix::getEntryFromPath()`.

The fix to that issue is a little more general and will result in an
HTTP redirect in any case where `kiwix::getEntryFromPath(zim, path)`
returns an entry with a real path different from the requested one. In
particular, this will affect the behaviour on ZIM files with the old
namespace scheme, where the requested resource - if not found - is also
looked up in the 'A', 'I', 'J', and/or '-' namespaces. Now instead of
returning the contents of that other resource an HTTP redirect response
will be sent.
2022-10-04 14:18:08 +04:00
Kelson f6ae75e41d Merge pull request #822 from kiwix/update-format-code-script
Update format_code.sh script
2022-10-03 16:20:32 +02:00
Emmanuel Engelhart ffbda34b75 Fix: improvement to handle dirs with spaces 2022-10-01 21:15:50 +02:00
Emmanuel Engelhart f61fc07121 Fix: autodetect proper directories to format 2022-09-29 20:37:20 +02:00
Emmanuel Engelhart de7fa771fc More generic format_code.sh script 2022-09-29 20:23:15 +02:00
Emmanuel Engelhart 24c1ca5a4a Move format_code.sh to script/ folder 2022-09-29 20:23:15 +02:00
Matthieu Gautier 15f5abad3c Merge pull request #821 from kiwix/taskbar_autohiding
Auto-hiding of the iframe-based taskbar
2022-09-28 17:15:59 +02:00
Veloman Yunkan 0a866fa914 Fixed auto-hiding of the toolbar 2022-09-28 17:00:00 +02:00
Veloman Yunkan ff192cba49 Fixed a misused setInterval()
In the commit that introduced `setInterval()` in `setupViewer()`
actually `setTimeout()` was intended.
2022-09-28 17:00:00 +02:00
Matthieu Gautier 0dd638f261 Merge pull request #825 from kiwix/no_impish
PPA: Drop impish
2022-09-28 16:59:26 +02:00
Kunal Mehta 229c0ceaf9 PPA: Drop impish 2022-09-28 16:31:33 +02:00
Matthieu Gautier 70f7be4202 Merge pull request #823 from kiwix/kiwix-desktop-friendly-search-results
Fixed search results for kiwix-desktop
2022-09-28 15:40:02 +02:00
Veloman Yunkan 60148717e1 Fixed search results for kiwix-desktop 2022-09-26 13:11:25 +04:00
Veloman Yunkan 266e29dff2 Merge pull request #787 from kiwix/translatewiki
Localisation updates from https://translatewiki.net.
2022-09-24 19:17:07 +04:00
Veloman Yunkan 11051b4eed Updated i18n_resources_list.txt 2022-09-24 19:03:06 +04:00
translatewiki.net 86eacea74e Localisation updates from https://translatewiki.net. 2022-09-22 13:06:57 +02:00
Matthieu Gautier 3a75facfdc Merge pull request #716 from kiwix/iframe_based_content_viewer
Iframe-based content viewer
2022-09-22 09:28:50 +02:00
Veloman Yunkan 0a0f52f1e2 Testing of the viewer settings endpoint 2022-09-21 17:42:54 +04:00
Veloman Yunkan 0994a8f1b0 Dropped taskbarless test server
With taskbar no longer being injected into the responses, it doesn't make any
sense testing the search on different flavours of the server.
2022-09-21 17:40:46 +04:00
Veloman Yunkan fa67b45f50 Got rid of unused *pendToFirstOccurence() funcs 2022-09-21 15:52:26 +04:00
Veloman Yunkan defa38719d Fix cacheids after a rebase
A rebase invalidated the cacheids in the previous commits of the
iframe_based_content_viewer branch. This commit fixes only the current
state leaving the history with wrong cacheids - this can be an issue
for `git bisect` being executed on a commit range overlapping with
the iframe_based_content_viewer branch.
2022-09-21 15:44:09 +04:00
Veloman Yunkan cac2d212c6 Respecting the --nosearchbar option of kiwix-serve
If `kiwix-serve` is run with the `--nosearchbar` option the toolbar is
disabled (hidden) in its viewer.

Note however that certain actions performed by the viewer merely with
the purpose of keeping the toolbar up-to-date are still carried out.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 4e06bb6a08 Partly fixed auto-hiding of the toolbar
Auto hiding of the toolbars on narrow screens works only for the first
page loaded in the viewer. Navigating to other pages interferes with
autohiding as follows:

- If the toolbar was hidden, it stays hidden.

- If the toolbar was not hidden, it loses the ability to autohide.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 796e729f52 Library button is disabled by setupViewer() 2022-09-21 15:41:40 +04:00
Veloman Yunkan ae01790375 Introduced setupViewer() 2022-09-21 15:41:40 +04:00
Veloman Yunkan da23e4eca4 Revert "Partly respecting the kiwix-serve --nosearchbar option"
This reverts commit 436d890893713c5eb98df6893d0e0b41b22e2472.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 2be9ac342f Partly respecting the kiwix-serve --nosearchbar option
`--nosearchbar` option of `kiwix-serve` (despite its misleading name)
was used to disable the entire taskbar. This commit accounts for the
existence of that option only partially:

1. Links to books on the welcome/library page are affected - by default
   books are displayed in the viewer, but in a kiwix-serve instance run
   with --nosearchbar books are loaded in the top window.

2. The `/viewer` endpoint is enabled unconditionally, so if anyone
   enters the viewer URL in the address bar they will see books in the
   viewer.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 369406fb5d Viewer settings
Made the viewer respect the `--blockexternal` and `--nolibrarybutton`
options of `kiwix-serve`. Those options are passed to the viewer
via the dynamically generated resource `/viewer_settings.js`.
2022-09-21 15:41:40 +04:00
Veloman Yunkan b81cb3a8e9 Got rid of raw mode in response generation 2022-09-21 15:41:40 +04:00
Veloman Yunkan 6cc677b8ad Dropped ContentResponse::contentDecorationAllowed() 2022-09-21 15:41:40 +04:00
Veloman Yunkan a674561110 Dropped root link injection
The only place that the root link is now used is in /skin/index.js,
so added it in static/templates/index.html. But it seems that nothing
prevents us from from switching from aboslute paths to relative paths
in /skin/index.js, which will eliminate the need for the root link
altogether.

As a result of this change content is never decorated by kiwix serve.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 685e7f8ad4 Unconditional blocking of external links 2022-09-21 15:41:40 +04:00
Veloman Yunkan 0ce36e6246 Got rid of isHomePage in ContentResponse::build() 2022-09-21 15:41:40 +04:00
Veloman Yunkan eb0a45b13e Undefaulted bool params of ContentResponse::build()
This resulted in compiler aided discovery of all call sites where the
default values were used. For OPDS/catalog requests now passing true for the
`raw` parameter, since XML content isn't supposed to undergo any
transformations.
2022-09-21 15:41:40 +04:00
Veloman Yunkan c988511561 Removed unused param from ContentResponse::build()
Removed the isHomePage param from one of the variants of
`ContentResponse::build()`. The other overload is dangerous since
failing to review&update all of its call site may result in changed
semantics. Will do it in a couple of separate commits.
2022-09-21 15:41:40 +04:00
Veloman Yunkan c73e6f9a81 Dropped unused params from ContentResponse ctor 2022-09-21 15:41:40 +04:00
Veloman Yunkan 0cf4850a9b Dropped TaskbarInfo 2022-09-21 15:41:40 +04:00
Veloman Yunkan 40c496d401 Removed old-style taskbar injection
Double-toolbar in the viewer has gone.

Some clean-up has to be performed after this change.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 9a193735fb Hiding of the suggestions drop-down list
- Suggestions disappear when search is performed as a result of pressing
  enter in the search box.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 2083c390b5 Searchbox correctly tracks the current book
Before this fix there were two issues with the taskbar search box:

1. The book used for the suggestions API was resolved only once during
   the page load and didn't change during navigation.

2. The current book could not be resolved from a search URL.

Now both issues are fixed.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 29efb88d48 Superficial cleanup in static/skin/viewer.js 2022-09-21 15:41:40 +04:00
Veloman Yunkan 948435794f Moved all viewer JS code to viewer.js 2022-09-21 15:41:40 +04:00
Veloman Yunkan 7ed01e7678 Renamed static/skin/{viewer_taskbar -> viewer}.js 2022-09-21 15:41:40 +04:00
Veloman Yunkan eadc0ac72b Welcome page interoperates with iframe-based viewer
- /viewer (without any hash) dynamically redirects to the welcome page

- The book links on the welcome page point to the iframe-based viewer
2022-09-21 15:41:40 +04:00
Veloman Yunkan 77d9777208 Enabled searchbox in the iframe-based viewer
Known issues:

- the placeholder text in the searchbox is incorrect
2022-09-21 15:41:40 +04:00
Veloman Yunkan 4a55b136f6 Enabled random page button in the iframe-based viewer 2022-09-21 15:41:40 +04:00
Veloman Yunkan a9446714ea Viewer respects the --urlRootLocation option 2022-09-21 15:41:40 +04:00
Veloman Yunkan 17ff2a094d Enabled home button in the iframe-based viewer 2022-09-21 15:41:40 +04:00
Veloman Yunkan 0c4d9e8730 Enabled the library button on the taskbar
The greenish taskbar placeholder is gone. The appearance of the old taskbar
is restored. However the taskbar currently contains only the library
button (but the latter leads to the currently blank welcome page).
2022-09-21 15:41:40 +04:00
Veloman Yunkan 7be7a8ed5f viewer += <!--static/templates/taskbar_part.html-->
Added to static/skin/viewer.html the contents of
static/templates/taskbar_part.html inside a comment block.
2022-09-21 15:41:40 +04:00
Veloman Yunkan f41e71b2d7 viewer_taskbar.js + viewer.html = BFF
Foundation for never-ending friendship between viewer_taskbar.js and
viewer.html has been established by a slight change in how the book name
is obtained and commenting out the rest of the code.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 58e45711ff Copied static/skin/taskbar.js as viewer_taskbar.js 2022-09-21 15:41:40 +04:00
Veloman Yunkan 5b545d81bd viewer += static/templates/head_taskbar.html
Javascript code inside taskbar.js doesn't work correctly with the new
viewer.  Will fix any issues in a clone of static/skin/taskbar.js.
2022-09-21 15:41:40 +04:00
Veloman Yunkan 7c6c315ead /viewer# displays a blank page 2022-09-21 15:41:40 +04:00
Veloman Yunkan 228e31cddd Handling of window size changes 2022-09-21 15:41:40 +04:00
Veloman Yunkan 4105be9bd2 Improved browsing history tracking & traversal
Before this fix, browsing history didn't work at all. Now it mostly
works but there are still some quirks that must be debugged further.

Since session history handling turns out to be a rather complex topic
(see https://html.spec.whatwg.org/multipage/history.html) the work in
that direction will be postponed until other features reach a comparable
level of readiness.
2022-09-21 15:41:40 +04:00
Veloman Yunkan e5f97d95b1 Handling of manual hash component change 2022-09-21 15:41:40 +04:00
Veloman Yunkan 4db443eca6 Embryo of iframe-based viewer 2022-09-21 15:41:40 +04:00
Veloman Yunkan dea674ef38 Added resources of autoComplete.js to test/server.cpp 2022-09-21 15:41:40 +04:00
Kelson 4b6c6452c0 Merge pull request #816 from kiwix/static-doc
Static file generation documentation in README.md
2022-09-14 18:56:18 +02:00
Emmanuel Engelhart 5130bf9774 Fix: testlog based cacheid retrieval 2022-09-14 15:54:25 +02:00
Emmanuel Engelhart ee3514d2d6 Documentation for static files 2022-09-14 15:37:12 +02:00
Emmanuel Engelhart e1847cb058 Move back the 'Troubleshooting' section to the end 2022-09-14 15:37:12 +02:00
Kelson dd2b82a6be Merge pull request #818 from kiwix/remove-last-kiwixlib
It's libkiwix, not kiwixlib
2022-09-13 16:53:44 +02:00
Emmanuel Engelhart 1062bd73a3 It's libkiwix, not kiwixlib 2022-09-11 16:05:25 +02:00
Kelson cd56277123 Merge pull request #813 from kiwix/small-css-fix
Small kiwix-serve welcome page CSS fix
2022-09-06 19:09:45 +02:00
Emmanuel Engelhart 5e8b977bec Small kiwix-serve welcome page CSS fix 2022-09-06 12:38:49 +05:30
Matthieu Gautier 9f545718c2 Merge pull request #806 from kiwix/content_endpoint
/content endpoint
2022-08-11 17:04:02 +02:00
Veloman Yunkan e323dcf6c9 Redirecting /nonendpoint URLs to /content/nonendpoint 2022-08-11 18:04:05 +04:00
Veloman Yunkan 3b98987cb3 More robust handling of endpoint URLs
The next goal is to redirect old-style /book/path/to/entry URLs to
/content/book/path/to/entry, which seemed pretty trivial.

However, given the current handling of some endpoint URLs, more work was
required to ensure that invalid endpoint URLs (e.g.  "/random/number" or
"/suggest/fr") are not interpreted as content URLs. Previously, that was
not a user-observable issue, since the result would be an immediate 404
error (except in certain edge cases, like handling the request for
"/random/number" when there is a book with name "random" containing an
article at path "/number"). With redirection of URLs that were assumed
to refer to content a 404 error would be issued for the
transformed URL ("/content/random/number") which may be confusing.

Therefore this change is to ensure the correct routing of endpoint URL
handling.
2022-08-11 18:04:05 +04:00
Veloman Yunkan fd36d11ccf Search results now use the /content URL scheme 2022-08-11 18:04:05 +04:00
Veloman Yunkan dc56f82c29 Using /content/... URLs in OPDS output 2022-08-11 18:04:05 +04:00
Veloman Yunkan 1b1c1e352e Introduced /content endpoint
Book content is now served under /content/book/...

The old access to book content via a top-level URL /book/... is so far
preserved for backward compatibility.

Redirects were changed to use the new URL scheme. Links in the search results
still use the old scheme.
2022-08-11 18:04:05 +04:00
Veloman Yunkan a4b18893aa Moved handling of the "/" URL 2022-08-11 18:04:05 +04:00
Matthieu Gautier d737db666a Merge pull request #802 from kiwix/include_tags_in_free_text_library_search
Included tags in free text catalog search
2022-08-10 16:43:48 +02:00
Veloman Yunkan cff143b4ec Included tags in free text catalog search 2022-08-06 07:39:45 +02:00
Matthieu Gautier 8e6d893f7f Merge pull request #804 from kiwix/illustration_url_uses_the_book_uuid
Illustration URL uses the book UUID
2022-08-04 15:43:22 +02:00
Veloman Yunkan 111aab0c23 Illustration URL uses the book UUID
If the server is initialized with a library.xml file, then the id
specified in the XML file is used (rather than the UUID recorded in the
ZIM file).

Note that in test/data/library.xml the book ids are fake and
different from the real ZIM IDs; that file was created for testing
of the /catalog endpoint which doesn't access ZIM content, so the
the same ZIM file zimfile.zim was added to library.xml three times as
three different books (with unique human-friendly ids). This explains
the diff in test/library_server.cpp.
2022-08-03 16:13:21 +02:00
Kelson dd90ca1018 Merge pull request #805 from kiwix/fixFavicon
Add favicons (for different devices) to kiwix-serve welcome page
2022-08-03 16:11:54 +02:00
Nikhil Tanwar 3facd594f6 Add favicon for different devices.
Added favicon files for a number of devices.
All files and html code is generated by: https://realfavicongenerator.net/
The file used to generate favicons can be found at: https://upload.wikimedia.org/wikipedia/commons/b/b0/Kiwix_logo_v3.svg
2022-08-03 18:52:13 +05:30
Kelson 4cd52b0809 Merge pull request #796 from kiwix/noJquery
No jquery
2022-08-01 15:15:02 +02:00
Nikhil Tanwar baf22c2516 So long, jQuery
Now after porting index.js and taskbar.js to vanilla JS, it is time to remove files.
Deleted static/skin/jquery-ui
Updated customIndexPage template in README.md.
Thank you for your service, jQuery :)
2022-07-31 19:16:46 +05:30
Nikhil Tanwar f8a530100f Implement taskbar scroll actions in vanilla JS
Completes the porting of remaining jQuery code in taskbar.js - scroll function, blur and focus events and the cybook hack.
2022-07-31 19:16:02 +05:30
Nikhil Tanwar a0db199388 Turn suggestions into hyperlinks
The suggestions are now clickable hyperlinks.
2022-07-31 19:11:46 +05:30
Matthieu Gautier f0f473b829 Show suggestions using autoComplete.js
This change only shows suggestions. Clicking them does nothing.
2022-07-31 17:15:08 +05:30
Nikhil Tanwar 1e247d75bb Welcome, autoComplete.js
Added autoComplete.css and .js files.
Linked files in head_taskbar.html
2022-07-31 16:16:07 +05:30
Matthieu Gautier 4f3ec817db Update index.js to not use jquery anymore. 2022-07-31 01:06:27 +05:30
Kelson 98bcf8acd6 Merge pull request #791 from kiwix/ci_pull_request
CI triggered on pull_request event
2022-07-27 21:28:30 +02:00
Emmanuel Engelhart b69bf4d062 Simplify branch retrieval 2022-07-20 21:21:31 +02:00
Emmanuel Engelhart 6891ce3b57 Use actions/checkout@v2 2022-07-20 21:21:31 +02:00
Emmanuel Engelhart 16197afc95 CI triggered on pull_request event 2022-07-20 21:21:31 +02:00
Kelson abccd9d706 Merge pull request #800 from kiwix/escClose
Exit download modal on pressing escape key.
2022-07-20 21:19:01 +02:00
Nikhil Tanwar d0adb4e722 Exit download modal on pressing escape key.
Adds an event listener to call closeModal() when Escape key is pressed.
2022-07-21 00:39:26 +05:30
Kelson 88c25b3a6c Merge pull request #786 from kiwix/optimizedWelcome
More tiles on kiwix-serve welcome page (optimised)
2022-07-20 19:41:50 +02:00
Emmanuel Engelhart 5aa74c62d6 Better align kiwix-serve welcome page filters 2022-07-20 19:18:18 +02:00
Nikhil Tanwar 2b6da38c46 Center tiles on welcome page
This change centers tiles on welcome page to give a more consistent whitespace look on both sides.
For this, the layout in Isotope JS is changed to masonry.
2022-07-20 19:18:18 +02:00
Matthieu Gautier dfc6cad9c2 Merge pull request #795 from kiwix/icu_data_check 2022-07-19 11:23:11 +02:00
Veloman Yunkan 28f8dbcf20 New unit-test stringTools.ICULanguageInfo 2022-07-07 16:13:49 +04:00
Matthieu Gautier 81865c0f0e Merge pull request #794 from kiwix/fixHeader 2022-07-06 17:05:40 +02:00
Nikhil Tanwar 538a46f262 Include iostream header in include/version.h
This is needed for kiwix-tools compilation.
2022-07-05 20:47:14 +05:30
Kelson e1d1d202bd Merge pull request #789 from kiwix/remove_wrappers
Remove libzim's wrapper.
2022-07-03 19:34:58 +02:00
Matthieu Gautier 71e2df7406 Explicit std
Removed headers were `using namespace std`.
So we have to be explicit everywhere.
2022-07-02 16:33:32 +02:00
Matthieu Gautier 69931fb347 Remove libzim's wrapper.
It is time to remove them. They are deprecated since 10.0.0
2022-07-02 16:33:32 +02:00
Veloman Yunkan 12e0fb6934 Merge pull request #711 from kiwix/tagFilter
Add tag filtering in kiwix-serve
2022-06-25 18:22:06 +04:00
Nikhil Tanwar 43ab6dfb6a Add ability to filter by tags in kiwix serve
This change introduces filtering by tags.
To filter, the user can click on the tag name and it will filter it.
A label is added (clickable) to show the tag filter, it can be clicked to remove the filter
2022-06-25 18:10:01 +04:00
Nikhil Tanwar 93f2686a94 Refactoring kiwixButton
Move hover behaviour as a different class - kiwixButtonHover
Add cursor:pointer to kiwixButton
2022-06-25 18:10:01 +04:00
Nikhil Tanwar 19a9c84e13 Change class name "searchButton" to "kiwixButton"
This is done to retain the button design in more button designs (ex: tags)
2022-06-25 18:10:01 +04:00
Nikhil Tanwar f034018b5c Extract setNoResultsContent() from checkAndInjectEmptyMessage()
Extracted the code from the un-named function in setTimeout for easier understanding.
2022-06-25 18:10:01 +04:00
Nikhil Tanwar 596b223a9d Drop onclick handler for reset-filter link
This removes the onclick handler around the reset-filter link which redirected to '/?lang='
Everything under the handler was already done on window.onload
2022-06-25 18:10:01 +04:00
Nikhil Tanwar 0c549af307 Add check to not add same link in session history
Previously, if the following steps were executed:
1. Click a book tile/visit an unrelated link from the address bar
2. Press back button
Then forward history was discarded (forward button gets disabled).
This happened because of the window.history.pushState on every window.onload event. This led to the same link being added in history and thus discarding the previous "forward-history"
This change adds a condition to only push the current state if the queries are not same.
2022-06-25 18:10:01 +04:00
Nikhil Tanwar 37b39430d1 Use shortened URL in pushState
Earlier we were using the full URL, now only query string is passed in pushState, much cleaner!
2022-06-25 18:10:01 +04:00
Nikhil Tanwar 947744caea Introduce updateVisibleParams()
Adds a function to wrap logic to update select boxes on history change
2022-06-25 18:10:01 +04:00
Kelson b9e03d2772 Merge pull request #790 from kiwix/docTypo 2022-06-25 07:38:28 +02:00
Nikhil Tanwar e9b7eeb3c9 Fix documentation typos
Replace wrong  mentions of libzim with libkiwix
Remove libkiwix deprecated functions mention in usage.rst - they are removed now
2022-06-25 09:44:51 +05:30
Matthieu Gautier 15cb9025bb Merge pull request #779 from kiwix/serving_customized_resources 2022-06-22 15:31:20 +02:00
Veloman Yunkan 1139f2cb4c Testing of static front-end resource customization
One important missing test is that the content of the customized
resource is read from storage every time rather than once. Testing
that requirement would involve creating temporary files which is a
little more work.
2022-06-22 17:11:08 +04:00
Veloman Yunkan 0086049d4f Extracted LibraryServerTest into a file of its own 2022-06-22 15:22:12 +04:00
Veloman Yunkan e3e4bfa533 Support for serving customized resources
During work on the kiwix-serve front-end, the edit-save-test cycle is
a multistep procedure:

1. build and install libkiwix
2. build kiwix-tools
3. run kiwix-serve
4. reload the web-page in the browser

When making changes in static resources that are served by kiwix-serve
unmodified, the steps 1-3 can be eliminated if kiwix-serve is capable of
serving resources from the file-system. This commit adds such a
functionality to kiwix-serve. Now, if during startup of kiwix-serve the
environment variable `KIWIX_SERVE_CUSTOMIZED_RESOURCES` is defined it is
assumed to point to a file where every line has the following format:

URL MIMETYPE RESOURCE_FILE_PATH

When a request is received by kiwix-serve and its URL matches any of the
URLs read from the customized resource file, then the resource data is
read from the respective file RESOURCE_FILE_PATH and served with
mime-type MIMETYPE.

Though this feature was introduced in order to facilitate the
development of the iframe-based content viewer, it can also be useful to
users who would like to customize the kiwix-serve front-end on their own
(without re-building all of kiwix-serve).

There is some overlap with a feature of the kiwix-compile-resources
script that also allows to override resources. The differences are:

1. The new way of customizing front-end resources has all such resources
   listed in a text file and there is a single environment variable
   from which the path of that file is read. kiwix-compile-resources
   associates a separate environment variable with each resource.

2. The new way uses regular paths to identify a resource. The
   kiwix-compile-resources method encodes the resource path by replacing
   any non-alphanumeric characters (including the path separator) with
   underscores (so that the resulting resource identifier can be used
   to construct the name of the environment variable controlling that
   resource).

3. The new method allows adding new front-end resources. The old method
   only allows to modify existing resources.

4. The new method allows (actually requires) to specify the URL at which
   the overriden resource should be served (similarly, the MIME-type can/must
   be specified, too). The old method only allows to override the contents of
   a resource.

5. The new method only allows to override front-end resources that are
   served without any preprocessing by kiwix-serve at runtime. The old
   method allows to override template resources as well (note that
   internationalization/translation resources cannot be overriden using the
   old method, either).
2022-06-22 10:59:41 +02:00
Matthieu Gautier 6938253e59 Merge pull request #784 from kiwix/version_11.0.0 2022-06-15 14:42:08 +02:00
Matthieu Gautier c5d3ffe0d7 Fix CI for android 2022-06-15 14:36:02 +02:00
Matthieu Gautier 3938d791e7 New version 11.0.0 2022-06-15 11:49:03 +02:00
Matthieu Gautier 1572956da0 Merge pull request #771 from kiwix/translatewiki 2022-06-13 19:12:23 +02:00
Matthieu Gautier 84b1321545 Update i18n_resources_list.txt 2022-06-13 18:46:29 +02:00
translatewiki.net 0f3bca442a Localisation updates from https://translatewiki.net. 2022-06-13 13:08:42 +02:00
Matthieu Gautier 83a9e54399 Merge pull request #780 from kiwix/deduping_searchResults_unittests 2022-06-10 15:47:50 +02:00
Veloman Yunkan baa97cadf0 Dropped test/server_xml_search.cpp 2022-06-10 15:34:18 +02:00
Veloman Yunkan 06d7a2320f test/server_search.cpp covers XML search too 2022-06-10 15:34:18 +02:00
Veloman Yunkan f279769435 Deduplicated the snippet regex 2022-06-10 15:34:18 +02:00
Veloman Yunkan 7d4867194a Moved a function 2022-06-10 15:34:18 +02:00
Veloman Yunkan 0340a49780 git mv test/server_{html_,}search.cpp 2022-06-10 15:34:18 +02:00
Veloman Yunkan ed6aa5a89a Renamed some functions and variables
Included the word "Html" in the names of those functions and variables
which will get Xml siblings soon.
2022-06-10 15:34:18 +02:00
Veloman Yunkan 75796ed6a5 Introduced struct SearchResult 2022-06-10 15:34:18 +02:00
Veloman Yunkan ddd639eaa1 Moved TestData out of ServerTest.searchResults
Now that ServerTest.searchResults is in a separate cpp file, there are
no reasons for hiding its test data definition inside the unit test
function.

The diff is much-much simpler if whitespace changes are ignored.
2022-06-10 15:34:18 +02:00
Veloman Yunkan 1c98b00128 Got rid of TaskbarlessServerTest
Now ServerTest provides an optional taskbarless kiwix::Server.
2022-06-10 15:34:18 +02:00
Veloman Yunkan 600acb76c7 XML responses should be taskbarless by default
Unit-tests of search results in XML format should work the same way with
a server that would inject a taskbar into HTML responses. This small
change actually validates that taskbar injection is disabled for XML
responses.
2022-06-10 15:34:18 +02:00
Matthieu Gautier 3bbbd1b15d Merge pull request #783 from kiwix/windows_fix 2022-06-10 15:34:05 +02:00
Matthieu Gautier ae47e5ee4e uint is not defined on Windows 2022-06-10 11:21:35 +02:00
Matthieu Gautier b442e2371e Do not use deprecated constructor for Reader.
We have a specific private non deprecated constructor especially for that,
let's use it.
2022-06-10 10:41:31 +02:00
Matthieu Gautier 69c5c88c30 Merge pull request #782 from kiwix/windows_fix 2022-06-09 16:21:00 +02:00
Matthieu Gautier 70382d15e2 Windows compiler complains about the implicit cast from double to size_t. 2022-06-09 15:21:06 +02:00
Matthieu Gautier 62306373be Merge pull request #781 from kiwix/no_wrapper 2022-06-09 14:23:04 +02:00
Matthieu Gautier 01c384bb64 Remove the java wrapper.
- The meson's `wrapper` option is removed.
- New meson's option `static-linkage` is added to tell meson to link
  with static library.
2022-06-09 10:23:02 +02:00
Veloman Yunkan 56167dc23e Merge pull request #731 from kiwix/opensearch
Render xml result - opensearch
2022-06-04 00:51:56 +04:00
Veloman Yunkan cc8ad9ebf2 Testing of HTTP errors in XML format 2022-06-03 15:46:41 +02:00
Matthieu Gautier bfcf317f09 Properly set "language" parameter in opensearch::Query tag. 2022-06-03 15:46:41 +02:00
Matthieu Gautier ee01859984 Adapt test/server_xml_search.cpp to xml search.
This is the real change.
2022-06-03 15:46:41 +02:00
Matthieu Gautier 9ec8593f8c Add a testing dummy version of xml search results.
`test/server_xml_search.cpp` is a plain copy of
`test/server_html_search.cpp`
2022-06-03 15:46:41 +02:00
Matthieu Gautier 7cb98f7f4e Make opensearch start parameter 1 indexed. 2022-06-03 15:46:41 +02:00
Matthieu Gautier 8100977cda Use a macro to create the SearchResult.
It avoid some duplication around the actual data to test.
2022-06-03 15:46:41 +02:00
Matthieu Gautier a0cf91157a Split test/server.cpp
The file starts now to be too long.

- Move testing of the search html result in `test/server_html_search.cpp`
- Move common code used to launch server and so
  in `test/server_testing_tools.h'

This is mainly code move with a small change:
Instead of setting the default PORT (8001) as a const int in the
`ServerTest` class, we now use SERVER_PORT.
SERVER_PORT must be defined before include `server_testing_tools.h`.
This allow several test to be run in parallele without trying to open
the same port.
2022-06-03 15:46:41 +02:00
Matthieu Gautier cadd2a5cbb Make the HTTPErrorHtmlResponse not Html only. 2022-06-03 15:46:41 +02:00
Matthieu Gautier e51a5b9ebc Introduce get_requested_format helper 2022-06-03 15:46:41 +02:00
Matthieu Gautier 5d6b0ea96a Add searchdescription.xml endpoint 2022-06-03 15:46:41 +02:00
Matthieu Gautier e5df5e936f Render the search result using (opensearch/atom) xml format. 2022-06-03 15:46:41 +02:00
Matthieu Gautier c4f706863c Merge pull request #778 from kiwix/small_fixes 2022-06-02 17:20:06 +02:00
Matthieu Gautier fbc7656b3f Use proper argument order when building the SearchRenderer from a Searcher 2022-06-02 17:08:50 +02:00
Matthieu Gautier d196496802 Make the Searcher owning the stored Reader
If we keep a reference to a `Reader` it is better to (share) owning
the reference. Else the reader may be deleted after we create the searcher.

This is especially the case now we are creating the `Reader` at demand
and we don't store it in the library's cache.
2022-06-02 17:08:17 +02:00
Matthieu Gautier 3704d8ab87 Merge pull request #729 from kiwix/multizimsearch 2022-06-02 12:49:57 +02:00
Matthieu Gautier a7651d0e9b Check early that provided bookIds are valid 2022-06-02 12:37:52 +02:00
Matthieu Gautier 3bca43344f Correctly url encode querystring
Fix tests with querystring needed url encoding
(pattern=jazz&books.query.title=Ray%20Charles)
2022-06-02 12:37:52 +02:00
Matthieu Gautier b857293cfd Build the bookSelection query string when we parse the query.
We have to reuse the query the user give us to generate the
pagination links.
At search result rendering step we don't have access to the query object.
The best place to know which arguments are used to select books
(and so which arguments to keep in the pagination links) is when we
parse the query to select books.

Fix tests (pagination links) with book selector other than "books.id="
(pattern=jazz&books.query.lang=eng)
2022-06-02 12:37:52 +02:00
Matthieu Gautier b483a8e4e4 Make the request_context be able to generate a querystring for a subset.
The request_context can now take a filter to select arguments to
keep in the query string.
2022-06-02 12:37:52 +02:00
Matthieu Gautier e2ab7fd62e Add some more testing.
Note that some tests are failing and will be fixed in next commits.
2022-06-02 12:37:52 +02:00
Veloman Yunkan f45962c697 First test case for multizim search 2022-06-02 12:37:52 +02:00
Veloman Yunkan 3b3d7ad9c4 Preparing to enhance the search results testsuite
Providing the core part of the query explicitly in the search results
testsuite test data.
2022-06-02 12:37:52 +02:00
Matthieu Gautier 1514661c26 Protect search from multi threading race condition.
libzim's search is not thread safe (mainly because xapian is not).
So we must protect our search objects from multi thread calls.

The best way to do this is to associate a mutex to the `zim::Searcher`
and lock the searcher each time we access object derivated from the
searcher (search, results, iterator, ...)
2022-06-02 12:37:52 +02:00
Matthieu Gautier e5ea210d2c Add a template specialization for ConcurrentCache storing shared_ptr
When ConcurrentCache store a shared_ptr we may have shared_ptr in used
while the ConcurrentCache has drop it.
When we "recreate" a value to put in the cache, we don't want to recreate
it, but copying the shared_ptr in use.

To do so we use a (unlimited) store of weak_ptr (aka `WeakStore`)
Every created shared_ptr added to the cache has a weak_ptr ref also stored
in the WeakStore, and we check the WeakStore before creating the value.
2022-06-02 12:37:52 +02:00
Matthieu Gautier 2b38d2cf1b Copy the lrucache test from libzim.
- Adapt lrucache.cpp for rigth include path
  and use `kiwix::lru_cache` instead of `zim::lru_cache`.
- Add missing `#include <set>` in lrucache.h
2022-06-02 12:37:52 +02:00
Matthieu Gautier 0081b4d8e7 Make the limit of zim files per search configurable.
The default value is 0, which means no limit.
2022-06-02 12:37:52 +02:00
Matthieu Gautier b74910b2af Limit the number of zim in multizim fulltext search.
We are currently limiting to 5 but it will be changed in next commit.
2022-06-02 12:37:50 +02:00
Matthieu Gautier cf30233358 Prefix env variable name with KIWIX_ 2022-06-02 12:23:43 +02:00
Matthieu Gautier f0065fdd6f Introduce Error exception to do i18n 2022-06-02 12:23:42 +02:00
Matthieu Gautier c72132054d Move i18n helper functions 2022-06-02 12:22:28 +02:00
Matthieu Gautier 077ceac5a5 Make the search_rendered handle multizim search.
This introduce a intermediate mustache object to store information
about the request made by the user.
2022-06-02 12:22:28 +02:00
Matthieu Gautier 39d0a56be8 Use selectBooks in handle_search 2022-06-02 12:22:28 +02:00
Matthieu Gautier 76d5fafb72 Introduce selectBooks
`selectBooks` allow us to parse a query in a "standard" way to get
the book(s) on which the user want to work.
2022-06-02 12:22:28 +02:00
Matthieu Gautier 4438106c2f Add a prefix in get_search_filter
The prefix will be used to parse a "query to select book" in different context.
For now we have only one context : selecting books for the catalog search.
But we will want to select books to do fulltext search on them
(will be done in later commit)
2022-06-02 12:22:28 +02:00
Matthieu Gautier 76ebfd7ea4 Move get_search_filter and subrange. 2022-06-02 12:22:27 +02:00
Matthieu Gautier 22996e4a6b Allow user to select multiple books when doing search. 2022-06-02 12:22:27 +02:00
Matthieu Gautier 98c54b2279 Handle multiple arguments in RequestContext. 2022-06-02 12:22:27 +02:00
Matthieu Gautier 854623618c Use the newly introduced searcherCache for multizim searcher. 2022-06-02 12:22:25 +02:00
Matthieu Gautier fd0edbba80 Use a set of id as key for a the searcher Cache.
It will allow use to cache seacher for multiple zim files.
2022-05-24 14:55:48 +02:00
Matthieu Gautier f5af0633ec Move the searcher cache into the Library 2022-05-24 14:55:48 +02:00
Matthieu Gautier 740581c55c Link the cache size to the book count.
Unless explicitly set via user env variable.
2022-05-24 14:55:48 +02:00
Matthieu Gautier 582e3ec46d Use a concurrent cache to store Archive cache. 2022-05-24 14:55:48 +02:00
Matthieu Gautier 28fb76bbc2 Remove m_readers in Library::impl
It is a deprecated interface and it is a simple wrapper on Archive.
2022-05-24 14:55:48 +02:00
Matthieu Gautier 7c688a4acc Move getCacheLength to a generic helper function getEnvVar 2022-05-24 14:55:48 +02:00
Kelson d4da05e591 Merge pull request #764 from kiwix/pre_multisearch
Preparatory work on multizim
2022-05-23 19:29:08 +02:00
Matthieu Gautier 66b2449800 Remove unnecessary catch
Catch of std::exception is already made in `handle_request`
2022-05-23 19:17:28 +02:00
Matthieu Gautier aad95e3413 Introduce a results intermediate object in the template rendering.
Url in href must not be html encoded. As we already url encode the path, it
is ok to have `'` in the url.
2022-05-23 19:16:14 +02:00
Matthieu Gautier f0dd34b6db Introduce buildQueryData helper in SearchRenderer 2022-05-23 19:13:25 +02:00
Matthieu Gautier bbdde93f49 Introduce a pagination object to render search result. 2022-05-23 19:12:17 +02:00
Matthieu Gautier cb62da65c3 Raise a exception if something went wrong in the template rendering. 2022-05-23 10:56:39 +02:00
Matthieu Gautier 288b4ae7df Fix count of remote books in Library::Impl::getBookCount 2022-05-23 10:56:39 +02:00
Matthieu Gautier 52c12b0c2f Introduce Library::Impl::getBookCount
We simply introduce a `getBookCount` which is not protected by a lock.
2022-05-23 10:56:39 +02:00
Matthieu Gautier 4695f47dd2 Introduce operator+= to simplify response creation. 2022-05-23 10:56:39 +02:00
Matthieu Gautier f42f6a60df Use extractFromString to parse request argument.
On top of reusing code, it throw a exception if we cannot convert given
argument in the type we want.
2022-05-23 10:56:39 +02:00
Matthieu Gautier 717c39f2ef Better ExtractFromString
- Throw a exception if we cannot extract from string.
  (We throw the same exception as `std::sto*`)
- Add a specialization to extract string from string
- Add some unit test
2022-05-23 10:56:39 +02:00
Matthieu Gautier aa1f73472d Remove unecessary BookDB helper class.
It was needed to not expose Xapian in public header.
Now we can remove it and directly use a Xapian db.
2022-05-23 10:56:39 +02:00
Matthieu Gautier 090c2fd31a Move LibraryBase out of public API.
We use composition instead of inheritance to implement Library.
2022-05-23 10:56:39 +02:00
Matthieu Gautier ff2c7b1fb2 Merge pull request #765 from kiwix/unittests_for_search_results_page 2022-05-23 10:55:28 +02:00
Veloman Yunkan 963362e1ea One more test-point for search result pagination 2022-05-18 13:30:42 +04:00
Veloman Yunkan 1a8d874a2c Testing the request for an out-of-bounds page 2022-05-18 13:30:42 +04:00
Veloman Yunkan 8e7658bb10 Almost full coverage of search result pagination
The snippets in the test data had to be updated to account for
pagination-dependent snippet variability of pre-7.2.2 libzim.
2022-05-18 13:28:52 +04:00
Veloman Yunkan 8f2f93371b Changed a test in order to avoid a bug in Xapian
Xapian version 1.4.18 contains a bug in snippet generation caused by
incorrect handling of stemming.

The test-point with a search pattern "beatles" produced snippets with no
highlights of the search term. Debugging showed that the search pattern
"beatles" was transformed to a search term "beatl" which then didn't
match the word "beatles" in the text from which a snippet had to be
extracted.

The test case passed on my development machine as well as for most CI
configurations. However the "Packages / build-deb (ubuntu-bionic)"
variant failed because of a slightly different handling of punctuation
at the snippet boundaries:

Test context:
  url: /ROOT/search?pattern=beatles&content=zimfile
  actual snippet:   ...side "Yellow Submarine" ...........
  expected snippet: ...-side "Yellow Submarine" ...........

Above mismatch resulted in a looser comparison of the snippet contents
and failed the requirement that the snippet MUST contain highlights
(this is how the said bug in Xapian was discovered).

An attempt to change the search pattern to "field" didn't eliminate the
problem. Despite the search pattern itself being in singular form (i.e.
identical to its stemmed version) the plural form "fields" in the
snippet was still not highlighted.

Using for a search pattern an adjective instead of a noun achieved the
desired outcome.
2022-05-18 13:28:52 +04:00
Veloman Yunkan eeca88573b Validation of snippets in search results
The "expected" snippets in the test data must be a union of all possible
snippets produced at runtime for a given (document, search terms) pair
on all platforms of interest:

- Overlapping snippets must be properly merged

- Non-overlapping snippets can be joined with a " ... " in between.
2022-05-18 13:20:27 +04:00
Veloman Yunkan 4521249452 Excluded snippets from search results validation 2022-05-18 13:05:29 +04:00
Veloman Yunkan 21e183c2e4 First test for a non-first page of search results 2022-05-18 12:45:47 +04:00
Veloman Yunkan d56ccbd019 First search results test-point with pagination 2022-05-18 12:45:47 +04:00
Veloman Yunkan 825cf1c948 Added a test-point for a large unpaginated search 2022-05-18 12:45:47 +04:00
Veloman Yunkan 57c31a43a4 Another simple test-point for /search endpoint 2022-05-18 12:45:47 +04:00
Veloman Yunkan 84c68d4d7b Search results pagination bugfix
Search results pagination is disabled for a single page outcome too.
2022-05-18 12:45:47 +04:00
Veloman Yunkan f2cf42427a New unit-test TaskbarlessServerTest.searchResults
This is a preliminary implementation checking only the following
cases:

- no search results
- all search results fitting on a single page

The second test-case fails because of a bug in search renderer (leading
to the pagination footer being pointlessly enabled). Will fix it in the
next commit.
2022-05-18 12:45:47 +04:00
Veloman Yunkan 612ecc975d Support for testing a server without a taskbar
Taskbar injected by a server adds distraction to unit-tests focusing
on the HTML contents of the returned pages. The new test-suite
TaskbarlessServerTest will have taskbar disabled.
2022-05-18 12:45:47 +04:00
Veloman Yunkan ae56d399b7 Explained why search_result.html needs inline CSS
In #727 inline CSS [was extracted](https://github.com/kiwix/libkiwix/pull/727/commits/e4a4b2f9618e126fbc6240b5693afe993a4943d0)
from `static/templates/no_search_result.html` into a separate stylesheet
resource. The purpose was to later

1. get rid of the custom `static/templates/no_search_result.html` error
   template and use a general purpose error template instead (this was
   accomplished by PR #744).

2. deduplicate the CSS code between `static/templates/no_search_result.html` and
   `static/templates/search_result.html` by making the latter to also refer to
   an internal CSS resource rather than containing inline stylesheet code.

While preparing to implement the 2nd point, I figured out that
`kiwix::SearchRenderer` is used as a component in `kiwix-desktop` too,
which probably would be upset by a link to a libkiwix's internal CSS resource.

This commit documents that finding.
2022-05-18 12:45:47 +04:00
Kelson eaa8c3c91c Merge pull request #776 from kiwix/fix_i18n_windows
Specify utf8 encoding when opening i18n resource file.
2022-05-17 22:50:20 +02:00
Matthieu Gautier 26c06d8c2a Specify utf8 encoding when opening i18n resource file.
Else, on windows, we will try to open files with "local" encoding (cp1252)
2022-05-17 18:36:35 +02:00
Matthieu Gautier eee6803328 Merge pull request #774 from kiwix/manually_generate_i18n_resource_list 2022-05-17 14:57:51 +02:00
Matthieu Gautier d19ae1b054 Update i18n_resources_list.txt using generate_i18n_resources_list.py 2022-05-16 14:27:48 +02:00
Matthieu Gautier abe2fa0179 Add a script to generate the i18n resource list automatically. 2022-05-16 14:27:48 +02:00
Matthieu Gautier 6e93bad565 Do not auto discover i18n files.
Revert to the plain old 'i18n_resources_list.txt' file.

Auto discovering of i18n file has a main flaw (and a small bug):
- The main flaw is that rerun the configure will not detect new
  translation files. It means that if we use cache in our CI,
  new translation will not be included.
- The bug is that on Windows, meson fails with a error about a non existent
  `` (empty) file name. I suppose it is because python replace
  `\n` by `\r\n` on Windows, and the the `.strip().split('\n')` keeps empty
  lines.

The small bug could be fixed, but the main flaw make the whole better if
we use a script to generate the listing.

This commit is somehow a half revert of 2eff5b55a6
2022-05-16 14:27:37 +02:00
Kelson 5fb919e73e Merge pull request #772 from kiwix/roundHomepage 2022-05-15 10:02:05 +02:00
Nikhil Tanwar 2771a95d40 Floor the value returned by viewPortToCount()
Previously, the value returned by viewPortToCount() could be a decimal number, this floors its value.
Helps in clean requests and caching.
Fix #766
2022-05-15 08:02:32 +05:30
Kelson 8dbf015689 Merge pull request #770 from kiwix/magnetLink
Use real magnet link in download modal
2022-05-14 17:05:05 +02:00
Nikhil Tanwar 6cdc47eb62 Use real magnet link in download modal
Previously, on clicking Magnet, we were redirecting to a different site:
https://download.kiwix.org/zim/other/xyzBookWithDate.zim.magnet

This had the real magnet link as page content
Now we use the real magnet link in the href, thus not redirecting and starting the download right away.
Fix #767
2022-05-14 17:00:14 +02:00
Matthieu Gautier cbd37073e8 Merge pull request #761 from kiwix/translatewiki 2022-05-11 17:04:33 +02:00
translatewiki.net d131b732d8 Localisation updates from https://translatewiki.net. 2022-05-11 16:11:17 +02:00
Matthieu Gautier 17c1b3b82f Merge pull request #759 from kiwix/diacritics_insensitive_suggestions 2022-05-10 15:51:18 +02:00
Veloman Yunkan 744dd87fb0 Testing that /suggest is diacritics insensitive 2022-05-10 15:15:19 +02:00
Matthieu Gautier d469e2aed8 Merge pull request #768 from kiwix/update_ci 2022-05-10 15:13:42 +02:00
Matthieu Gautier 73d2d47ca7 Run the CI on Ubuntu Bionic and Fedora 35
Xenial and f31 are eol
2022-05-10 14:58:56 +02:00
Matthieu Gautier 55149407d2 Merge pull request #763 from kiwix/i18n_resource_discovery 2022-05-09 15:11:02 +02:00
Veloman Yunkan 2eff5b55a6 Automatic discovery of i18n resources
Excluding qqq.json any .json file under static/i18n is now considered to
be a i18n resource. This eliminates the need to update the
i18n_resources_list.txt file every time a new language json file is
added. Thus Translatewiki PRs will not require extra work.
2022-05-09 15:12:16 +04:00
Kelson 26eccb5a5f Merge pull request #712 from kiwix/static_resource_versioning
Static resource versioning
2022-05-02 23:49:55 +02:00
Veloman Yunkan 1b81ccc5e5 Using a regular expression with named groups 2022-05-02 20:48:05 +04:00
Veloman Yunkan 091786c7d8 A slight simplification of resource preprocessing
Now the whole content of a resource is preprocessed with a single
invocation of `re.sub()` rather than line-by-line.

Also, the function `get_preprocessed_resource()` returns a single value
rather than a (preprocessed_content, modification_count) pair; the
situation when the preprocessed resource is identical to the source
version is signalled by a return value of None.
2022-05-02 20:38:08 +04:00
Veloman Yunkan c0b9e2a466 Cache-id of resources with account for dependency
The cache-id of resources now includes dependency information. This commit
illustrates that property with the changed cache-id of skin/index.js which
depends on skin/{download,hash,magnet,bittorent}.png.

The implementation is not fool-proof - cyclic dependency between
resources is not detected and will lead to infinite recursion.
2022-05-02 20:37:22 +04:00
Veloman Yunkan 03ab2f67dd Using global variables for base & output directories 2022-05-02 20:37:22 +04:00
Veloman Yunkan 157f01e951 Preparing to handle inter-resource dependency
The current implementation of resource preprocessing contains a bug
(with respect to the problem that it tries to solve): it doesn't take
into account the dependence of static resources on each other. If
resource A refers to B and B refers to C, then a change in C would
result in its cache id being updated in the preprocessed version of B.
However the cache id of B won't change since the cache id is derived
from the source rather than from the preprocessed output.

This commit is the first step towards addressing the described issue.

Now cache-id of a resource is computed on demand rather than precomputed
for all resources. The only thing remaining is to compute the cache-id
from the preprocessed content.
2022-05-02 20:37:22 +04:00
Veloman Yunkan 42fd6e8926 Made kiwix-resources work with python 3.5-
Formatted string literals appeared in Python 3.6. Some CI platforms
still use older versions of Python.
2022-05-02 20:37:22 +04:00
Veloman Yunkan 707df3d10b Removing the old preprocessed resource, if any
If during an earlier build a resource was symlinked in the build
directory (because it wasn't modified by preprocessing) and later
changes are made to the resource that result in its preprocessing no
longer being a no-op, then the preprocessing is performed (in place) on
the original resource directly (via the symlink). Therefore any symlinks
must be removed before preprocessing a resource.
2022-05-02 20:37:22 +04:00
Veloman Yunkan c016dfd2ce Resource preprocessing handles relative links
... but only if they contain "/skin/" as a substring.
2022-05-02 20:37:22 +04:00
Veloman Yunkan 150851b33d kiwix-resources preprocesses all resources
kiwix-resources preprocesses all resources rather than only templates. At
this point this doesn't change anything since only (some) template resources
contain KIWIXCACHEID placeholders. But this enhancement opens the door
to the preprocessing of static/skin/index.js (after preprocessing is
able to handle relative links, which comes in the next commit).
2022-05-02 20:37:22 +04:00
Veloman Yunkan 3b9f28b2b5 Applied cache-id to search_results.css
The story of search_results.css

static/skin/search_results.css was extracted from
static/templates/no_search_result.html before the latter was dropped.

static/templates/no_search_result.html in turn seems to be a copied and
edited version of static/templates/search_result.html.

In the context of exploratory work on the internationalization of
kiwix-serve (PR #679) I noticed duplication of inline CSS across those
two templates and intended to eliminated it. That goal was not fully
accomplished (static/templates/search_result.html remained untouched)
because by that time PR #679 grew too big and the efforts were diverted
into splitting it into smaller ones. Thus search_results.css slipped
into one of those small PRs, without making much sense because nothing
really justifies preserving custom CSS in the "Fulltext search unavailable"
error page.

At the same time, it served as the only case where a link to a cacheable
resource is generated in C++ code (rather than found in a template).
This poses certain problems to the handling of cache-ids. A workaround
is to expel the URL into a template so that it is processed by
`kiwix-resources`. This commit merely demonstrates that solution. But
whether it should be preserved (or rather the "Fulltext search
unavailable" page should be deprived of CSS) is questionable.
2022-05-02 20:37:22 +04:00
Veloman Yunkan fc85215ea0 Preprocessing of template resources
In template resources (found under static/templates), strings of the
form "PATH/TO/STATIC/RESOURCE?KIWIXCACHEID" are expanded into
"PATH/TO/STATIC/RESOURCE?cacheid=CACHEIDVAL" where CACHEIDVAL is a
8-digit hexadecimal hash digest of the file at
static/PATH/TO/STATIC/RESOURCE.
2022-05-02 20:37:22 +04:00
Veloman Yunkan acdc1dfb27 New unit-test ServerTest.CacheIdsOfStaticResources
Introduced a new unit-test which will ensure that static resources of
kiwix-serve have the cache ids applied to them in the links embedded into
the HTML code.

At this point there are no cache ids. The new unit-test will help to
visualize how they come into existence.
2022-05-02 20:37:22 +04:00
Matthieu Gautier f90cc39a52 Merge pull request #757 from kiwix/gzip_compression 2022-04-28 14:36:51 +02:00
Matthieu Gautier fba0f09f4f Do not compress content smaller than 1400 Bytes 2022-04-27 18:23:39 +02:00
Matthieu Gautier 0d294c50a5 [SERVER] Support gzip encoding instead of deflate.
The `compress` function is copied from httplib
2022-04-27 18:23:38 +02:00
Kelson dc42f831c0 Merge pull request #756 from kiwix/doc-badge
Add documentation badge in README
2022-04-23 11:20:42 +02:00
Emmanuel Engelhart 1757f7f168 Add documentation badge in README 2022-04-23 10:38:15 +02:00
Matthieu Gautier c43c637bea Merge pull request #679 from kiwix/kiwix-serve-i18n 2022-04-14 15:21:47 +02:00
Veloman Yunkan 927c12574a Preliminary support for Accept-Language: header
In the absence of the "userlang" query parameter in the URL, the value
of the "Accept-Language" header is used. However, it is assumed that
"Accept-Language" specifies a single language (rather than a comma
separated list of languages possibly weighted with quality values).

Example:

Accept-Language: fr
// should work

Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5
// The requested language will be considered to be
// "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5".
// The i18n code will fail to find resources for such a language
// and will use the default "en" instead.
2022-04-13 16:40:20 +02:00
Veloman Yunkan 9987fbd488 Fixed CI build failure under android_arm* 2022-04-13 16:40:20 +02:00
Veloman Yunkan a0d9a824e1 Internationalized searchbox tooltip 2022-04-13 16:40:20 +02:00
Veloman Yunkan 5052d4018c hy translation of the suggest-search message 2022-04-13 16:40:20 +02:00
Veloman Yunkan 11be821c46 Internationalized "Go to a randomly selected page"
At this point a potential issue has been revealed. Now we produce
the final HTML via 2-level template expansion

1. Render parameterized messages
2. Render the HTML template

In which templates we should use double mustache "{{}}" (HTML-escaping)
tags and where we may use triple mustache "{{{}}}" (non-escaping) tags?
2022-04-13 16:40:20 +02:00
Veloman Yunkan 527a606281 Testing the translation of "Go to random page"
The new test fails since the "Go to random page" button is not yet
internationalized.
2022-04-13 16:40:20 +02:00
Veloman Yunkan 3da81a3d0f Internationalized "Go to the main page" button 2022-04-13 16:40:20 +02:00
Veloman Yunkan ed7717c1e7 Testing the translation of "Go to the main page"
The new test fails since the "Go to the main page" button is not yet
internationalized.
2022-04-13 16:40:20 +02:00
Veloman Yunkan f73be3cde7 Initializing mustache data via initializer list 2022-04-13 16:40:20 +02:00
Veloman Yunkan c2bfeb4030 "Go to welcome page" is internationalized 2022-04-13 16:40:20 +02:00
Veloman Yunkan 901664b097 "Go to welcome page" in taskbar isn't translated
The (failing) tests now demonstrate that some text in the taskbar is not
translated. Will fix in the next commit.
2022-04-13 16:40:20 +02:00
Veloman Yunkan 6f3db20078 Internationalized "Fulltext search unavailable" page 2022-04-13 16:40:20 +02:00
Veloman Yunkan fbd23a8329 Fully internationalized 400, 404 & 500 error pages 2022-04-13 16:40:20 +02:00
Veloman Yunkan d2c864b010 Internationalized raw-entry-not-found message 2022-04-13 16:40:20 +02:00
Veloman Yunkan 779382642b Internationalized bad raw access datatype message 2022-04-13 16:40:20 +02:00
Veloman Yunkan ca7e0fb4a0 Internationalized random article failure message 2022-04-13 16:40:20 +02:00
Veloman Yunkan 52d4f73e89 RIP searchSuggestionHTML() & English-only message 2022-04-13 16:40:20 +02:00
Veloman Yunkan 1ace16229d Internationalized search suggestion message 2022-04-13 16:40:20 +02:00
Veloman Yunkan cb5ae01fd8 Localized "No such book" 404 message for /random
However the title and the heading of the 404 page are not localized yet.
2022-04-13 16:40:20 +02:00
Veloman Yunkan b2526c7a98 Translation of the url-not-found message 2022-04-13 16:40:20 +02:00
Veloman Yunkan 387f977d6c Enter ParameterizedMessage 2022-04-13 16:40:20 +02:00
Veloman Yunkan 202ec81d8b URL-not-found message went into i18n JSON resource
Yet, the URL-not-found message is not yet fully internationalized
since its usage is hardcoded to English.
2022-04-13 16:40:20 +02:00
Veloman Yunkan 577b6e29f9 kiwix::i18n::expandParameterizedString() 2022-04-13 16:40:20 +02:00
Veloman Yunkan e4a0a029ff User language control via userlang query param
This is a draft commit enabling the testing of the support for
kiwix-serve internationalization.
2022-04-13 16:40:20 +02:00
Veloman Yunkan 507e111f34 i18n data is kept in and generated from JSON files
Introduced a new resource compiler script kiwix-compile-i18n that
processes i18n string data stored in JSON files and generates sorted C++
tables of string keys and values for all languages.
2022-04-13 16:40:20 +02:00
Veloman Yunkan d029c2b8d5 Enter I18nStringDB 2022-04-13 16:40:20 +02:00
Veloman Yunkan c574735f51 makeFulltextSearchSuggestion() works via mustache 2022-04-13 16:40:20 +02:00
Veloman Yunkan a18dd82d82 Introduced makeFulltextSearchSuggestion() helper 2022-04-13 16:40:20 +02:00
Matthieu Gautier e22e073d43 Merge pull request #747 from kiwix/version_10.1.1 2022-04-12 11:32:06 +02:00
Matthieu Gautier 6dcf4ee034 New version 10.1.1 2022-04-11 17:13:58 +02:00
Kelson 61ccbc65fb Merge pull request #743 from kiwix/fix_article_count
Correctly detect the number of article for zim version <= 6
2022-04-06 17:28:51 +02:00
Matthieu Gautier 85a9d35488 Correctly detect the number of article for zim version <= 6 2022-04-06 17:21:14 +02:00
Matthieu Gautier a17258fcc9 Merge pull request #744 from kiwix/fullsearch_text_unavailable_error 2022-04-06 15:14:18 +02:00
Veloman Yunkan ae1bf39023 Got rid of static/templates/no_search_result.html
The "Fulltext search unavailable" error page is now generated using the
static/templates/error.html template. Also added two test cases checking
that error page.
2022-04-06 14:42:29 +02:00
Veloman Yunkan dbcbdff275 Added an optional CSS link to error.html 2022-04-05 20:49:09 +04:00
Matthieu Gautier c1823b8ee4 Merge pull request #738 from kiwix/HTTPErrorHtmlResponse 2022-04-04 18:47:12 +02:00
Veloman Yunkan 3f41ce8337 Unit test for HTTP 500 Internal Server Error
Currently an internal server error can be triggered by accessing an
entry belonging to a redirect loop. The ZIM file (test/data/poor.zim)
containing such a loop was copied from openzim/zim-tools repository
(test/data/zimfiles/poor.zim).
2022-04-04 18:35:20 +02:00
Veloman Yunkan 2a20e87341 Got rid of Response::build_500()
This change is not tested (mostly due to the difficulties of triggering
an internal server error).
2022-04-04 18:35:20 +02:00
Veloman Yunkan 2028bf3a98 Fixed the CI build failure under android_arm* 2022-04-04 18:35:20 +02:00
Veloman Yunkan 545d409150 Reused HTTPErrorHtmlResponse in HTTP400HtmlResponse 2022-04-04 18:35:20 +02:00
Veloman Yunkan 89dc9afc28 Renamed 404.html to error.html
404.html no longer contains anything specific to the 404 error and will
henceforth serve (with some enhancements) as a general purpose error
page template.
2022-04-04 18:35:20 +02:00
Veloman Yunkan 647118dd5e Enter HTTPErrorHtmlResponse
In addition to serving as a base class for `HTTP404HtmlResponse`,
`HTTPErrorHtmlResponse` is going to be used for a couple of other error
pages.
2022-04-04 18:35:20 +02:00
Veloman Yunkan d8a60db739 Preparing for a single error page template 2022-04-04 18:35:20 +02:00
Veloman Yunkan f4059f3faf Got rid of withTaskbarInfo() 2022-04-04 18:35:20 +02:00
Veloman Yunkan 800cc5b68a Got rid of Response::build_404() 2022-04-04 18:35:19 +02:00
Kelson b1f03385e4 Merge pull request #739 from kiwix/fix_windows_extern 2022-04-03 13:36:21 +02:00
Matthieu Gautier feb30d08aa Correctly define the variable urlNotFoundMsg and invalidUrlMsg.
As we must declare the two variables as `extern` in response.h,
we must define it somewhere (and `response.cpp` is a good place).
2022-04-01 11:58:57 +02:00
Matthieu Gautier 95d4dd63ac Merge pull request #724 from kiwix/search_improvement 2022-03-29 14:42:24 +02:00
Matthieu Gautier 311f783ea9 Always use the search pattern when searching in the server.
There is no reason to not use the pattern if there is a geo_query.
If both the pattern and the qeo_query are provided, we must use both.
2022-03-29 14:06:19 +02:00
Matthieu Gautier f2a1c0f106 Add braces around for loop's body. 2022-03-29 14:05:45 +02:00
Matthieu Gautier 2cc4befb12 Correctly display searchpattern in search result page.
The `searchPattern` is already "diples encoded".
So we can simply using it without protecting us from script injection.

Fix #723
2022-03-29 14:05:45 +02:00
Matthieu Gautier 3641dbf14d Handle book without xapian index. 2022-03-29 14:05:45 +02:00
Matthieu Gautier 1962262f94 Correctly handle invalid book.
If user request for a non existent book, we must return a 400 page.
(This is done by throwing a `std::invalid_argument` and let the catch
handle it)
2022-03-29 14:05:45 +02:00
Matthieu Gautier 7407f30790 Better cache usage.
It is better to directly try to get the `Search` from the cache instead
of getting the `Searcher` first which could be useless in Search already
exist.
2022-03-29 14:05:45 +02:00
Matthieu Gautier d740ffe465 Introduce SearchInfo.
SearchInfo is a small helper structure to store information about the
queried search. It regroup already existing information (`patternString`,
geo query, ...) in one structure.
It is also used as key in the cache instead of using a generated string.
2022-03-29 14:05:39 +02:00
Matthieu Gautier e7293346be Return http 400 error response when needed. 2022-03-28 17:37:41 +02:00
Matthieu Gautier b1643e422e Introduce HTTP400HtmlResponse.
HTTP400HtmlResponse is build on the same design than HTTP404HtmlResponse.
2022-03-28 17:35:15 +02:00
Kelson 574c1ad690 Merge pull request #736 from kiwix/pin_jinja2_doc
Remove pinning of Sphinx<4
2022-03-28 15:50:17 +02:00
Matthieu Gautier 59364a737a [WIP] Remove pinning of Sphinx<4
It seems we add this pinning to fix a dependencies issue.
Let's remove it.
2022-03-28 15:37:05 +02:00
Kelson 49f24d18df Merge pull request #732 from kiwix/HTTP404HtmlResponse
New way of building 404 error HTML responses
2022-03-28 15:27:46 +02:00
Veloman Yunkan ec2e10b40e Moved taskbarInfo into ContentResponseBlueprint 2022-03-28 14:56:40 +02:00
Veloman Yunkan 2da8ea1650 Moved function definition to cpp 2022-03-28 14:56:40 +02:00
Veloman Yunkan 0eb8f09f79 One more victory of HTTP404HtmlResponse
One more instance of `Response::build_404()` & `withTaskbarInfo()`
was taken over by `HTTP404HtmlResponse`.
2022-03-28 14:56:40 +02:00
Veloman Yunkan 0ecbdbcf63 Enter TaskbarInfo
After this change it's time to say thank you and good-bye to
`withTaskbarInfo()`. But it will take a while.
2022-03-28 14:56:40 +02:00
Veloman Yunkan 9bc09a815c noSuchBookErrorMsg() 2022-03-28 14:56:40 +02:00
Veloman Yunkan 48d377ca44 HTTP404HtmlResponse::operator+(const std::string&) 2022-03-28 14:56:40 +02:00
Veloman Yunkan d5ae92e4e2 More uses of HTTP404HtmlResponse 2022-03-28 14:56:40 +02:00
Veloman Yunkan 1a5e2eda0f HTTP404HtmlResponse::operator+(UrlNotFoundMsg) 2022-03-28 14:56:40 +02:00
Veloman Yunkan 89785a259a Enter HTTP404HtmlResponse 2022-03-28 14:56:40 +02:00
Veloman Yunkan 668063205c Enter UrlNotFoundMsg iomanipulator-like class 2022-03-28 14:56:40 +02:00
Veloman Yunkan df98c58d07 Enter ContentResponseBlueprint 2022-03-28 14:56:40 +02:00
Veloman Yunkan ff8da65c68 Separated make404ResponseData() 2022-03-28 14:56:40 +02:00
Veloman Yunkan ae60ba806b Made 404.html error template a little more generic
The fact that an info message was moved into C++ code is temporary
since it will be moved to a message resource file soon.
2022-03-28 14:56:40 +02:00
Veloman Yunkan 8cfcf2ea86 A new overload of Response::build_404() 2022-03-28 14:56:40 +02:00
Veloman Yunkan 26c16bb1b2 Renamed a variable 2022-03-28 14:56:40 +02:00
Veloman Yunkan ca965d448f Got rid of 2 parameters in Response::build_404()
Instead of passing the `bookName` and `bookTitle` parameters to
`Response::build_404()`, `withTaskbarInfo()` is applied to its result
when needed. Note, that in `InternalServer::handle_raw()`
`withTaskbarInfo()` was not utilized since the results of the `/raw`
endpoint are not supposed to be decorated with a taskbar.
2022-03-28 14:56:40 +02:00
Veloman Yunkan 6d16d7386d Changed the signature of ContentResponse::set_taskbar() 2022-03-28 14:56:40 +02:00
Veloman Yunkan 40e9a19c48 Introduced withTaskbarInfo() helper function
This was done in preparation for removing the `bookName` and `bookTitle`
parameters from `Response::build_404()`, but since the new function
could already be put to some use in this commit that was done too.
2022-03-28 14:56:40 +02:00
Veloman Yunkan d487c78ea4 Changed the return type of Response::build_404() 2022-03-28 14:56:40 +02:00
Veloman Yunkan 96cbd2bf26 kiwix::onlyAsNonEmptyMustacheValue() 2022-03-28 14:56:40 +02:00
Matthieu Gautier 941c3b5df3 Merge pull request #734 from kiwix/br_10.1.0 2022-03-24 18:55:38 +01:00
Matthieu Gautier b9e40def88 New version 10.1.0 2022-03-24 18:26:35 +01:00
Kelson 116ecd1c78 Merge pull request #733 from kiwix/kelson42-patch-1
Add release badge
2022-03-24 17:45:54 +01:00
Kelson 8f2faf37dc Add release badge 2022-03-24 17:45:03 +01:00
Matthieu Gautier ddc4c3ec2c Merge pull request #727 from kiwix/testing_of_ft_search_unavailable_page 2022-03-23 15:06:47 +01:00
Veloman Yunkan 511261cc81 Testing of "Fulltext search unavailable" page 2022-03-18 15:57:11 +04:00
Veloman Yunkan aaf232bee4 Support for CSS URL in HTML response tests 2022-03-18 15:56:19 +04:00
Veloman Yunkan a3460f6f48 Supporting varying page title in HTML response tests 2022-03-18 15:50:25 +04:00
Veloman Yunkan e4a4b2f961 Extracted CSS out of no_search_results.html 2022-03-18 15:46:54 +04:00
Veloman Yunkan 389d29c92e Searching in a non-existent book is a 404 case 2022-03-18 15:46:41 +04:00
Veloman Yunkan c64fce52e7 Made 404 HTML template consistent with the rest 2022-03-18 15:46:01 +04:00
Kelson a5baafd09f Merge pull request #725 from kiwix/safer_testing_of_html_responses
Safer testing of HTML responses
2022-03-18 07:03:02 +01:00
Veloman Yunkan ed46541b6f Clean-up promised in the previous commit 2022-03-11 22:53:46 +04:00
Veloman Yunkan e93ccd18d4 Robust test data in ServerTest.404WithBodyTesting
Before this change the meaning of test data in the ServerTest.404WithBodyTesting
unit test entirely depended on the number of entries:

- 2 entries: url, expected body
- 4 entries: url, book name, book title and expected body

This was fragile and non scalable (if other combinations of expected
response data are needed).

This commit defines a mini-DSL taking advantage of operator overloading
that allows to define test data in a robust way with the help of the compiler.

Some code in `TestContentIn404HtmlResponse` is obsoleted by this change
however it is not removed in this commit so that the change is easier to
understand. That will be done next.
2022-03-11 22:53:38 +04:00
Kelson f893777dc0 Merge pull request #721 from kiwix/xssVul
Use encoded URLs for searchSuggestionHtml
2022-03-09 14:33:11 +01:00
Nikhil Tanwar 04d682486a Add some tests to emulate XSS attack 2022-03-09 06:31:24 +01:00
Nikhil Tanwar 8136138492 use encoded URLs for searchSuggestionHtml
Previously, the seachURL was not encoded.
This resulted in an XSS vulnerability, a concept of proof is:

start kiwix-serve
visit - http://192.168.18.1:8081/"><svg onload="alert(1)">
This would display an alert message.

This encodes the searchURL before passing it to searchSuggestionHtml
2022-03-09 06:31:24 +01:00
Matthieu Gautier e48b550b68 Merge pull request #620 from kiwix/search_caching 2022-03-08 18:12:33 +01:00
Maneesh P M 6523d9f563 Retrieve SuggestionSearcher from LRU Cache
We create a cache for SuggestionSearcher very similar to that of FT
searcher. User can specify a custom cache size using the environment
variable SUGGESTION_SEARCHER_CACHE_SIZE. It has a default value of 10%
of the number of books in the library.
2022-03-08 17:35:39 +01:00
Maneesh P M 7cb4c1361f Retrieve Searcher and Search from LRU Cache
We use the new cache template to implement two kind of cache.
1: The Searcher cache is more general in terms of its usage. A Searcher
   can be used for multiple searches without much change to itself. We
   try to retrieve the searcher and perform searches using it whenever
   possible, and if not we put a searcher into the cache. User can
   specify a custom cache length by manipulating the environment
   variable SEARCHER_CACHE_SIZE. It's default value is 10% of all the
   books available.
2: The search cache is much more restricted in terms of usage. It's main
   purpose is to avoid re-searching on the searcher during page changes
   to generate SearchResultSet of various ranges. User can specify a
   custom cache length using the environment variable SEARCH_CACHE_SIZE
   with a default value of 2;
2022-03-08 17:35:39 +01:00
Maneesh P M a51f8d66a7 Introduce a LRU Cache and concurrent cache
The cache is copied from libzim project : https://github.com/openzim/libzim
The exact file as been copied from commit 27f5e70
2022-03-08 17:34:27 +01:00
Kelson 833bbc89ba Merge pull request #701 from kiwix/ladakhISO
Add mappings for languages not given by libicu
2022-03-05 17:07:48 +01:00
Emmanuel Engelhart 4bd02f07eb Beautify slightly the code 2022-03-05 16:59:15 +01:00
Nikhil Tanwar 9488842416 Add dagbani language in language map
Adds dagbani (dag) language in iso639_3 language map
2022-03-05 16:51:59 +01:00
Nikhil Tanwar 34b50ba30e Add mappings for languages not given by libicu
Adds a std::map<std::string, std::string> with display names for language codes not given by libicu
Fault language codes are taken from library.kiwix.org
2022-03-05 16:51:59 +01:00
Kelson cfab560d74 Merge pull request #718 from kiwix/fix_booktitle_renderer
Fix search rendered for book title
2022-03-04 21:30:37 +01:00
Matthieu Gautier 422f4c7dd7 Reuse constructor when creating the SearchRenderer with basic constructor. 2022-03-04 17:08:59 +01:00
Matthieu Gautier cc3545ac3b fixup! Readd a SearchRenderer constructor without Library argument. 2022-03-04 17:07:41 +01:00
Matthieu Gautier 609bc24cbe Small cleanups.
- Remove unused `archive`
- Replace tab by spaces
2022-02-25 15:46:13 +01:00
Matthieu Gautier d9124ed40b Set the book title only if we have a library. 2022-02-25 15:46:13 +01:00
Matthieu Gautier 921671eb4d Do not use ostringstream to convert the uuid into string.
`zim::Uuid` already have a string convertion operator. Let's use it.
2022-02-25 15:46:13 +01:00
Matthieu Gautier ec18eb40ea Readd a SearchRenderer constructor without Library argument.
Adding the library argument breaks the API. It is better to add
another constructor to not have to create another major version.
2022-02-25 15:46:13 +01:00
Matthieu Gautier a11abcf480 Merge pull request #715 from kiwix/opds_dc_issued 2022-02-23 14:39:14 +01:00
Veloman Yunkan ae2d7d20dc Handling of <dc:issued> in OPDS import 2022-02-23 14:20:49 +01:00
Veloman Yunkan 42ee14c8f5 New unit-test LibraryOpdsImportTest.allInOne 2022-02-21 23:20:35 +04:00
Veloman Yunkan afb556bf64 Added <dc:issued> field to OPDS entries 2022-02-19 11:35:44 +04:00
Kelson 5c38300504 Merge pull request #713 from kiwix/use-local-include
Fix library.h include
2022-02-17 13:08:56 +01:00
Emmanuel Engelhart cb2226c11f Fix library.h include 2022-02-17 10:56:46 +01:00
Matthieu Gautier 4cce4dce0b Merge pull request #710 from kiwix/unittests_for_404_html_page 2022-02-16 14:38:23 +01:00
Veloman Yunkan 34d069e61f Two more 404 error tests for the /raw endpoint 2022-02-16 14:25:43 +01:00
Veloman Yunkan 7a6562395a Testing of /ROOT/zimfile/invalid-article 2022-02-16 14:23:11 +01:00
Veloman Yunkan 92f9ee9280 Preparing to test archive dependent 404 responses 2022-02-16 14:23:11 +01:00
Veloman Yunkan ae2d9b234f More test points in ServerTest.404WithBodyTesting 2022-02-16 14:23:11 +01:00
Veloman Yunkan 0ba452aece New unit-test ServerTest.404WithBodyTesting
The `ServerTest.RandomOnNonExistentBook` unit test was replaced with a
more general one testing multiple 404 scenarios where the content of the
body is checked too.
2022-02-16 14:23:11 +01:00
Veloman Yunkan 5f4256b900 Enter helper function makeExpected404Response() 2022-02-16 14:23:11 +01:00
Veloman Yunkan a34dc725f9 ServerTest.RandomOnNonExistentBook
This test was introduced with the purpose of testing the error message
in the 404 page returned by /random for a non-existent book. The actual
expected output currently present in this new unit-test is too much for
that purpose and may become a maintenance burden if more tests of that
kind are added.
2022-02-16 14:23:11 +01:00
Kelson 892db07a2d Merge pull request #705 from thavelick/book_title_in_search_results
Add book titles to search results
2022-02-16 12:59:38 +01:00
Tristan Havelick 58be502f3f add book titles to search results 2022-02-16 12:50:18 +01:00
Matthieu Gautier 62ba2f4861 Merge pull request #709 from kiwix/unittest_for_suggestions 2022-02-16 11:30:26 +01:00
Veloman Yunkan c782cc718a Workaround for Packages/build-deb CI failures
Packages/build-deb CI flows failed on ubuntu-bionic and ubuntu-focal
with the following mismatch in the ServerTest.suggestions unit-test:

```
[ RUN      ] ServerTest.suggestions
../test/server.cpp:715: Failure
Expected equality of these values:
  r->body
    Which is: ...
  removeEOLWhitespaceMarkers(expectedResponse)
    Which is: ...
With diff:
@@ -2,5 +2,5 @@
   {
     \"value\" : \"Ray (movie)\",
-    \"label\" : \"Ray (&lt;b&gt;movie&lt;/b&gt;...\",
+    \"label\" : \"Ray (&lt;b&gt;movie&lt;/b&gt;)\",
     \"kind\" : \"path\"
       , \"path\" : \"A/Ray_(movie)\"

Test context:
	url: /ROOT/suggest?content=zimfile&term=movie
```

For some reason (probably, a bug), the implementation of
`Xapian::MSet::snippet()` on those platforms decided that a single closing
parenthesis is more than is appropriate for inclusion in the snippet and
replaced it with a (longer) ellipsis.

Taking advantage of the necessity to work around that bug, the
ServerTest.suggestions's functional coverage was enhanced - the
problematic test point was replaced with a new one using a phrase
instead of a single term.
2022-02-14 18:17:48 +04:00
Veloman Yunkan 9a6aef4dba Moved/renamed LibraryServerTest.suggestions_in_range 2022-02-11 16:06:52 +04:00
Veloman Yunkan 943cbbf6ce New unit test ServerTest.suggestions 2022-02-11 16:06:52 +04:00
Kelson ec94d9bfd9 Merge pull request #703 from kiwix/fix-mipsel-cross-compilation
Use "host_machine", not "target_machine" for cross-compilation
2022-02-09 07:09:56 +01:00
Emmanuel Engelhart f2088d7fe0 Use "host_machine", not "target_machine" for cross-compilation
Read https://mesonbuild.com/Cross-compilation.html for all the rationals.
2022-02-09 07:02:14 +01:00
Kelson 19dd068e5a Merge pull request #706 from kiwix/langFix
Only add value in language object if value entry node is 'language'
2022-02-08 21:31:58 +01:00
Nikhil Tanwar d56e56293b Only add value in language object if value entry node is 'language' 2022-02-08 19:03:35 +05:30
Kelson dc4f9a4939 Merge pull request #700 from kiwix/ipLimit
Add method to change MHD_OPTION_PER_IP_CONNECTION_LIMIT
2022-02-06 15:12:32 +01:00
Nikhil Tanwar 261adf0ef9 Add method to change MHD_OPTION_PER_IP_CONNECTION_LIMIT
Adds new method setIpConnectionLimit() to server.
Default is 0 (infinite)
2022-02-05 18:31:42 +05:30
Matthieu Gautier ce24b1fa5f Merge pull request #699 from kiwix/br_10.0.1 2022-02-02 16:06:18 +01:00
Matthieu Gautier 9193719c8f New version 10.0.1 2022-02-02 15:55:40 +01:00
Kelson d0d253beed Merge pull request #698 from kiwix/legoktm-patch-1
PPA: Remove Ubuntu Hirsute, EOL
2022-02-01 08:27:50 +01:00
Kunal Mehta cf95d513d6 PPA: Remove Ubuntu Hirsute, EOL 2022-01-31 23:13:00 -08:00
Kelson e72c0b75f6 Merge pull request #697 from kiwix/titleWithLanguage
Add title with full language name
2022-01-29 10:01:20 +01:00
Nikhil Tanwar 4d996584fa Add title with full language name
This adds title and aria-label attributes with value as the language of book
Provides tooltip on language badges
2022-01-28 22:53:38 +05:30
Kelson dd3338c2d0 Merge pull request #694 from kiwix/kelson42-patch-1
Fix macOS CI
2022-01-28 10:45:42 +01:00
Kelson b19eb1ea61 Stop publishing code coverage for macOS
No reason to upload code coverage twice
2022-01-27 21:23:16 +01:00
Kelson 6d14639f77 Use Python 3.10 to fix macOS CI 2022-01-27 21:22:19 +01:00
Kelson 89e3a57a05 Merge pull request #693 from kiwix/non-minified-isotope
Add non-minified version of isotope.pkgd.js
2022-01-27 20:02:28 +01:00
Kunal Mehta b94e4b7e3b Add non-minified version of isotope.pkgd.js
Debian wants to have the source files for minified scripts. Otherwise
same rationale as #368 which was for jquery-ui.

I downloaded this from <https://unpkg.com/isotope-layout@3.0.6/dist/isotope.pkgd.js>.
2022-01-27 00:11:04 -08:00
Kelson 68465079f0 Merge pull request #691 from kiwix/downloadLinkFix
Add span in querySelector
2022-01-24 15:43:10 +01:00
Nikhil Tanwar f6309bb4c8 Add span in querySelector
Earlier querySelector for download button was returning a div, on which we called the getAttribute function hence returning null
This now returns a <span> element which returns the correct link with getAttribute
2022-01-24 19:23:26 +05:30
Kelson 45e9b76b19 Merge pull request #689 from kiwix/slightly-better-fix-685
Fix title='_' case too #685
2022-01-24 09:05:35 +01:00
Emmanuel Engelhart 5a9dbf85ec Fix title='_' case too #685 2022-01-24 08:35:36 +01:00
Kelson cd412867d9 Merge pull request #688 from kiwix/legoktm-patch-1 2022-01-24 06:42:52 +01:00
Kunal Mehta 01edd830bc PPA: Fix libzim-dev dependency
Our libzim packages are "7.2.0~focal" but the ~ means that "7.2.0" is greater than
"7.2.0~focal" so the dependency can't be satisfied. Depending on "7.2.0~" will
allow "7.2.0~focal" to satisfy the dependency.
2022-01-23 20:30:23 -08:00
Kelson ceb46f1069 Merge pull request #687 from kiwix/langCatBoxFill
Add undefined check for humanFriendlyTitle
2022-01-23 20:39:48 +01:00
Nikhil Tanwar 270773d6ba Add undefined check for humanFriendlyTitle
humanFriendlyTitle() now returns an empty string if title is undefined
which is handled in loadAndDisplayOptions()
2022-01-23 20:33:46 +01:00
Kelson 234606b170 Merge pull request #686 from kiwix/catalog_search_with_zero_count 2022-01-22 08:47:06 +01:00
Veloman Yunkan b8328a78f6 /catalog/search?count=0 returns all entries 2022-01-21 19:31:46 +04:00
Veloman Yunkan 08c3a9d8b2 Testing of /catalog/search?count=0 2022-01-21 19:28:16 +04:00
Matthieu Gautier 744065276b Merge pull request #682 from kiwix/fix_test_compilation_windows 2022-01-19 16:22:16 +01:00
Matthieu Gautier e3f8046915 Do not include posix header on Windows
They are included by 3dbcbe5 which need them to test permission rights on
posix only.
2022-01-19 16:15:59 +01:00
Matthieu Gautier 3198a849e2 Merge pull request #681 from kiwix/version_10.0.0 2022-01-19 16:08:08 +01:00
Matthieu Gautier fcae21c55b Update Changelog 2022-01-19 16:02:39 +01:00
Matthieu Gautier 7da81acaa3 Update libzim dependency version to 7.2.0 2022-01-19 16:02:39 +01:00
Matthieu Gautier a7d19b170a Update .gitignore 2022-01-19 12:47:40 +01:00
Matthieu Gautier 000029166b Fix the copyright in the doc configuration 2022-01-19 12:47:00 +01:00
Kelson 2ccea8e370 Merge pull request #680 from kiwix/fix_windows_compilation
Add a new private constructor not deprecated for Reader.
2022-01-18 16:31:32 +01:00
Matthieu Gautier 84587e7f03 Add a new private constructor not deprecated for Reader.
As we still create a `Reader` in the deprecated code of `Library`,
we need a way to create a reader without raising a deprecated warning.

So we create a another constructor with a dummy argument and we use it.
2022-01-18 12:22:11 +01:00
Kelson 38fc187303 Merge pull request #678 from kiwix/depends_libzim_7.1.0
Needs libzim 7.1.0 getMetadataItem()
2022-01-16 09:59:54 +01:00
Emmanuel Engelhart 2dc8fc9ab3 Needs libzim 7.1.0 getMetadataItem() 2022-01-15 15:57:04 +01:00
Kelson 60b4be2286 Merge pull request #676 from kiwix/customURLfix
Remove {root} from book item's link in library
2022-01-14 16:31:16 +01:00
Nikhil Tanwar a8a68c54a2 Remove {root} from book item's link in library
The OPDS stream now provides full URL, including the custom root
Appending {root} duplicates the custom root, when given resulting in a broken link
2022-01-14 16:23:52 +01:00
Kelson 367e5d2636 Merge pull request #675 from kiwix/fix_android
Revert removing of deprecated methods used by android wrapper.
2022-01-14 16:19:14 +01:00
Matthieu Gautier fcd865bb81 Revert removing of deprecated methods used by android wrapper. 2022-01-14 12:28:50 +01:00
Matthieu Gautier 715151d725 Merge pull request #674 from kiwix/deprecated 2022-01-13 14:32:28 +01:00
Matthieu Gautier e5eeb08206 Remove old deprecated methods. 2022-01-13 14:23:29 +01:00
Matthieu Gautier ac6f91798f Assume SuggestionItem has a public constructor.
`SuggestionItem` is somehow a simple container.
2022-01-13 14:23:29 +01:00
Matthieu Gautier e5d26a4699 Deprecate SearchRenderer creation from a Searcher. 2022-01-13 14:23:29 +01:00
Matthieu Gautier 3d64a9d9a9 Deprecate Searcher creation.
As the `Searcher` is now deprecated, we also remove the unit tests on it.
`Searcher` is now untested, and so it reduces the code coverage.
2022-01-13 14:23:29 +01:00
Matthieu Gautier fb7d9f02c8 Deprecate Reader creation.
As we `Reader` is now deprecated, we also remove the unit tests on it.
`Reader` is now untested, and so it reduces the code coverage.
2022-01-13 14:23:29 +01:00
Matthieu Gautier 96e0d15ab4 Deprecate Entry creation.
As the `Entry` is still created by `Reader` we need a way to create a
entry without raising a deprecated warning.
To do so we create a second constructor with a dummy argument.
This second constructor is private and is not marked as deprecated so we
can use it.
2022-01-13 14:23:29 +01:00
Matthieu Gautier 39732e2bcf Deprecate methods on Book.
- `update(const Reader& reader)` is replaced by
  `update(const zim::Archive& archive)`
- `getFavicon*()` is replaced by `getIllustration(48)->*`
2022-01-12 18:07:46 +01:00
Kelson 7dfafe0196 Merge pull request #673 from kiwix/urlEncode 2022-01-12 13:19:54 +01:00
Matthieu Gautier 3052d0787a UrlEncode the content_id.
The HumanReadableId can contains special char (`&`/`=`/...)
As it is used as to create a url in the opds template,
we must url encode it.

- We don't need to encode the book id as it is a uuid, it never contains
special char.
- We don't need to encode the book url as it is read from the library and
the url must already be correctly encoded in the library.xml.
(tests modified accordingly)
2022-01-11 17:53:29 +01:00
Kelson d4db090bb9 Merge pull request #672 from kiwix/LadakhiISO
Add new method for language code
2022-01-11 15:39:49 +01:00
Nikhil Tanwar 0633f68f80 Add new values from wikipedia
Added new values. This now covers all iso 639-1 codes from https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
2022-01-11 15:32:06 +01:00
Nikhil Tanwar 2a5db3e7ab Use iso6391to3.js for language tag value
Improves upon the previous method of truncating language to first 2 values which was showing wrong values
2022-01-11 15:31:55 +01:00
Matthieu Gautier 468a080b09 Merge pull request #669 from kiwix/remove_meta_endpoints 2022-01-10 13:44:23 +01:00
Matthieu Gautier 1705f938b5 Extend unittest to check 404 error on wrong raw endpoints.
Check that `/raw` endpoint behaves correctly with wrong book name or
wrong kind.
2022-01-10 13:13:27 +01:00
Matthieu Gautier 0112e6102d Remove the meta endpoint in the server.
Now we have `/raw` and `catalog/v2/illustration` endpoints we don't need
to keep the meta endpoint.
2022-01-10 13:13:27 +01:00
Kelson e4d99f0374 Merge pull request #668 from kiwix/fileExists
Introduce kiwix::fileReadable
2022-01-09 20:16:56 +01:00
Emmanuel Engelhart aa50845e22 Fix small typos in comments 2022-01-09 20:05:30 +01:00
Nikhil Tanwar 3dbcbe542b Add tests for kiwix::fileExists and kiwix::fileReadable 2022-01-10 00:18:44 +05:30
Nikhil Tanwar 854058f842 Introduce kiwix::fileReadable
kiwix::fileExists only checks for file existence now
kiwix::fileReadable will check if the file is readable (implicitly checking for file existence also)
2022-01-05 20:16:38 +05:30
Matthieu Gautier c9eb3196f7 Merge pull request #646 from kiwix/raw_endpoints 2022-01-05 15:31:35 +01:00
Matthieu Gautier dc15a9a824 Add raw endpoint.
As the name suggests it, this endpoint is not smart :
It returns the content as it is and only if it is present
(no compatibility or whatever).

The only "smart" thing is to return a redirect if the entry is a redirect.
2022-01-05 15:12:41 +01:00
Matthieu Gautier 160a74f5f8 Extend ItemResponse and ContentResponse to return raw content. 2022-01-05 15:12:41 +01:00
Matthieu Gautier 78c10346f2 Merge pull request #645 from kiwix/illustration_api 2022-01-04 14:34:00 +01:00
Matthieu Gautier 6f1799db9f Use the new endpoint in the OPDS stream. 2022-01-04 14:16:46 +01:00
Matthieu Gautier e108fb0e47 Add /catalog/v2/illustration endpoint 2022-01-04 14:16:46 +01:00
Matthieu Gautier 9482bfb95b Add a method to get the a book illustration for a specific size. 2022-01-04 14:16:46 +01:00
Matthieu Gautier 66c40817ee Fix the OPDS stream to handle custom ROOT prefix
As we render the entry's xml in a separated steps, we need to pass the
rootLocation to all the internal rendering.

Testing with and without root is not so easy.
I've simply made all server tests using a ROOT prefix.
We can assume that if the ROOT is present everywhere we need it, it will not
when we don't need. (As long as we don't hardcode "ROOT" in the server.)
2022-01-04 11:15:18 +01:00
Matthieu Gautier 22e5327dcf Do not create a dummy illustration if library.xml doesn't contain one.
Fix #644
2022-01-04 11:12:32 +01:00
Kelson d29611ed75 Merge pull request #667 from kiwix/issue603
Safer scroll bound detection
2022-01-03 19:16:27 +01:00
renaud gaudin b1bc883bf5 Fixed #603: safer scroll bound detection
At least on Retina Macbook Pros but most likely on other configurations,
the viewport's sizes is not exactly consistent to integer.
For instance, on a maximized Firefox, document.body.offsetHeight is 1,600.
When looking at the <html> on the inspector, I'd get 1,599.6, so **roughly** the same
but not exactly. Those inconsistencies are present on every level so being too strict
about those is probably not adequate.

This fixes #603 but allowing a 2% margin on the scroll position
to match the _end of screen_ and thus trigger the loading of additional cards.
This means that for the example above, it triggers at 1,568 instead of never reaching 1,600.

2% might be too large but it seems safe considering the potential of various resolutions
we may encounter and I don't see any side effect.
2022-01-03 14:41:19 +00:00
Kelson a8577d7a01 Merge pull request #666 from kiwix/aria2Security
Make aria2 secret a random value
2022-01-03 09:46:11 +01:00
Nikhil Tanwar 8bdcb90818 Make aria2 secret a random value
Apps using this service will not have a default aria secret (previously 'kiwixariarpc')
2022-01-03 09:35:04 +01:00
Kelson 91a4491b74 Merge pull request #665 from kiwix/dependences_version
Dependences version
2022-01-02 12:31:25 +01:00
Emmanuel Engelhart f36d8e9851 New kiwix::getVersions() and printVersions() 2022-01-02 12:22:11 +01:00
Kelson 5e1988640c Merge pull request #664 from kiwix/missingMetadataFix 2021-12-28 20:35:16 +01:00
Nikhil Tanwar aa3bd8560b Add fallback image if thumbnail metadata is not available in zim 2021-12-29 00:15:34 +05:30
Nikhil Tanwar 9c047844c0 Add fallback if metadata (title, description, language, tags)
This provides a workaround the crash happening because of missing metadata.
Language div is set to be hidden if no language data is found
2021-12-29 00:11:57 +05:30
Matthieu Gautier 843d315b93 Merge pull request #663 from kiwix/fix_win32 2021-12-23 18:38:25 +01:00
Matthieu Gautier f1035fa472 Fix win32 compilation.
WSASocket return a `INVALID_SOCKET` if something goes wrong,
not SOCKET_ERROR.
2021-12-23 18:32:43 +01:00
Kelson 6c95458f5e Merge pull request #622 from juuz0/issue613
Provide HTTP URL for the server
2021-12-22 18:35:34 +01:00
Nikhil Tanwar 9554ab5db0 Make getNetworkInterfaces() and getBestPublicIp() available via tools.h
Remove HTTP URL helper line - should be done in kiwix-serve
Add getters at server level - getAddress and getPort
2021-12-22 22:38:16 +05:30
Nikhil Tanwar 4b563e567e Provide HTTP URL for the server
Added a line to display the IP (use best if nothing is provided) along with port.
2021-12-22 22:08:25 +05:30
Matthieu Gautier a77fae0993 Merge pull request #651 from kiwix/less_confusing_404_errors 2021-12-22 17:30:29 +01:00
Veloman Yunkan ed2f914e10 Minor cleanup
The code for obtaining the archive now looks the same for the /meta,
/suggest, /search and /random endpoints.
2021-12-22 17:12:34 +01:00
Veloman Yunkan 872ddd9cb3 Cleaned up InternalServer::handle_suggest()
As a result of this clean-up the /suggest endpoint too stopped
generating confusing 404 Not Found errors (which, like in /meta's case
is not that important). Another functional change is that the "term"
parameter became optional.
2021-12-22 17:12:34 +01:00
Veloman Yunkan 20b5a2b971 Less confusing 404 errors from /meta endpoint
Before this fix the /meta endpoint could return a 404 Not Found page
saying

  The requested URL "/meta" was not found on this server.

Error cases producing such a result were:

- `/meta?content=NON-EXISTING-BOOK&name=metaname`

- `/meta?content=book&name=BAD-META-NAME`

Now a proper message is shown for each of those cases.

This fix is being done just for consistency (the /meta endpoint is not
a user-facing one and the scripts don't bother about error texts).
2021-12-22 17:12:34 +01:00
Veloman Yunkan d8c525289b Changed the signature of Response::build_404()
Now Response::build_404() takes the URL instead of the entire
RequestContext object. An empty url suppresses the

 The requested URL "url" was not found on this server.

part of the error text.
2021-12-22 17:12:34 +01:00
Veloman Yunkan f7b853373c Less confusing 404 errors from /random endpoint
Before this fix the /random endpoint could return a 404 Not Found page
saying

  The requested URL "/random" was not found on this server.

Error cases producing such a result were:

- `/random?content=NON-EXISTING-BOOK` (can happen when a server is
restarted or the library is reloaded and the current book is no longer
available).

- Failure of the libkiwix routine for picking a random article.

Now a proper message is shown for each of those cases.
2021-12-22 17:12:34 +01:00
Kelson d21879ebda Merge pull request #662 from kiwix/legoktm-patch-1
PPA: Add Ubuntu Jammy
2021-12-20 07:57:34 +01:00
Kunal Mehta 35dc59d4bb PPA: Add Ubuntu Jammy 2021-12-19 16:45:16 -08:00
Kelson a89924a23f Merge pull request #661 from kiwix/javascript_quotting_fix
Fix javascript/DOM quotting bug
2021-12-19 11:33:43 +01:00
Emmanuel Engelhart 7f6a6055a9 Fix javascript/DOM quotting bug 2021-12-19 11:27:45 +01:00
Matthieu Gautier 90910c5cab Merge pull request #648 from kiwix/unique_readers_in_searcher 2021-12-16 17:17:46 +01:00
Veloman Yunkan 250f46c7f9 fixup! Searcher::add_reader() rejects duplicate readers 2021-12-16 16:51:03 +01:00
Veloman Yunkan 0be00b791f Searcher::add_reader() rejects duplicate readers
A O(N) linear search was added to `Searcher::add_reader()` deliberately.
This doesn't seem to be an operation that may lead to performance
problems.
2021-12-16 16:51:03 +01:00
Matthieu Gautier ff050dc811 Merge pull request #659 from kiwix/better-kiwix-version 2021-12-14 10:49:52 +01:00
Emmanuel Engelhart 9f3459f3f3 Better libkiwix version variable name 2021-12-13 18:22:40 +01:00
Kelson 7ea12697f4 Merge pull request #649 from kiwix/improve-kiwix-serve-topbar-accessibility
Improve kiwix-serve topbar accessibility
2021-12-11 17:27:43 +01:00
Emmanuel Engelhart ab53e0cff1 Improve kiwix-serve topbar accessibility 2021-12-11 14:56:51 +01:00
Matthieu Gautier 27414f7731 Merge pull request #642 from kiwix/deadlock_in_Library_writeBookmarksToFile 2021-12-06 11:37:02 +01:00
Veloman Yunkan e1db9164c8 Fixed deadlock in Library::writeBookmarksToFile() 2021-12-05 20:31:21 +04:00
Kelson fa8d0f8e07 Merge pull request #640 from kiwix/docs
Add basic documentation for libkiwix.
2021-12-03 16:48:14 +01:00
Matthieu Gautier 3589a51fff Add basic documentation for libkiwix.
It follows the same logic of libzim documentation.
2021-12-01 16:06:36 +01:00
Matthieu Gautier 01ac0b2fe1 Merge pull request #636 from kiwix/library_reloading 2021-11-30 18:08:46 +01:00
Veloman Yunkan 405ea29900 Added Library::addOrUpdateBook() alias 2021-11-30 18:20:27 +04:00
Veloman Yunkan 7161db8e2a Manager::reload() also removes books from Library 2021-11-30 18:20:27 +04:00
Veloman Yunkan 262e13845c Enter Library::removeBooksNotUpdatedSince() 2021-11-30 18:20:27 +04:00
Veloman Yunkan 1d5383435d Noted a potential bug in Library::addBook() 2021-11-30 18:20:27 +04:00
Veloman Yunkan ad2eb52553 Thread safe dumping of the OPDS feed 2021-11-30 18:20:27 +04:00
Veloman Yunkan 473d2d2a69 Introduced Library::getBookByIdThreadSafe() 2021-11-30 18:20:27 +04:00
Veloman Yunkan 02b9e32d18 Library became almost thread-safe
Library became thread-safe with the exception of `getBookById()`
and `getBookByPath()` methods - thread safety in those accessors is
rendered meaningless by their return type (they return a reference
to a book which can be removed any time later by another thread).
2021-11-30 18:20:27 +04:00
Veloman Yunkan c2927ce6f7 Library got a yet unused mutex
Introducing a mutex in `Library` necessitates manually implementing the
move constructor and assignment operator. It's better to still delegate
that work to the compiler to eliminate any possibility of bugs when new
data members are added to `Library`. The trick is to move the data into
an auxiliary class `LibraryBase` and derive `Library` from it.
2021-11-30 18:20:27 +04:00
Veloman Yunkan b712c732f2 Dropped Library::getBookBy*() non-const functions 2021-11-30 18:20:27 +04:00
Veloman Yunkan 298247ca9b Renamed NameMapperProxy -> UpdatableNameMapper 2021-11-30 18:20:27 +04:00
Veloman Yunkan 3aeeeeee76 Manager::reload() 2021-11-30 18:20:27 +04:00
Veloman Yunkan 226dac2604 LibraryManipulator is now merely a notifier
Originally `LibraryManipulator` was an abstract class completely decoupled
from `Library`. Its `addBookToLibrary()` and `addBookmarkToLibrary()`
methods could be defined in an arbitrary way. Now `LibraryManipulator` has to be
bound to a library object, those methods are no longer virtual, they always
update the library and allow for some additional actions via virtual
functions `bookWasAddedToLibrary()` and `bookmarkWasAddedToLibrary()`.
2021-11-30 18:20:27 +04:00
Veloman Yunkan 76a5e3a877 Library::addBook() updates the reader cache 2021-11-30 18:20:27 +04:00
Veloman Yunkan 2d6a7fe88d Testing of NameMapperProxy 2021-11-30 18:20:23 +04:00
Veloman Yunkan 6199c11505 NameMapperProxy respects the withAlias flag 2021-11-30 18:18:16 +04:00
Veloman Yunkan 8fffa59974 Added NameMapperProxy from kiwix/kiwix-desktop#714
The right place for NameMapperProxy introduced by kiwix/kiwix-desktop#714 is in
libkiwix (so that it can be reused in kiwix-serve).
2021-11-30 18:18:16 +04:00
Veloman Yunkan 4ccbdcb740 Code deduplication in NameMapperTest 2021-11-30 18:17:43 +04:00
Veloman Yunkan 5f3c34ed93 NameMapper's API is now const 2021-11-22 21:06:27 +04:00
Veloman Yunkan d62c4fd521 Testing of HumanReadableNameMapper 2021-11-22 20:54:44 +04:00
Veloman Yunkan 339f845fb0 Bugfix in Book::getHumanReadableIdFromPath() 2021-11-22 20:54:44 +04:00
Veloman Yunkan 3296a020a1 Testing of Book::getHumanReadableIdFromPath()
New unit test BookTest.getHumanReadableIdFromPath revealed a bug in
`Book::getHumanReadableIdFromPath()`.
2021-11-22 20:54:44 +04:00
Veloman Yunkan 571e417d1e Manager is now safe to copy 2021-11-20 20:38:39 +04:00
Veloman Yunkan 913a368a12 Made Manager's ctors explicit 2021-11-20 20:34:13 +04:00
Veloman Yunkan 0e48baf9f9 Simplified Library::getReaderById()
Reused `Library::getArchiveById()` in `Library::getReaderById()`.
2021-11-19 20:17:12 +04:00
Matthieu Gautier c7b88398bd Merge pull request #630 from kiwix/multi_illustration_books 2021-11-19 14:08:21 +01:00
Veloman Yunkan 4a01081e83 Thread-safe Book::Illustration::getData() 2021-11-19 16:44:25 +04:00
Veloman Yunkan eb6a0d6456 Enter Book::getIllustrations() 2021-11-18 14:39:00 +04:00
Veloman Yunkan e2544799a1 Shorter Book::update() 2021-11-18 14:39:00 +04:00
Veloman Yunkan 9f42884507 Book's illustrations are now immutable 2021-11-18 14:39:00 +04:00
Veloman Yunkan 8a6adddc16 Non-throwing Book::getDefaultIllustration() 2021-11-18 14:39:00 +04:00
Veloman Yunkan c8da5eea2b Dropped Book::getMutableDefaultIllustration()
Now a Book is created without a default illustration.
2021-11-18 14:38:00 +04:00
Veloman Yunkan bd29c4c7ef Book::updateFromOpds() resets Book::m_illustrations 2021-11-18 14:37:12 +04:00
Veloman Yunkan e52a4a646b Book::updateFromXml() resets Book::m_illustrations 2021-11-18 14:36:42 +04:00
Veloman Yunkan 537ba7e6b9 Book::update() reads illustrations from ZIM file 2021-11-18 14:35:49 +04:00
Veloman Yunkan f4bc3c8ced Book::Illustration got dimensions 2021-11-18 14:34:51 +04:00
Veloman Yunkan 5263f6880c Internally Book supports multiple illustrations 2021-11-18 14:34:51 +04:00
Veloman Yunkan c129952605 Added a couple of notes on data consistency 2021-11-18 14:34:48 +04:00
Veloman Yunkan 9f0db6b7fa Book::Illustration::getData() 2021-11-18 14:33:50 +04:00
Veloman Yunkan 7d8a83cc97 Encapsulated access to Book::m_illustration 2021-11-18 14:32:52 +04:00
Veloman Yunkan ec5a423924 Enter Book::Illustration
`Book::m_favicon` and its 2 friends are replaced with a single
`Book::m_illustration` data member.
2021-11-18 13:31:08 +04:00
Veloman Yunkan 811b73a4f1 Moved 2 small method definitions to cpp 2021-11-18 13:27:27 +04:00
Veloman Yunkan 3e5372ef29 RIP Book::{setFavicon(),setFaviconMimeType()} 2021-11-18 13:25:34 +04:00
Veloman Yunkan abfd9d88d8 Book.updateTest creates the source book from XML
... thus eliminating the need for the Book::setFavicon*() methods.
2021-11-18 12:57:21 +04:00
Veloman Yunkan 4f65811011 Moved Book.updateTest below Book.updateFromXMLTest
Book.updateTest is going to be modified so that it relies on
functionality tested by Book.updateFromXMLTest. Hence the order of the
tests better reflect that dependency.
2021-11-18 12:57:21 +04:00
Veloman Yunkan 59e5c7ff4e Enhanced Book.updateFromXMLTest with favicon 2021-11-18 12:57:21 +04:00
Matthieu Gautier ef1ad4bf47 Merge pull request #628 from kiwix/clickable-kiwix-serve-tile 2021-11-16 14:07:33 +01:00
renaud gaudin 8d50d5e293 added border-radius to download button 2021-11-16 12:33:05 +00:00
renaud gaudin d76e670d5b CSS codefactor fix 2021-11-16 12:10:15 +00:00
Emmanuel Engelhart 8f5ffc5ef5 Duplicated ids are not allowed in a HTML doc 2021-11-16 12:10:15 +00:00
Emmanuel Engelhart 98f9c57e12 Better use double-quote for HTML attributes 2021-11-16 12:10:15 +00:00
Emmanuel Engelhart db06b6b797 Renave static/home.css to static/index.css 2021-11-16 12:10:15 +00:00
Emmanuel Engelhart 513c547d99 Remove shadow around kiwix-serve home language in tile 2021-11-16 12:10:15 +00:00
Emmanuel Engelhart c3d2e01157 Move kiwix-serve home download button at top of the tile 2021-11-16 12:10:15 +00:00
Emmanuel Engelhart 4adad9b281 Make kiwix-serve home tiles clickable 2021-11-16 12:10:15 +00:00
Matthieu Gautier 251f3a01ed Merge pull request #635 from kiwix/fix_httplib 2021-11-16 09:45:44 +01:00
Matthieu Gautier 0fcf166111 Fix warning in httplib.
The bug has been fixed upstream at yhirose/cpp-httplib#1091
This commit is a backport of the fix.
2021-11-16 09:39:56 +01:00
Matthieu Gautier eea6f9fe27 Revert "Fix maybe initialized warning in httplib."
This reverts commit 1f6fb238ba.
2021-11-16 09:36:21 +01:00
Matthieu Gautier 0b9ff92e42 Merge pull request #634 from kiwix/fix_httplib 2021-11-10 14:35:11 +01:00
Matthieu Gautier 1f6fb238ba Fix maybe initialized warning in httplib.
Patch has been send upstream :
https://github.com/yhirose/cpp-httplib/pull/1085
2021-11-08 16:58:11 +01:00
Kelson 9479c0685d Merge pull request #623 from kiwix/update-ci
Re-introduce Ubuntu Impish in CI
2021-10-21 12:41:23 +02:00
Emmanuel Engelhart 09a55d71d6 Re-introduce Ubuntu Impish in CI 2021-10-21 12:36:05 +02:00
Matthieu Gautier 503eb5c4ce Merge pull request #621 from kiwix/fix_ci_docker_version 2021-10-19 11:49:20 +02:00
Matthieu Gautier f714ff8d3e New docker image version is 31. 2021-10-18 18:09:36 +02:00
Matthieu Gautier 08e3d52957 Merge pull request #607 from kiwix/issue/571 2021-10-12 17:40:27 +02:00
Manan Jethwani 30e4c549e4 exposed fileExist, getMimeTypeForFile and getFileCoontent functions 2021-10-12 19:44:38 +05:30
Manan Jethwani b7b385d87b added custom index template 2021-10-12 19:44:05 +05:30
Matthieu Gautier e46b0c07b5 Merge pull request #617 from kiwix/adapt_new_libzim_api 2021-09-30 14:52:17 +02:00
Matthieu Gautier cd9fb541fc Fix method call for new libzim API.
`add_archive` is now `addArchive`.
2021-09-29 11:55:22 +02:00
Matthieu Gautier 3b942bb745 Merge pull request #602 from kiwix/partial_opds_entries
OPDS feed with partial entries
2021-09-09 12:07:02 +02:00
Veloman Yunkan c0bda426b4 Removed duplication across two mustache templates
Deduplicated the mustache templates static/templates/catalog_v2_entries.xml
and static/templates/catalog_v2_complete_entry.xml (the latter was
renamed to static/templates/catalog_v2_entry.xml).
2021-09-09 12:19:22 +04:00
Veloman Yunkan b3f7556096 Added partial entries feed to the OPDS root feed 2021-09-09 12:19:22 +04:00
Veloman Yunkan 4c657c082e /catalog/v2/partial_entries OPDS API endpoint 2021-09-09 12:19:22 +04:00
Veloman Yunkan e773a29f29 Rearranged elements in OPDS entry XML 2021-09-09 12:19:22 +04:00
Veloman Yunkan e15a0f4338 /catalog/v2/entry/<entry_id> OPDS API endpoint 2021-09-09 12:19:22 +04:00
Veloman Yunkan 12d9b69806 OPDSDumper::dumpOPDSCompleteEntry() 2021-09-09 12:19:22 +04:00
Veloman Yunkan 027854e4f4 Extracted getSingleBookData() in opds_dumper.cpp 2021-09-09 12:19:22 +04:00
Matthieu Gautier 417e7471ac Merge pull request #614 from kiwix/disable-impish 2021-09-09 10:10:50 +02:00
Matthieu Gautier 51ac1240f8 PPA: Temporarily disable Impish builds 2021-09-09 10:05:18 +02:00
Kelson ea6413ff88 Merge pull request #591 from kiwix/suggestion_range
Allow kiwix-serve to get suggestions of custom range
2021-08-20 08:09:35 +02:00
Maneesh P M 61209ea0d7 Allow kiwix-serve to get suggestions of custom range
This will allow handle_suggest API to accept two arguments `start` and
`suggestionLength` that will allow handle_suggest to retrieve
suggestions in the given range rather than the default 0-10 range.
2021-08-19 21:05:39 +05:30
Kelson e9eaadde9e Merge pull request #567 from kiwix/suggestion_api_fix 2021-08-14 19:21:29 +02:00
Maneesh P M 8a4080baba Update libkiwix with new libzim api 2021-08-14 22:26:39 +05:30
Kelson ba05999cba Merge pull request #604 from kiwix/issue/603 2021-08-11 06:50:30 +02:00
Manan Jethwani a4c3cad018 fixed books availablity on larger screens and added zoom level support 2021-08-10 21:45:10 +05:30
Kelson 83e757a530 Merge pull request #600 from kiwix/dynamic_select_box_value
Use OPDS API to populate categories/languages select boxes on Kiwix Serve welcome page
2021-08-07 15:33:52 +02:00
Manan Jethwani 5e8f3a5505 added use of lang and category api for select boxes on welcome page 2021-08-07 02:39:50 +05:30
Manan Jethwani fe93035a4c updated welcome page to support OPDS multiple Icon 2021-08-07 02:35:29 +05:30
Kelson 6e26c5aa75 Merge pull request #577 from kiwix/opds_multiple_icons
Support for multiple illustrations in OPDS entry
2021-08-05 23:22:07 +02:00
Veloman Yunkan 452283cfe6 Handling of /meta?name=Illustration_WxH@1 requests 2021-08-05 22:28:09 +04:00
Veloman Yunkan e5168d8b3d Support for multiple illustrations in OPDS entry 2021-08-05 22:21:13 +04:00
Matthieu Gautier b8aee8a42c Merge pull request #597 from kiwix/fix_get_results 2021-08-04 15:57:58 +02:00
Maneesh P M 9addd82d2d Fix usage of zim::Searcher::getResults() in libkiwix
The correct usage does not require the user to calculate an `end` using
the `pageLength`. We can directly use getResults(start, pageLength)
2021-08-04 19:20:50 +05:30
Maneesh P M e74e7f5623 Add unit test for incremental searching
With this, we eventually want to see the usage of getResults giving
a FAILING TEST. This happens because the second argument to
getResults is NOT `end` of the range, but `maxResultCount` to retrieve.
This will be fixed in the next commit.
2021-08-04 19:20:05 +05:30
Matthieu Gautier a032d65eb8 Merge pull request #576 from kiwix/extend_libkiwix_structures_to_use_libzim 2021-08-03 11:50:24 +02:00
Maneesh P M 19afe9442f Remove OriginId functions since they are not useful right now 2021-08-03 11:42:58 +02:00
Maneesh P M a3ba7619df Update Manager to use Archive instead of Reader
kiwix::Manager uses Reader to import a zim file, it should be using
zim::Archive directly.
2021-08-03 11:42:58 +02:00
Maneesh P M 8b12434ff2 Update kiwix::book to use libzim structure
Some methods in kiwix::Book uses wrapper structure reader. This usage should
be extended from the native libzim structure zim::Archive
2021-08-03 11:42:58 +02:00
Matthieu Gautier b4f7dfa5a2 Merge pull request #553 from kiwix/catalog_languages_endpoint 2021-08-03 11:41:31 +02:00
Veloman Yunkan ab3095745e Languages OPDS feed includes book counts 2021-08-03 11:32:38 +02:00
Veloman Yunkan 45adda44b3 Got rid of <content> node in languages OPDS entry 2021-08-03 11:32:38 +02:00
Veloman Yunkan 96cf7e78a5 OPDSDumper::categoriesOPDSFeed() with no args 2021-08-03 11:32:38 +02:00
Veloman Yunkan dd118df612 Got rid of langMap in opds_dumper.cpp
Language code to human friendly name translation is now done with the
help of the ICU library. It works if the line

```
-include $(LANGSRCDIR)/resfiles.mk
```

in the file `source/data/Makefile.in` of the icu4c dependency is not
commented out. Currently, the said line is commented out (along with
some other include's) by the `icu4c_custom_data.patch` patch of the
`kiwix-build` tool.
2021-08-03 11:32:38 +02:00
Veloman Yunkan 8a4248e48e Language code in /catalog/v2/languages entries 2021-08-03 11:32:38 +02:00
Veloman Yunkan 5f90f5ee2a Preliminary version of /catalog/v2/languages 2021-08-03 11:32:38 +02:00
Veloman Yunkan 64b55dbdc7 Made test library.xml a multi-language library 2021-08-03 11:32:38 +02:00
Veloman Yunkan 18871b4b15 Helper function Library::getBookPropValueSet()
Introduced a helper function `Library::getBookPropValueSet()` and
deduplicated Library::getBooks{Languages,Creators,Publishers}() methods.
2021-08-03 11:32:38 +02:00
Veloman Yunkan b2027b397c List of languages entry in /catalog/v2/root.xml
Added a new entry in /catalog/v2/root.xml that points to a
not-yet-existing list of languages navigation feed.
2021-08-03 11:32:38 +02:00
Kelson 49322f5961 Merge pull request #596 from kiwix/better_filter
improved browser lang filter working
2021-07-31 23:24:14 +02:00
Manan Jethwani 0466b9759c improved browser lang filter working 2021-07-30 12:57:59 +05:30
Kelson 20cdefcdb8 Merge pull request #593 from kiwix/remove_groovy_package
Remove groovy deb package
2021-07-28 21:40:02 +02:00
Emmanuel Engelhart 6ea40f57da Remove groovy deb package 2021-07-28 21:34:24 +02:00
Kelson a312d2218d Merge pull request #590 from kiwix/root_prefix_addition
corrected relative links in preview and icon url
2021-07-25 08:59:24 +02:00
Manan Jethwani 15839df594 corrected relative links in preview and icon url 2021-07-24 19:26:22 +05:30
Kelson 03a929e88e Merge pull request #583 from kiwix/download-modal
Modal download  box on Kiwix Serve welcome page
2021-07-13 16:47:58 +02:00
Manan Jethwani 646502f9cf changed font style for modal 2021-07-13 20:00:43 +05:30
Manan Jethwani a8a96a99f4 corrected working of magnet link 2021-07-13 00:23:38 +05:30
Manan Jethwani a517d3b529 added modal for downloading zim file on welcome page 2021-07-12 17:59:26 +05:30
Kelson 60f0f81286 Merge pull request #559 from kiwix/Css_revamp
Revamped Kiwix Serve Welcome page layout
2021-07-08 12:36:19 +02:00
Manan Jethwani 2ed9a50eca fixed button allignment 2021-07-08 12:33:28 +02:00
Manan Jethwani bce922ab89 bug fix for loader 2021-07-08 12:33:28 +02:00
Manan Jethwani ad7a63a471 minor change in UI 2021-07-08 12:33:28 +02:00
Manan Jethwani 6e8200637e corrected search button in mobile view 2021-07-08 12:33:28 +02:00
Manan Jethwani cc45c840d1 fixed minor codefactor issue 2021-07-08 12:33:28 +02:00
Manan Jethwani 0590f27fa1 corrected select box and search bar design 2021-07-08 12:33:28 +02:00
Manan Jethwani dd27c3a873 changed tile background color 2021-07-08 12:33:28 +02:00
Manan Jethwani 736841818d fixed font and other minor issues in title cards 2021-07-08 12:33:28 +02:00
Manan Jethwani c1868e22f4 minor codefactor fix 2021-07-08 12:33:28 +02:00
Manan Jethwani aabfc1d82e fixed card design 2021-07-08 12:33:28 +02:00
Manan Jethwani 2effb3490e minoor changes in responsive behaviour 2021-07-08 12:33:28 +02:00
Manan Jethwani 55672b0288 revamped basic layout and cards 2021-07-08 12:33:28 +02:00
Kelson 0abbeabfe2 Merge pull request #568 from kiwix/ppa-impish
PPA: Build for Ubuntu Impish
2021-07-08 10:24:52 +02:00
Kunal Mehta 1bf52e8ebe PPA: Build for Ubuntu Impish 2021-07-08 09:50:55 +02:00
Kelson e2db1b3688 Merge pull request #574 from kiwix/remove_mustache_public_header
Fix public headers inclusion (+ small other fixes)
2021-07-07 18:00:17 +02:00
Matthieu Gautier 0b6b6716de Rename split argument from trimEmpty to dropEmpty. 2021-07-07 14:43:13 +02:00
Matthieu Gautier 18b6433322 Correct method declaration in SuggestionItem 2021-07-07 14:43:13 +02:00
Matthieu Gautier b70c92cade Move back used helper functions to the public API.
- Add docstring
- Move the declaration in kiwix namespace.
- Adapt our include to include the right headers.
2021-07-07 14:43:13 +02:00
Matthieu Gautier 09d843da3a Add a (empty) include/tools.h header.
This header will contain our public tool functions.
2021-07-07 14:43:13 +02:00
Matthieu Gautier fa83a61a54 Move all public *Tools.h in src.
This by definition remove all the tool functions from the public API.
2021-07-07 14:43:13 +02:00
Matthieu Gautier 967eb10cbf Merge pull request #578 from kiwix/fix_ci_deps
Use correct deps archive in the CI.
2021-07-07 10:59:53 +02:00
Matthieu Gautier feeee25eac Use correct deps archive in the CI.
Now that project is named libkiwix, the dependencies archive is also
renamed.
2021-07-07 10:53:07 +02:00
Matthieu Gautier 1c0b4502cd Merge pull request #536 from kiwix/internally_drop_reader_searcher 2021-07-06 16:18:10 +02:00
Maneesh P M 6f639144ab Add unit tests for Searcher and Reader
Even though we will be removing the wrappers soon, the test coverage
should be complete and we could simply remove these files later.
2021-07-03 14:07:14 +05:30
Maneesh P M a94a03cd22 Remove unwanted reader functions
Removing the functions in InternalServer that are no longer needed.
2021-07-03 14:07:14 +05:30
Maneesh P M bc821638da Drop wrapper structures from handle_search
Since we now have SearcherRenderer that can work with native libzim
structure, we will drop the wrapper and use them instead.
2021-07-03 14:07:12 +05:30
Maneesh P M bcece66960 Add SearchRenderer handles for libzim structures
Introduces a new member mp_search that houses the zim::Search object,
adds a new constructor for this purpose. This commit also add an
overload for getHtml that takes start and end integers as arguments
since they are not part of the search object we include.
2021-07-03 14:05:50 +05:30
Maneesh P M c046f64d83 Drop Reader and Entry wrappers from handle_content 2021-07-03 14:05:50 +05:30
Maneesh P M 75b4d311d7 Drop Reader from InternalServer::handle_random 2021-07-03 14:04:04 +05:30
Maneesh P M a236751c74 Drop usage of Reader from InternalServer::handle_suggest 2021-07-03 14:04:04 +05:30
Maneesh P M 7d68926539 Drop usage of Reader from InternalServer::handle_meta
This is essentially a code move of meta handlers from using Reader
functions to directly using Archive.
2021-07-03 14:04:02 +05:30
Maneesh P M 940368b8ac Add m_archives and getArchiveById to Library
These members will mirror the functionality offered by equivalent usage
of Reader class.
2021-07-03 14:02:31 +05:30
Kelson 0594e60df3 Merge pull request #527 from kiwix/catalog_search_url_generation
OpdsCatalog::getSearchUrl()
2021-06-30 21:35:43 +02:00
Veloman Yunkan b5c1b26761 OpdsCatalog::getSearchUrl() 2021-06-30 18:27:00 +02:00
Kelson 4124ad30d5 Merge pull request #561 from kiwix/issue/557
Keep Kiwix Serve filter values over time
2021-06-25 08:05:21 +02:00
Manan Jethwani 3c5d73027d created separate variable for time delta 2021-06-24 15:41:28 +05:30
Manan Jethwani d88bdd3ebf corrected filter on no results 2021-06-23 14:15:22 +05:30
Manan Jethwani 5cfe34a5c2 corrected filter working 2021-06-22 19:36:22 +05:30
Manan Jethwani ad133bc9a3 added cookies for filter effect 2021-06-21 19:57:52 +05:30
Kelson 8eabae6286 Merge pull request #560 from kiwix/fix_compilation_illustration 2021-06-19 13:15:44 +02:00
Maneesh P M f3c96b23fd Use getIllustrationItem instead of getFaviconEntry method
With openzim/libzim#540 we now have a new function to get
illustration(previously favicon in 48x48 size and unity scale) in
multiple sizes. We need to replace getFaviconEntry with this new
getIllustrationItem method.
2021-06-19 10:23:24 +05:30
Kelson a92e9d8756 Merge pull request #490 from soumyankar/404ContentHomeButton
404 content home button
2021-06-17 09:59:45 +02:00
Vertigo 8d39b2c4c1 Added content ZIM home button on 404 2021-06-17 12:51:27 +05:30
Kelson 6d237ff1d5 Merge pull request #492 from kiwix/opds_categories_feed 2021-06-08 20:01:37 +02:00
Veloman Yunkan 78083f1f4a Moved OPDS templates under static/templates 2021-06-08 20:37:00 +04:00
Veloman Yunkan dd60235010 Fixed the self link in the output of /catalog/v2/entries 2021-06-08 20:37:00 +04:00
Veloman Yunkan e799f2ff1e OPDSDumper::dumpOPDSFeed() works via mustache
This changes the output of `/catalog/search` as follows:

- Entire search query (rather than only the value of the `q` parameter)
  is put in the <title> node.

- Search performed with an empty query presents itself as "All zims".

- The feed id remains stable for identical searches on the same
  library.
2021-06-08 20:37:00 +04:00
Veloman Yunkan 312f2cb560 Moved handle_catalog_v2*() methods into a new file 2021-06-08 20:37:00 +04:00
Veloman Yunkan fa42cbc48f Pagination info in /catalog/v2/entries 2021-06-08 20:37:00 +04:00
Veloman Yunkan f1797993af Reused InternalServer::search_catalog() 2021-06-08 20:37:00 +04:00
Veloman Yunkan f886c8c07b Root url is normalized once in the constructor 2021-06-08 20:37:00 +04:00
Veloman Yunkan 9ca6bd006f /catalog/v2/categories goes through OPDSDumper too 2021-06-08 20:37:00 +04:00
Veloman Yunkan cdacc0caf1 /catalog/v2/entries going through OPDSDumper
OPDSDumper sensed threats to its job security, so it lobbied to be
involved in handling the /catalog/v2 endpoints, too.
2021-06-08 20:37:00 +04:00
Veloman Yunkan dfad1c3815 /catalog/v2/searchdescription.xml 2021-06-08 20:37:00 +04:00
Veloman Yunkan 07252a127a /catalog/v2/entries is also a search endpoint 2021-06-08 20:37:00 +04:00
Veloman Yunkan b60e3ffb26 RequestContext::get_optional_param() 2021-06-08 20:37:00 +04:00
Veloman Yunkan 70d42aec98 A small simplification 2021-06-08 20:37:00 +04:00
Veloman Yunkan 4aa3c792aa Extracted get_search_filter() 2021-06-08 20:37:00 +04:00
Veloman Yunkan 208dece7e3 Reordered several statements
Reordered several statements so that the next couple of commits are a
little simpler.
2021-06-08 20:37:00 +04:00
Veloman Yunkan 19b59fd72f Serving /catalog/v2/entries
/catalog/v2/entries is intended to play the combined role of
/catalog/root.xml and /catalog/search of the old OPDS API. Currently,
the latter role is not yet implemented.

Implementation note: instead of tweaking and reusing
`OPDSDumper::dumpOPDSFeed()`, the generation of the OPDS feed is done via `mustache`
and a new template `static/catalog_v2_entries.xml`.
2021-06-08 20:37:00 +04:00
Veloman Yunkan 92c2de8d46 Enter InternalServer::m_library_id
The new field is intended to serve as a seed for generating semi-stable
OPDS feed ids that only need to change when the library is updated.
2021-06-08 20:37:00 +04:00
Veloman Yunkan feeb9f206e /catalog/v2/* XMLs are OPDS 1.2 2021-06-08 20:37:00 +04:00
Veloman Yunkan a1520ce7f1 Fixing the xenial build
Under Ubuntu 16.04/xenial, ccache seems to have issues with multiline
raw string literals used inside macros.
2021-06-08 20:37:00 +04:00
Veloman Yunkan 2e53b51696 Serving /catalog/v2/categories 2021-06-08 20:37:00 +04:00
Veloman Yunkan b259afa408 Library::getBooksCategories()
Note: no unit test added
2021-06-08 20:37:00 +04:00
Veloman Yunkan 3c3cf08a1a Serving /catalog/v2/root.xml
Note: This commit somewhat relaxes validation of non variable
`<updated>` elements in the OPDS feed - the contents of any `<updated>`
element is replaced with the YYYY-MM-DDThh:mm:ssZ placeholder.
2021-06-08 16:03:43 +04:00
Veloman Yunkan 54b78eaf56 Moved gen_date_str() to tools/otherTools.cpp 2021-06-08 16:03:43 +04:00
Veloman Yunkan 1e0ff1fbb0 Fixed the double colon in OPDS date string 2021-06-08 16:03:43 +04:00
Veloman Yunkan 5b272ac49c Fixed handling of /catalogBLABLA/root.xml & alike
Also removed an unneeded namespace qualifier.
2021-06-08 16:03:43 +04:00
Veloman Yunkan 0a3d293ae0 Broke Server.404 with /catalogBLABLABLA/root.xml
The new negative test-point demonstrates that Kiwix server doesn't
distinguish /catalogBLABLABLA from /catalog.
2021-06-08 16:03:43 +04:00
Kelson 86ef2e2199 Merge pull request #550 from kiwix/remove-bintray
Remove Bintray badge
2021-06-07 16:01:37 +02:00
Emmanuel Engelhart a0332e7599 Remove Bintray badge 2021-06-07 15:55:19 +02:00
Kelson 2ef488816c Merge pull request #534 from kiwix/filter_library
Add filters to kiwix-serve welcome page
2021-06-07 15:46:37 +02:00
Manan Jethwani 1ccafe2d97 minor changes in fadeout effect 2021-06-07 15:38:31 +02:00
Manan Jethwani d6c62b3cd3 corrected spinner and fadeout effect 2021-06-07 15:37:20 +02:00
Manan Jethwani f39c558d2a added fade out 2021-06-07 15:37:20 +02:00
Manan Jethwani 5b46ad5934 added spinned 2021-06-07 15:37:20 +02:00
Manan Jethwani 49dbd0aa52 fixed reset filters link 2021-06-07 15:37:20 +02:00
Manan Jethwani 179f0faeb1 added minor features 2021-06-07 15:37:20 +02:00
Manan Jethwani bb92f26b60 added filter functionality 2021-06-07 15:37:20 +02:00
Matthieu Gautier 3a4e8303a0 Merge pull request #541 from kiwix/adding_dynamic_and_subset_loading
Dynamic and subset loading of catalogue in kiwix-serve
2021-06-07 15:35:13 +02:00
Manan Jethwani 063bb8cd65 added dynamic and subset loading of zim-files in kiwix-serve 2021-06-01 19:33:42 +05:30
Kelson b54e5ab969 Merge pull request #543 from kiwix/add-libmicrohttpd-compilation-hint
Add libmicrohttpd compilation hint
2021-05-30 15:51:40 +02:00
Emmanuel Engelhart 2632a21d24 Move Repology to wiki 2021-05-30 15:46:45 +02:00
Emmanuel Engelhart 5c97b1fff9 gtest is need for testing 2021-05-30 15:43:21 +02:00
Emmanuel Engelhart 4f7175ad59 Libkiwix, not Kiwix library 2021-05-30 15:42:28 +02:00
Emmanuel Engelhart f4b8d0c303 Add libmicrohttpd compilation hint 2021-05-30 15:35:40 +02:00
Matthieu Gautier 188694f2a1 Merge pull request #510 from kiwix/add_function_zimId 2021-05-26 15:15:13 +02:00
Maneesh P M e2f6d91d51 Remove get_readerIndex in favor of get_zimId
The function get_readerIndex was used to get the zimId using an ordered
vector of readers. Now we can use get_zimId directly.
2021-05-26 14:45:25 +02:00
Maneesh P M c35f6f9142 Add get_zimId method to Result
get_zimId method allows the user to get the uuid of the archive from
which a result is retrieved directly from the search result itself.
2021-05-26 14:45:25 +02:00
Matthieu Gautier 7f0d3004c9 Merge pull request #505 from kiwix/suggestion_snippets 2021-05-26 11:04:52 +02:00
Maneesh P M 5567d8ca49 Replace std::vector<std::string> with SuggestionItem
Each sugestions used to be stored as vector of strings to hold various values
such as title, path etc inside them. With this commit, we use the new
dedicated class `SuggestionItem` to do the same.
2021-05-26 10:53:39 +02:00
Maneesh P M 5315034afe Introduce SuggestionItem class
This is a helper class that allows to create and manage individual
suggestion item and their data.
2021-05-26 10:53:00 +02:00
Maneesh P M 3288cd80e5 Render suggestion snippet properly
To render the snippets properly, we need to use the _renderItem property
of the autocomple ui.
2021-05-26 10:53:00 +02:00
Maneesh P M 56434de79e Set label to title snippet if present
With openzim/libzim#545 we now support snippet generation of titles
which can be used as the display label on the ui for highlighted titles
via the "label" field.
The old version used plain title which is still available in the value
field.
2021-05-26 10:52:58 +02:00
Matthieu Gautier e9ba151e6f Merge pull request #539 from kiwix/fix_windows_build
Avoid windows header to define min/max macros.
2021-05-26 09:52:43 +02:00
Matthieu Gautier 5f83944699 Avoid windows header to define min/max macros.
PR #507 use std::min.
But on windows, the header define min and max macros and so the
compilation is broken.
Add `-DNOMINMAX` define to avoid that.
2021-05-26 09:20:17 +02:00
Kelson 9c0ae835e2 Merge pull request #537 from kiwix/search_iterator_api_rename
Update libkiwix with search iterator rename in libzim
2021-05-26 08:49:26 +02:00
Maneesh P M e5fac30cee Update libkiwix with search iterator rename in libzim
Search iterator API in libzim has been shifted to use camel case naming.
This has to be accomodated in libkiwix as well.
2021-05-26 08:39:13 +02:00
Matthieu Gautier 7ef08b670b Merge pull request #538 from kiwix/revert-530-adding_dynamic_and_subset_loading
Revert "Kiwix Serve welcome page dynamic and subset loading (OPDS based)"
2021-05-25 17:33:23 +02:00
Matthieu Gautier 2736a46cfe Revert "Kiwix Serve welcome page dynamic and subset loading (OPDS based)" 2021-05-25 17:30:05 +02:00
Kelson 672b4fc907 Merge pull request #530 from kiwix/adding_dynamic_and_subset_loading
Kiwix Serve welcome page dynamic and subset loading (OPDS based)
2021-05-25 16:22:54 +02:00
Manan Jethwani 012973d14a added dynamic and subset loading of zim-files in kiwix-serve 2021-05-25 02:41:12 +05:30
Kelson 67984cca5b Merge pull request #535 from kiwix/further-kiwix-lib-renaming
Rename kiwix-lib in libkiwix
2021-05-23 21:57:03 +02:00
Emmanuel Engelhart d4e35c7067 Rename kiwix-lib in libkiwix 2021-05-23 21:46:52 +02:00
Matthieu Gautier 6e37cabaea Merge pull request #529 from kiwix/libkiwix-github-url-fix
Fix Libkiwix Github repository URLS
2021-05-21 16:09:15 +02:00
Emmanuel Engelhart c8b7f8772a Fix Libkiwix Github repository URLS 2021-05-20 08:56:44 +02:00
Veloman Yunkan fc7484ac86 Merge pull request #528 from kiwix/fix_suggestion_search_result_page
Check if bookName is available in url parameters
2021-05-19 00:36:15 +04:00
Maneesh P M c236f3a32b Check if bookName is available in url parameters
In certain pages like the search result page, bookName is not of the
form `/bookName/endpoint?parameters`. Rather it is available as a query
parameter. From these pages bookName should be assigned from parameters.
2021-05-19 01:12:29 +05:30
Matthieu Gautier 3c7faddb6e Merge pull request #526 from kiwix/lizim_search_api_change
Fixed the libkiwix build broken by the changed libzim search API
2021-05-17 15:06:15 +02:00
Veloman Yunkan cd02b4de3b Dummy application of new libzim search API
Didn't take any advantage of the new libzim search API. Just fixed the
libkiwix build in the most straightforward way.
2021-05-15 23:34:51 +04:00
Kelson 5188355878 Merge pull request #525 from kiwix/html-only-root-link
Insert root link only if html content
2021-05-14 16:51:33 +02:00
Emmanuel Engelhart 05cc3d015f Insert root link only if html content 2021-05-14 14:49:28 +02:00
Kelson 39b62c6108 Merge pull request #522 from kiwix/libkiwix_ci_fix
Fixed CI after repository rename
2021-05-13 11:09:57 +02:00
Veloman Yunkan 9c43353b72 Fixed CI after repository rename 2021-05-13 12:49:44 +04:00
Matthieu Gautier b82fff9855 Merge pull request #507 from kiwix/fix_for_issue_504
/catalog/search handles out-of-bounds pagination
2021-05-10 11:47:49 +02:00
Veloman Yunkan 68189de162 /catalog/search handles out-of-bounds pagination 2021-05-10 11:25:06 +02:00
Matthieu Gautier 6aab9b6981 Merge pull request #506 from kiwix/library_filtering_by_empty_query
Empty query acts as a match-all query
2021-05-10 10:27:37 +02:00
Veloman Yunkan 41276341d0 Empty query acts as a match-all query
After switching to Xapian-based search in the library/catalog, an empty
query stopped acting as a match-all query. This commit restores the old
behaviour in that regard.
2021-05-09 15:14:43 +02:00
Kelson 02c3dff142 Merge pull request #508 from kiwix/remove_204_status_code
Revert "added 204 code for empty return of search"
2021-05-09 07:49:43 +02:00
Maneesh P M be6b58c6ad Revert "added 204 code for empty return of search"
Returning status code 204 in case of an empty results doesn't show the
empty results page as described in #466. Reverting the changes in #396
fixes the issue.
2021-05-09 10:47:18 +05:30
Matthieu Gautier ab0ffb55bc Merge pull request #502 from kiwix/no-meta4-file
No metalink file on fs
2021-05-04 13:52:54 +02:00
Emmanuel Engelhart 950e742116 No metalink file on fs 2021-05-04 13:15:43 +02:00
Matthieu Gautier 69257610e8 Merge pull request #495 from kiwix/replace_buggy_zim
Replace buggy example.zim with a correct one
2021-04-28 16:28:37 +02:00
maneeshpm 700d4becb9 Replace buggy example.zim with a correct one
The existing example.zim has an improper main page entry hence an
unusable index as reported in openzim/libzim#521
To replace the buggy zim, a new zim has been generated using the latest
zimwriterfs with latest libzim.

-------------------------------------------------------------------------
The directory used to create zim is given below and are two pages from
wikibooks site:

htmlContent
├── favicon.png
├── FreedomBox for Communities_Offline Wikipedia - Wikibooks, open books for an open world_files
│   ├── index.php
│   ├── load.php
│   ├── poweredby_mediawiki_88x31.png
│   └── wikimedia-button.png
├── FreedomBox for Communities_Offline Wikipedia - Wikibooks, open books for an open world.html
├── Wikibooks_files
│   ├── 234px-Megakaryocyte1.svg.png
│   ├── 287px-ChewyGingerCookies.jpg
│   ├── 36px-Commons-logo.svg.png
│   ├── 40px-Wikiquote-logo.svg.png
│   ├── 41px-Wikispecies-logo.svg.png
│   ├── 46px-Wikisource-logo.svg.png
│   ├── 48px-MediaWiki-2020-icon.svg.png
│   ├── 48px-Phacility_phabricator_logo.png
│   ├── 48px-Wikimedia_Cloud_Services_logo.svg.png
│   ├── 48px-Wikimedia_Community_Logo.svg.png
│   ├── 48px-Wikivoyage-Logo-v3-icon.svg.png
│   ├── 51px-Wiktionary-logo.svg.png
│   ├── 53px-Wikipedia-logo-v2.svg.png
│   ├── 59px-Wikiversity_logo_2017.svg.png
│   ├── 86px-Wikidata-logo.svg.png
│   ├── 88px-Wikinews-logo.svg.png
│   ├── Haskell-logo.png
│   ├── index.php
│   ├── load.php
│   ├── poweredby_mediawiki_88x31.png
│   └── wikimedia-button.png
└── Wikibooks.html

The command for writing the zim:
$ zimwriterfs --welcome=Wikibooks.html --favicon=favicon.png --language=en --title=Wikibooks --description=testZim --creator=test --publisher=test --verbose ./htmlContent  ./out/example.zim
2021-04-28 15:24:50 +02:00
Matthieu Gautier dd795bd56d Merge pull request #498 from kiwix/issue/446
fixed suggestion system
2021-04-28 14:40:06 +02:00
Manan Jethwani 5fdc51b23e fixed suggestion system 2021-04-28 14:34:24 +02:00
Matthieu Gautier 32cc6b0dcb Merge pull request #499 from kiwix/const_correct_library
const-correct kiwix::Library
2021-04-28 14:31:28 +02:00
Veloman Yunkan 3879b82112 const-correct kiwix::Library
- Made most methods of kiwix::Library const.
- Also added const versions of getBookById() and getBookByPath()
  methods.
2021-04-28 11:42:55 +04:00
Matthieu Gautier 7336dcab1d Merge pull request #488 from kiwix/fully_xapian_powered_catalog_search 2021-04-27 15:10:40 +02:00
Veloman Yunkan 63e9a09259 Cleaned up/beautified Library::updateBookDB() 2021-04-27 16:59:21 +04:00
Veloman Yunkan 4178c169dd Xapian documents in book DB store only the book id 2021-04-27 16:59:21 +04:00
Veloman Yunkan 59e9a0cd77 Merged XmlLibraryTest with LibraryTest
The library set up by LibraryTest now contains two valid books
initialized via XML. Therefore XmlLibraryTest is not needed as a
separate test suite.
2021-04-27 16:59:21 +04:00
Veloman Yunkan f751aff2fb Full case/diacritics insensitivity in catalog filtering
Catalog filtering should now be case/diacritics insensitive for all
fields. However it is not validated for language, name and category
fields, and is validated for tags, creator & publisher only for text
supplied in the filter (but not for values read from the book).
2021-04-27 16:59:21 +04:00
Veloman Yunkan 87dc9d2723 Made catalog filtering by query diacritics insensitive
Catalog filtering by titles/description was sensitive to diacritics
present in the query string. Fixed that.

Also enhanced the unit test to validate the insensitivity to diacritics
present in either the title/description or the query string.
2021-04-27 16:59:21 +04:00
Veloman Yunkan 9c7366890d Catalog filtering by tags works via Xapian 2021-04-27 16:59:21 +04:00
Veloman Yunkan 19e195cb7d Filter::Tags typedef 2021-04-27 16:59:21 +04:00
Veloman Yunkan 3d5fd8f585 Catalog filtering by creator works via Xapian 2021-04-27 16:59:21 +04:00
Veloman Yunkan d3d5abe14d Handling of non-words in publisher query
This change fixes the failure of the LibraryTest.filterByPublisher
unit-test broken by the previous commit.

The previous approach used in `publisherQuery()` for building a phrase
query enforcing the specified prefix for all terms fails if

1. the input phrase contains a non-word term that Xapian's query parser
   doesn't like (e.g. a standalone ampersand character, 1/2, a#1, etc);
2. the input phrase contains at least three terms that Xapian's query
   parser has no issue with.

Using the `quest` tool (coming with xapian-tools under Ubuntu) the
issue can be demonstrated as follows:

```
$ quest -o phrase -d some_xapian_db "Energy & security"
Parsed Query: Query((energy@1 PHRASE 11 Zsecur@2))
Exactly 0 matches
MSet:

$ quest -o phrase -d some_xapian_db "Energy & security act"
UnimplementedError: OP_NEAR and OP_PHRASE only currently support leaf subqueries

$ quest -o phrase -d some_xapian_db 'Energy 1/2 security act'
UnimplementedError: OP_NEAR and OP_PHRASE only currently support leaf subqueries

$ quest -o phrase -d some_xapian_db "Energy a#1 security act"
UnimplementedError: OP_NEAR and OP_PHRASE only currently support leaf subqueries
```

The problem comes from parsing the query with the default operation set
to `OP_PHRASE` (exemplified by the `-o phrase` option in above
invocations of `quest`). A workaround is to parse the phrase with a
default operation of `OP_OR` and then combine all the terms with
`OP_PHRASE`.

Besides stemming should be disabled in order to target an exact phrase
match (save for the non-word terms, if any, that are ignored by the
query parser).
2021-04-27 16:59:21 +04:00
Veloman Yunkan e805f68994 Enhanced & broke LibraryTest.filterByPublisher 2021-04-27 16:59:21 +04:00
Veloman Yunkan a759ab989f Catalog filtering by publisher works via Xapian 2021-04-27 16:59:21 +04:00
Veloman Yunkan 7ccd9ffcce Catalog filtering by language works via Xapian 2021-04-27 16:59:21 +04:00
Veloman Yunkan 0c0a37073b Catalog filtering by category works via Xapian 2021-04-27 16:59:21 +04:00
Veloman Yunkan 415c65cf03 Catalog filtering by book name works via Xapian 2021-04-27 16:59:21 +04:00
Veloman Yunkan 8287f351e7 Final logic of Library::filterViaBookDB()
Moved the `filter.hasQuery()` check inside `buildXapianQuery()`.
`Library::filterViaBookDB()` only cares if the query that is going to be
run on the book DB would match all documents. The rest of changes
related to enhancing the usage of Xapian for the catalog search will
happen inside `buildXapianQuery()` and `updateBookDB()`.
2021-04-27 16:59:21 +04:00
Veloman Yunkan ea779ac200 Extracted buildXapianQuery() 2021-04-27 16:59:21 +04:00
Veloman Yunkan 80cd1fc989 Renamed 2 functions in Filter and Library 2021-04-27 16:59:21 +04:00
Veloman Yunkan 2d76f8395e Dropped unused functions from Filter's private API
This should have been done back in PR #460
2021-04-27 16:59:21 +04:00
Veloman Yunkan 29a6a34ecf Delimited kiwix::Filter's public and private APIs 2021-04-27 16:59:21 +04:00
Veloman Yunkan 2f3f1a4859 Improved LibraryTest.filterByMultipleCriteria 2021-04-27 16:59:21 +04:00
Veloman Yunkan b9be742085 LibraryTest.filterByMaxSize 2021-04-27 16:59:21 +04:00
Veloman Yunkan 95c354a5fa LibraryTest.filterByCategory 2021-04-27 16:59:21 +04:00
Veloman Yunkan cdd272fc5a LibraryTest.filterByName 2021-04-27 16:59:21 +04:00
Veloman Yunkan ef962a9174 LibraryTest.filterByPublisher 2021-04-27 16:59:21 +04:00
Veloman Yunkan f063d350c6 LibraryTest.{filterLocal,filterRemote} 2021-04-27 16:59:21 +04:00
Veloman Yunkan d8fe593f59 Extended the unit-test library with 2 XML entries 2021-04-27 16:59:21 +04:00
Veloman Yunkan 22b8625033 Enter EXPECT_FILTER_RESULTS()
This diff is easier to view if whitespace change is ignored.
2021-04-27 16:59:21 +04:00
Veloman Yunkan 0f277ffa34 Enhanced the LibraryTest.filterByTags unit-test 2021-04-27 16:59:21 +04:00
Veloman Yunkan 068f7e5e95 New unit-test LibraryTest.filterByCreator 2021-04-27 16:59:21 +04:00
Veloman Yunkan 8c810d2d2f Enhanced the LibraryTest.filterByQuery unit-test 2021-04-27 16:59:21 +04:00
Veloman Yunkan 8c18a37961 Split LibraryTest.filterCheck into several tests 2021-04-27 16:59:21 +04:00
Veloman Yunkan db3e0d7f72 Enhanced the LibraryTest.filterCheck unit-test
Now the LibraryTest.filterCheck unit-test validates the actual entries
returned by `Library::filter` (previously only the count of the results
was checked).
2021-04-27 16:59:21 +04:00
Matthieu Gautier d134ad417f Merge pull request #497 from MananJethwani/issue/481
removed redirect to articles in search
2021-04-20 17:13:01 +02:00
Manan Jethwani 965b9622c2 removed redirect to articles in search 2021-04-20 20:23:42 +05:30
Kelson 11db5dec4e Merge pull request #494 from kiwix/ripple_effect_of_libzim_pr524
get_url() was renamed in zim::search_iterator
2021-04-16 12:38:15 +02:00
Veloman Yunkan 9d4370403b get_url() was renamed in zim::search_iterator 2021-04-16 13:30:36 +04:00
Kelson cb57178c23 Merge pull request #491 from kiwix/fix_macos_ci
Update brew before installing packages
2021-04-12 18:41:00 +02:00
Matthieu Gautier 9ba5ab4678 Update brew before installing packages
brew changed his backend repository, we must update brew itself first.
2021-04-12 18:31:29 +02:00
Matthieu Gautier a597870025 Merge pull request #465 from soumyankar/master 2021-04-12 18:17:57 +02:00
Vertigo 611146aa37 Added Search Link for bad bookName/articleName on 404 2021-04-12 21:31:47 +05:30
Matthieu Gautier 6d2f227c42 Merge pull request #486 from kiwix/fix_for_issue462 2021-04-12 15:18:57 +02:00
Veloman Yunkan 0c7d19ab45 Testing of Manager.readXml() 2021-04-12 15:14:12 +02:00
Veloman Yunkan b54215f146 Manager::readOpds() doesn't modify its input 2021-04-12 15:14:12 +02:00
Veloman Yunkan 9033f2f28e Manager::readXml() doesn't modify its input 2021-04-12 15:14:12 +02:00
Matthieu Gautier 5c289abd0e Merge pull request #485 from kiwix/fix_for_issue478 2021-04-12 15:05:13 +02:00
Veloman Yunkan ec9186b174 Library::removeBookById() updates the search DB
This fix makes the `XmlLibraryTest.removeBookByIdUpdatesTheSearchDB`
unit-test pass.
2021-04-09 17:06:45 +04:00
Veloman Yunkan aaaa5a637e Library::filter() doesn't create empty books
This changes how the `XmlLibraryTest.removeBookByIdUpdatesTheSearchDB`
unit-test fails.
2021-04-09 17:06:45 +04:00
Veloman Yunkan 49940a30d0 XmlLibraryTest.removeBookByIdUpdatesTheSearchDB
The new unit-test fails with a reason not expected before it was
written. The `Library::filter()` operation returns a correct result
after the call to `removeBookById()` (this was a surprise!) but it has
a side-effect of re-adding an empty book with the id still surviving
in the search DB (the emptiness of this re-created book doesn't allow
it to pass the other filtering criteria, which explains why the result
of `Library::filter()` is correct). Had to add a special check
to the new unit-test against that hidden side-effect of
`Library::removeBookById()` + `Library::filter()` combination.
2021-04-09 17:06:45 +04:00
Veloman Yunkan 24ed96a38c Library.removeBookById() drops the reader too
This fix makes the `XmlLibraryTest.removeBookByIdDropsTheReader`
unit-test pass.
2021-04-09 17:05:56 +04:00
Veloman Yunkan ccdc316217 Two unit-tests for Library::removeBookById
The `XmlLibraryTest.removeBookByIdDropsTheReader` unit-test fails,
demonstrating a bug in `kiwix::Library::removeBookById()`.
2021-04-09 16:59:55 +04:00
Matthieu Gautier ba44033273 Merge pull request #464 from MananJethwani/issue/kiwix-tools/205
adding kind and path attributes to suggest response object and using it in autocomplete
2021-04-07 18:08:29 +02:00
Manan Jethwani 5cb276a933 adding kind and path attributes to suggest response object and using it in autocomplete 2021-04-07 21:04:33 +05:30
Matthieu Gautier e4be97a032 Merge pull request #470 from kiwix/xapian_should_not_be_exposed 2021-04-07 16:55:24 +02:00
Veloman Yunkan aa2a031ba4 Xapian headers are not exposed through libkiwix 2021-04-07 18:24:33 +04:00
Kelson 803cb1c2c5 Merge pull request #476 from MananJethwani/correcting#474
changed method of injecting root link
2021-03-24 10:20:54 +01:00
Manan Jethwani 7872734f44 changed method of injecting root link 2021-03-24 14:17:58 +05:30
Kelson d061697de7 Merge pull request #474 from MananJethwani/issue/473
injecting root link directly and renamed head_part to head_taskbar
2021-03-24 09:24:42 +01:00
Manan Jethwani c557bb271b injecting root link directly and renamed head_part to head_taskbar 2021-03-24 02:10:16 +05:30
Kelson 1f45c42c32 Merge pull request #472 from MananJethwani/issue/407
added root functionality for block external link feature
2021-03-23 10:54:22 +01:00
Manan Jethwani 93264f7409 added root functionality for block external link feature 2021-03-23 03:17:14 +05:30
Matthieu Gautier baed447dd3 Merge pull request #460 from kiwix/xapian_based_catalog_search 2021-03-17 14:45:56 +01:00
Veloman Yunkan 20b487da8d Added Xapian as direct dependency 2021-03-17 14:32:03 +01:00
Veloman Yunkan e214efecd4 Language code conversion via ICU
Language code is converted from ISO 639-3 to ISO 639 (which is
understood by Xapian) via ICU. The previous approach via an explicit
map had its advantages since Xapian has more than one stemmer
implementations for some languages (selectable via Xapian-specific
identifiers). This commit relies on the defaults associated with the
ISO 639 language codes.
2021-03-17 14:32:03 +01:00
Veloman Yunkan 09233bf4f3 Support for partial queries in catalog search
The search text in the catalog query is interpreted as partial by
default, but partial query mode can be disabled in C++. The latter
possibility is not exposed via the /catalog/search kiwix-serve endpoint,
though.
2021-03-17 14:32:03 +01:00
Veloman Yunkan 47c67a4202 LibraryServerTest.catalog_search_with_word_exclusion 2021-03-17 14:32:03 +01:00
Veloman Yunkan 6b600a18eb LibraryServerTest.catalog_prefix_search 2021-03-17 14:32:03 +01:00
Veloman Yunkan 9e887cadf1 Added some diversity to test/data/library.xml 2021-03-17 14:32:03 +01:00
Veloman Yunkan a599fb3892 Initial version of Xapian-based catalog search 2021-03-17 14:32:03 +01:00
Veloman Yunkan a17fc0ef2d Library::getBooksByTitleOrDescription() 2021-03-17 14:32:03 +01:00
Veloman Yunkan db06b2c7ca Library::BookIdCollection typedef 2021-03-17 14:32:03 +01:00
Veloman Yunkan a20f9e2ce1 Library::filter() works in two stages
1. Get the subset of books matching the q (title/description) parameter
   of the search

2. Filter out books not matching the other parameters of the search.

Stage 1. currently works in the old way, but will be replaced by Xapian
based search in subsequent commits.
2021-03-17 14:32:03 +01:00
Kelson f7c867f8a7 Merge pull request #459 from kiwix/opds_category_support
Support for book categories in OPDS feed
2021-03-17 12:37:16 +01:00
Veloman Yunkan b7b0bdbdd8 Both Book::update() methods update the category 2021-03-17 14:10:57 +04:00
Veloman Yunkan a870e05621 Slight enhancement of BookTest.updateTest 2021-03-17 14:10:57 +04:00
Veloman Yunkan 4abc4f8518 Support for book category attribute in library.xml 2021-03-17 14:10:57 +04:00
Veloman Yunkan 6b2067c236 Reading category element from OPDS stream 2021-03-17 14:10:57 +04:00
Veloman Yunkan e55bf514e8 Dedicated 'category' parameter in catalog search 2021-03-17 14:10:57 +04:00
Veloman Yunkan 80d4f7e349 Extracted InternalServer::search_catalog() 2021-03-17 14:10:57 +04:00
Veloman Yunkan f270724b1f Testing of a library entry without a category 2021-03-17 14:10:44 +04:00
Veloman Yunkan 58186ffb26 kiwix::Book::getCategory() 2021-03-17 14:09:48 +04:00
Veloman Yunkan 6d43fd065f Less boilerplate in LibraryServerTest unit-tests 2021-03-17 14:02:27 +04:00
Veloman Yunkan 071d2bedd3 LibraryServerTest.catalog_search_by_text 2021-03-17 14:02:27 +04:00
Veloman Yunkan 0b1740e6c5 LibraryServerTest.catalog_search_by_tag 2021-03-17 14:02:27 +04:00
Veloman Yunkan 9913f748e2 LibraryServerTest.catalog_searchdescription_xml 2021-03-17 14:02:27 +04:00
Veloman Yunkan c5c40cb189 New unit-test LibraryServerTest.catalog_root_xml 2021-03-17 14:02:27 +04:00
Veloman Yunkan ae32ff40c0 Dropped an extra colon from book <updated> dates 2021-03-17 14:02:27 +04:00
Veloman Yunkan 26331b401e Fixed the month in OPDS feed <updated> date
`tm::tm_mon` varies in the [0, 11] range.
2021-03-17 14:02:27 +04:00
Matthieu Gautier 0f368791a2 Merge pull request #461 from MananJethwani/issue/444 2021-03-15 16:57:10 +01:00
Manan Jethwani fb26f6b9c5 moved autocomplete from head_part.html to taskbar.js 2021-03-15 18:10:10 +05:30
Matthieu Gautier 32643fbd94 Merge pull request #463 from soumyankar/master
Change Mustache-3.0 to Mustache-4.1
2021-03-15 11:38:57 +01:00
Vertigo faa9e1f8b5 Change Mustache-3.0 to Mustache-4.1 2021-03-14 11:43:48 +05:30
Kelson bd781f8e8b Merge pull request #458 from kiwix/html_decoded_suggestions
Correctly encoding/decoding HTML entities in search suggestions
2021-03-04 14:34:47 +01:00
Veloman Yunkan c7d77395e7 label field of suggestions is also HTML escaped
Without this if the suggestion text contains a double quote, the
response stops being a valid json.
2021-03-04 14:18:58 +01:00
Veloman Yunkan a7fea462b0 HTML decoding of suggestions in the frontend
Since the `value` field of the search suggestion results is HTML
escaped/encoded in the backend (see static/templates/suggestion.json) it
must be decoded in the frontend.
2021-03-04 14:18:58 +01:00
Matthieu Gautier 89d7e68a39 Merge pull request #446 from kiwix/libzim_random
Use the new libzim's getRandomEntry instead of implementing it ourselves.
2021-03-03 16:04:00 +01:00
Matthieu Gautier 67caae6c32 Use the new libzim's getRandomEntry instead of implementing it ourselves. 2021-03-02 14:16:09 +01:00
Kelson d3f2e08b35 Merge pull request #429 from kiwix/open_zimfile_by_fd
JNI interface to opening ZIM archives (including embedded ones) by fd
2021-02-26 09:20:58 +01:00
Veloman Yunkan 839fc10a4f Fixed the Windows build
Opening ZIM archives by file descriptor (as well as embedded
ZIM archives) is not supported under Windows.
2021-02-10 14:19:47 +01:00
Veloman Yunkan 5a8b825c70 Testing of JNIKiwixReader.getDirectAccessInformation() 2021-02-10 14:19:47 +01:00
Veloman Yunkan 7a465e66d7 Renamed org.kiwix.kiwixlib.{Pair->DirectAccessInfo} 2021-02-10 14:19:47 +01:00
Veloman Yunkan 5a99634dfd Java wrapper test checks favicon.png too 2021-02-10 14:19:47 +01:00
Veloman Yunkan e028bcbb04 Android's java.io.FileDescriptor is different 2021-02-10 14:19:47 +01:00
Veloman Yunkan 9cdf7a44c0 JNIKiwixReader can open an embedded ZIM archive 2021-02-10 14:19:47 +01:00
Veloman Yunkan 4d23e44de7 JNIKiwixReader ctor taking a file descriptor
... and a corresponding unit test
2021-02-10 14:19:47 +01:00
Veloman Yunkan 98d69ef59b Added testReader unit-test for the java wrapper 2021-02-10 14:19:47 +01:00
Veloman Yunkan e40827fbac Renamed the java wrapper unit test runner script 2021-02-10 14:19:47 +01:00
Veloman Yunkan a798e0c0a1 Made the java wrapper unit test run & pass
The kiwixlib java wrapper unit test can be run manually via the
src/wrapper/java/org/kiwix/testing/compile_test.sh script.

The test ZIM files in src/wrapper/java/org/kiwix/testing were created
using the create_test_zimfiles. They must be updated/re-generated and
committed in git whenever their source data or the create_test_zimfiles
script changes. Note: small.zim.embedded is not used at this point, it
was created for testing the enhancement coming in a few commits.
2021-02-10 14:19:47 +01:00
Matthieu Gautier 971374e049 Merge pull request #455 from kiwix/api-break-bumpup-major-version
Bump-up version to 10.0.0
2021-02-10 10:47:06 +01:00
Emmanuel Engelhart f7608c378e Bump-up version to 10.0.0 2021-02-10 10:31:01 +01:00
Kelson c13a43010a Merge pull request #453 from kiwix/fixed-typo
Typo fix in error message
2021-02-09 09:41:00 +01:00
Emmanuel Engelhart eea10ec3f5 Typo fix in error message 2021-02-09 09:38:18 +01:00
Kelson c9bc2b48b0 Merge pull request #452 from kiwix/version-update
Bump-up version (and libzim required version)
2021-02-08 21:30:11 +01:00
Veloman Yunkan b1689e0d3c Bump-up version (and libzim required version) 2021-02-07 19:53:46 +04:00
Kelson c70c370ae0 Merge pull request #435 from kiwix/ppa-soname-bump
PPA: Update for soname bump
2021-01-27 09:25:39 +01:00
Kunal Mehta c0ec5eeffd PPA: Update for soname bump 2021-01-27 09:14:36 +01:00
Matthieu Gautier c81c2a4630 Merge pull request #445 from kiwix/no_pthread 2021-01-26 18:06:16 +01:00
Matthieu Gautier 24b2e6e585 Remove unnecessary include. 2021-01-26 17:53:25 +01:00
Matthieu Gautier 3fd1310008 Use c++11 std::thread instead of pthread. 2021-01-26 17:53:25 +01:00
Matthieu Gautier 17bc1a3e1a [TEST] Do not try to use the bookId if it is wrong. 2021-01-26 17:53:25 +01:00
Matthieu Gautier f5d9a3714d Merge pull request #449 from kiwix/handle_no_counter
Do not crash if zim file has no `Counter` metadata.
2021-01-26 17:52:33 +01:00
Matthieu Gautier 4749656828 Do not crash if zim file has no Counter metadata. 2021-01-26 15:15:27 +01:00
Kelson e0bcafd89a Merge pull request #442 from kiwix/better-taskbar-insertion
Better taskbar insertion
2021-01-18 13:32:11 +01:00
Emmanuel Engelhart 84895c4036 Better </head> detection regex 2021-01-18 13:16:56 +01:00
Emmanuel Engelhart a8bf9dd5b4 Better Kiwix Serve Taskbar insertion (after charset definition) 2021-01-18 11:18:53 +01:00
Emmanuel Engelhart a61c94ef10 Add GPLv3 header 2021-01-18 10:54:33 +01:00
Kelson a8a864f70e Merge pull request #434 from kiwix/mandatory_xapian
Build kiwix-lib only if meson is compiled with xapian.
2021-01-15 10:03:57 +01:00
Matthieu Gautier a231dfd8e4 Build kiwix-lib only if meson is compiled with xapian. 2021-01-14 12:07:17 +01:00
Kelson 321d08e3d5 Merge pull request #440 from kiwix/better-taskbar-introduction
Fix taskbar insertion in case of '<head>' attributes
2021-01-12 11:48:57 +01:00
Emmanuel Engelhart 8c43fd8d36 Fix taskbar insertion in case of '<head>' attributes 2021-01-11 14:37:19 +01:00
Kelson 9e032b6eea Merge pull request #439 from kiwix/mediacount-video-audio
Support 'video/*' * 'audio/*' mimetypes in getMediaCount()
2021-01-08 13:01:42 +01:00
Emmanuel Engelhart 3e2810dff4 Support 'video/*' * 'audio/*' mimetypes in getMediaCount() 2021-01-07 12:32:32 +01:00
Kelson 18afa97674 Merge pull request #437 from kiwix/count-webp-media
More robust getMediaCount()
2021-01-03 21:15:55 +01:00
Emmanuel Engelhart 44c4aa931a Better use kiwix::startsWith() 2021-01-03 15:17:03 +01:00
Emmanuel Engelhart 95b32b168d More robust getMediaCount() 2021-01-01 17:05:32 +01:00
Kelson 2659f323cd Merge pull request #433 from kiwix/small_fixes
Fixes related to libzim next.
2020-12-11 06:46:40 +01:00
Matthieu Gautier 1002c15e0d Remove unnecessary checks.
`Reader` cannot be created with a null `zimArchive`.
We don't have to check for zimArchive being not null.
2020-12-09 14:25:02 +01:00
Matthieu Gautier d51000c4a9 Use new libzim method hasFulltextIndex to check for fulltext index. 2020-12-09 14:25:02 +01:00
Matthieu Gautier ba302bed33 Use new libzim method getFaviconEntry to get the favicon. 2020-12-09 14:25:02 +01:00
Kelson 9941d245e1 Merge pull request #432 from swills/fbsd-build-fix1
fix build on FreeBSD
2020-12-09 14:24:04 +01:00
Steve Wills 6900b4e506 fix build on FreeBSD
With this header, sockaddr_in and INADDR_ANY are not defined
2020-12-07 09:38:46 -05:00
Kelson 6fa20f6dcf Merge pull request #431 from kiwix/legoktm-patch-1
PPA: Build for Ubuntu Hirsute
2020-12-05 09:29:47 +01:00
Kunal Mehta 8eacb0d635 PPA: Build for Ubuntu Hirsute 2020-12-03 22:35:46 -08:00
Kelson 84c320d5d3 Merge pull request #428 from kiwix/libzim_next
Adapt kiwx-lib to the new api of libzim (libzim_next).
2020-12-03 09:11:28 +01:00
Matthieu Gautier 1a5a2e7a8e Adapt kiwix-lib to the new libzim api. 2020-12-02 12:16:48 +01:00
Matthieu Gautier d87079ec13 Remove deprecated method in the reader. 2020-11-24 19:00:52 +01:00
Matthieu Gautier fbd4332c87 New version 9.4.1 2020-11-17 15:42:13 +01:00
Matthieu Gautier 7c4517ca3c Merge pull request #427 from kiwix/fix_deps_zlib 2020-11-17 12:05:50 +01:00
Matthieu Gautier bc4b6846ef Add missing dependency declaration in the README. 2020-11-17 11:54:36 +01:00
Matthieu Gautier f408fecdd0 Add missing zlib dependency.
libzim were dependent of zlib and we were (wrongly) using its
dependency declaration to link with zlib.

Now that libzim doesn't depends on zlib, we need to fix our build system
and explicitly depend on it.
2020-11-17 11:54:10 +01:00
Kelson 038e86e0d8 Merge pull request #419 from kiwix/legoktm-patch-1
debian: Have libkiwix-dev depend on libmicrohttpd-dev
2020-11-04 15:20:36 +01:00
Kunal Mehta 41cee1cfe0 debian: Have libkiwix-dev depend on libmicrohttpd-dev
As of 9c925f6778, it's now required in the pkg-config file.
2020-11-04 15:14:09 +01:00
Kelson 7e2d174cfb Merge pull request #422 from kiwix/rgaudin/taskbar-height
Adjust body padding-top for taskbar
2020-11-04 15:13:18 +01:00
renaud gaudin 52da58a294 Adjust body padding-top for taskbar
taskbar is placed *above* content using a `padding-top: 3em;` rule
Currently, in regular case, padding-top is too large and leaves ~4/5px between the
taskbar and the content.
This fixes it by using a `calc()` rule to eliminate this extra space
2020-11-04 11:53:59 +00:00
Matthieu Gautier 0f8caba3a5 Merge pull request #418 from kiwix/fix_counter_parsing 2020-10-30 13:42:52 +01:00
Veloman Yunkan 0f8fe1f63f Alternative implementation of parseMimetypeCounter() 2020-10-29 14:11:27 +04:00
Matthieu Gautier ed32e16db2 Use a reference in test/server.cpp loop.
This is mainly to make the macos CI pass.
2020-10-28 16:08:37 +01:00
Matthieu Gautier 08464f23bc Better parsing of M/Counter
Mimetype may contain a parameters.
Then, the mimetype would be something like "text/html;foo=bar;foz=baz"

It will contains a `;` and `=` and it conflicts with the same operators
we use to separate the items in our list.

We have to use a more advanced algorithm which takes the context into
account.

Fix #416
2020-10-28 16:03:18 +01:00
Matthieu Gautier ef42abea4b Add some tests of parseMimetypeCounter 2020-10-28 14:44:23 +01:00
Matthieu Gautier 4407dd12bd Move mimetypeCounter parsing in its own function. 2020-10-28 14:08:06 +01:00
Matthieu Gautier d546ae38c4 Merge pull request #417 from kiwix/fix_macos_ci_install
[CI] Fix macos packages installation
2020-10-27 15:18:23 +01:00
Matthieu Gautier 7a11ec6ea4 [CI] Fix macos packages installation 2020-10-27 15:13:19 +01:00
Matthieu Gautier 095c86cf90 Merge pull request #415 from kiwix/stop_server 2020-10-16 14:12:47 +02:00
Matthieu Gautier 632583ede2 Add missing include 2020-10-07 18:43:57 +02:00
Matthieu Gautier 9c925f6778 kiwix-lib pc need libmicrohttpd 2020-10-07 17:48:30 +02:00
Matthieu Gautier 61f9d4ab3a Stop the internal server only if it exists. 2020-10-07 14:36:45 +02:00
Kelson de6b8ba4de Merge pull request #413 from hashworks/archCommunityPkg
Add repology package badge
2020-08-30 22:05:37 +02:00
hashworks ab7349dbc8 Switch to repology package badge 2020-08-30 20:59:14 +02:00
hashworks 292004703e Add shield and link to official Arch Linux package
I recently became an Arch Linux Trusted User and moved kiwix-lib
to the official community repository.
2020-08-30 13:22:13 +02:00
Kelson c3e1e46d58 No AUR libkiwix package anymore 2020-08-30 09:56:38 +02:00
Matthieu Gautier aba2f35092 New version 9.4.0 2020-08-28 16:04:40 +02:00
Matthieu Gautier b3a3dfb79f Merge pull request #411 from kiwix/fix_subprocess_destructor 2020-08-28 16:02:25 +02:00
Matthieu Gautier 470bfc3f1f Better variable name for outStream. 2020-08-28 15:27:03 +02:00
Matthieu Gautier ea3180cb8c Better error printing. 2020-08-28 15:27:03 +02:00
Matthieu Gautier 72d3f8f8e2 Fix segmentation fault with curl requests.
Use a heap allocated buffer (with lifetime of Aria2 class) instead of
a stack allocated one.

Original fix made by @ZaWertun. Kudos to him.

Fix #kiwix/kiwix-desktop#123, kiwix/kiwix-desktop#513
and kiwix/kiwix-desktop#423
2020-08-26 12:42:16 +02:00
Matthieu Gautier af9e03904c Use std::mutex and std::unique_lock instead of pthread mutex/lock.
It simplify a bit the code and ensure that mutex is correctly unlock
even in case of exception.
2020-08-26 12:30:56 +02:00
Matthieu Gautier 39611cbd60 Wait for waitingThread to exit before destroying the subprocess memory.
WaitingThread read some shared memory with the SubProcess
(`mutex`, `m_running`).
When we destroy the SubProcess, we must be sure that WaitingThread has
correctly finished else we may have invalid read/write on freed memory.
2020-08-26 12:26:04 +02:00
Kelson 4e98a76c19 Merge pull request #408 from kiwix/ppa-bionic
PPA: Build and publish packages for Ubuntu BIonic
2020-08-21 19:17:22 +02:00
Kunal Mehta 14767e6edb debian: Support already gzipped manpages
meson stopped automatically compressing in 0.49.0, but bionic uses 0.45.0.
2020-08-21 19:12:20 +02:00
Kunal Mehta 39bc8828cd PPA: Build packages for Ubuntu Bionic 2020-08-21 19:12:20 +02:00
Kelson c183f57670 Merge pull request #401 from kiwix/rgaudin/external-block-warn
Added comment marking dependency of a JS variable with warc2zim
2020-08-19 18:32:22 +02:00
renaud gaudin 009eb7f905 Added comment marking dependency of a JS variable with warc2zim
warc2zim's service worker captures all requests and then decides what to do based on
availability of the URL in the ZIM or not.
To allow the external URL blocking mechanism, it needs to known whether this was
enabled or not (as those in-iframe links won't be caught).
It detects this by looking for the `window.block_path` variable that is set in the
`block_external.js` script.

As this is fragile, we're adding a comment so that a future maintainer knows that
a third party tools relies on it.
2020-08-19 18:31:46 +02:00
Matthieu Gautier eb7a8beb77 Merge pull request #397 from kiwix/refactor_response 2020-08-13 11:22:06 +02:00
Matthieu Gautier 6f0d3003ac Remove m_compress member. 2020-08-13 11:16:41 +02:00
Matthieu Gautier ee17b0739a Fix compilation on CI native dyn.
On the CI, the native_dyn docker image is setup with a packaged version
on libmicrohttpd for which `MHD_HTTP_RANGE_NOT_SATISFIABLE` is not
defined.

When the CI will be fixed, we can revert this commit.
2020-08-13 11:16:41 +02:00
Matthieu Gautier 47436f7bdd Move some header setting in response's constructors.
It make easier to understand what is somehow constant and what depends
of the context.
2020-08-13 11:16:41 +02:00
Matthieu Gautier 3352c95314 Remove the RedirectResponse and use a basic Response with header. 2020-08-13 11:16:41 +02:00
Matthieu Gautier 77123ac74c Move the adding of 304 headers in 304 factory.
This avoid us to create a ContentResponse just to have some correct
headers.
2020-08-13 11:16:41 +02:00
Matthieu Gautier 9078f0ac6e Remove ResponseMode. 2020-08-13 11:16:41 +02:00
Matthieu Gautier 8d6567d067 Create a utility builder for 416 response.
Also add a map in the response to store specific headers.
2020-08-13 11:16:41 +02:00
Matthieu Gautier 6d5cddca12 Fix android compilation
Android clang complains about the fact it cannot move the
`std::unique_ptr<ContentResponse>` into a `std::unique_ptr<Response>&&`
(for the implicit `std::unique_ptr<Response>` constructor).
Let's help him a bit.
2020-08-13 11:16:41 +02:00
Matthieu Gautier a3939e9a05 Move all the content code in the ContentResponse. 2020-08-13 11:16:41 +02:00
Matthieu Gautier eee621d15b Move small utilities method to create response in Response class. 2020-08-13 11:16:41 +02:00
Matthieu Gautier 7b2ee37437 Move the entry response to its own class. 2020-08-13 11:16:41 +02:00
Matthieu Gautier f014fb2895 Introduce a ContentResponse.
This is only an "interface" for now as other type of response (entry) may
be "transformed" to a ContentResponse.
We cannot move all the code in the class.
2020-08-13 11:16:41 +02:00
Matthieu Gautier 1011d1ff0b Move the redirection response in its own class.
The redirection is the easiest to move, let's start with this one.
2020-08-13 11:16:41 +02:00
Matthieu Gautier 9e351b279e Remove get_default_response in favor of a static Response method.
We want to build different kind of response depending of the context.
2020-08-13 11:16:41 +02:00
Matthieu Gautier a0bdc0821c Move internalServer code into its own source files. 2020-08-13 11:16:41 +02:00
Matthieu Gautier a819d9e3e0 Make the server handle pointer to response instead of plain response.
This is a preparatory work.
We will specialize the response and so we need a pointer to response
instead of plain response.
2020-08-13 11:16:41 +02:00
rgaudin 49f3c56680 Merge pull request #400 from kiwix/rgaudin/home-favicon-size
Set fixed size for favicon in home page listing
2020-08-13 09:59:25 +02:00
renaud gaudin 1657b1744c Set fixed size for favicon in home page listing
While [spec](https://wiki.openzim.org/wiki/Metadata#Favicon) says that the favicon
should be a 48x48 image, ZIM creators might not respect it.

If a ZIM contains a larger favicon, the UI is broken. This fixes it ans ensures all
favicon have equal sizes, removing the unpleasing lack of harmony that we can see sometimes.

Note that ZIM will smaller size favicon would get blurry as those would be upscaled.
2020-08-12 14:47:37 +02:00
Matthieu Gautier a126482d69 Merge pull request #399 from MananJethwani/search_pagination 2020-08-12 11:11:40 +02:00
manan jethwani c74b935a9b added pageLength for search_pagination 2020-08-12 02:08:02 +05:30
Matthieu Gautier 015444cfd5 Merge pull request #406 from kiwix/fix_taskbar_impl 2020-08-11 18:37:42 +02:00
Matthieu Gautier a55d504017 Fix getArticleCount.
With #403, the article mimetype may be different than "text/html".
It can also be "text/html; raw=true".
(And in fact it already could have any kind of optional argument).
2020-08-11 18:27:54 +02:00
Matthieu Gautier 87b5adcaf4 Make the response responsible to detect if we must introduce taskbar.
The response detect if taskbar must be added depending of the mimetype.

Now, `set_taskbar` can be call unconditionally
(no need to check for the mimetype)

And we don't need to call set_taskbar if we have no information to set.
2020-08-11 18:27:54 +02:00
Matthieu Gautier c14c148af7 Merge pull request #405 from kiwix/support_for_meson_0_45 2020-08-11 18:27:37 +02:00
Veloman Yunkan 56e46c43f8 Upped meson version in the README 2020-08-11 18:17:18 +02:00
Veloman Yunkan c4e6313c90 x in a --> a.contains(x) in meson.build files 2020-08-11 18:17:18 +02:00
Veloman Yunkan 18e46969b7 Workaround for configure_file(copy:true)
The `copy` keyword argument of `configure_file()` first appears in
meson 0.47. Now performing file copy via python.
2020-08-11 18:17:18 +02:00
Veloman Yunkan e8cc6e4205 Copying data files via a loop 2020-08-11 18:17:18 +02:00
Veloman Yunkan 5f0bcd2bfa Renamed wikipedia_en_ray_charles_mini_2020-03.zim 2020-08-11 18:17:18 +02:00
Veloman Yunkan a3bef76083 example.zim is copied only if gtest is available 2020-08-11 18:17:18 +02:00
Kelson 66563d93cc Merge pull request #403 from kiwix/rgaudin/no-taskbar
Prevent taskbar and blocker at article level
2020-08-07 11:55:09 +02:00
renaud gaudin 3f25a3d005 Fixed #391: prevent taskbar and blocker at article level
Some HTML articles are meant to be displayed through a viewer. In this case,
we know we don't want the server to inject the taskbar nor the link blocker
because the content is not a user-ready web page but a partial element of it.

Such articles still need to be `text/html` to be parsed properly by browsers.

This changes the way we decide to display the tasbar or not.
Previously, we were adding it to every article with a MIME __starting with__ `text/html`.
Now, we're additionally preventing it on `text/html` MIME if there is a `;raw=true` string inside.

This leaves articles with MIME `text/html;raw=true` (warc2zim convention) outside
of the taskbar target.

For similar reasons, the external-link blocker is set to apply to the same set of articles.
Previously, it was applied to all articles which was an (unoticable) mistake.
2020-08-07 09:26:24 +02:00
Kelson 98a10d2ca1 Merge pull request #402 from kiwix/legoktm-aria2
Move aria2 from a build dependency to runtime
2020-08-05 23:08:21 +02:00
Kunal Mehta fdc59b1ec9 debian: Move aria2 from build dep to runtime dependency
Fixes https://github.com/kiwix/kiwix-desktop/issues/505.
2020-08-05 14:02:03 -07:00
Kunal Mehta 1b399fc0a2 README: Clarify aria2 is only a runtime dependency 2020-08-05 13:58:53 -07:00
Kelson 5f8c099829 Merge pull request #396 from MananJethwani/add_204_status_code
Added 204 code for empty return of search.
2020-08-01 10:28:56 +02:00
MananJethwani 599aaa4c1b added code for status code 204 for empty return of search. 2020-08-01 01:45:42 +05:30
Matthieu Gautier 1884081ebe Merge pull request #388 from kiwix/case_insensitive_request_headers
Request header case is ignored
2020-07-30 16:27:14 +02:00
Veloman Yunkan 3d425f44de Request header case is ignored
Originally reported against case sensitivity of the Range header
(see issue #387), this fix applies to all request headers (since
according to RFC 7230 all header fields are case-insensitive, see
https://tools.ietf.org/html/rfc7230#section-3.2). However, a
corresponding unit-test was added only for the Range header.
2020-07-30 16:01:51 +02:00
Kelson d8991c5459 Merge pull request #389 from kiwix/ppa-sync
PPA: Drop eoan and sync with proper Debian package
2020-07-24 11:21:41 +02:00
Kunal Mehta c7cb87dd57 debian: Sync with proper Debian package
* Switch to debhelper compat 13
* Increase test timeout via `meson test`
* Depend on same version of libzim as meson.build specifies
* Restore mistakenly deleted libkiwix-dev.manpages
  * We still need this file to instruct Debian to associate it with the
    libkiwix-dev package.
2020-07-24 02:01:34 -07:00
Kunal Mehta 1145af43e7 PPA: Stop building for Ubuntu eoan, its EOL
Launchpad no longer accepts uploads for eoan.
2020-07-24 01:58:30 -07:00
Kelson d5b2742fbb Merge pull request #384 from kiwix/legoktm-fail-fast
PPA: Set fail-fast: false
2020-07-24 08:45:04 +02:00
Kunal Mehta a0eb972595 PPA: Set fail-fast: false
See discussion/rationale at <https://github.com/openzim/libzim/pull/370>.
2020-07-16 06:02:41 -07:00
Matthieu Gautier 3bf70f4315 New version 9.3.1 2020-07-15 16:42:16 +02:00
Matthieu Gautier a8130bd4f2 Fix licensing in meson.build. 2020-07-15 16:41:57 +02:00
Matthieu Gautier a35d95207e Merge pull request #381 from kiwix/manpage
Have meson manage/install the kiwix-compile-resources.1 man page
2020-07-15 14:39:02 +02:00
Kunal Mehta b18c8e079e Have meson manage/install the kiwix-compile-resources.1 man page 2020-07-15 14:23:05 +02:00
Matthieu Gautier 4e9f563b45 Merge pull request #383 from kiwix/fix_path_windows 2020-07-15 12:00:58 +02:00
Matthieu Gautier 7ece383004 Add support for samba path on windows.
Fix kiwix/kiwix-desktop#429
2020-07-15 11:40:02 +02:00
Matthieu Gautier 4ca9558e30 Fix library test on windows. 2020-07-15 11:40:02 +02:00
Kelson 89582d526e Merge pull request #382 from kiwix/legoktm-sh4-atomic
Pass -latomic on sh4 architecture too
2020-07-15 06:39:40 +02:00
Kunal Mehta 5913f7efab Pass -latomic on sh4 architecture too
Same as #372.

I originally missed this because meson didn't know about sh4 until
recently (c.f. https://github.com/mesonbuild/meson/pull/7359), but
this should work fine on older meson versions too.
2020-07-14 17:22:55 -07:00
Matthieu Gautier 1367c5630f Merge pull request #368 from kiwix/jquery-ui-source
Add non-minified version of jquery-ui.js
2020-07-13 17:30:43 +02:00
Kunal Mehta 0ca27d8edf Add non-minified version of jquery-ui.js
Debian wants to have the source files for minified scripts. Also the
jqueryui.com downloader is broken, so if we ever needed to modify/fix the
library, it would be good to have a non-minified version on hand.

The non-minified version comes from
<https://github.com/components/jqueryui/blob/1.11.0/jquery-ui.js>, which
was the source for the now-deprecated bower package manager.
2020-07-13 16:45:24 +02:00
Kelson 60c6cc35d5 Merge pull request #379 from kiwix/ppa
Automatically build Debian packages and publish to PPA
2020-07-10 15:21:27 +02:00
Kunal Mehta 6b783b3998 Automatically build and publish packages via Github Actions
We can currently only build for Ubuntu versions because we're not yet
publishing libzim for Debian.

Development builds (on commits to master) will build against master libzim
while release builds (on tag pushes) will build against the most recent
release of libzim.
2020-07-10 02:48:23 -07:00
Kunal Mehta 55515f2fc6 Add Debian packaging
It may make sense to move kiwix-compile-resources.1 into the main source
and have meson manage it in the future.
2020-07-10 02:14:38 -07:00
Kelson 7fe07c65fd Merge pull request #378 from kiwix/increase-test-timeout
Increase test timeout to 160s
2020-07-10 10:16:22 +02:00
Kelson ee204a9b5e Increase test timeout to 160s 2020-07-09 10:02:36 +02:00
Kelson e743e04b94 Merge pull request #377 from kiwix/libmicrohttpd-compilation-fix
Fix compilation with libmicrohttpd v0.97.1
2020-07-08 14:56:13 +02:00
Kelson cf8e8b94eb Fix compilation with libmicrohttpd v0.97.1 2020-07-08 14:42:46 +02:00
Matthieu Gautier d9557da813 Merge pull request #376 from kiwix/dont_include_config
Do not include `kiwix_config.h` in public header.
2020-07-06 16:55:20 +02:00
Matthieu Gautier c19b983914 Do not include kiwix_config.h in public header.
This define `VERSION` and may conflict with dependent projects.

If some want to get the version of kiwix-lib they can include
`kiwix_config.h` directly.
2020-07-06 16:03:06 +02:00
Matthieu Gautier f997fdb232 Release 9.3.0 2020-07-02 15:17:46 +02:00
Matthieu Gautier f0b037f37f Merge pull request #374 from kiwix/new_api_multithread_suggestion
Add new thread safe suggestion API.
2020-07-02 14:12:12 +02:00
Matthieu Gautier 4d307e18eb Add new thread safe suggestion API.
Previous API were using an internal vector to store the suggestions search
results.

The new API takes a vector as out argument. So user can call the functions
without having to protect the search.

We should change the android API to reflect the change but it is a bit
more complex to do at JNI level. As android do not call it multithreaded
we are safe for now. And we need the new API asap for kiwix-desktop.

So we keep the same API on android for now, the new api will be made
in next version.
2020-07-01 17:16:13 +02:00
Matthieu Gautier e05bd8efd6 Release 9.2.3 2020-07-01 11:33:30 +02:00
Matthieu Gautier 71462696bd Merge pull request #372 from kiwix/link-atomic
Pass -latomic for architectures that need it
2020-06-29 14:43:16 +02:00
Kunal Mehta fb79cde729 Pass -latomic for architectures that need it
Some architectures, specifically armel, mipsel, m68k & powerpc in
Debian, need to explicitly link to atomic.

Use meson to see if the target's CPU family is one of those, and if so,
pass -latomic to the linker.

Tested on armel and mipsel machines to verify passing -latomic works, and
on armhf and amd64 to ensure normal builds aren't broken.

Fixes #371.
2020-06-29 00:18:13 -07:00
Matthieu Gautier c986290d83 Merge pull request #359 from kiwix/packaged-mustache
Support building against packaged libkainjow-mustache
2020-06-12 11:13:05 +02:00
Kunal Mehta af9afab821 Support building against packaged libkainjow-mustache
The Debian/Ubuntu package for mustache.hpp installs it to
/usr/include/kainjow/mustache.hpp. Have meson look for it in that include
directory as well before erroring out.

Fixes #318.
2020-06-12 11:09:34 +02:00
Matthieu Gautier 14af7b756e Merge pull request #366 from kiwix/fix_build_windows
Include missing `algorithm` header.
2020-06-10 16:00:36 +02:00
Matthieu Gautier ff605873ed Include missing algorithm header.
`min` and `max` functions are defined here.
2020-06-10 15:27:51 +02:00
Matthieu Gautier 6c49c7ee0a Merge pull request #362 from kiwix/build_ci_bionic 2020-06-09 12:13:34 +02:00
Matthieu Gautier 157d1664cf Fix test compilation on bionic 2020-06-09 12:10:05 +02:00
Matthieu Gautier 6f92b7e120 Build the CI also on bionic.
Bionic has a more recent compiler who will catch more issue with the
code.
2020-06-09 12:10:05 +02:00
Matthieu Gautier fd62acd232 Merge pull request #365 from kiwix/server_corner_cases_unit_test 2020-06-08 15:28:59 +02:00
Veloman Yunkan 1cdf830217 Testing of byte-range requests of 0-sized entries 2020-06-03 14:18:22 +04:00
Veloman Yunkan 0b48ab20bb Enhanced the server unit-test with corner cases 2020-06-03 13:45:31 +04:00
Matthieu Gautier 081a2b2fa6 New version 9.2.2 2020-06-03 10:47:39 +02:00
Matthieu Gautier bf93d10cde Merge pull request #364 from kiwix/issue363
Fix for the failing assertion in the ByteRange constructor
2020-06-03 10:43:16 +02:00
Veloman Yunkan 05ef5d5f51 Assertion in ByteRange allows 0-sized content
The assertion in the ByteRange constructor was written under the assumption that the content must have non-zero size. Now it allows that corner case.
2020-06-02 21:53:47 +04:00
Matthieu Gautier 4cdae3ca98 New version 9.2.1 2020-06-02 10:18:12 +02:00
Matthieu Gautier 7dcaeed33a Merge pull request #360 from kiwix/http_byte_range 2020-06-01 17:41:59 +02:00
Veloman Yunkan f52b220d01 Dropped RequestContext::has_range() 2020-05-26 14:10:26 +04:00
Veloman Yunkan 50a850f3a9 Fixed a comment 2020-05-26 14:04:18 +04:00
Veloman Yunkan 886ae17274 Fixed a CodeFactor issue 2020-05-26 13:59:47 +04:00
Veloman Yunkan a9b6d481cc ServerTest.RangeHasPrecedenceOverCompression 2020-05-26 13:58:20 +04:00
Veloman Yunkan 85d6daabac Rolled back minor unneeded changes 2020-05-26 13:10:50 +04:00
Veloman Yunkan 5f1918d005 Split a long line 2020-05-26 13:04:03 +04:00
Veloman Yunkan 16bd79fa1b Final clean-up of byte_range.{h,cpp} 2020-05-26 12:50:08 +04:00
Veloman Yunkan c2ebdefe8d Handling of unsatisfiable ranges 2020-05-26 02:11:26 +04:00
Veloman Yunkan 37032892a4 Fixed compilation error under win32_*
ERROR is a macro under Windows
2020-05-26 01:58:17 +04:00
Veloman Yunkan 6b43438b74 Fixed compilation error under native_dyn
MHD_HTTP_RANGE_NOT_SATISFIABLE is not defined in the older version of
libmicrohttpd (that is used under CI/Linux native_dyn).
2020-05-26 01:54:36 +04:00
Veloman Yunkan 7301bf89bb Some refactoring of byte-range parsing 2020-05-26 01:50:29 +04:00
Veloman Yunkan ff23b28e7c Removed unnecessary qualifier 2020-05-26 01:41:37 +04:00
Veloman Yunkan 931e95f391 Invalid byte ranges result in 416 responses 2020-05-26 01:40:07 +04:00
Veloman Yunkan f7571b5b69 Content-Range header is set only for partial content 2020-05-25 17:42:18 +04:00
Veloman Yunkan 801ad18a89 ByteRange::resolve() 2020-05-25 17:27:35 +04:00
Veloman Yunkan 67a347c0c4 Moved byte-range parsing to byte_range.cpp 2020-05-25 17:21:10 +04:00
Veloman Yunkan 693905eb68 Default constructed ByteRange is a full range 2020-05-25 17:17:56 +04:00
Veloman Yunkan f3e79c6b4c Introduced src/server/byte_range.cpp 2020-05-25 16:43:44 +04:00
Veloman Yunkan 52f207eaa6 Support for single-ended byte ranges 2020-05-25 16:37:01 +04:00
Veloman Yunkan 67294217a8 ByteRange::Kind 2020-05-25 16:23:44 +04:00
Veloman Yunkan d111a40ce8 Response::m_byteRange 2020-05-23 20:35:22 +04:00
Veloman Yunkan 0c5bb3fcfe Moved ByteRange to a header file of its own 2020-05-23 20:08:53 +04:00
Veloman Yunkan 3fba8c20a0 Converted RequestContext::ByteRange to a class
Also renamed the `range_pair` data member of `RequestContext` to `byteRange_`
2020-05-23 19:59:47 +04:00
Veloman Yunkan 54db6049b7 Byte-range parsing not exposed in the header file 2020-05-23 18:58:19 +04:00
Veloman Yunkan 81c38d6b2b parse_byte_range() without side-effects 2020-05-23 18:53:16 +04:00
Veloman Yunkan e6a86c02ae Got rid of RequestContext::accept_range 2020-05-23 17:15:42 +04:00
Veloman Yunkan a0f7f32570 Re-ordered function definitions 2020-05-23 17:11:26 +04:00
Veloman Yunkan c39fce8839 RequestContext::parse_byte_range() 2020-05-23 17:09:51 +04:00
Veloman Yunkan bd2d0bc489 Unit-test for valid single range requests 2020-05-22 17:39:00 +04:00
Veloman Yunkan de37489c53 Range header starts with a unit spec
After this commit valid ranges of the form "bytes=firstbyte-lastbyte" should
be handled correctly.
2020-05-22 17:17:31 +04:00
Veloman Yunkan 2a35a86de6 Fixed the size value used creating a response
In case of a partial response the size of the response is different
from the served entry size.
2020-05-22 16:49:35 +04:00
Veloman Yunkan 0a30a77c08 Handling of out of bound byte ranges 2020-05-22 16:46:38 +04:00
Veloman Yunkan 1a99bacfe3 Byte ranges are inclusive
The second component of a byte range, if present, designates the
index of the last byte to be included in the partial response.
2020-05-22 16:30:43 +04:00
Matthieu Gautier 2bf35f1651 New version 9.2 2020-05-18 15:23:01 +02:00
Matthieu Gautier 48cc277468 Merge pull request #356 from kiwix/fix_test_httplib 2020-05-18 14:44:18 +02:00
Matthieu Gautier d8498fd655 Do not build server test on windows.
On the appveyor CI, the link of the `server` test fails with
`libmicrohttpd`.

Do not build the test on windows to not break the CI.
2020-05-18 13:13:17 +02:00
Matthieu Gautier 7ec8e33b83 Fix include of httplib.h on windows.
On windows, `httplib.h` must be included before `windows.h`
We do not include directly `windows.h` in the test but it is included
indirectly by other headers.

Let's include httplib first.
2020-05-18 11:16:25 +02:00
Kelson 8eb2d0c2a1 Explain how to run automated tests 2020-05-18 08:37:51 +02:00
Kelson 5995cc276d Merge pull request #355 from kiwix/more-often-http-compression
Add two OPDS related mime-types to compress for HTTP
2020-05-18 08:33:44 +02:00
Kelson 94c2ab4395 Add two OPDS related mime-types to compress for HTTP 2020-05-18 08:19:51 +02:00
Kelson 15179db945 Merge pull request #354 from kiwix/small-http-header-beautification
Small HTTP header beautification
2020-05-17 21:50:26 +02:00
Kelson 0f07cab920 Small HTTP header beautification 2020-05-17 20:19:19 +02:00
Kelson 4f8b397081 Merge pull request #352 from kiwix/small-compilation-error-fix
Fix small compilation error in tests
2020-05-17 18:37:53 +02:00
Kelson 2df74d9755 Fix small compilation error in tests 2020-05-17 16:47:21 +02:00
Matthieu Gautier 0b25492edc Merge pull request #348 from kiwix/http_head_and_etag 2020-05-15 13:55:50 +02:00
Veloman Yunkan 5f0a9d0b08 Added a comment clarifying a non-obvious case 2020-05-15 15:17:04 +04:00
Veloman Yunkan 54f5dbbd35 Handling of If-None-Match conditional requests 2020-05-14 17:01:22 +04:00
Veloman Yunkan 95a5cde359 ETags are set in the response as needed
Also added server-unit tests related to ETags in the response.
2020-05-14 17:01:22 +04:00
Veloman Yunkan 3d08ef43f2 HEAD request is not rejected
libmicrohttpd handles HEAD requests by dropping the body of the response
(if any). Hence letting a HEAD request through into the code that
processes GET requests is safe.

Also added server unit-tests related to the handling of HEAD requests.
2020-05-14 17:01:22 +04:00
Matthieu Gautier 381ff186cb Merge pull request #349 from kiwix/fix_python 2020-05-04 10:55:55 +02:00
Matthieu Gautier e32fa28a6c Use python3 instead of python.
`python` binary is not installed on all platform.
But `python3` is (because meson is python3).
And the script we launch is python3 so use the correct version.
2020-05-04 10:52:11 +02:00
Matthieu Gautier 1842e8f51c Merge pull request #345 from kiwix/server_refactoring 2020-04-29 17:38:41 +02:00
Veloman Yunkan bfa51c2d87 Refactoring: got rid of duplicate get_mime_type() 2020-04-29 18:33:25 +04:00
Veloman Yunkan 81e781133d Refactoring: utilized is_compressible_mime_type() 2020-04-29 18:33:01 +04:00
Veloman Yunkan 9ec7757efe Refactoring: smart Response::set_entry()
Response::set_entry() was upgraded from a simple setter to a method
performing certain business logic that was previously taken care of by
InternalServer::handle_content().
2020-04-29 18:22:15 +04:00
Veloman Yunkan 7bd7ec4937 Refactoring: preparing to move some code 2020-04-29 18:22:15 +04:00
Veloman Yunkan 14d8583c83 Refactoring in InternalServer::handle_content()
Deduplicated common code found in the two branches of the last
if(){}else{} statement in InternalServer::handle_content().
2020-04-29 18:22:15 +04:00
Veloman Yunkan a004d96cd7 Refactoring: extracted get_range_len() 2020-04-29 18:22:15 +04:00
Veloman Yunkan 21c6de2f80 Refactoring: split Response::create_mhd_response()
The changes are easier to understand in ignore-white-space mode
(git diff -w, git show -w).
2020-04-29 18:22:15 +04:00
Veloman Yunkan a8e78f27e1 Refactoring: extracted Response::create_mhd_response() 2020-04-29 18:22:15 +04:00
Veloman Yunkan 6c7ab6ff54 Refactoring: moved local variable declarations 2020-04-29 18:21:40 +04:00
Veloman Yunkan 659ee6ba71 Refactoring: extracted InternalServer::build_redirect() 2020-04-29 16:08:10 +04:00
Veloman Yunkan 83ee8dec15 Made InternalServer::get_default_response() const 2020-04-29 16:08:10 +04:00
Veloman Yunkan 87cbbed9e3 Refactoring: extracted is_compressible_mime_type() 2020-04-29 16:08:10 +04:00
Veloman Yunkan a058520628 Refactoring: extracted get_mime_type() 2020-04-29 16:08:10 +04:00
Veloman Yunkan 1ef5ebfb52 Refactoring: extracted InternalServer::get_reader() 2020-04-29 16:08:10 +04:00
Veloman Yunkan bbc06931ad Refactoring: extracted get_book_name() 2020-04-29 16:08:10 +04:00
Veloman Yunkan 2d3bf9b981 Refactoring: extracted InternalServer::homepage_data()
Also typedef'ed kainjow::mustache::data as MustacheData
2020-04-29 16:08:10 +04:00
Veloman Yunkan fd80f2a89f Refactoring: extracted fullURL2LocalURL()
Also dropped RequestContex::valid_url
2020-04-29 16:08:10 +04:00
Veloman Yunkan abb3dec700 Refactoring: extracted str2RequestMethod() 2020-04-29 16:08:10 +04:00
Kelson 80fcbceeb3 Merge pull request #344 from kiwix/server_unittests
Server unittests
2020-04-29 14:02:57 +02:00
Veloman Yunkan 9a893a854e Revert "Server can be started on a random free port"
This change failed to build under the following platforms
due to an older version of libmicrohttpd missing support for
the MHD_DAEMON_INFO_BIND_PORT query:
- Linux (native_dyn)
- Linux (win32_dyn)
2020-04-29 15:40:02 +04:00
Veloman Yunkan b0f65a02f2 Server can be started on a random free port
If the server is started with a port value of 0, it binds to a random
free port. The bound port can be obtained with a `getPort()` method.
2020-04-29 15:40:02 +04:00
Veloman Yunkan 9bf6d0621f Introducing 1st real unit test of the server
Added a new unit test 'test/server.cpp'. The pre-existing unit test
test/kiwixserve.cpp tests kiwixlib indirectly by running the kiwix-serve
executable which may be built with another version of the library.

Included with this commit is the cpp-httplib C++ HTTP/HTTPS library
(https://github.com/yhirose/cpp-httplib, v0.5.11).
The new file test/httplib.h was copied from
https://raw.githubusercontent.com/yhirose/cpp-httplib/v0.5.11/httplib.h
2020-04-29 15:39:18 +04:00
Veloman Yunkan fcadacb0ad Resources are compiled as needed
Correct dependencies are set up for resource compilation and
build_always_stale is set to false.
2020-04-28 19:46:14 +04:00
Matthieu Gautier 8f07689c57 Merge pull request #346 from kiwix/unit-test 2020-04-28 11:04:58 +02:00
luddens 0630298fb9 Manager::addBookFromPathAndGetId unit test 2020-04-28 10:56:12 +02:00
Matthieu Gautier 9f61301423 New version 9.1.2 2020-04-20 15:31:14 +02:00
Matthieu Gautier 9c101daad7 Merge pull request #341 from kiwix/fix-addBookFromPathAndGetId 2020-04-20 15:27:57 +02:00
luddens 0586ef6d41 fix open external zim
Check if the parameter `pathToSave` is empty before use it otherwise the
book path is empty too, which causes crash on opening external zim files
2020-04-20 15:22:36 +02:00
Matthieu Gautier 8fc42558d3 New version 9.1.1 2020-04-17 17:36:11 +02:00
Matthieu Gautier 5d98a6964e Merge pull request #343 from kiwix/fix_datadir_windows
Fix datadir windows
2020-04-15 10:18:51 +02:00
Matthieu Gautier 9d8bf8ddcb Create the dataDirectory before returning its path. 2020-04-15 08:24:55 +02:00
Matthieu Gautier 4c8aad0e68 Do not use std::fstream has it doesn't support wchar path.
This is surprising, but C++11 fstream doesn't have a constructor
that take wchar as path.
So, on windows, we cannot open a stream on a path containing non ascii
char. VC++ provide an extension for that, but it is not standard and
g++ mingwin doesn't provide it.

So move all our write/read tools function to the plain old c versions,
using _wopen to open wide path on windows.
2020-04-14 18:13:35 +02:00
Matthieu Gautier eb6f0f710c Correctly detetect the dataDir on windows.
We must use the wide version of the getenv to correctly handle the case
we have accents in the user directory.

This also change the default dataDirectory on windows from $APPDATA to
$APPDATA/kiwix.
2020-04-14 12:12:34 +02:00
Matthieu Gautier d9d2a702ef Merge pull request #342 from kiwix/fix_iterator
Adapt to new libzim api.
2020-04-13 16:18:57 +02:00
Matthieu Gautier cbf5bd57a8 Adapt to new libzim api.
It is not possible to create a iterator without argument anymore.
2020-04-13 16:06:17 +02:00
Matthieu Gautier 2bf6b04726 Update minimum version of libzim. 2020-04-08 18:03:18 +02:00
Matthieu Gautier 12a0660342 New version 9.1.0 2020-04-08 15:38:25 +02:00
Matthieu Gautier ab478ed4cf Merge pull request #337 from kiwix/fix_book_articlecount
Fix book articlecount
2020-04-07 12:46:56 +02:00
Matthieu Gautier 533541cf45 Write the articleCount and mediaCount metadata in the OPDS stream.
This is not standard OPDS. But clients need this information.
2020-04-07 12:22:44 +02:00
Matthieu Gautier bab0fd3d4f Correctly initialize members' value of book.
Fix #333
2020-04-07 12:21:36 +02:00
Kelson 375792a686 Merge pull request #335 from kiwix/fix_taskbar
attach taskbar to <head> instead of <head>\n
2020-04-03 16:56:55 +02:00
renaud gaudin 7155c788e2 attach taskbar to <head> instead of <head>\n
Fixed a regression introduced in block-external-links feature.

For cleaner source, the taskbar (and the block-external JS file) were both
attached to `<head>\n`.
Unfortunately, this isn't safe enough as some ZIM files might have all kinds of HTML
syntax. Sotoki for instance have no CR after head, rendering the attachment impossible.

Note: realizing this method is somehow fragile as any HTML content with extra attribute
on the `<head>` tag or without a `<head>` tag would break the taskbar and the block external feature.
2020-04-03 16:53:43 +02:00
Kelson 3ac926b39b Merge pull request #331 from kiwix/readme-mustache
add required info to README
2020-04-03 16:41:37 +02:00
renaud gaudin ea3444e2fe add required info to README
Mustache 4 was release in late october 2019 and is not compatible with kiwix-lib as is.
Replacement in taskbar is messed-up and breaks suggestions.
Until this is fixed/adapted, inform users to use version 3.
2020-04-03 16:38:16 +02:00
Kelson 083c06d170 Merge pull request #336 from kiwix/better-ci-event
Run Github actions on any push (not only in PR)
2020-04-03 16:37:01 +02:00
Kelson 286fbba9f6 Run Github actions on any push (not only in PR) 2020-04-03 16:32:49 +02:00
Kelson 778603e1bf Use Github Actions CI badge (instead of Travis CI) 2020-04-03 16:30:42 +02:00
Kelson 411d4b0779 Merge pull request #334 from kiwix/fix-external
fix external link blocking for nested elems in link
2020-04-01 20:05:24 +02:00
renaud gaudin bce0e8c37c fix external link blocking for nested elems in link
if a link contains nested elements like `<a href="http://somewhere"><strong>goto</strong></a>`
then the link is trigger by the `<strong />` element which has no `href` attribute.
We were thus releasing the event in this case, resulting in legitimate external links
not blocked.

We are now looking for the closest `<a />` parent (might be self) to retrieve the `href`
attribute and capture if necessary.
2020-04-01 17:50:54 +00:00
Matthieu Gautier 507002d34e Merge pull request #330 from kiwix/block-external-links
Add external links blocking in serve
2020-03-30 16:57:08 +02:00
renaud gaudin 34a8144f51 cleaned-up external link blocker page
- removed useless JS/CSS
- set specific title
2020-03-30 14:42:51 +00:00
renaud gaudin 4709a42f4f disable external links blocking on 500 handler 2020-03-30 14:42:37 +00:00
renaud gaudin d04d9bf7f3 Unblock external link in catch page in JS code
Instead of disabling the blocking for the handler, the JS code detects it is
displaying the handler and allows external links to go through
2020-03-27 12:26:22 +00:00
renaud gaudin 412f0d9c61 moved blockExternalLink outside of taskbar
- `setBlockExternalLinks()` on server
- zero-dependency JS code
- JS script added in `inject_externallinks_blocker()`
- changed URL to `/catch/external?source=<source>`
2020-03-27 11:25:39 +00:00
renaud gaudin 0ad8bf45fc Add external links blocking in serve
In many use cases, it is not wanted to have user accidentaly click on external links
and leave the served ZIM content.
This could be because the result is unpredictible (reader not implementing this properly)
or because the serve user knows there's no backup internet connexion or because there is
an induced cost behind external links that doesn't affect served content.

using a new flag (`blockExternalLinks`) on `Response`/`setTaskBar`, a piece of JS code
is injected into the taskbar code.
This code adds a JS handler on all link click events and verifies the destination.
If the destination appears to be an external link (1), the link target is changed to
a specific URL:

```
/external?source=<original_uri>
```

(1) external is a link that's not on the same origin and starts with either `http:` `https:` or `//`.

Server implements a new handler on `/external` that displays a new page (`captured_external.html`)
which returns a generic message explaining the situation and offering to click on the link
again should the user really want to.
This is done by specifically asking `set_taskbar` to not block external requests on that page.

This approach allows integrators using a reverse proxy to handle that endpoint differently (rebrand it)

1. `Server` now has an `m_blockExternalLinks` defaulting to `false`
1. `Server.setTaskbar` is extended to support an additional bool to set the variable.
1. `Response` now has an `m_blockExternalLinks`
1. `Response` constr expects an additional bool for `blockExternalLinks`.
1. `Response.set_taskbar` is extended to support an additional bool to set the variable.
1. JNI/Java Wrapper reflects the extensions.
1. New resource file `templates/block_external.js` (included in head_part). Should it be in skin?
1. New resource file `templates/captured_external.html` for `handle_captured_external()`
1. Added a comment on `head_part.html` to help with JS insertion at the right place
1. `introduce_taskbar()` conditionnaly inserts the JS inside the taskbar
2020-03-26 12:06:36 +00:00
Matthieu Gautier 3ab3ffe3ea Merge pull request #329 from kiwix/getBookByPath
Get book by path
2020-03-06 12:12:43 +01:00
Matthieu Gautier 064d5f3fa6 Make the search argument constant. 2020-03-06 12:08:05 +01:00
Matthieu Gautier 46626a3f98 Add the method get bookByPath in library. 2020-03-06 12:08:05 +01:00
Matthieu Gautier 90ba27fbab Merge pull request #328 from kiwix/java_article_size
[JAVA] Add a method to get the size of an article.
2020-03-04 17:10:18 +01:00
Matthieu Gautier 76c293e403 [JAVA] Add a method to get the size of an article.
Fix #327
2020-03-04 16:40:03 +01:00
Matthieu Gautier 78e57c1a51 New version 9.0.1 2020-02-21 14:58:04 +01:00
Matthieu Gautier 7c49dc6af9 Merge pull request #326 from kiwix/fix_pair_size
[JAVA] Use a long to store the offset of a article in the zim file.
2020-02-19 14:58:43 +01:00
Matthieu Gautier 2e60a088ab [JAVA] Use a long to store the offset of a article in the zim file.
Fixes kiwix/kiwix-android#1769
2020-02-19 14:27:51 +01:00
Matthieu Gautier 9ab0f825f4 Merge pull request #325 from kiwix/new_version
New version 9.0.0
2020-02-12 14:54:12 +01:00
Matthieu Gautier 411ca28598 New version 9.0.0 2020-02-12 14:48:03 +01:00
Matthieu Gautier cc2b5e63ca Merge pull request #323 from kiwix/fix_wrapper
Fix wrapper
2020-02-12 10:47:29 +01:00
Matthieu Gautier ea29557a33 [Java] Add a wrapper on method to update book from another book or reader. 2020-02-11 17:44:14 +01:00
Matthieu Gautier b53f531f2b Fix typo getTagStr in the wrapper 2020-02-10 17:25:31 +01:00
Matthieu Gautier bd74ebed1e Merge pull request #320 from kiwix/path_win
Fix launching command with path containing spaces.
2020-02-07 13:15:24 +01:00
Matthieu Gautier 1632e9c55b Fix launching command with path containing spaces.
We must correctly quote path with space on windows.
This is needed as we can't launch command using a array of string on
windows but by giving only one string using space as separator.

Fix kiwix/kiwix-desktop#268
2020-02-06 11:46:33 +01:00
Kelson 6dd6a5dd80 Github Kiwix Sponsoring page link 2020-02-01 17:44:42 +01:00
Kelson b65b90d78c Merge pull request #319 from kiwix/fix-missing-stdexcept-include
Include stdexcept to fix GCC v10 compilation
2020-02-01 17:20:53 +01:00
Kelson 6a975994cc Include stdexcept to fix GCC v10 compilation 2020-02-01 13:52:27 +01:00
Matthieu Gautier 3ae596783d Name size filtering (#315)
Name size filtering
2020-01-30 19:13:55 +01:00
Matthieu Gautier ce6e956434 [OPDS] Add the url argument to filter by size and name.
Fix kiwix/kiwix-tools#231
2020-01-30 19:02:33 +01:00
Matthieu Gautier f560a1f815 Be able to filter the books by name. 2020-01-30 19:02:33 +01:00
Matthieu Gautier d14ba0c2e8 Merge pull request #314 from kiwix/trust_library
Trust the library.xml information by default.
2020-01-30 19:02:13 +01:00
Matthieu Gautier 34257cfc1f Trust the library.xml information by default.
Do not try to read the zim file and update the book when parsing a
library.xml.
Needed by kiwix/kiwix-tools#319
2020-01-30 18:22:07 +01:00
Matthieu Gautier 8f990feabb Merge pull request #316 from kiwix/tagging_system
Tagging system
2020-01-30 18:21:28 +01:00
Matthieu Gautier fff2524ee2 Fix opensearch description. 2020-01-30 17:48:56 +01:00
Matthieu Gautier a756e7f8f3 Add flavour attribute to book.
Fix #259
Fix kiwix/kiwix-tools#316
2020-01-30 17:48:56 +01:00
Matthieu Gautier bc257d2d6d Add method to get value of tag from a book.
Only the `getTagStr` method is available on android because we need a
proper exception handling on wrapping side.

Fix #298
2020-01-30 17:48:56 +01:00
Matthieu Gautier 7275f9b8e3 Move function to convert and use tags inside otherTools. 2020-01-30 17:48:56 +01:00
Matthieu Gautier b63827196c Small fixes (#313)
Small fixes
2020-01-30 17:23:30 +01:00
Matthieu Gautier 2881face70 Add missing setting of attribute. 2020-01-30 15:42:54 +01:00
Matthieu Gautier 77ba09c310 Reorder setting and dumper of book attribute.
No real change. Reordering setting and dumping of attribute in the same
order (mostly) they are declared in book.h make it easier to detect missing
attribute.
2020-01-30 15:42:54 +01:00
Matthieu Gautier 49aa0fbb9f Use a macro to write the filters. 2020-01-30 15:42:54 +01:00
Matthieu Gautier 7846b45bef Fix opds filtering by tag. 2020-01-30 15:42:54 +01:00
Matthieu Gautier 7e26f3502d Fix opds dumper/parser.
Add missing attributes.
2020-01-30 15:42:54 +01:00
Matthieu Gautier 47a866400c Add parameter options to start a download with aria2 (#310)
Add parameter options to start a download with aria2
2020-01-30 15:42:40 +01:00
luddens 4b6c26bd0b add parameter option to start a download with aria2
Downloader::startDownload has a new parameter option which is a vector of
pair that represents the options that can be set for adding a uri with aria2
with the function Aria2::addUri.

Aria2::addUri uses this parameter to set the struct of parameters for the
aria2 command
2020-01-29 15:38:09 +01:00
Matthieu Gautier 94c47383a9 Remove useless Aria2c error handling functions (#306)
Remove useless Aria2c error handling functions
2020-01-28 17:36:54 +01:00
luddens 6bcecc2677 remove useless error handling functions
Some of the changes from https://github.com/kiwix/kiwix-lib/pull/292
that doesn't work properly are removed
2020-01-28 16:58:55 +01:00
Matthieu Gautier e20c3520dc Android manager (#311)
Android manager
2020-01-28 15:48:38 +01:00
Matthieu Gautier 24fb1868d7 Fix typo in metadata. 2020-01-28 12:08:18 +01:00
Matthieu Gautier 82afb804e1 Add a small java test on the kiwix-lib.
Will the compilation should be made by meson.
It seems it is not possible to specify a existing jar
to link with. Use a custom script for now.
2020-01-28 12:08:18 +01:00
Matthieu Gautier 0951546356 Create the jar library when creating the java wrapper. 2020-01-28 12:08:18 +01:00
Matthieu Gautier f09c739c1f Be able to create a wrapper for java.
Android is a specific wrapper.
Java is another one.
2020-01-28 12:08:18 +01:00
Matthieu Gautier df9ddd5451 Use correct mutex on android and java. 2020-01-28 12:08:18 +01:00
Matthieu Gautier fe513951d3 Use a macro to print error log.
This allow use to compile the JNI wrapper not for
android.
2020-01-28 12:08:18 +01:00
Matthieu Gautier 7f0d509a88 Add the filter functionality. 2020-01-28 12:08:18 +01:00
Matthieu Gautier 54f671b2f1 Add some methods to get information from the library.
Else, the library is useless.
2020-01-28 12:08:18 +01:00
Matthieu Gautier c2c89c6c86 Rename the JNIKiwixLibrary class to Library.
This mainly use the "new memory system". No need to call dispose function.
Rename the class to Library to conform with the naming semantics
(JNIKiwix* use old memory system)
2020-01-28 12:08:18 +01:00
Matthieu Gautier 75652d0e9f WIP Add a wrapper around the kiwix::manager class.
The JNIKiwixManager is used to manage (insertion of book in) the library.

It is created, as needed, using an existing Library as input.
It is then used to add books, parse library.xml or opds content.
Then it can be destruct (and must be) with the `dispose` method.

```java
library = JNILibrary(...);
manager = JNIManager(library);
manager.parseOpds(opdscontent);
manager.dispose();
// library contains the books declared in the opds content.
// Use the library methods to get the books' info.
```
2020-01-28 12:08:18 +01:00
Matthieu Gautier 6535dc2e38 Add a wrapper for the Book class. 2020-01-28 12:08:18 +01:00
Matthieu Gautier 6b2f768c8f Use template function c2jni to convert c++ type to jni. 2020-01-28 12:08:18 +01:00
Matthieu Gautier 6099c3113f Readd code coverage (#312)
Readd code coverage
2020-01-28 10:53:36 +01:00
Matthieu Gautier 21d8a6952f Readd code coverage 2020-01-27 18:05:12 +01:00
Matthieu Gautier b84f4e03ea update book even if the members aren't empty (#302)
update book even if the members aren't empty
2020-01-27 17:58:41 +01:00
luddens ff21a095cb update book even if the members aren't empty
remove the conditions to always update the book
2020-01-27 17:50:44 +01:00
Matthieu Gautier fa091a19c6 Merge pull request #309 from kiwix/github-action
Use github actions to run the CI.
2020-01-21 18:18:56 +01:00
Matthieu Gautier e3ba9fa5cc Use github actions to run the CI. 2020-01-21 18:10:33 +01:00
Matthieu Gautier 560f67522f Do not build tests if we are cross-compiling (#308)
Do not build tests if we are cross-compiling
2020-01-21 11:11:22 +01:00
Matthieu Gautier 11118efd84 Do not build tests if we are cross-compiling 2020-01-21 10:58:43 +01:00
Matthieu Gautier 9c2bc6affc Fix tests. (#307)
Fix tests.
2020-01-20 17:12:58 +01:00
Matthieu Gautier 4fe31a20e3 Fix tests.
As we use the main library of gtest (if already installed)
we don't need to (and must not) define a main function for the tests.

Does the same (use main library) if we use the subproject.
2020-01-20 17:00:18 +01:00
Matthieu Gautier 0f99c1ad20 Win library path (#305)
Win library path
2020-01-13 17:12:16 +01:00
Matthieu Gautier 91db055d86 Remove function to read file using a native path.
All path must be utf8. This is already the case in all our project.
(If this not the case, this is a bug)

So we don't need to have a version with a native and utf8 path.
2020-01-13 16:59:58 +01:00
Matthieu Gautier 5540149e2b Correctly open the library path on windows.
We need to convert the path to wstring on Windows to handle directory
with accented characters.

Fix kiwix-desktop#269
2020-01-13 16:54:09 +01:00
Matthieu Gautier 7c7e351d34 Add missing function's declarations to convert path for windows. 2020-01-13 16:51:48 +01:00
Matthieu Gautier c5051b343e Catalog empty search (#304)
Catalog empty search
2020-01-13 14:09:33 +01:00
Matthieu Gautier 02a0d592f9 Install python3 in Travis MacOS
For some reason, `homebrew install gcovr` now install python3 as
dependency.
This is a dependency since a long time, I don't know why it was not
installing it before.

But the installation fails because it cannot link correctly python3
because python2 is already installed.

Then meson, when it tries to run the conversion script, fails because
the script cannot find python3.

The solution I've found is to unlink python2 and relink python3 to have
a correct installation of python3.
2020-01-13 13:29:18 +01:00
Matthieu Gautier 071e9e3fec Correctly filter the catalog when we don't what to filter.
Set the different filter's fields only when we are requested to filter
them. Else, we ends to requests that some fields are empty.

If the request has no argument, we raise an exception (catched) and so
we don't set the corresponding field in the filter.

Fix #303
2020-01-07 17:29:43 +01:00
Matthieu Gautier 4a01303438 Correctly set the id of the opds stream.
Set the id of the stream *after* the uuid is generated.
2020-01-07 17:29:29 +01:00
Kelson 8095a87bf1 Bump-up version to 8.2.2 and update Changelog 2019-12-08 12:12:39 +01:00
Kelson bb55527508 Merge pull request #301 from kiwix/remove-trailing-spaces
Remove trailing spaces
2019-12-08 12:07:21 +01:00
Kelson b7c5e5f339 Remove trailing spaces 2019-12-08 11:52:16 +01:00
Kelson 316deeb485 Merge pull request #300 from kiwix/exec-perm
Add execution permission to a few scripts
2019-12-08 10:03:57 +01:00
Kelson 721d981825 Add execution permission to a few scripts 2019-12-07 14:00:22 +01:00
Kelson 2244074f3c travis-ci.org -> travis-ci.com 2019-12-05 08:10:56 +01:00
Kelson 0a1e01eb2b Update install_deps.sh 2019-11-29 17:28:25 +01:00
Kelson abd2fa3bf3 Bump-up to 8.2.1 in build.gradle 2019-11-27 19:15:24 +01:00
Kelson ea3349f37c Merge pull request #297 from kiwix/reintroduce-taskbar
Reintroduce taskbar
2019-11-26 08:55:19 -05:00
Kelson e3c6ca0d1b Bump-up version to 8.2.1 2019-11-26 11:54:39 +01:00
Kelson 52e165cf78 Reintroduce kiwix-serve taskbar 2019-11-26 11:54:00 +01:00
Kelson 3b7c805183 Bump-up version to 8.2.0 2019-11-20 13:07:28 +01:00
Kelson 9c4867a95a Update Changelog 2019-11-20 13:06:24 +01:00
Kelson 223f7ee78a Add default Github configuration 2019-11-20 06:12:08 +01:00
Kelson 20690bd5f5 Merge pull request #294 from kiwix/remove-absolute-url-support
Remove absolute internal URL support
2019-11-08 15:29:40 +01:00
Emmanuel Engelhart de7b7c34b5 Remove absolute internal URL support 2019-11-07 18:05:58 +01:00
Kelson f0ac66aea1 Merge pull request #292 from kiwix/aria2-comment
More error handling for aria2 cmd
2019-11-01 15:40:51 +01:00
luddens 20a2c78733 add get aria2 launch cmd method 2019-11-01 15:27:21 +01:00
luddens 9850be7267 add Curl error message 2019-11-01 15:27:21 +01:00
luddens 0dd996c6a3 add try catch around aria2 first commands 2019-11-01 15:27:21 +01:00
Kelson 2500cc8e63 Merge pull request #288 from kiwix/get-bookmarks-api
Add a parameter to getBookmarks fct to get valid bookmarks only
2019-10-31 14:38:50 +01:00
luddens bd6797143c add getBookmarks test 2019-10-31 15:01:52 +02:00
luddens c9a15c9961 Add a parameter to getBookmarks fct to get valid bookmarks only
The default value of this parameter is false, in this case all the bookmarks
are returned, otherwise only those who are related to books of the library.
2019-10-31 14:05:21 +02:00
Kelson f1d55f8e86 Merge pull request #290 from kiwix/set-port-kiwixserve
add setPort() method
2019-10-28 16:41:19 +01:00
luddens a2c2955f41 add kiwixserve unit test 2019-10-28 16:00:26 +01:00
luddens 9975e0b369 add setPort() method 2019-10-28 15:56:49 +01:00
Kelson efe1c2dea3 Merge pull request #289 from Aditya-Sood/kiwix-android/issue/765
Fixes kiwix-android issue#765
2019-10-03 11:25:18 +01:00
Aditya-Sood 2af9ba4eab Readd original getNextSuggestion() 2019-10-01 13:30:35 +05:30
Aditya-Sood c007373b46 Re-add comment 2019-10-01 13:30:34 +05:30
Aditya-Sood e1acf9acff Code & local repository cleanup 2019-10-01 13:30:34 +05:30
Aditya-Sood daaadf3e1c Comment out previous definitions 2019-10-01 13:30:34 +05:30
Aditya-Sood 74bd482335 Preliminary work 2019-10-01 13:30:34 +05:30
Matthieu Gautier 2aebffb27c New version 8.1.0 2019-09-26 15:56:30 +02:00
Kelson da247b3242 Merge pull request #287 from kiwix/codecov-badge
Add Codecov badge to README
2019-09-26 13:40:57 +03:00
Kelson f85ec9ea6f Add Codecov badge to README 2019-09-26 12:37:57 +02:00
Matthieu Gautier b4fac9d0df Remove test directory from codecoverage (#286)
Remove test directory from codecoverage
2019-09-26 12:14:03 +02:00
Matthieu Gautier 4f2ede80e5 Remove test directory from codecoverage 2019-09-26 12:00:33 +02:00
Matthieu Gautier c2ecb9d126 Add code coverage in travis CI. (#285)
Add code coverage in travis CI.
2019-09-26 11:58:49 +02:00
Matthieu Gautier 5883dba0ef Add code coverage in travis CI.
Fix #284
2019-09-26 11:34:35 +02:00
Matthieu Gautier 7ad6aedd66 Convert path get from windows environment to utf8. (#283)
Convert path get from windows environment to utf8.
2019-09-25 18:13:59 +02:00
Matthieu Gautier 67170709bb Convert path get from windows environment to utf8.
Fix kiwix/kiwix-desktop#203
2019-09-25 18:07:42 +02:00
Matthieu Gautier dfd16155af Add missing implementation of android's getArticleCount and getM… (#282)
Add missing implementation of android's getArticleCount and getMediaCount.
2019-09-24 11:57:00 +02:00
Matthieu Gautier 0db06d98a8 Add missing implementation of android's getArticleCount and getMediaCount.
Fix #281
2019-09-24 11:47:05 +02:00
Matthieu Gautier 742156d366 [API Break] Fix pathTools (and a bit stringTools). (#280)
[API Break] Fix pathTools (and a bit stringTools).
2019-09-24 10:58:51 +02:00
Matthieu Gautier 598dd3c175 [API Break] Fix pathTools (and a bit stringTools).
Api changes :
 - removeLastPathElement do not takes extra arguments
   `removePreSeparator` and `removePostSeparator`.
   This is not needed as path do not need special tailing separator.
 - Only one function `split`. Arguments can be implicitly convert to
   string. No need for overloading functions to explicitly cast them.
 - `split` function takes another argument `trimEmpty`. If true, empty
   element are removed.

Path manipulation now almost pass trough a vector<string> to store each
path's part.

Most of the complex works is now made in the normalizeParts function.
2019-09-19 18:16:06 +02:00
Matthieu Gautier 49c0c5ff47 Fix join (#279)
Fix join
2019-09-17 16:28:52 +02:00
Matthieu Gautier 65ebc7fe7f New version 8.0.1 2019-09-17 16:22:28 +02:00
Matthieu Gautier 2f4636e2df Fix stringTools join function. 2019-09-17 16:22:28 +02:00
Kelson f4e9148b1d Small fix of OSes names in the README 2019-09-17 12:20:17 +02:00
Matthieu Gautier 891666b8c4 new version 8.0.0 2019-09-17 11:47:18 +02:00
Matthieu Gautier 57a2b98e7a [ABI Break] Correctly detect the executable path in appimage. (#277)
[ABI Break] Correctly detect the executable path in appimage.
2019-09-17 11:41:15 +02:00
Matthieu Gautier 9b4419f3fc [ABI Break] Correctly detect the executable path in appimage.
There are two executable path :
- The user one (the appimage path)
- The real one (in the appimage archive)

When we search of `library.xml` we need the user one.
But when we search of `aria2c` or `kiwix-serve` we need the real one.

Fix kiwix/kiwix-desktop#256
2019-09-17 11:23:16 +02:00
Matthieu Gautier 15d5b4ed58 Metadata (#276)
Metadata
2019-09-17 11:21:19 +02:00
Matthieu Gautier 2f91149da3 Update .gitignore. 2019-09-17 10:38:16 +02:00
Matthieu Gautier 6ee174b546 Add a method to get the value of a specific tag.
Fix #258
2019-09-17 10:37:53 +02:00
Matthieu Gautier 2a6772b76d [API Change] Convert tags to the new convention.
Use the new convention describe here : https://wiki.openzim.org/wiki/Tags
2019-09-17 10:30:24 +02:00
Matthieu Gautier 660d5d7fb7 [API Change] Rename getMatatag to getMetadata. 2019-09-16 10:36:04 +02:00
Matthieu Gautier 157c1c939c Add a string tool to join a list of strings together. 2019-09-16 09:42:10 +02:00
Matthieu Gautier bd91e89785 Add missing method to get the zim metadata.
According to https://wiki.openzim.org/wiki/Metadata
2019-09-12 15:33:07 +02:00
Matthieu Gautier 1245d4e467 Use a macro to get the content of the metadata. 2019-09-12 15:26:53 +02:00
Matthieu Gautier 420be55bfa Reorder methods to get metadata.
Use the same order than https://wiki.openzim.org/wiki/Metadata
2019-09-12 15:24:17 +02:00
Matthieu Gautier 651cb9165c Win kiwix serve (#274)
Win kiwix serve
2019-09-11 15:25:41 +02:00
Matthieu Gautier 49046248fd New version 7.0.0 2019-09-11 14:04:21 +02:00
Matthieu Gautier e42e061d45 Add a way to specify a library to use with kiwix-serve.
If kiwix-desktop use a `library.xml` in the same directory than the
executable, we need to use it instead of the default one.

Instead of detect again the `library.xml` to use, let `kiwix-desktop` set
the library to use.

This also fix a issue when `/` is not a valid path separator in windows.
2019-09-11 14:04:21 +02:00
Kelson d90774450d Slightly bigger top-padding for kiwix-serve 2019-09-11 13:50:33 +02:00
Matthieu Gautier 9e36c876f5 New version 6.0.4 2019-09-10 15:54:15 +02:00
Matthieu Gautier 1a4c434e3c Correctly cast double to int. (#273)
Correctly cast double to int.
2019-09-10 15:09:09 +02:00
Matthieu Gautier 3294508d87 Correctly cast double to int.
Ms cl compiler complains about the implicit conversion.
2019-09-10 14:10:40 +02:00
Matthieu Gautier 351e573bce Correctly detect the executable path if we use a AppImage. (#272)
Correctly detect the executable path if we use a AppImage.
2019-09-09 18:37:37 +02:00
Matthieu Gautier a32363e6a2 Correctly detect the executable path if we use a AppImage.
AppImage works by decompressing the "program" in a temporary directory.
So the executable path is not the path of the AppImage file.

By using the environment variables set by appimage we can find the correct
"path" of the executable.

Fix kiwix/kiwix-desktop#46
2019-09-09 18:27:53 +02:00
Matthieu Gautier 56f8b7a876 Fix search (#271)
Fix search
2019-09-09 14:59:35 +02:00
Matthieu Gautier 87dc145dc7 Correctly set searcher information even if resultStart equals resultEnd. 2019-09-09 14:43:51 +02:00
Matthieu Gautier a13244dc0e Rename hasResult to hasResults 2019-09-09 14:43:51 +02:00
Matthieu Gautier 78dbd66522 [HTML Rendering] Do not render page navigation buttons if only one page. 2019-09-09 14:43:51 +02:00
Matthieu Gautier fdc291b7c2 [HTML Rendering] Do not do division by zero.
We must correctly handle the case if resultStart is equal to resultEnd.
2019-09-09 14:43:51 +02:00
Kelson d372cea146 Merge pull request #270 from kiwix/aur-badges
Add AUR badge
2019-09-08 17:06:49 +02:00
Kelson e1fcd12e48 Add AUR badge 2019-09-08 17:05:44 +02:00
Matthieu Gautier 828bd032c4 Merge pull request #269 from kiwix/fix-multiple-column-suggestions
Force one columned suggestions in kiwix-serve
2019-09-04 17:40:45 +02:00
Kelson 26d32a36ad Force one columned suggestions in kiwix-serve 2019-09-04 17:34:15 +02:00
Matthieu Gautier c031547461 Fix fulltext search link in kiwix-serve suggestions (#268)
Fix fulltext search link in kiwix-serve suggestions
2019-09-04 17:17:34 +02:00
Kelson d0833bdcd4 Fix fulltext search link in kiwix-serve suggestions 2019-09-04 17:07:05 +02:00
Matthieu Gautier 1bb5e278ed Allow the gradle to add an extra build version in the pom file.
This is needed to be able to publish new build of the same version on
bintray.
2019-09-04 11:01:28 +02:00
Matthieu Gautier 0a331f8ba9 Fix release of 6.0.3. 2019-09-04 11:00:15 +02:00
Kelson b1a4bbd345 Update changelog for 6.0.3 2019-09-03 19:42:10 +02:00
Kelson 14dbe843b9 Merge pull request #266 from kiwix/kiwix-serve-box-size
Kiwix serve welcome page box size fix
2019-08-29 21:06:07 +02:00
Kelson e111316636 Kiwix serve welcome page box size fix 2019-08-29 21:01:21 +02:00
Kelson bbb346b685 Slight improvements of the README.md 2019-08-27 16:31:04 +02:00
Kelson 56a08f49b2 Merge pull request #263 from kiwix/improve-again-top-padding
Better kiwix-serve content (because of taskbar) top-padding
2019-08-27 16:25:54 +02:00
Kelson fc2ad81185 Better kiwix-serve content (because of taskbar) top-padding 2019-08-27 16:24:52 +02:00
Kelson af78aa5fd0 Remove spaces which had visual impact 2019-08-27 16:24:14 +02:00
Matthieu Gautier 2ea0e5bab0 New version 6.0.2 2019-08-22 16:05:35 +02:00
Matthieu Gautier b92a4b2e04 Correctly set the groupId in the pom file. 2019-08-22 16:03:46 +02:00
Matthieu Gautier ef758aa0a6 New version 6.0.1 2019-08-21 15:38:39 +02:00
Matthieu Gautier b8e5de6a47 Merge pull request #262 from kiwix/pom_gradle
Generate the pom file from gradle
2019-08-21 14:28:52 +02:00
Matthieu Gautier aed808ae5e Generate the pom file from gradle 2019-08-21 14:22:07 +02:00
Matthieu Gautier e25b27b354 Fix use of strtok on windows. (#261)
Fix use of strtok on windows.
2019-08-19 17:42:55 +02:00
Matthieu Gautier 12a93c3e29 Fix use of strtok on windows.
On windows, strtok_r is called strto_s.
2019-08-19 17:35:22 +02:00
Matthieu Gautier b3abb3a35b New version 6.0.0 (#260)
New version 6.0.0
2019-08-19 17:27:20 +02:00
Matthieu Gautier 8c3b51b81c New version 6.0.0 2019-08-19 17:18:16 +02:00
Matthieu Gautier 5f81fab1e2 Specs says ZIM favicon should be at '-/favicon', should be tried… (#257)
Specs says ZIM favicon should be at '-/favicon', should be tried first
2019-08-19 17:17:34 +02:00
Emmanuel Engelhart cea201b394 Specs says ZIM favicon should be at '-/favicon', should be tried first 2019-08-19 16:27:55 +02:00
Matthieu Gautier d0f6fadda2 Add JNIKiwixString constructors (#256)
Add JNIKiwixString constructors
2019-08-14 10:38:36 +02:00
mhutti1 8672aede97 Add JNIKiwixString constructors 2019-08-13 17:55:48 +02:00
Matthieu Gautier 8edac07fcc Merge pull request #255 from kiwix/JNI_checkUrl
Add a JNI method to check if an url exists and is a redirection.
2019-08-13 11:30:36 +02:00
Matthieu Gautier 6ab52e2b9e Add a JNI method to check if an url exists and is a redirection. 2019-08-13 11:19:39 +02:00
Matthieu Gautier 858c2fecbe Fix nameMapper initialization. (#254)
Fix nameMapper initialization.
2019-08-13 11:19:21 +02:00
Matthieu Gautier d90a27af11 Fix nameMapper initialization. 2019-08-12 16:16:26 +02:00
Matthieu Gautier a8668db2fe Make the gtest dependency optional. (#253)
Make the gtest dependency optional.
2019-08-12 15:59:31 +02:00
Matthieu Gautier 3e3e1683f5 Make the gtest dependency optional.
This is needed to build in flatpak.
2019-08-12 15:31:16 +02:00
Matthieu Gautier 1e0c9a120a Do not embed the gtest dependency. (#252)
Do not embed the gtest dependency.
2019-08-12 15:01:40 +02:00
Matthieu Gautier ca27ddf41a Do not embed the gtest dependency.
We have a special wrap file for that.
2019-08-12 14:55:39 +02:00
Matthieu Gautier 99dcdd849a Jni fix (#251)
Jni fix
2019-08-12 14:55:30 +02:00
Matthieu Gautier a65e192f0f [JNI] Allow android to know that an article is a redirect.
Android need to handle the redirection by doing a redirection in the web
view, not by providing the content of the targeted article.

This is already what we do in kiwix-serve or ios.

The API should be far better by returning a Entry but for now,
we just change the given url if the article is a redirection.
2019-08-12 13:03:20 +02:00
Matthieu Gautier 513cc9c90f [JNI] Fix log typo. 2019-08-12 12:43:52 +02:00
Matthieu Gautier 231ae095f6 Correctly set that book's path is valid when updating it from a reader. 2019-08-12 12:43:52 +02:00
Matthieu Gautier 9a0c6da018 Library construction doesn't take argument 2019-08-12 12:43:52 +02:00
Matthieu Gautier 52299ef767 Fix computeAbsolutePath.
Correctly delete the duplicated string.
Use strtok_r to be thread safe.
2019-08-12 12:43:52 +02:00
Matthieu Gautier 44bec86f31 Ci test (#248)
Ci test
2019-08-12 12:39:51 +02:00
Matthieu Gautier c4963268ba Fix regexTools.
The buildMatcher must not take a rvalue as it will keep a reference
to it.
2019-08-12 12:05:51 +02:00
Matthieu Gautier fee2da57e6 Add tests of regex tools. 2019-08-12 12:05:51 +02:00
Matthieu Gautier 0154131d74 Run test on the CI. 2019-08-12 12:05:51 +02:00
Matthieu Gautier 3fa503efb1 [JNI] Fix implementation of setDataDirectory. (#247)
[JNI] Fix implementation of setDataDirectory.
2019-08-11 15:14:24 +02:00
Matthieu Gautier 73a29ccb24 [JNI] Fix implementation of setDataDirectory.
Now that setDataDirectory is a static method, we need to take an
jclass instead of a jobject.
2019-08-11 15:09:26 +02:00
Matthieu Gautier 1e94665c07 Http integration (#246)
Http integration
2019-08-11 11:54:09 +02:00
Matthieu Gautier 7060afae66 [SERVER] Catch any error and return a 500 response instead of crashing.
The server will be running some code on the behalf of the calling code.
We really don't what to crash the library (and the binary) because
of a wrong request.
2019-08-11 11:30:43 +02:00
Matthieu Gautier de819dff25 Fix few errors in static files. 2019-08-11 11:30:43 +02:00
Matthieu Gautier 4d3df4e889 Add JNI wrapper around the library and the server. 2019-08-11 11:30:43 +02:00
Matthieu Gautier cd050ddcc8 Use camelCase. 2019-08-11 11:30:43 +02:00
Matthieu Gautier 635d4438e5 Make the server take a pointer to the library instead of a reference. 2019-08-11 11:30:43 +02:00
Matthieu Gautier ce09375c6c Reduce complexity of handle_search. 2019-08-11 11:30:43 +02:00
Matthieu Gautier fae0918f49 Reduce complexity of handle_catalog. 2019-08-11 11:30:43 +02:00
Matthieu Gautier d90f8b0f05 Add a name_mapper mapping the HumanReadable name to the id. 2019-08-11 11:30:43 +02:00
Matthieu Gautier abb5db0193 Clean up includes in server.cpp 2019-08-11 11:30:43 +02:00
Matthieu Gautier e452f5cf36 Ensure that the root is correctly formatted. 2019-08-11 11:30:43 +02:00
Matthieu Gautier c890e1c87e Add support of a binding to a specific ip address. 2019-08-11 11:30:43 +02:00
Matthieu Gautier e5ef3780db Rename humanReadableBookId to bookName.
`humanReadableBookId` is a bit long and doesn't represent what it is
(this is not a id).
`bookName` is far better.
2019-08-11 11:30:43 +02:00
Matthieu Gautier 2aeed65205 Better handling of invalid request.
Do no crash if we can get a book or a reader for the requested content.
2019-08-11 11:30:43 +02:00
Matthieu Gautier c1faf55ae8 Introduce the server functionality in the kiwix-lib.
This code is mainly copied from kiwix-tools.

But :
- Move all the response thing in a new class Response.
- This Response class is responsible to handle all the MHD_response
  configuration. This way the server handle a global object and do
  no call to MHD_response*
- Server uses a lot more the templating system with mustache.
  There are still few regex operations (because we need to
  change a content already existing).
- By default, the server serves the content using the id as name.
- Server creates a new Searcher per request. This way, we don't have
  to protect the search for multi-thread and we can do several search
  in the same time.
- search results are not cached, this will allow future improvement in the
  search algorithm.
- the home page is not cached.
- Few more verbose information (number of request served, time spend to
  respond to a request).

TOOD:
 - Readd interface selection.
 - Do Android wrapper.
 - Remove KiwixServer (who use a external process).
 -
2019-08-11 11:30:43 +02:00
Matthieu Gautier 64dfea2547 Move the search html renderer in a different class than the searcher.
This is two different functionnalies, we don't need to polute the searcher
api with things to render the html.
2019-08-11 10:19:48 +02:00
Matthieu Gautier cca5980b27 Remove limitation of the search len in the Searcher.
The limitation should be made elsewhere (the code using the searcher).
2019-08-11 10:19:48 +02:00
Matthieu Gautier 68a768f58a Introduce the new class NameMapper.
This class is used to map an id (uuid) to a name (potentially human
readable).

This will be use by the server to or renderer to use a different "name"
than the id.

The default NameMapper provided use the id as a name.
2019-08-11 10:19:48 +02:00
Matthieu Gautier ce8fff0b42 Make the library create the reader. 2019-08-11 10:19:48 +02:00
Matthieu Gautier e56335109c Make appendToFirstOccurence take argument by reference. 2019-08-11 10:19:48 +02:00
Matthieu Gautier 656bf183b7 Make getHumanReadableFromPath method const. 2019-08-11 10:19:48 +02:00
Matthieu Gautier cbe8e20118 Fix include in otherTools.h 2019-08-11 10:19:48 +02:00
Matthieu Gautier e013d38cc6 Add startWith function in stringTools.h 2019-08-11 10:19:48 +02:00
Matthieu Gautier 6234457920 Fix include in stringTools.h 2019-08-11 10:19:48 +02:00
Matthieu Gautier 72223d69fe Fix include in pathTools.h 2019-08-10 11:02:23 +02:00
Matthieu Gautier ddeb862395 Add getMimeTypeForFile in pathTool. 2019-08-10 10:59:13 +02:00
Matthieu Gautier 61c28f0e3d Make the regexTool thread safe. 2019-08-10 10:59:13 +02:00
Matthieu Gautier c8e719101e Add a new tool Lock to lock a mutex.
And automaticlly unlock it when the `Lock` got out of scope.
2019-08-10 10:59:13 +02:00
Kelson 1b8e7849bd Merge pull request #244 from kiwix/badges
Add badges to the README
2019-07-31 18:09:46 +02:00
Emmanuel Engelhart efce01aec4 Add badges to the README 2019-07-31 18:08:09 +02:00
Matthieu Gautier d55976271f Merge pull request #243 from kiwix/new_version
New version 5.2.0
2019-07-30 18:01:31 +02:00
Matthieu Gautier 5eeccbae21 New version 5.2.0 2019-07-30 17:40:46 +02:00
Matthieu Gautier 77770e1bd4 Merge pull request #105 from kiwix/verbose_search
Set the verbosity of the underlying zim::Search.
2019-07-30 17:33:01 +02:00
Matthieu Gautier 654a8e304c Set the verbosity of the underlying zim::Search. 2019-07-30 17:03:44 +02:00
Matthieu Gautier ed7a8343fa Merge pull request #241 from kiwix/relinker
#239 ReLinker should be used to load library
2019-07-30 16:58:22 +02:00
Sean Mac Gillicuddy 5adf7891cc #239 ReLinker should be used to load library 2019-07-29 18:31:57 +02:00
Kelson 93c404a952 Merge pull request #238 from kiwix/http-https
Replace HTTP link by HTTPs one
2019-07-23 16:06:56 +02:00
Kelson f33f4eb381 Replace HTTP links by HTTPs one 2019-07-23 15:19:01 +02:00
Matthieu Gautier 4bece7017f Merge pull request #231 from kiwix/macgills/feature/auto-publish-android-library
Create library and set up publishing task
2019-07-23 15:16:56 +02:00
Sean Mac Gillicuddy cab8eec00b create library to build kiwix-lib for android 2019-07-23 11:23:20 +02:00
Matthieu Gautier f41155e060 Merge pull request #236 from kiwix/return-port-kiwix-serve
kiwix local server port can be set at the constructor
2019-06-27 17:59:14 +02:00
luddens c17abdae5e port can be set with the constructor
add a method to return the port
2019-06-27 16:50:22 +02:00
Matthieu Gautier 8164b4dadc Merge pull request #234 from kiwix/listBook_api
List book api
2019-06-26 17:32:00 +02:00
Matthieu Gautier 31c9375a3a Better API to filter books in a library.
Instead of having a single method `listBooksIds` that tries to be
exhaustive about all the filter and sort option, split the method in
two separated methods `filter` and `sort`.

The `filter` method takes a `Filter` object that represent on what we are
filtering. This object has to be construct before calling `filter`.

```cpp
Filter filter;
filter.query("Astring");
filter.acceptTags({"nopic"});
// return all book in eng and with "Astring" in the tile or description".
library.filter(filter);
//equivalent to
library.listBooksIds(ALL, UNSORTED, "Astring", "", "", "", {"nopic"});
// or better
library.filter(Filter().query("Astring").acceptTags({"nopic"}));
```

The method `listBooksIds` has been marked as deprecated.

Add a small test on the library.
2019-06-26 16:41:01 +02:00
Matthieu Gautier 21592af8b2 Remove invalid method declaration in kiwix::Manager.
Those methods were totally obsolete. They were even not implemented.
2019-06-26 16:41:01 +02:00
Matthieu Gautier 15b3ed24b7 Merge pull request #235 from kiwix/fix_exit
Force the exit of the forked process.
2019-06-25 18:53:31 +02:00
Matthieu Gautier 3d689e790b Force the exit of the forked process.
The `exit` function will call the functions registered.
Qt may (and does) register function and may (and does) hangup waiting
for some mutex to be free.

Here we are in a forked process and we want to process to exit without
doing any cleanup (because we are a clone of a process that will continue
and we don't want to mess it).
2019-06-25 16:52:46 +02:00
Matthieu Gautier e740a511c6 Merge pull request #233 from kiwix/kiwix-serve-is-running
add isRunning method to check if the local server is running
2019-06-24 15:16:31 +02:00
luddens 87f5b56b72 add isRunning method 2019-06-24 15:05:20 +02:00
Matthieu Gautier cfdd634c3c Merge pull request #228 from kiwix/fix-crash-suggestion
Fix crash searchbar's suggestions
2019-06-24 11:54:23 +02:00
luddens df76db4f47 Fix crash searchbar's suggestions
The suggestion's list was filled without checking if the current suggestion
was wrong which caused crash in this case.
2019-06-24 11:48:14 +02:00
Matthieu Gautier 15f7eaa400 Merge pull request #232 from kiwix/fix_fork_wait_child
Fix waitpid option.
2019-06-24 11:47:56 +02:00
Matthieu Gautier 6fe6f88b10 Fix waitpid option.
`WEXITED` is an option for the `waitid` function not `waitpid`.

We don't need to pass a option to `waitpid`.
2019-06-24 11:34:03 +02:00
Matthieu Gautier 687a15877a Merge pull request #230 from kiwix/fix_kiwix-serve
Remove unnecessary include.
2019-06-12 14:33:33 +02:00
Matthieu Gautier 4e746916a7 Remove unnecessary include.
And unistd.h is not available on windows.
2019-06-12 14:27:15 +02:00
Matthieu Gautier 7c1d051305 Merge pull request #221 from kiwix/kiwix-serve
kiwix-serve integration in kiwix-lib
2019-06-11 10:54:35 +02:00
luddens 5dc96d7145 kiwix-serve integration 2019-06-11 10:35:16 +02:00
Matthieu Gautier 3721d7439d Merge pull request #227 from kiwix/new_version
New version 5.1.0
2019-05-28 23:47:43 +02:00
Matthieu Gautier 701829ae11 New version 5.1.0 2019-05-28 17:40:09 +02:00
Matthieu Gautier 91a0e100cc Merge pull request #226 from kiwix/new_api_libzim
suggestions method return a unique_ptr instead of a raw pointer.
2019-05-28 16:48:04 +02:00
Matthieu Gautier 1f672056a9 [CI] Build on xenial. 2019-05-28 15:12:53 +02:00
Matthieu Gautier 48347825a9 suggestions method return a unique_ptr instead of a raw pointer. 2019-05-28 15:08:16 +02:00
Kelson d0d7e11093 Merge pull request #223 from kiwix/tags-opds-stream
Add tags to OPDS stream
2019-05-15 09:50:24 +02:00
luddens 519dd110f5 add tags in opds stream 2019-05-14 10:51:22 +02:00
Matthieu Gautier 568b2b0e0c Merge pull request #218 from kiwix/downloadPauseResume
Add pause and unpause functions for aria2
2019-05-13 10:41:29 +02:00
luddens 491b6d655b add remove fct with aria2 2019-05-13 10:30:19 +02:00
luddens ec8f1ffe9c Add pause and unpause functions for aria2
This functions enable to stop and resume download with aria2.

The Downloader's constructor now checks the paused downloads with the
function "tellWaiting()" to get them at the start of kiwix-desktop.
2019-05-13 10:30:19 +02:00
luddens 12ffad55f7 update download's status when we get it 2019-05-13 10:30:19 +02:00
Matthieu Gautier 8698407e1e Merge pull request #219 from kiwix/fix_sleep_windows
Revert Do not use this_thread::sleep.
2019-05-03 15:54:49 +02:00
Matthieu Gautier 0b2c9fa7ce Revert Do not use this_thread::sleep.
We already have a custom sleep method.
2019-05-03 15:38:47 +02:00
Matthieu Gautier f93c31754a Merge pull request #216 from kiwix/thread_win
Do not use this_thread::sleep.
2019-04-17 17:56:56 +02:00
Matthieu Gautier fe682f855a Do not use this_thread::sleep.
Mingw doesn't implement it. So, we should not use it.
I suppose that it was working before because mingw package for debian trusty
simply no provides a "thread" header.
We may face to include the native "thread" header.
2019-04-17 15:44:14 +00:00
Matthieu Gautier 9321c589c8 Merge pull request #215 from kiwix/new_version
New version 5.0.0
2019-04-15 17:14:27 +02:00
Matthieu Gautier ee330398b2 New version 5.0.0 2019-04-15 17:07:07 +02:00
Matthieu Gautier ec4525fd47 Merge pull request #214 from kiwix/cyrillemoureaux-fix-self-redirect
Detect and reject infinite redirect loops.
2019-04-15 17:01:43 +02:00
cyrillemoureaux e1980d190f Detect and reject infinite redirect loops.
This will prevent kiwix/kiwix-tools#207.
2019-04-15 16:55:48 +02:00
Matthieu Gautier 03b1750313 Merge pull request #212 from xvitaly/kill-rpath
Removed Rpath from compiled binaries
2019-04-15 16:54:20 +02:00
Vitaly Zaitsev 28f144796d Removed Rpath from compiled binaries.
Rpath is not needed to run installed binaries. Most of GNU/Linux
distributions strictly forbid it.

Signed-off-by: Vitaly Zaitsev <vitaly@easycoding.org>
2019-04-15 16:09:53 +02:00
Matthieu Gautier 6c27743663 Merge pull request #213 from kiwix/fix_include_windows
Remove unused include unistd.h
2019-04-15 10:56:21 +02:00
Matthieu Gautier e7e88617d5 Remove unused include unistd.h
We don't use it anymore and it is not present on Windows.
2019-04-15 10:50:26 +02:00
Matthieu Gautier 4e90f3614d Merge pull request #211 from kiwix/makeTmpDirectory
Rewrite makeTmpDirectory to not use Uuid methods on windows.
2019-04-04 17:07:17 +02:00
Matthieu Gautier f8522fb26e Remove getNetworkInterfaces and getBestPublicIp function.
They are not used at all and the windows version need some extra libs
that complexify the code.

Remove them for now. If it happens that they are needed, we will readd
them.
2019-04-04 17:00:45 +02:00
Matthieu Gautier 938e2a81c1 Rewrite makeTmpDirectory to not use Uuid methods on windows.
`UuidCreate`, `UuidToString` and `RpcStringFree` need special library
on windows. Lets not use them.
2019-04-04 16:11:36 +02:00
Matthieu Gautier d9e72685ba Merge pull request #210 from kiwix/no_error_message
Remove error message when trying to opening a wrong zim file.
2019-04-02 16:02:47 +02:00
Matthieu Gautier d40982f760 Remove error message when trying to opening a wrong zim file.
The library should not print a message.

Fix kiwix/kiwix-tools#235
2019-04-02 15:28:46 +02:00
Matthieu Gautier 42b7692f9b Merge pull request #208 from kiwix/new_version
Version 4.1.0
2019-03-19 16:35:57 +01:00
Matthieu Gautier cd654b9cae Version 4.1.0 2019-03-19 16:26:14 +01:00
Matthieu Gautier 15dafcaa80 Force use of meson 0.49.2 2019-03-19 15:27:03 +01:00
Matthieu Gautier f71f2935e0 Merge pull request #204 from kiwix/library_filter_tag
Allow the library to be filtered by tags.
2019-03-07 17:19:31 +01:00
Matthieu Gautier c6254d9504 Allow the library to be filtered by tags.
This add an argument to `listBooksIds` to filter by tags.
So, this is an API break.
2019-03-07 17:08:39 +01:00
Matthieu Gautier f1a046757e Merge pull request #203 from kiwix/fix_lang_mapping
Fix the language mapping.
2019-03-05 18:43:00 +01:00
Matthieu Gautier 93af3aa2d1 Fix the language mapping.
The previous mapping was taken from an unknown (:/) source.

The new mapping is generated with a script taking
https://www.loc.gov/standards/iso639-2/php/code_list.php as source.

The source list is sanitized to keep only language for which we
(http://library.kiwix.org/) have content.
2019-03-05 17:53:37 +01:00
Matthieu Gautier 336a987bb2 Merge pull request #202 from kiwix/update_readme_mustache
Add information about mustache dependency in the README.
2019-03-04 17:03:56 +01:00
Matthieu Gautier 72b4af4d65 Add information about mustache dependency in the README. 2019-03-04 14:26:40 +01:00
Matthieu Gautier 9aa1c65d7a Merge pull request #200 from kiwix/new_version
New version 4.0.1
2019-02-22 11:18:55 +01:00
Matthieu Gautier ad6b20a530 New version 4.0.1 2019-02-22 10:29:16 +01:00
Matthieu Gautier c1d04cc5b5 Merge pull request #199 from kiwix/fix_warning_android
Correctly initialize variable.
2019-02-19 14:15:20 +01:00
Matthieu Gautier af9734c87f Correctly initialize variable. 2019-02-19 14:05:37 +01:00
Matthieu Gautier a7a0798f99 Merge pull request #198 from kiwix/use_correct_dep_archive
Use new xz archive.
2019-02-19 14:05:08 +01:00
Matthieu Gautier 0154fdd190 Use new xz archive. 2019-02-19 13:31:26 +01:00
Matthieu Gautier 788d16ec01 Merge pull request #197 from kiwix/ensure_path_abs
Ensure path abs
2019-02-07 15:55:51 +01:00
Matthieu Gautier 35d812a5f7 Ensure the book's path is absolute.
We must use absolute path whenever possible.
Relative path has sense only related to the "interaction" with the user
(current directory, library location, ...).
2019-02-07 15:22:33 +01:00
Matthieu Gautier 432f9c30a3 Remove unused variable url. 2019-02-07 15:20:18 +01:00
Matthieu Gautier ab94ac0ee8 Merge pull request #195 from kiwix/new_version
New version
2019-01-29 11:38:06 +01:00
Matthieu Gautier 1ac6d4cb20 New version 4.0.0 2019-01-29 11:29:59 +01:00
Matthieu Gautier 26b61a2d09 We do not need the exact version 0.43.0 for meson. 2019-01-29 11:29:59 +01:00
Matthieu Gautier aab88c9022 Merge pull request #194 from kiwix/common2tools
[API break] Move all the tools in the tools directory instead of common.
2019-01-23 16:55:09 +01:00
Matthieu Gautier af7689e3e8 [API break] Move all the tools in the tools directory instead of common.
The `common` name is from the time where kiwix was only one repository
for all the project (android, desktop, server...).

Now we have split the repositories and kiwix-lib is the "common" repo,
the "common" directory is somehow nonsense.
2019-01-23 15:31:38 +01:00
Matthieu Gautier ecb2a80baf Merge pull request #193 from kiwix/fix_uninitalized
Correctly initialize retVal.
2019-01-23 12:05:34 +01:00
Matthieu Gautier b996a2877c Correctly initialize retVal. 2019-01-23 11:51:30 +01:00
Matthieu Gautier a98594c084 Merge pull request #192 from kiwix/workaround_depend_files
Workaround a bug in meson 0.43.0 about custom_target's depend_files option.
2019-01-10 16:08:24 +01:00
Matthieu Gautier b9696dceac Workaround a bug in meson 0.43.0 about custom_target's depend_files option.
There is a bug in meson 0.43.0 about the option depend_files
(mesonbuild/meson#2633)

By using the `files('search_result.tmpl')`, we workaround the bug and
have everything working whatever the meson version is.
2019-01-10 15:59:42 +01:00
Matthieu Gautier 550b6df414 Merge pull request #191 from kiwix/mustache_template
Move the templating system to mustache instead of ctpp2.
2019-01-10 11:45:56 +01:00
Matthieu Gautier be498c3b16 Make the string Tools functions available in android. 2019-01-09 18:29:20 +01:00
Matthieu Gautier 92c9a47a0d Move the templating system to mustache instead of ctpp2.
Mustache templating system is a bit simpler than ctpp2 and ctpp2 is no
more maintained (see #189).
We are moving to the kainjow's Mustache project
(https://github.com/kainjow/Mustache).

It simplify a lot our system has it is header only and we don't have to
precompile the template.

Fix #21
2019-01-09 18:28:48 +01:00
Matthieu Gautier c73ac9f2cd Merge pull request #190 from kiwix/no_external_index
Remove support for external index.
2019-01-08 16:13:54 +01:00
Matthieu Gautier 5159d985c6 Remove support for external index.
This feature is considered obsolete for a while.
In fact, it was already not supported since June 2018 as we were compiling
xapian without the chert backend support.

Assume that we don't support it and remove it from the code.
See kiwix/kiwix-tools#245

This is a API break. library.xml files will still work but the indexPath
and indexType will be dropped silently from the file.
2019-01-07 16:47:08 +01:00
Matthieu Gautier cb98f11ddc Merge pull request #188 from kiwix/create_directory
Create the datadirectory to not fail to write the aria2 session file.
2018-12-14 16:44:46 +01:00
Matthieu Gautier 29046bfc05 Create the datadirectory to not fail to write the aria2 session file.
Fix kiwix/kiwix-desktop#69
2018-12-14 15:24:13 +01:00
Matthieu Gautier dd5dd14ec9 Merge pull request #187 from kiwix/new_version
new version 3.1.1
2018-12-13 18:05:35 +01:00
Matthieu Gautier 49a606a043 new version 3.1.1 2018-12-13 17:29:21 +01:00
Matthieu Gautier b641f7b116 Merge pull request #186 from kiwix/fix_library
Fix library
2018-12-11 17:08:30 +01:00
Matthieu Gautier e6d7ba06fb Convert the standard opds date to our format (YYYY-MM-DD) 2018-12-11 17:02:02 +01:00
Matthieu Gautier 0f812c6584 The update entry of the book should be the date of the book, not the feed. 2018-12-11 17:01:33 +01:00
Matthieu Gautier 716c87dd20 Remove duplicate language attribute in the libxml dumper.
Silly copy/paste.
2018-12-11 17:00:56 +01:00
Matthieu Gautier 090c4f5970 Merge pull request #185 from kiwix/new_version
new version 3.1.0
2018-12-03 11:21:15 +01:00
Matthieu Gautier cf28af4439 new version 3.1.0 2018-12-02 15:56:00 +01:00
Matthieu Gautier 6777bfeecf Merge pull request #184 from kiwix/bookmarks
Bookmarks
2018-12-02 15:52:52 +01:00
Matthieu Gautier 12498e2cfe Add bookmarks support.
The library now contains (simple) methods to handle bookmarks.
The bookmark are stored in a separate xml file.

Bookmark are mainly a couple (`zimId`, `articleUrl`).
However, in the xml we store a bit more data :
- The article's title (for display)
- The book's title, lang and date (for potential update of zim files)
2018-12-02 15:47:29 +01:00
Matthieu Gautier b5ce60a627 Move the dump of the library into library.xml in a specific class.
The same way the dump into a opds feed is in a specific class.
2018-11-28 12:09:28 +01:00
Matthieu Gautier c9cc58973c Merge pull request #183 from kiwix/book_faviconUrl
Add Book::getFaviconUrl
2018-11-15 17:53:24 +01:00
Matthieu Gautier 062124a2a0 Add Book::getFaviconUrl 2018-11-15 17:47:41 +01:00
Matthieu Gautier 622b22b2cc Merge pull request #180 from kiwix/new_version
New version 3.0.3
2018-11-12 18:05:43 +01:00
Matthieu Gautier 2821b9e06a New version 3.0.3 2018-11-12 16:48:35 +01:00
Matthieu Gautier ac49776792 Merge pull request #182 from kiwix/fix_aria2c_launch
Wait a bit more between attempts to connect to aria2c rpc.
2018-11-12 16:28:21 +01:00
Matthieu Gautier 94a053e821 Wait a bit more between attempts to connect to aria2c rpc. 2018-11-12 16:14:21 +01:00
Matthieu Gautier 84e831eae9 Merge pull request #181 from kiwix/fix_aria2c_launch
Correctly run aria2c when packaged with kiwix-desktop in appimage.
2018-11-12 14:41:57 +01:00
Matthieu Gautier 4b9692bbd5 Correctly run aria2c when packaged with kiwix-desktop in appimage.
By default, we are searching in the PATH env var.
However, with an appImage, the executable directory is not in the PATH,
so we have to use an absolute path if we can.

If we cannot find the aria2c executable in the executable directory let's
try to use the system one.
2018-11-12 14:35:17 +01:00
Matthieu Gautier be6f96adc0 Merge pull request #179 from kiwix/fix_library
Fix library
2018-11-12 12:21:54 +01:00
Matthieu Gautier 4b31842c4a Correctly convert filesize from Kbyte to byte.
`reader.getFileSize()` return the size of the zim in Kbyte in a
`unsigned int` (32 bits). This is ok as it would overflow if the size
of the size is greater than 4294967295 kbytes (so ~4Tbytes).

However, we need to convert the return size into a unsigned 64 bits integer
else, when converting to bytes, we will overflow at 4Gbytes.
Even in `m_size` is a uint64_t.
2018-11-12 12:16:05 +01:00
Matthieu Gautier cf1cfe774e Correctly check for ArticleCount and MediaCount before writing them. 2018-11-12 10:58:10 +01:00
Matthieu Gautier 82b38b96e2 Merge pull request #178 from kiwix/fix_en_mapping
Fix en mapping
2018-11-12 10:57:18 +01:00
Matthieu Gautier 8c4b9fbe95 Add missing en->eng mapping to codeisomapping.
The most common used language was missing :/

Fix kiwix/kiwix-desktop#51
2018-11-12 10:36:45 +01:00
Matthieu Gautier ab63cb2fb8 Sort codeisomapping alphabetically.
This is only code formating, no real change.
2018-11-12 10:34:19 +01:00
Matthieu Gautier 3958b2a06f Make the internal map codeisomapping static.
Symbole should not be visible outside of the compilation unit.
2018-11-12 10:33:35 +01:00
662 changed files with 41477 additions and 160629 deletions

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
codecov:
notify:
require_ci_to_pass: yes
coverage:
status:
project:
default:
threshold: 1%
ignore:
- "test"
+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: kiwix
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # https://kiwix.org/support-us/
+15
View File
@@ -0,0 +1,15 @@
daysUntilClose: false
staleLabel: stale
issues:
daysUntilStale: 60
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be now be reviewed manually. Thank you
for your contributions.
pulls:
daysUntilStale: 7
markComment: >
This pull request has been automatically marked as stale because it has not had
recent activity. It will be now be reviewed manually. Thank you
for your contributions.
+200
View File
@@ -0,0 +1,200 @@
name: CI
on:
push:
branches:
- main
pull_request:
jobs:
macOS:
strategy:
fail-fast: false
matrix:
target:
- macos-aarch64-dyn
- macos-x86_64-dyn
- ios-arm64-dyn
- ios-x86_64-dyn
include:
- target: macos-aarch64-dyn
arch_name: arm64-apple-macos
run_test: true
- target: macos-x86_64-dyn
arch_name: x86_64-apple-darwin
run_test: true
- target: ios-arm64-dyn
arch_name: aarch64-apple-ios
run_test: false
- target: ios-x86_64-dyn
arch_name: x86-apple-ios-simulator
run_test: false
runs-on: macos-15
env:
HOME: /Users/runner
steps:
- name: Retrieve source code
uses: actions/checkout@v4
- name: Install packages
run: |
brew update
brew install ninja meson
- name: Install dependencies
uses: kiwix/kiwix-build/actions/dl_deps_archive@main
with:
target_platform: ${{ matrix.target }}
- name: Compile
env:
PKG_CONFIG_PATH: ${{env.HOME}}/BUILD_${{matrix.arch_name}}/INSTALL/lib/pkgconfig
CPPFLAGS: -I${{env.HOME}}/BUILD_${{matrix.arch_name}}/INSTALL/include
MESON_OPTION: --default-library=shared -Db_coverage=true
MESON_CROSSFILE: ${{env.HOME}}/BUILD_${{matrix.arch_name}}/meson_cross_file.txt
shell: bash
run: |
if [ -e $MESON_CROSSFILE ]; then
MESON_OPTION="$MESON_OPTION --cross-file $MESON_CROSSFILE -Dstatic-linkage=true"
fi
meson . build ${MESON_OPTION}
ninja -C build
- name: Test libkiwix
if: matrix.run_test
env:
SKIP_BIG_MEMORY_TEST: 1
LD_LIBRARY_PATH: ${{env.HOME}}/BUILD_${{matrix.arch_name}}/INSTALL/lib:${{env.HOME}}/BUILD_${{matrix.arch_name}}/INSTALL/lib64
run: meson test -C build --verbose
Windows:
runs-on: windows-2025
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install packages
run:
choco install pkgconfiglite ninja
- name: Install python modules
run: pip3 install meson
- name: Setup MSVC compiler
uses: bus1/cabuild/action/msdevshell@v1
with:
architecture: x64
- name: Install dependencies
uses: kiwix/kiwix-build/actions/dl_deps_archive@main
with:
target_platform: win-x86_64-static
- name: Compile
shell: cmd
run: |
set PKG_CONFIG_PATH=%cd%\BUILD_win-amd64\INSTALL\lib\pkgconfig
set CPPFLAGS=-I%cd%\BUILD_win-amd64\INSTALL\include
meson.exe setup . build -Dwerror=false --default-library=static --buildtype=release
cd build
ninja.exe
- name: Test
shell: cmd
run: |
cd build
meson.exe test --verbose
env:
WAIT_TIME_FACTOR_TEST: 10
Linux:
strategy:
fail-fast: false
matrix:
target:
- linux-x86_64-static
- linux-x86_64-dyn
- android-arm
- android-arm64
image_variant: ['jammy']
include:
- target: linux-x86_64-static
lib_postfix: '/x86_64-linux-gnu'
arch_name: linux-x86_64
run_test: true
coverage: true
- target: linux-x86_64-dyn
lib_postfix: '/x86_64-linux-gnu'
arch_name: linux-x86_64
run_test: true
coverage: true
- target: android-arm
lib_postfix: '/arm-linux-androideabi'
arch_name: arm-linux-androideabi
run_test: false
coverage: false
- target: android-arm64
lib_postfix: '/aarch64-linux-android'
arch_name: aarch64-linux-android
run_test: false
coverage: false
env:
HOME: /home/runner
runs-on: ubuntu-22.04
container:
image: "ghcr.io/kiwix/kiwix-build_ci_${{matrix.image_variant}}:2025-06-07"
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
uses: kiwix/kiwix-build/actions/dl_deps_archive@main
with:
target_platform: ${{ matrix.target }}
- name: Compile
shell: bash
run: |
meson --version
if [[ "${{matrix.target}}" =~ .*-dyn ]]; then
MESON_OPTION="--default-library=shared"
else
MESON_OPTION="--default-library=static"
fi
if [ -e "${{env.HOME}}/BUILD_${{matrix.arch_name}}/meson_cross_file.txt" ]; then
MESON_OPTION="$MESON_OPTION --cross-file ${{env.HOME}}/BUILD_${{matrix.arch_name}}/meson_cross_file.txt"
else
MESON_OPTION="$MESON_OPTION -Db_coverage=true"
fi
if [[ "${{matrix.target}}" =~ android-.* ]]; then
MESON_OPTION="$MESON_OPTION -Dstatic-linkage=true"
fi
meson . build ${MESON_OPTION}
cd build
ninja
env:
PKG_CONFIG_PATH: "/home/runner/BUILD_${{matrix.arch_name}}/INSTALL/lib/pkgconfig:/home/runner/BUILD_${{matrix.arch_name}}/INSTALL/lib${{matrix.lib_postfix}}/pkgconfig"
CPPFLAGS: "-I/home/runner/BUILD_${{matrix.arch_name}}/INSTALL/include"
- name: Test
if: matrix.run_test
shell: bash
run: |
cd build
meson test --verbose
if [[ "${{matrix.coverage}}" = "true" ]]; then
ninja coverage
fi
env:
LD_LIBRARY_PATH: "/home/runner/BUILD_${{matrix.arch_name}}/INSTALL/lib:/home/runner/BUILD_${{matrix.arch_name}}/INSTALL/lib${{matrix.lib_postfix}}"
SKIP_BIG_MEMORY_TEST: 1
- name: Publish coverage
if: matrix.coverage
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
+111
View File
@@ -0,0 +1,111 @@
name: Packages
on:
pull_request:
push:
branches:
- main
release:
types: [published]
jobs:
build-deb:
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
distro:
# - debian-unstable
# - debian-trixie
# - debian-bookworm
# - debian-bullseye
- ubuntu-noble
- ubuntu-jammy
steps:
- uses: actions/checkout@v4
# Determine which PPA we should upload to
- name: PPA
id: ppa
run: |
if [[ $REF == refs/tags* ]]
then
echo "ppa=kiwixteam/release" >> $GITHUB_OUTPUT
else
echo "ppa=kiwixteam/dev" >> $GITHUB_OUTPUT
fi
env:
REF: ${{ github.ref }}
- uses: legoktm/gh-action-auto-dch@main
with:
fullname: Kiwix builder
email: release+launchpad@kiwix.org
distro: ${{ matrix.distro }}
# - uses: legoktm/gh-action-build-deb@debian-unstable
# if: matrix.distro == 'debian-unstable'
# name: Build package for debian-unstable
# id: build-debian-unstable
# with:
# args: --no-sign
#
# - uses: legoktm/gh-action-build-deb@b47978ba8498dc8b8153cc3b5f99a5fc1afa5de1 # pin@debian-trixie
# if: matrix.distro == 'debian-trixie'
# name: Build package for debian-trixie
# id: build-debian-trixie
# with:
# args: --no-sign
#
# - uses: legoktm/gh-action-build-deb@1f4e86a6bb34aaad388167eaf5eb85d553935336 # pin@debian-bookworm
# if: matrix.distro == 'debian-bookworm'
# name: Build package for debian-bookworm
# id: build-debian-bookworm
# with:
# args: --no-sign
#
# - uses: legoktm/gh-action-build-deb@084b4263209252ec80a75d2c78a586192c17f18d # pin@debian-bullseye
# if: matrix.distro == 'debian-bullseye'
# name: Build package for debian-bullseye
# id: build-debian-bullseye
# with:
# args: --no-sign
- uses: legoktm/gh-action-build-deb@9114a536498b65c40b932209b9833aa942bf108d # pin@ubuntu-noble
if: matrix.distro == 'ubuntu-noble'
name: Build package for ubuntu-noble
id: build-ubuntu-noble
with:
args: --no-sign
ppa: ${{ steps.ppa.outputs.ppa }}
- uses: legoktm/gh-action-build-deb@ubuntu-jammy
if: matrix.distro == 'ubuntu-jammy'
name: Build package for ubuntu-jammy
id: build-ubuntu-jammy
with:
args: --no-sign
ppa: ${{ steps.ppa.outputs.ppa }}
- uses: actions/upload-artifact@v4
with:
name: Packages for ${{ matrix.distro }}
path: output
- uses: legoktm/gh-action-dput@main
name: Upload dev package
# Only upload on pushes to main
if: github.event_name == 'push' && github.event.ref == 'refs/heads/main' && startswith(matrix.distro, 'ubuntu-')
with:
gpg_key: ${{ secrets.LAUNCHPAD_GPG }}
repository: ppa:kiwixteam/dev
packages: output/*_source.changes
- uses: legoktm/gh-action-dput@main
name: Upload release package
if: github.event_name == 'release' && startswith(matrix.distro, 'ubuntu-')
with:
gpg_key: ${{ secrets.LAUNCHPAD_GPG }}
repository: ppa:kiwixteam/release
packages: output/*_source.changes
+9
View File
@@ -0,0 +1,9 @@
.idea/
*.swp
subprojects/googletest-release*
*.class
build/
.vscode/
builddir/
.cache/
.clangd/
+21
View File
@@ -0,0 +1,21 @@
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
# We recommend specifying your dependencies to enable reproducible builds:
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: docs/requirements.txt
-36
View File
@@ -1,36 +0,0 @@
language: cpp
dist: trusty
sudo: false
cache: ccache
before_install:
- PATH=$PATH:$HOME/bin
install: travis/install_deps.sh
script: travis/compile.sh
env:
matrix:
- PLATFORM="native_static"
- PLATFORM="native_dyn"
- PLATFORM="win32_static"
- PLATFORM="win32_dyn"
- PLATFORM="android_arm"
- PLATFORM="android_arm64"
addons:
apt:
packages:
- cmake
- python3-pip
- libbz2-dev
- ccache
- zlib1g-dev
- uuid-dev
- libctpp2-dev
- ctpp2-utils
- libmicrohttpd-dev
- g++-mingw-w64-i686
- gcc-mingw-w64-i686
- gcc-mingw-w64-base
- mingw-w64-tools
matrix:
include:
- env: PLATFORM="native_dyn"
os: osx
+2 -2
View File
@@ -77,7 +77,7 @@ modification follow.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
@@ -510,7 +510,7 @@ actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
+580
View File
@@ -1,3 +1,583 @@
libkiwix 14.2.0
===============
* Server:
- Add 10.211 IPv4 range to known local ranges (@kelson42 #1273)
- Fix regression to properly deal with IPv4-only systems (@veloman-yunkan #1272)
- Improve mgmt of empty search input (@pippotadde #1255 #1258 #1259)
- Remove pagination for OPDS/Atom feed URL (@kelson42 #1274)
- Updated documentation of lang and category filters in catalog query API endpoints (@veloman-yunkan #804)
* Other
- Optimized (speed) removeAccents() for ASCII-only input (@veloman-yunkan #1276)
- Fix a few stability, correctness, and memory problems (@shbhmexe #1261)
- Introduce Manager::addBooksFromDirectory (@juuz0 #1220)
* Compilation
- Move MS Windows CI to 2025 runner (@kelson42 #1269)
- Fix readthedocs update process (@kelson42 #1247)
libkiwix 14.1.1
===============
* Server:
- Fix regression for kiwix-serve --nosearchbar (@veloman-yunkan #1250)
- Avoid results content interpretation... crash in fulltext search (@vighnesh-sawant #1241)
- Fix for intermittent /content/blank.html errors (@veloman-yunkan #1249)
libkiwix 14.1.0
===============
* Server:
- Viewer detects & tracks intrapage navigation anchors too (@veloman-yunkan #1213)
- Add support for catalog only mode (@veloman-yunkan #1219)
- Add API which returns server access url (@vighnesh-sawant #1234)
- Fix chrome searchbar placeholder text overflow (@aditii2712 #1185)
- Fix magnet link queryStyring (@rgaudin #1160)
- Improve chrome printing stylesheet (@kelson42 #1202)
- Default white background (@kelson42 #1205)
* Other:
- Switched to the new libzim illustrations API (@veloman-yunkan #1226)
- Stop building Windows with DEBUG symbols in CI (@kelson42 #1165)
- Update many things in the CI/CD (@kelson42 #1203 #1194 #1209 #1207 #1235)
- Requires now libzim 9.4.0 (@kelson42 #1231)
- Fix compilation for FreeBSD (@OICe2 #1173 #1174)
- Wait up to 1s to let aria2c to start before complaining (@kelson42 #1169)
libkiwix 14.0.0
===============
* Server:
- Support of IPv6 (@veloman-yunkan @aryanA101a #1074 #1093)
- Better public IP configuration/detection (@sgourdas #1132)
- Fix API errors in catalog searches if Xapian keyword in used (@veloman-yunkan #1137)
- Clearly define which Web browsers are supported (@kelson42 @rgaudin @jaifroid @benoit74 #1132)
- Improve welcome page download buttons (@veloman-yunkan #1094)
- Better handling of external (non-HTTP) links (@veloman-yunkan #1123)
- Fix book illustration size on welcome page to 48x48 pixels (@veloman-yunkan #1127)
- Remove "Multiple Languages" in language filter (@veloman-yunkan #1098)
- Stop transforming tags casing (@kelson42 @veloman-yunkan #1079 #1121)
- ZIM file size consistently advertised in MiB (@harsha-mangena #1132)
- Few new supported languages in the filter (@kelson42 #1080)
- Improve accesskeys (@kelson42 #1075)
- Add OpenSearch <link> to head of pages (@kelson42 #1070)
* Compilation/Packaging:
- Multiple fixes around deb packaging (@kelson42 #1108 #1114 #1135)
- Generating of libkiwix.pc via Meson (@veloman-yunkan #1133)
- Native Windows CI/CD (@mgautierfr @kelson42 #1113 #1125)
- Better check (maximum) libzim version (@kelson42 #1124)
- Multiple automated tests improvements (@veloman-yunkan #1068 #1067)
* Other:
- Deleted supported env. variable `$KIWIX_DATA_DIR` and `kiwix::getDataDirectory()` (@sgourdas #1107)
- New string slugification for filenames (@shaopenglin #1105)
- Multiple improvements around aria2c download mgmt. (@veloman-yunkan #1097)
libkiwix 13.1.0
===============
* Server:
- Properly translated error pages (@veloman-yunkan #1032)
- Properly translated search result page (@veloman-yunkan #1046)
- Default UI language is resolved in frontend (@veloman-yunkan #1044)
- Better support of older Web browsers by polyfilling replaceAll() (@veloman-yunkan #1054)
* New API to migrate bookmarks between books (@mgautierfr #1043)
* Fixed compilation on Haiku OS (@Begasus #1048)
libkiwix 13.0.0
===============
* Server:
- Improved look & feel of kiwix-serve UI (@veloman-yunkan #917 #1021)
- Increase tolerance to malformed (control characters) ZIM entry titles (@veloman-yunkan #1023)
- API allowing to filter many categories at once (@juuz0 #974)
- Cookie-less user language control (@veloman-yumkan #997)
- Hack to fix Mirrorbrain based broken magnet URLs (@rgaudin #1001)
* Fix handling of books with 'Name' metadata with dots (@mgautier #1016)
* New method beautifyFileSize() to provide nice-looking book sizes (@vuuz0 #971)
* Fix a few missing includes (@mgautierfr #978)
* New functions to read - kiwix-serve - languages and categories streams (@juuz0 #967)
* Add support of Fon language (@kelson42 #1013)
* C++17 code base compliancy (@mgautierfr #996)
* Use everywhere std::shared_ptr in place of raw pointer (@mgautierfr #991)
* Do not use [[nodiscard]] attribute on compiler not supporting it (@mgautierfr #1003)
* Add a non minified version of autoComplete.js (@mgautierfr #1008)
* Multiple CI/CD improvements (@kelson42 #982)
libkiwix 12.1.0
===============
* Server:
- Introduce a `/nojs` endpoint to browse catalog and zim files with a browser without js (@juuz0 #897)
- Translate the viewer (@veloman-yunkan #871 #846)
- Display `mul` on tile when zim is multi-languages (@juuz0 #934)
- Suggestion links point to the `/content` endpoint (@veloman-yunkan #862)
- Correctly compress web fonts in http answers (@kelson42 #856)
- Correctly encode link in suggestions (@veloman-yunkan #859 #860 #963)
- Correctly encode url redirection (@veloman-yunkan #866 #890)
- Properly handle user language, through cookies and http headers (@veloman-yunkan #849 #869)
- Fix url encoding (@veloman-yunkan #870)
- Fix viewer for viewer for SeaMonkey (@veloman-yunkan #887)
- Make the downloader threadsafe (@mgautierfr #886)
- Add RSS feed in the main page (pointing to the catalog) (@juuz0 #882 #920)
- Correctly set the mimetype for json and ico (@veloman-yunkan #892)
- `count=-1` correspond to unlimited count (instead of 0) (@veloman-yunkan #894)
- Keep the navigation bar on top (@juuz0 #896)
- Make the viewer's iframe "safe" (@veloman-yunkan #906 #930)
- Correctly escape search link in XML Opds output (@veloman-yunkan #936)
- Store values needed for the viewer js in the url fragment instead of the query string (@juuz0 #907)
- Get rid of legacy OPDS API usage in the viewer (@veloman-yunkan #939)
- Fix charset encoding declaration in OPDS response MIME types (@veloman-yunkan #942)
- Fix PDF in the viewer (@veloman-yunkan #940)
- Fix external links handling in the viewer (@veloman-yunkan #959)
- Add tests of searching with accents (@mgautierfs #954)
* Fix handling of missing illustration in the book (@veloman-yunkan #961)
* Add support for multi languages zim files (@veloman-yunkan #904)
* Fix includes for openbsd (@bentley #949)
* Fix pathes in git to allow git clone on Windows (@adamlamar #868)
* Switch to `main` as principal branch (instead of `master`) (@kelson42)
* Remove libkiwix android publisher from the repository (@kelson42 #884)
* Various fixes of meson and CI. (@mgautierfr @kelson42)
libkiwix 12.0.0
===============
* [API Break] Remove wrapper around libzim (@mgautierfr #789)
* Allow kiwix-serve to use custom resource files (@veloman-yunkan #779)
* Properly handle searchProtocolPrefix when rendering search result (@veloman-yunkan #823)
* Prevent search on multi language content (@veloman-yunkan #838)
* Use new `zim::Archive::getMediaCount` from libzim (@mgautierfr #836)
* Catalog:
- Include tags in free text catalog search (@veloman-yunkan #802)
- Illustration's url is based on book's uuid (@veloman-yunkan #804)
- Cleanup of the opds-dumper (@veloman-yunkan #829)
- Allow filtering of catalog content using multiple languages (@veloman-yunkan #841)
- Make opds-dumper respect the namemapper (@mgautierfr #837)
* Server:
- Correctly handle `\` in suggestion json generation (@veloman-yunkan #843)
- Better http caching (@veloman-yunkan #833)
- Make `/suggest` endpoint thread-safe (@veloman-yunkan #834)
- Better redirection of main page (@veloman-yunkan #827)
- Remove jquery (@mgautierfr @juuz0 #796)
- Better Viewer of zim content :
. Introduce `/content` endpoints (@veloman-yunkan #806)
. Switch to iframe based content viewer (@veloman-yunkan #716)
- Optimised design of the welcome page:
. Alignement (@juuz0 @kelson42 #786)
. Exit download modal on pressing escape key (@juzz0 #800)
. Add favicon for different devices (@juzz0 #805)
. Fix auto hidding of the toolbar (@veloman-yunkan #821)
. Allow user to filter books by tags in the front page (@juuz0 #711)
* CI :
- Trigger CI on pull_request (@kelson42 #791)
- Drop Ubuntu Impish packaging (@legoktm #825)
- Add Ubuntu Kinetic packaging (@legoktm #801)
* Testing:
- Test ICULanguageInfo (@veloman-yunkan #795)
- Introduce fake `test` language to test i18n (@veloman-yunkan #848)
* Fix documentation (@kelson42 #816)
* Udpate translation (#787 #839 #847)
libkiwix 11.0.0
===============
* [server] Add support for internationalization (@veloman-yunkan #679)
* [server] Use gzip compression instead of deflat (mgautierfr #757)
* [server] Version the static resources. This allow better invalidating
browser cache when resources are changed (@veloman-yunkan #712)
* [server|front] Use integer to query the host for page length (@juuz0 #772)
* [server] Improve multizim search API:
- Improvement of the cache system
- Better API to select on which books to search in.
- SysAdmin is now able to limit the number of book we search in for a multizim search
* [server] Introduce a opensearch API for multizim fulltext search
* [wrapper] Remove java wrapper
* Testing:
- Testing of search result pages content (@veloman-yunkan #765)
- Better testing structure of xml search result (@veloman-yunkan #780)
libkiwix 10.1.1
===============
* Correctly detect the number of article for older zims (<=6) (@mgautier #743)
* [server] Fix fulltext search (@mgautierfr #724)
* [server][internal] New way to build Error message (@veloman-yunkan #732 #738 #744)
* Fix CI (@mgautierfr #736)
libkiwix 10.1.0
===============
This release is an important one as it fixes a Xss vulnerability introduced
in libkiwix 10.0.0
* [SECURITY] Fix a Xss attack vulnerability (introduced in 10.0.0) (@juuz0 #721)
* [server] Add a option to set a limit on the number of connexion per IP (@kelson42 #700)
* [server] Do not display a lang tag in the UI if the book has no language (@juuz0 #706)
* [server] Add the book title associated to a search results (@thavelick #705, @mgautierfr #718)
* Add `dc:issued` to opds output stream (@veloman-yunkan #715)
* Add handling of several languages not provided by ICU (@juuz0 #701)
* [server] Add a caching system for search and suggestion (@maneeshpm #620)
* Fix cross-compilation (@kelson42 #703)
* Add unit-testing of suggestions and error pages (@veloman-yunkan #709 #710 #727)
* Better testing system of html response (@veloman-yunkan #725)
libkiwix 10.0.1
===============
* [server] The catalog search interpret `count=0` as no limit.
This was the case for a long time. This was changed unintentionally
(@veloman-yunkan #686)
* [server] Correctly generere a human friendly title in the server frontend.
(@juuz0 #687, @kelson42 #689)
* [server] Fix download button if there is no url do download from.
(@juuz0 #691)
* Add non-minified isotope.pkdg.js
Needed for debian packaging as we need the source and minified version is
not the source (@legoktm #693)
* [server] Add a tooltip with the full language for the lang tag.
* CI fixes (@kelson42 @legoktm)
libkiwix 10.0.0
===============
This release is huge release.
The project has been renamed to libkiwix, it is more coherent with the library name.
* Server front page :
- Use js in the front page to display the available book,
using the OPDS stream as source. The front page is now populated only with
the visible books and user can search for books. (@MananJethwany #530, #541, #534)
(@kelson42 #628)
- Revamp css (@MananJethwany #559)
- Correctly Convert 3iso language code to 2iso (@juuz0 #672)
* Server suggestions search :
- Add pagination for suggestion search (@maneeshpm #591)
- Fix suggestion system (@MananJethwany #498)
- Provide the kind and path (when adapted) to the suggestion answer (@MananJethwany #464)
- The displayed suggestion have now highligth on the searched terms (@maneeshpm #505)
- Properly handle html encoding of suggestions (@veloman-yunkan #458)
* Server improvements :
- Remove meta endpoints (@mgautier #669)
- Add raw endpoints to get the raw content of a zim (@mgautierfr #646)
- Add details on 404 error pages (@soumyankar #490)
- Fix headbar insertion when `<head>` tag has attributes (@kelson42 #440)
- Better headbar insertion (after charset definition) (@kelson42 #442)
* New OPDS Stream v2 :
- Add a list of categories (@veloman-yunkan)
- Support for partial entries (@veloman-yunkan #602)
- Support multiple icons size in the OPDS stream (@veloman-yunkan #577 #630)
- Add language endpoint to catalog (@veloman-yunkan #553)
- Add illustration API to get the illustration of a book (@mgautierfr #645)
- OPDS search can now filter books by category (@veloman-yunkan #459)
* Library improvements :
- Allow the libray to be live reloaded when the library.xml changes (@veloman-yunkan #636)
- Properly handle removing of book from the library (@veloman-yunkan #485)
- Use xapian to search for books in the library (@veloman-yunkan #460, #488)
* Added methods/functions :
- Fix `fileExist` and introduce `fileReadable` (@juuz0 #668)
- Add `getVersions` and `printVersions` functions (@kelson42 #665)
- Add `getNetworkInterfaces()` and `getBestPublicIP()` functions (@juuz0 #622)
- Add `get_zimid()` method to the search result (@maneeshpm #510)
* Various improvements :
- Better secret value for aria2c rpc (@juuz0 #666)
- Avoid duplicated Archive/Reader in the Searcher (@veloman-yunkan #648)
- Add basic documentation (@mgautierfr #640)
- Do not use Reader internally (@maneeshpm #536 #576)
- Remove dependency headers from our public headers (@mgautierfr #574)
- Downloader now don't write metalink on the filesystem (@kelson42 #502)
- Support opening a zim file using a fd (@veloman-yukan #429)
- Use C++11 std::thread instead of pthread (@mgautierfr #445)
- [READER] Do not crash if zim file has no `Counter` metadata (@mgautierfr #449)
- Ensure libzim dependency is compiled with xapian (@mgautierfr #434)
- Support video and audio mimetype in `getMediaCount` (@kelson42 #439)
- Better parsing of the counterMap (@kelson42 #437)
- Adapt libkiwix to libzim 7.0.0 (@mgautierfr #428)
- Remove deprecated methods (@mgautierfr)
- CI: Build package for Ubuntu Hirsute, Impish and Jammy (@legoktm #431 #568) and remove Groovy
- Fix compilation for FreeBSD (@swills g#432)
- Many fixes and improvement (@MananJethwany, @maneeshpm, @veloman-yunkan, @mgautierfr)
kiwix-lib 9.4.1
===============
* Fix `M/Counter` parsing.
* [SERVER] Adjust body padding-top for taskbar
* Fix potential crash when stoping a server not started.
* Various fix in build system and the CI.
kiwix-lib 9.4.0
===============
* [SERVER] Make the headers handling case insensitive.
* [SERVER] Make server answer 204 http status code for empty search
* [PACKAGING] Made CI build deb packages.
* [SERVER] Add a way to prevent taskbar and external link bloquer at article
level.
* Fix meson file to be compatible with meson 0.45
* [SERVER] Update search requests to use pageStart/pageLength instead of
pageStart/pageEnd arguments.
* [SERVER] Set a fixed favicon size in the main page.
* [SERVER] Refactor the response system code to better handling future new
libzim api.
* Fix segmentation fault around exchange with aria2 process making
kiwix-desktop crash at exit.
kiwix-lib 9.3.1
===============
* Fix handling of samba path on windows.
* Do not include `kiwix_config.h` in public header.
* Fix compilation with libmicrohttpd v0.97.1
* Increase default test timeout to 160seconds/test.
* Add automatic debian packaging.
* Use non-minified version of jquery-ui.js
* Pass `-latomic` compile option for sh4 architecture.
* Make mesion install `kiwix-compile-resources` man page.
kiwix-lib 9.3.0
===============
* Add a thread safe method to search suggestions.
Old methods are now deprecated.
kiwix-lib 9.2.3
===============
* Add test on byte-range
* Fix compilation on bionic and windows.
* Allow building using debian packaged kainjow-mustache
* Pass `-latomic` compile option for architectures that need it
kiwix-lib 9.2.2
===============
* Fix handling on empty content in byte range management (wrong assert)
kiwix-lib 9.2.1
===============
* Fix support of byte range request.
kiwix-lib 9.2
=============
* Add tests
* Refactoring server code.
* [SERVER] Add HEAD, Etag and If-None-Match support.
* [SERVER] Compress opds catalog answers.
kiwix-lib 9.1.2
===============
* Do not use the pathToSave if it is empty.
kiwix-lib 9.1.1
===============
* Fix the detection of the dataDirectory on windows.
kiwix-lib 9.1.0
===============
* [JAVA] Add a method to get the size of an article.
* Add a new method to the libray to get the book by path.
* Add a option to make the server blocks external link.
Links are intercepted by js an redirected to a "portail" page.
* [ODPS] Correctly handle book's articleCount and mediaCount.
kiwix-lib 9.0.1
===============
* [JAVA] Use a long to store the offset of an article in the zim file instead
of an int.
kiwix-lib 9.0.0
===============
* [OPDS] Correctly set the id of the OPDS stream.
* [OPDS] Do not try to filter the catalog if no filter field is given in the
request.
* [WINDOWS] Correctly convert path to wide chars when opening the library.xml
* [LIBRARY] Remove the function the read file using a native path.
All path must be utf8, no need to pass a native path along the utf8 path.
* [TEST] Fix tests using the main function of gtest instead of custom one.
* [CI] Move to github CI instead of Travis.
* The `Book::update` method always update the book's fields. Even if they are
not empty.
* [JAVA] Add wrapping around the library manager (opds parsing)
* [ARIA2] Add api option to start download with option (destination folder)
* [OPDS] Fixes about opds parsing, generation (missing attributes)
and requesting (server)
* Add methods on `Book` to get specific tag values (was on `Reader` only)
* Add flavour attribute to `Book`
* Fix opensearch description.
* Trust the given library.xml (by default) instead of reading the value from
the zim files.
* [OPDS] Be able to filter the content by name or size.
* [WINDOWS] Fix launching subcommand when there is spaces in the path.
kiwix-lib 8.2.2
===============
* Improve a few compilation scripts
kiwix-lib 8.2.1
===============
* Reintroduce kiwix-serve taskbar
kiwix-lib 8.2.0
===============
* More debug information if aria2c command fails
* Allow to set kiwix-serve port
* Better (dead) bookmarks mgmt
kiwix-lib 8.1.0
===============
* Fix pathTools manipulation.
* Add missing implementation of getArticleCount and getMediaCount on android.
* Correctly convert windows path to utf8.
* Add code coverage in the CI
kiwix-lib 8.0.1
===============
* Fix join function
kiwix-lib 8.0.0
===============
* Add new methods to get all (and new) metadata from the zim file.
* Add methods to get the value of a specific tag.
* [API Change] Convert tags value to the new convention.
* [API Change] Rename `getMatatag` method to `getMetadata`
* [ABI Change] Correctly detect executable path in appimage.
kiwix-lib 7.0.0
===============
* [API break] Add a argument to kiwix-serve to specify the library to use.
kiwix-lib 6.0.4
===============
* Fix HTML rendering of the search result if there is no result.
* Do not crash at html rendering if request ask for 0 results (start == end)
* Correctly find the executable path if we are using AppImage
kiwix-lib 6.0.3
===============
* force one column suggestion in kiwix-serve suggestions
* fix fulltext search link in suggestions
* UI fixes in kiwix-serve rendering
kiwix-lib 6.0.2
===============
* Correctly set the groupId in the pom file.
kiwix-lib 6.0.1
===============
* Generate the pom file for android/maven
kiwix-lib 6.0.0
===============
* Move the server code in kiwix-lib (from kiwix-serve).
* Add unit test on regex functions.
* Fix computerAbsolutePath (thread safe, memory leak).
* Correctly set the book's path as valid if we construct the book from a
reader.
* [JNI] Add a method to know if a article is a redirection.
* Do not embed the gtest dependency.
* [JNI] Add a constructor to JNIKiwixString.
* Change order of search of the favicon urls.
* Clean a lot of unecessary includes in headers. (potential "API break")
kiwix-lib 5.2.0
===============
* kiwix-serve integration (as a seperated process).
* Fix crash in the suggestion search.
* Better API to filter the library books.
* New kiwix-lib application for android. (.aar)
* Use ReLinker to link with libkiwix.so in android.
* Correctly set the verbosity of zim search.
kiwix-lib 5.1.0
===============
* Add function to pause, resume and stop downloads.
* Add zim's tags in the opds stream.
* Addapt to new libzim 5.0.0 API.
kiwix-lib 5.0.0
===============
* Remove error message when trying to open an wrong zim file.
* Rewrite `makeTmpDirectory` to not use uuid functions on windows.
* [API break] Remove `getNetworkInterfaces` and `getBestPublicIp`.
* Remove rpath
* Detect infinite (and too long) redirect loops.
kiwix-lib 4.1.0
===============
* Allow the library to be filtered by tags.
* Fix language mapping.
* Update README about mustache dependency.
kiwix-lib 4.0.1
===============
* Fix "maybe uninitialize variable" issue.
* Ensure path are stored correctly (absolute path) in the library.
* [CI] Use the new deps archive xz
kiwix-lib 4.0.0
===============
* [API break] Remove support for external index.
* Move to the mustache templating system instead of ctpp2.
* Make meson.build works for meson>=0.43.0
* [API break] Move the basic tools from the `common` directory to `tools`.
kiwix-lib 3.1.1
===============
* The OPDS feed book's date must be the date of the book, not the date of the
feed generation.
* Convert the standard opds date to our format (YYYY-MM-DD)
* Remove duplicate language attribute in the libxml dumper.
* Create the datadirectory to not fail to write a file in a non-existent
directory
kiwix-lib 3.1.0
===============
* Add a method to get the favicon url of book (if available).
* Move dump code of library.xml in a specific class.
* Add a first support to bookmarks
kiwix-lib 3.0.3
===============
* Add the 'en' language to the mapping alpha2-code ('en') to alpha3-code
('eng').
* Correctly write the 'ArticleCount' and 'MediaCount' in the library.xml.
* Correctly fill the book size for the zim file size.
* Fix launch of aria2c.
kiwix-lib 3.0.2
===============
+153 -59
View File
@@ -1,121 +1,220 @@
Kiwix library
=============
Libkiwix
========
The Kiwix library provides the Kiwix software core. It contains the
code shared by all Kiwix ports (Windows, Linux, OSX, Android, ...).
The Libkiwix provides the [Kiwix](https://kiwix.org) software suite
core. It contains the code shared by all Kiwix ports (Windows,
GNU/Linux, macOS, Android, iOS, ...).
[![Release](https://img.shields.io/github/v/tag/kiwix/libkiwix?label=release&sort=semver)](https://download.kiwix.org/release/libkiwix/)
[![Repositories](https://img.shields.io/repology/repositories/libkiwix?label=repositories)](https://github.com/kiwix/libkiwix/wiki/Repology)
[![Build Status](https://github.com/kiwix/libkiwix/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/kiwix/libkiwix/actions?query=branch%3Amain)
[![Doc](https://readthedocs.org/projects/libkiwix/badge/?style=flat)](https://libkiwix.readthedocs.org/en/latest/?badge=latest)
[![CodeFactor](https://www.codefactor.io/repository/github/kiwix/libkiwix/badge)](https://www.codefactor.io/repository/github/kiwix/libkiwix)
[![Codecov](https://codecov.io/gh/kiwix/libkiwix/branch/main/graph/badge.svg)](https://codecov.io/gh/kiwix/libkiwix)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
Disclaimer
----------
This document assumes you have a little knowledge about software
compilation. If you experience difficulties with the dependencies or
with the Kiwix libary compilation itself, we recommend to have a look
to [kiwix-build](https://github.com/kiwix/kiwix-build).
with the Libkiwix compilation itself, we recommend to have a look to
[kiwix-build](https://github.com/kiwix/kiwix-build).
Preamble
--------
Although the Kiwix library can be (cross-)compiled on/for many
sytems, the following documentation explains how to do it on POSIX
ones. It is primarly thought for GNU/Linux systems and has been tested
on recent releases of Ubuntu and Fedora.
Although the Libkiwix can be (cross-)compiled on/for many systems, the
following documentation explains how to do it on POSIX ones. It is
primarily thought for GNU/Linux systems and has been tested on recent
releases of Ubuntu and Fedora.
Dependencies
------------
The Kiwix library relies on many third parts software libraries. They
are prerequisites to the Kiwix library compilation. Following
libraries need to be available:
The Libkiwix relies on many third party software libraries. They are
prerequisites to the Libkiwix compilation. Following libraries need to
be available:
* [ICU](https://site.icu-project.org/) (package `libicu-dev` on Ubuntu)
* [ZIM](https://openzim.org/) (package `libzim-dev` on Ubuntu)
* [Pugixml](https://pugixml.org/) (package `libpugixml-dev` on Ubuntu)
* [Mustache](https://github.com/kainjow/Mustache) (Just copy the
header `mustache.hpp` somewhere it can be found by the compiler and/or
set CPPFLAGS with correct `-I` option). Use Mustache version 4.1 or above.
* [Libcurl](https://curl.se/libcurl) (`libcurl4-gnutls-dev`, `libcurl4-nss-dev` or `libcurl4-openssl-dev` on Ubuntu)
* [Microhttpd](https://www.gnu.org/software/libmicrohttpd) (package `libmicrohttpd-dev` on Ubuntu)
* [Zlib](https://zlib.net/) (package `zlib1g-dev` on Ubuntu)
* ICU ................................... http://site.icu-project.org/
(package libicu-dev on Ubuntu)
* ZIM ........................................ http://www.openzim.org/
(package libzim-dev on Ubuntu)
* Pugixml ........................................ http://pugixml.org/
(package libpugixml-dev on Ubuntu)
* ctpp2 ........................................ http://ctpp.havoc.ru/
(package libctpp2-dev on Ubuntu)
* Xapian ......................................... https://xapian.org/
(package libxapian-dev on Ubuntu)
* libaria2 .................................. https://aria2.github.io/
(no package on Ubuntu)
To test the code:
* [Google Test](https://github.com/google/googletest) (package `googletest` on Ubuntu)
The following dependency needs to be available at runtime:
* [Aria2](https://aria2.github.io/) (package `aria2` on Ubuntu)
These dependencies may or may not be packaged by your operating
system. They may also be packaged but only in an older version. The
compilation script will tell you if one of them is missing or too old.
In the worse case, you will have to download and compile bleeding edge
In the worst case, you will have to download and compile bleeding edge
version by hand.
If you want to install these dependencies locally, then use the
kiwix-lib directory as install prefix.
If you compile ctpp2 from source and want to compile the Kiwix library
statically then you will probably need to rename ctpp2 static library
from ctpp2-st.a to ctpp2.a.
`libkiwix` directory as install prefix.
Environment
-------------
The Kiwix library builds using [Meson](http://mesonbuild.com/) version
0.39 or higher. Meson relies itself on Ninja, pkg-config and few other
The Libkiwix builds using [Meson](https://mesonbuild.com/) version
0.45 or higher. Meson relies itself on Ninja, pkg-config and few other
compilation tools.
Install first the few common compilation tools:
* Meson
* Ninja
* Pkg-config
* [Meson](https://mesonbuild.com/)
* [Ninja](https://ninja-build.org/)
* [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/)
These tools should be packaged if you use a cutting edge operating
system. If not, have a look to the "Troubleshooting" section.
system. If not, have a look to the [Troubleshooting](#Troubleshooting)
section.
Compilation
-----------
Once all dependencies are installed, you can compile the Kiwix library
Once all dependencies are installed, you can compile the Libkiwix
with:
```
```bash
meson . build
ninja -C build
```
By default, it will compile dynamic linked libraries. All binary files
will be created in the "build" directory created automatically by
will be created in the `build` directory created automatically by
Meson. If you want statically linked libraries, you can add
`--default-library=static` option to the Meson command.
Depending of you system, `ninja` may be called `ninja-build`.
The android wrapper uses deprecated methods of libkiwix so it cannot be compiled
with `werror=true` (the default). So you must pass `-Dwerror=false` to meson:
```bash
meson . build -Dwrapper=android -Dwerror=false
ninja -C build
```
Static files compilation
------------------------
Libkiwix has a few static files 'compiled' within the binary
code. This is mostly Javascript/HTML/pictures necessary for the HTTP
daemon.
These static files are available in the `static` directory and are
compiled by custom Python code available in this repository `scripts`
directory. This happens automatically at compilation time without any
additional command to run.
To avoid HTTP caching issues, the URLs (to the static content) are
appended with a `cacheid` parameter (this is called "cache
busting"). This `cacheid` value derived from the
[sha1sum](https://en.wikipedia.org/wiki/Sha1sum) of each targeted
static file. As a consequence, each time you change a static file, the
corresponding `cacheid` value will change.
To properly test this feature, this `cacheid` needs to be added
manually to the automated tests and has to be commited. After
modifying the needed static file, [run the automated
tests](#Testing). They will fail, but the inspection of the testing
log will give you the new `cacheid` value(s). Finally update
`test/server.cpp` with the appropriate `cacheid` value(s) which have
changed.
Testing
-------
To run the automated tests:
```bash
cd build
meson test
```
Installation
------------
If you want to install the Kiwix library and the headers you just have
If you want to install the Libkiwix and the headers you just have
compiled on your system, here we go:
```
```bash
ninja -C build install
```
You might need to run the command as root (or using 'sudo'), depending
You might need to run the command as root (or using `sudo`), depending
where you want to install the libraries. After the installation
succeeded, you may need to run ldconfig (as root).
succeeded, you may need to run `ldconfig` (as `root`).
Uninstallation
------------
--------------
If you want to uninstall the Kiwix library:
```
```bash
ninja -C build uninstall
```
Like for the installation, you might need to run the command as root
(or using 'sudo').
Like for the installation, you might need to run the command as `root`
(or using `sudo`).
Custom Index Page
-----------------
to use custom welcome page mention `customIndexPage` argument in `kiwix::internalServer()` or use `kiwix::server->setCustomIndexTemplate()`.
(note - while using custom html file please mention all external links as absolute path.)
to create a HTML template with custom JS you need to have a look at various OPDS based endpoints as mentioned [here](https://wiki.kiwix.org/wiki/OPDS) to load books.
To use JS provided by kiwix-serve you can use the following template to start with ->
```
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title><-- Custom Tittle --></title>
<script src="{{root}}/skin/isotope.pkgd.min.js" defer></script>
<script src="{{root}}/skin/iso6391To3.js"></script>
<script type="text/javascript" src="{{root}}/skin/index.js" defer></script>
</head>
<body>
</body>
</html>
```
- To get books listed using `index.js` add - `<div class="book__list"></div>` under body tag.
- To get number of books listed add - `<h3 class="kiwixHomeBody__results"></h3>` under body tag.
- To add language select box add - `<select id="languageFilter"></select>` under body tag.
- To add category select box add - `<select id="categoryFilter"></select>` under body tag.
- To add search box for books use following form -
```
<form id='kiwixSearchForm'>
<input type="text" name="q" placeholder="Search" id="searchFilter" class='kiwixSearch filter'>
<input type="submit" class="kiwixButton" value="Search"/>
</form>
```
If you compile manually Libmicrohttpd, you might need to compile it
without GNU TLS, a bug here will impeach further compilation
otherwise.
If the compilation still fails, you might need to get a more recent
version of a dependency than the one packaged by your Linux
distribution. Try then with a source tarball distributed by the
problematic upstream project or even directly from the source code
repository.
Troubleshooting
---------------
If you need to install Meson "manually":
```
```bash
virtualenv -p python3 ./ # Create virtualenv
source bin/activate # Activate the virtualenv
pip3 install meson # Install Meson
@@ -123,7 +222,7 @@ hash -r # Refresh bash paths
```
If you need to install Ninja "manually":
```
```bash
git clone git://github.com/ninja-build/ninja.git
cd ninja
git checkout release
@@ -133,13 +232,8 @@ cp ninja ../bin
cd ..
```
If the compilation still fails, you might need to get a more recent
version of a dependency than the one packaged by your Linux
distribution. Try then with a source tarball distributed by the
problematic upstream project or even directly from the source code
repository.
License
-------
GPLv3 or later, see COPYING for more details.
[GPLv3](https://www.gnu.org/licenses/gpl-3.0) or later, see
[COPYING](COPYING) for more details.
+5
View File
@@ -0,0 +1,5 @@
libkiwix (0.0.0) unstable; urgency=medium
* Initial release
-- Kunal Mehta <legoktm@debian.org> Wed, 08 Jul 2020 18:12:32 -0700
+47
View File
@@ -0,0 +1,47 @@
Source: libkiwix
Priority: optional
Maintainer: Kiwix team <kiwix@kiwix.org>
Build-Depends: debhelper-compat (= 13),
meson,
pkgconf,
libzim-dev (>= 9.0), libzim-dev (<< 10.0),
libcurl4-gnutls-dev,
libicu-dev,
libgtest-dev,
libkainjow-mustache-dev,
libmicrohttpd-dev,
libpugixml-dev,
zlib1g-dev
Standards-Version: 4.5.0
Section: libs
Homepage: https://github.com/kiwix/libkiwix
Rules-Requires-Root: no
Package: libkiwix-dev
Section: libdevel
Architecture: any
Multi-Arch: same
Depends: libkiwix14 (= ${binary:Version}), ${misc:Depends}, python3,
libzim-dev (>= 9.0), libzim-dev (<< 10.0),
libicu-dev,
libpugixml-dev,
libcurl4-gnutls-dev,
libmicrohttpd-dev,
zlib1g-dev
Description: library of common code for Kiwix (development)
Kiwix is an offline Wikipedia reader. libkiwix provides the
software core for Kiwix, and contains the code shared by all
Kiwix ports (Windows, Linux, OSX, Android, etc.).
.
This package contains development files.
Package: libkiwix14
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends}, ${misc:Depends}, aria2
Conflicts: libkiwix0, libkiwix3, libkiwix9, libkiwix10, libkiwix11, libkiwix12, libkiwix13
Replaces: libkiwix0, libkiwix3, libkiwix9, libkiwix10, libkiwix11, libkiwix12, libkiwix13
Description: library of common code for Kiwix
Kiwix is an offline Wikipedia reader. libkiwix provides the
software core for Kiwix, and contains the code shared by all
Kiwix ports (Windows, Linux, OSX, Android, etc.).
+1
View File
@@ -0,0 +1 @@
See COPYING in the repository root.
+4
View File
@@ -0,0 +1,4 @@
usr/include
usr/lib/*/libkiwix.so
usr/lib/*/pkgconfig
usr/bin
+2
View File
@@ -0,0 +1,2 @@
usr/share/man/man1/kiwix-compile-resources.1*
usr/share/man/man1/kiwix-compile-i18n.1*
+1
View File
@@ -0,0 +1 @@
usr/lib/*/libkiwix.so.*
Vendored Executable
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/make -f
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
%:
dh $@ --buildsystem=meson
override_dh_auto_test:
dh_auto_test -- -t 3
+1
View File
@@ -0,0 +1 @@
3.0 (native)
+2
View File
@@ -0,0 +1,2 @@
api
xml
+68
View File
@@ -0,0 +1,68 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'libkiwix'
copyright = '2026, libkiwix-team'
author = 'libkiwix-team'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'breathe',
'exhale'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
breathe_projects = {
"libkiwix": "./xml"
}
breathe_default_project = 'libkiwix'
exhale_args = {
"containmentFolder": "./api",
"rootFileName": "ref_api.rst",
"rootFileTitle": "Reference API",
"doxygenStripFromPath":"..",
"treeViewIsBootstrap": True,
"createTreeView" : True,
"exhaleExecutesDoxygen": True,
"exhaleDoxygenStdin": "INPUT = ../include"
}
primary_domain = 'cpp'
highlight_language = 'cpp'
+14
View File
@@ -0,0 +1,14 @@
.. libkiwix documentation master file, created by
sphinx-quickstart on Fri Jul 24 15:40:50 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to libkiwix's documentation!
==================================
.. toctree::
:maxdepth: 2
:caption: Contents:
usage
api/ref_api
+7
View File
@@ -0,0 +1,7 @@
sphinx = find_program('sphinx-build', native:true)
sphinx_target = run_target('doc',
command: [sphinx, '-bhtml',
meson.current_source_dir(),
meson.current_build_dir()])
+3
View File
@@ -0,0 +1,3 @@
breathe
exhale
sphinx_rtd_theme
+15
View File
@@ -0,0 +1,15 @@
Libkiwix programming
====================
Introduction
------------
libkiwix is written in C++. To use the library, you need the include files of libkiwix have
to link against libzim.
Errors are handled with exceptions. When something goes wrong, libkiwix throws an error,
which is always derived from std::exception.
All classes are defined in the namespace kiwix.
libkiwix is a set of tools to manage zim files and provide some common functionnality.
-36
View File
@@ -1,36 +0,0 @@
#!/usr/bin/bash
files=(
"include/library.h"
"include/common/stringTools.h"
"include/common/pathTools.h"
"include/common/otherTools.h"
"include/common/regexTools.h"
"include/common/networkTools.h"
"include/manager.h"
"include/reader.h"
"include/kiwix.h"
"include/xapianSearcher.h"
"include/searcher.h"
"src/library.cpp"
"src/android/kiwix.cpp"
"src/android/org/kiwix/kiwixlib/JNIKiwixBool.java"
"src/android/org/kiwix/kiwixlib/JNIKiwix.java"
"src/android/org/kiwix/kiwixlib/JNIKiwixString.java"
"src/android/org/kiwix/kiwixlib/JNIKiwixInt.java"
"src/searcher.cpp"
"src/common/pathTools.cpp"
"src/common/regexTools.cpp"
"src/common/otherTools.cpp"
"src/common/networkTools.cpp"
"src/common/stringTools.cpp"
"src/xapianSearcher.cpp"
"src/manager.cpp"
"src/reader.cpp"
)
for i in "${files[@]}"
do
echo $i
clang-format -i -style=file $i
done
+62 -25
View File
@@ -21,62 +21,94 @@
#define KIWIX_BOOK_H
#include <string>
#include <vector>
#include <memory>
#include <mutex>
#include "common.h"
namespace pugi {
class xml_node;
}
namespace zim {
class Archive;
}
namespace kiwix
{
enum supportedIndexType { UNKNOWN, XAPIAN };
class OPDSDumper;
class Reader;
/**
* A class to store information about a book (a zim file)
*/
class Book
{
public:
public: // types
class Illustration
{
friend class Book;
public:
uint16_t width = 48;
uint16_t height = 48;
std::string mimeType;
std::string url;
const std::string& getData() const;
private:
mutable std::string data;
mutable std::mutex mutex;
};
typedef std::vector<std::shared_ptr<const Illustration>> Illustrations;
public: // functions
Book();
~Book();
bool update(const Book& other);
void update(const Reader& reader);
void update(const zim::Archive& archive);
void updateFromXml(const pugi::xml_node& node, const std::string& baseDir);
void updateFromOpds(const pugi::xml_node& node, const std::string& urlHost);
std::string getHumanReadableIdFromPath();
std::string getHumanReadableIdFromPath() const;
bool readOnly() const { return m_readOnly; }
const std::string& getId() const { return m_id; }
const std::string& getPath() const { return m_path; }
bool isPathValid() const { return m_pathValid; }
const std::string& getIndexPath() const { return m_indexPath; }
const supportedIndexType& getIndexType() const { return m_indexType; }
const std::string& getTitle() const { return m_title; }
const std::string& getDescription() const { return m_description; }
const std::string& getLanguage() const { return m_language; }
DEPRECATED const std::string& getLanguage() const { return m_language; }
const std::string& getCommaSeparatedLanguages() const { return m_language; }
const std::vector<std::string> getLanguages() const;
const std::string& getCreator() const { return m_creator; }
const std::string& getPublisher() const { return m_publisher; }
const std::string& getDate() const { return m_date; }
const std::string& getUrl() const { return m_url; }
const std::string& getName() const { return m_name; }
std::string getCategory() const;
const std::string& getTags() const { return m_tags; }
std::string getTagStr(const std::string& tagName) const;
bool getTagBool(const std::string& tagName) const;
const std::string& getFlavour() const { return m_flavour; }
const std::string& getOrigId() const { return m_origId; }
const uint64_t& getArticleCount() const { return m_articleCount; }
const uint64_t& getMediaCount() const { return m_mediaCount; }
const uint64_t& getSize() const { return m_size; }
const std::string& getFavicon() const;
const std::string& getFaviconMimeType() const { return m_faviconMimeType; }
DEPRECATED const std::string& getFavicon() const;
DEPRECATED const std::string& getFaviconUrl() const;
DEPRECATED const std::string& getFaviconMimeType() const;
Illustrations getIllustrations() const;
std::shared_ptr<const Illustration> getIllustration(unsigned int size) const;
const std::string& getDownloadId() const { return m_downloadId; }
void setReadOnly(bool readOnly) { m_readOnly = readOnly; }
void setId(const std::string& id) { m_id = id; }
void setPath(const std::string& path);
void setPathValid(bool valid) { m_pathValid = valid; }
void setIndexPath(const std::string& indexPath);
void setIndexType(supportedIndexType indexType) { m_indexType = indexType;}
void setTitle(const std::string& title) { m_title = title; }
void setDescription(const std::string& description) { m_description = description; }
void setLanguage(const std::string& language) { m_language = language; }
@@ -85,39 +117,44 @@ class Book
void setDate(const std::string& date) { m_date = date; }
void setUrl(const std::string& url) { m_url = url; }
void setName(const std::string& name) { m_name = name; }
void setFlavour(const std::string& flavour) { m_flavour = flavour; }
void setTags(const std::string& tags) { m_tags = tags; }
void setOrigId(const std::string& origId) { m_origId = origId; }
void setArticleCount(uint64_t articleCount) { m_articleCount = articleCount; }
void setMediaCount(uint64_t mediaCount) { m_mediaCount = mediaCount; }
void setSize(uint64_t size) { m_size = size; }
void setFavicon(const std::string& favicon) { m_favicon = favicon; }
void setFaviconMimeType(const std::string& faviconMimeType) { m_faviconMimeType = faviconMimeType; }
void setDownloadId(const std::string& downloadId) { m_downloadId = downloadId; }
protected:
private: // functions
std::string getCategoryFromTags() const;
const Illustration& getDefaultIllustration() const;
protected: // data
std::string m_id;
std::string m_downloadId;
std::string m_path;
bool m_pathValid;
std::string m_indexPath;
supportedIndexType m_indexType;
bool m_pathValid = false;
std::string m_title;
std::string m_description;
std::string m_category;
std::string m_language;
std::string m_creator;
std::string m_publisher;
std::string m_date;
std::string m_url;
std::string m_name;
std::string m_flavour;
std::string m_tags;
std::string m_origId;
uint64_t m_articleCount;
uint64_t m_mediaCount;
bool m_readOnly;
uint64_t m_size;
mutable std::string m_favicon;
std::string m_faviconUrl;
std::string m_faviconMimeType;
uint64_t m_articleCount = 0;
uint64_t m_mediaCount = 0;
bool m_readOnly = false;
uint64_t m_size = 0;
Illustrations m_illustrations;
// Used as the return value of getDefaultIllustration() when no default
// illustration is found in the book
static const Illustration missingDefaultIllustration;
};
}
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright 2018 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_BOOKMARK_H
#define KIWIX_BOOKMARK_H
#include <string>
namespace pugi {
class xml_node;
}
namespace kiwix
{
class Book;
/**
* A class to store information about a bookmark (an article in a book)
*/
class Bookmark
{
public:
/**
* Create an empty bookmark.
*
* Bookmark must be populated with `set*` methods
*/
Bookmark();
/**
* Create a bookmark given a Book, a path and a title.
*/
Bookmark(const Book& book, const std::string& path, const std::string& title);
~Bookmark();
void updateFromXml(const pugi::xml_node& node);
const std::string& getBookId() const { return m_bookId; }
const std::string& getBookTitle() const { return m_bookTitle; }
const std::string& getBookName() const { return m_bookName; }
const std::string& getBookFlavour() const { return m_bookFlavour; }
const std::string& getUrl() const { return m_url; }
const std::string& getTitle() const { return m_title; }
const std::string& getLanguage() const { return m_language; }
const std::string& getDate() const { return m_date; }
void setBookId(const std::string& bookId) { m_bookId = bookId; }
void setBookTitle(const std::string& bookTitle) { m_bookTitle = bookTitle; }
void setBookName(const std::string& bookName) { m_bookName = bookName; }
void setBookFlavour(const std::string& bookFlavour) { m_bookFlavour = bookFlavour; }
void setUrl(const std::string& url) { m_url = url; }
void setTitle(const std::string& title) { m_title = title; }
void setLanguage(const std::string& language) { m_language = language; }
void setDate(const std::string& date) { m_date = date; }
protected:
std::string m_bookId;
std::string m_bookTitle;
std::string m_bookName;
std::string m_bookFlavour;
std::string m_url;
std::string m_title;
std::string m_language;
std::string m_date;
};
}
#endif
+34 -2
View File
@@ -14,11 +14,43 @@
#endif
namespace kiwix {
namespace kiwix
{
/**
* `IpMode` is used to [configure](@ref Server::setIpMode()) a `Server` object
* to listen for incoming connections not on a single IP address but on all
* addresses of the specified family.
*/
enum class IpMode
{
/**
* Listen on all IPv4 addresses.
*/
IPV4,
/**
* Listen on all IPv6 addresses.
*/
IPV6,
/**
* Listen on all available addresses.
*/
ALL,
/**
* `IpMode::AUTO` (which is the default) must be used when an explicit
* (non-empty) IP address for listening is provided via
* `Server::setAddress()`. If no such address is enforced, then
* `IpMode::AUTO` is equivalent to `IpMode::ALL`.
*/
AUTO
};
typedef zim::size_type size_type;
typedef zim::offset_type offset_type;
}
} // namespace kiwix
#endif //_KIWIX_COMMON_H_
-64
View File
@@ -1,64 +0,0 @@
/*
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_PATHTOOLS_H
#define KIWIX_PATHTOOLS_H
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fstream>
#include <ios>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#ifdef _WIN32
#include <direct.h>
#endif
#include "stringTools.h"
using namespace std;
bool isRelativePath(const string& path);
string computeAbsolutePath(const string path, const string relativePath);
string computeRelativePath(const string path, const string absolutePath);
string removeLastPathElement(const string path,
const bool removePreSeparator = false,
const bool removePostSeparator = false);
string appendToDirectory(const string& directoryPath, const string& filename);
unsigned int getFileSize(const string& path);
string getFileSizeAsString(const string& path);
string getFileContent(const string& path);
bool fileExists(const string& path);
bool makeDirectory(const string& path);
string makeTmpDirectory();
bool copyFile(const string& sourcePath, const string& destPath);
string getLastPathElement(const string& path);
string getExecutablePath();
string getCurrentDirectory();
string getDataDirectory();
bool writeTextFile(const string& path, const string& content);
#endif
-79
View File
@@ -1,79 +0,0 @@
/*
* Copyright 2013 Renaud Gaudin <reg@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef _CTPP2_VM_STRING_LOADER_HPP__
#define _CTPP2_VM_STRING_LOADER_HPP__ 1
#include <ctpp2/CTPP2VMLoader.hpp>
#include <ctpp2/CTPP2Util.hpp>
#include <ctpp2/CTPP2Exception.hpp>
#include <ctpp2/CTPP2VMExecutable.hpp>
#include <ctpp2/CTPP2VMInstruction.hpp>
#include <ctpp2/CTPP2VMMemoryCore.hpp>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
/**
@file VMStringLoader.hpp
@brief Load program core from file
*/
namespace CTPP // C++ Template Engine
{
// FWD
struct VMExecutable;
/**
@class VMStringLoader CTPP2VMStringLoader.hpp <CTPP2VMStringLoader.hpp>
@brief Load program core from file
*/
class CTPP2DECL VMStringLoader:
public VMLoader
{
public:
/**
*/
VMStringLoader(CCHAR_P rawContent, size_t rawContentSize);
/**
@brief Get ready-to-run program
*/
const VMMemoryCore * GetCore() const;
/**
@brief A destructor
*/
~VMStringLoader() throw();
private:
/** Program core */
VMExecutable * oCore;
/** Ready-to-run program */
VMMemoryCore * pVMMemoryCore;
};
} // namespace CTPP
#endif // _CTPP2_VM_STRING_LOADER_HPP__
// End.
+147 -19
View File
@@ -23,8 +23,9 @@
#include <string>
#include <vector>
#include <map>
#include <pthread.h>
#include <memory>
#include <stdexcept>
#include <mutex>
namespace kiwix
{
@@ -43,6 +44,14 @@ class AriaError : public std::runtime_error {
};
/**
* A representation of a current download.
*
* `Download` is not thread safe. User must care to not call method on a
* same download from different threads.
* However, it is safe to use different `Download`s from different threads.
*/
class Download {
public:
typedef enum { K_ACTIVE, K_WAITING, K_PAUSED, K_ERROR, K_COMPLETE, K_REMOVED, K_UNKNOWN } StatusResult;
@@ -53,16 +62,89 @@ class Download {
: mp_aria(p_aria),
m_status(K_UNKNOWN),
m_did(did) {};
void updateStatus(bool follow=false);
StatusResult getStatus() { return m_status; }
std::string getDid() { return m_did; }
std::string getFollowedBy() { return m_followedBy; }
uint64_t getTotalLength() { return m_totalLength; }
uint64_t getCompletedLength() { return m_completedLength; }
uint64_t getDownloadSpeed() { return m_downloadSpeed; }
uint64_t getVerifiedLength() { return m_verifiedLength; }
std::string getPath() { return m_path; }
std::vector<std::string>& getUris() { return m_uris; }
/**
* Update the status of the download.
*
* This call make an aria rpc call and is blocking.
* Some download (started with a metalink) are in fact several downloads.
* - A first one to download the metadlink.
* - A second one to download the real file.
*
* If `follow` is true, updateStatus tries to detect that and tracks
* the second download when the first one is finished.
* By passing false to `follow`, `Download` will only track the first download.
*
* `getFoo` methods are based on the last statusUpdate.
*
* @param follow: Do we have to follow following downloads.
*/
void updateStatus(bool follow);
/**
* Pause the download (and call updateStatus)
*/
void pauseDownload();
/**
* Resume the download (and call updateStatus)
*/
void resumeDownload();
/**
* Cancel the download.
*
* A canceled downlod cannot be resume and updateStatus does nothing.
* However, you can still get information based on the last known information.
*/
void cancelDownload();
/*
* Get the status of the download.
*/
StatusResult getStatus() const { return m_status; }
/*
* Get the id of the download.
*/
const std::string& getDid() const { return m_did; }
/*
* Get the id of the "second" download.
*
* Set only if the "first" download is a metalink and is complete.
*/
const std::string& getFollowedBy() const { return m_followedBy; }
/*
* Get the total length of the download.
*/
uint64_t getTotalLength() const { return m_totalLength; }
/*
* Get the completed length of the download.
*/
uint64_t getCompletedLength() const { return m_completedLength; }
/*
* Get the download speed of the download.
*/
uint64_t getDownloadSpeed() const { return m_downloadSpeed; }
/*
* Get the verified length of the download.
*/
uint64_t getVerifiedLength() const { return m_verifiedLength; }
/*
* Get the path (local file) of the download.
*/
const std::string& getPath() const { return m_path; }
/*
* Get the download uris of the download.
*/
const std::vector<std::string>& getUris() const { return m_uris; }
protected:
std::shared_ptr<Aria2> mp_aria;
@@ -80,23 +162,69 @@ class Download {
/**
* A tool to download things.
*
* A Downloader manages `Download` using aria2 in the background.
* `Downloader` is threadsafe.
* However, the returned `Download`s are NOT threadsafe.
*/
class Downloader
{
public:
Downloader();
public: // types
typedef std::vector<std::pair<std::string, std::string>> Options;
public: // functions
/*
* Create a new Downloader object.
*
* @param sessionFileDir: The directory where aria2 will store its session file.
*/
explicit Downloader(std::string sessionFileDir);
virtual ~Downloader();
void close();
Download* startDownload(const std::string& uri);
Download* getDownload(const std::string& did);
/**
* Start a new download.
*
* This method is thread safe and returns a pointer to a newly created
* `Download` or an existing one with a matching URI. In the latter case
* the options parameter is ignored, which can lead to surprising results.
* For example, if the old and new download requests (sharing the same URI)
* have different values for the download directory or output file name
* options, after the download is reported to be complete the downloaded file
* will be present only at the location specified for the first request.
*
* User should call `update` on the returned `Download` to have an accurate status.
*
* @param uri: The uri of the thing to download.
* @param downloadDir: The download directory where the thing should be stored (takes precedence over any "dir" in `options`).
* @param options: A series of pair <option_name, option_value> to pass to aria.
* @return: The newly created Download.
*/
std::shared_ptr<Download> startDownload(const std::string& uri, const std::string& downloadDir, Options options = {});
size_t getNbDownload() { return m_knownDownloads.size(); }
std::vector<std::string> getDownloadIds();
/**
* Get a download corrsponding to a download id (did)
* User should call `update` on the returned `Download` to have an accurate status.
*
* @param did: The download id to search for.
* @return: The Download corresponding to did.
* @throw: Throw std::out_of_range if did is not found.
*/
std::shared_ptr<Download> getDownload(const std::string& did);
private:
std::map<std::string, std::unique_ptr<Download>> m_knownDownloads;
/**
* Get the number of downloads currently managed.
*/
size_t getNbDownload() const;
/**
* Get the ids of the managed downloads.
*/
std::vector<std::string> getDownloadIds() const;
private: // data
mutable std::mutex m_lock;
std::map<std::string, std::shared_ptr<Download>> m_knownDownloads;
std::shared_ptr<Aria2> mp_aria;
};
}
-191
View File
@@ -1,191 +0,0 @@
/*
* Copyright 2018 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_ENTRY_H
#define KIWIX_ENTRY_H
#include <stdio.h>
#include <zim/article.h>
#include <exception>
#include <string>
#include "common.h"
using namespace std;
namespace kiwix
{
class NoEntry : public std::exception {};
/**
* A entry represent an.. entry in a zim file.
*/
class Entry
{
public:
/**
* Default constructor.
*
* Construct an invalid entry.
*/
Entry() = default;
/**
* Construct an entry making reference to an zim article.
*
* @param article a zim::Article object
*/
Entry(zim::Article article);
virtual ~Entry() = default;
/**
* Get the path of the entry.
*
* The path is the "key" of an entry.
*
* @return the path of the entry.
*/
std::string getPath() const;
/**
* Get the title of the entry.
*
* @return the title of the entry.
*/
std::string getTitle() const;
/**
* Get the content of the entry.
*
* The string is a copy of the content.
* If you don't want to do a copy, use get_blob.
*
* @return the content of the entry.
*/
std::string getContent() const;
/**
* Get the blob of the entry.
*
* A blob make reference to the content without copying it.
*
* @param offset The starting offset of the blob.
* @return the blob of the entry.
*/
zim::Blob getBlob(offset_type offset = 0) const;
/**
* Get the blob of the entry.
*
* A blob make reference to the content without copying it.
*
* @param offset The starting offset of the blob.
* @param size The size of the blob.
* @return the blob of the entry.
*/
zim::Blob getBlob(offset_type offset, size_type size) const;
/**
* Get the info for direct access to the content of the entry.
*
* Some entry (ie binary ones) have their content plain stored
* in the zim file. Knowing the offset where the content is stored
* an user can directly read the content in the zim file bypassing the
* kiwix-lib/libzim.
*
* @return A pair specifying where to read the content.
* The string is the real file to read (may be different that .zim
* file if zim is cut).
* The offset is the offset to read in the file.
* Return <"",0> if is not possible to read directly.
*/
std::pair<std::string, offset_type> getDirectAccessInfo() const;
/**
* Get the size of the entry.
*
* @return the size of the entry.
*/
size_type getSize() const;
/**
* Get the mime_type of the entry.
*
* @return the mime_type of the entry.
*/
std::string getMimetype() const;
/**
* Get if the entry is a redirect entry.
*
* @return True if the entry is a redirect.
*/
bool isRedirect() const;
/**
* Get if the entry is a link target entry.
*
* @return True if the entry is a link target.
*/
bool isLinkTarget() const;
/**
* Get if the entry is a deleted entry.
*
* @return True if the entry is a deleted entry.
*/
bool isDeleted() const;
/**
* Get the entry pointed by this entry.
*
* @return the entry pointed.
* @throw NoEntry if the entry is not a redirected entry.
*/
Entry getRedirectEntry() const;
/**
* Get the final entry pointed by this entry.
*
* Follow the redirection until a "not redirecting" entry is found.
* If the entry is not a redirected entry, return the entry itself.
*
* @return the final entry.
*/
Entry getFinalEntry() const;
/**
* Convert the entry to a boolean value.
*
* @return True if the entry is valid.
*/
explicit operator bool() const { return good(); }
private:
zim::Article article;
mutable zim::Article final_article;
bool good() const { return article.good(); }
};
}
#endif // KIWIX_ENTRY_H
+92
View File
@@ -0,0 +1,92 @@
/*
* Copyright 2024 Veloman Yunkan <veloman.yunkan@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_I18N
#define KIWIX_I18N
#include <map>
#include <string>
namespace kiwix
{
std::string getTranslatedString(const std::string& lang, const std::string& key);
namespace i18n
{
typedef std::map<std::string, std::string> Parameters;
std::string expandParameterizedString(const std::string& lang,
const std::string& key,
const Parameters& params);
class GetTranslatedString
{
public:
explicit GetTranslatedString(const std::string& lang) : m_lang(lang) {}
std::string operator()(const std::string& key) const
{
return getTranslatedString(m_lang, key);
}
std::string operator()(const std::string& key, const Parameters& params) const
{
return expandParameterizedString(m_lang, key, params);
}
private:
const std::string m_lang;
};
} // namespace i18n
class ParameterizedMessage
{
public: // types
typedef i18n::Parameters Parameters;
public: // functions
ParameterizedMessage(const std::string& msgId, const Parameters& params)
: msgId(msgId)
, params(params)
{}
std::string getText(const std::string& lang) const;
const std::string& getMsgId() const { return msgId; }
const Parameters& getParams() const { return params; }
private: // data
const std::string msgId;
const Parameters params;
};
inline ParameterizedMessage nonParameterizedMessage(const std::string& msgId)
{
const ParameterizedMessage::Parameters noParams;
return ParameterizedMessage(msgId, noParams);
}
std::string translateBookCategory(const std::string& lang, const std::string& category);
} // namespace kiwix
#endif // KIWIX_I18N
+1 -1
View File
@@ -22,4 +22,4 @@
#include "library.h"
#endif
#endif
+30
View File
@@ -0,0 +1,30 @@
#ifndef KIWIXLIB_KIWIX_SERVE_H_
#define KIWIXLIB_KIWIX_SERVE_H_
#include <memory>
#include <string>
class Subprocess;
namespace kiwix {
class KiwixServe
{
public:
KiwixServe(const std::string& libraryPath, int port = 8181);
~KiwixServe();
void run();
void shutDown();
bool isRunning();
int getPort() { return m_port; }
int setPort(int port);
private:
std::unique_ptr<Subprocess> mp_kiwixServe;
int m_port;
std::string m_libraryPath;
};
}; //end namespace kiwix
#endif // KIWIXLIB_KIWIX_SERVE_H_
+388 -46
View File
@@ -23,14 +23,26 @@
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <mutex>
#include <zim/archive.h>
#include <zim/search.h>
#include "book.h"
#include "bookmark.h"
#include "common.h"
#define KIWIX_LIBRARY_VERSION "20110515"
namespace Xapian {
class WritableDatabase;
};
namespace kiwix
{
class Book;
class OPDSDumper;
class Library;
enum supportedListSortBy { UNSORTED, TITLE, SIZE, DATE, CREATOR, PUBLISHER };
enum supportedListMode {
@@ -42,17 +54,198 @@ enum supportedListMode {
VALID = 1 << 4,
NOVALID = 1 << 5
};
enum MigrationMode {
/** When migrating bookmarks, do not allow to migrate to an older book than the currently pointed one
* (or date stored in the bookmark if book is invalid)
*
* If no newer books are found, no upgrade is made.
*/
UPGRADE_ONLY = 0,
/** Try hard to do a migration. This mostly does:
* - Try to find a newer book.
* - If book is invalid: find a best book, potentially older.
* Older book will never be returned if current book is a valid one.
*/
ALLOW_DOWNGRADE = 1,
};
class Filter {
public: // types
using Tags = std::vector<std::string>;
private: // data
uint64_t activeFilters;
Tags _acceptTags;
Tags _rejectTags;
std::string _category;
std::string _lang;
std::string _publisher;
std::string _creator;
size_t _maxSize;
std::string _query;
bool _queryIsPartial;
std::string _name;
std::string _flavour;
public: // functions
Filter();
~Filter() = default;
/**
* Set the filter to check local.
*
* A local book is a book with a path.
* If accept is true, only local book are accepted.
* If accept is false, only non local book are accepted.
*/
Filter& local(bool accept);
/**
* Set the filter to check remote.
*
* A remote book is a book with a url.
* If accept is true, only remote book are accepted.
* If accept is false, only non remote book are accepted.
*/
Filter& remote(bool accept);
/**
* Set the filter to check validity.
*
* A valid book is a book with a path pointing to a existing zim file.
* If accept is true, only valid book are accepted.
* If accept is false, only non valid book are accepted.
*/
Filter& valid(bool accept);
/**
* Set the filter to only accept book with corresponding tag.
*/
Filter& acceptTags(const Tags& tags);
Filter& rejectTags(const Tags& tags);
/**
* Set the filter to only accept books in the specified category.
*
* Multiple categories can be specified as a comma-separated list (in
* which case a book in any of those categories will match).
*/
Filter& category(std::string category);
/**
* Set the filter to only accept books in the specified language.
*
* Multiple languages can be specified as a comma-separated list (in
* which case a book in any of those languages will match).
*/
Filter& lang(std::string lang);
Filter& publisher(std::string publisher);
Filter& creator(std::string creator);
Filter& maxSize(size_t size);
Filter& query(std::string query, bool partial=true);
Filter& name(std::string name);
Filter& flavour(std::string flavour);
Filter& clearLang();
Filter& clearCategory();
bool hasQuery() const;
const std::string& getQuery() const { return _query; }
bool queryIsPartial() const { return _queryIsPartial; }
bool hasName() const;
const std::string& getName() const { return _name; }
bool hasCategory() const;
const std::string& getCategory() const { return _category; }
bool hasLang() const;
const std::string& getLang() const { return _lang; }
bool hasPublisher() const;
const std::string& getPublisher() const { return _publisher; }
bool hasCreator() const;
const std::string& getCreator() const { return _creator; }
bool hasFlavour() const;
const std::string& getFlavour() const { return _flavour; }
const Tags& getAcceptTags() const { return _acceptTags; }
const Tags& getRejectTags() const { return _rejectTags; }
private: // functions
friend class Library;
bool accept(const Book& book) const;
};
class ZimSearcher : public zim::Searcher
{
public:
explicit ZimSearcher(zim::Searcher&& searcher)
: zim::Searcher(searcher)
{}
std::unique_lock<std::mutex> getLock() {
return std::unique_lock<std::mutex>(m_mutex);
}
virtual ~ZimSearcher() = default;
private:
std::mutex m_mutex;
};
template<typename, typename>
class ConcurrentCache;
template<typename, typename>
class MultiKeyCache;
using LibraryPtr = std::shared_ptr<Library>;
using ConstLibraryPtr = std::shared_ptr<const Library>;
// Some compiler we use don't have [[nodiscard]] attribute.
// We don't want to declare `create` with it in this case.
#define LIBKIWIX_NODISCARD
#if defined __has_cpp_attribute
#if __has_cpp_attribute (nodiscard)
#undef LIBKIWIX_NODISCARD
#define LIBKIWIX_NODISCARD [[nodiscard]]
#endif
#endif
/**
* A Library store several books.
*/
class Library
class Library: public std::enable_shared_from_this<Library>
{
std::map<std::string, kiwix::Book> books;
public:
typedef uint64_t Revision;
typedef std::vector<std::string> BookIdCollection;
typedef std::map<std::string, int> AttributeCounts;
typedef std::set<std::string> BookIdSet;
private:
Library();
public:
LIBKIWIX_NODISCARD static LibraryPtr create() {
return LibraryPtr(new Library());
}
~Library();
std::string version;
/**
* Library is not a copiable object. However it can be moved.
*/
Library(const Library& ) = delete;
Library(Library&& ) = delete;
void operator=(const Library& ) = delete;
Library& operator=(Library&& ) = delete;
/**
* Add a book to the library.
*
@@ -65,7 +258,99 @@ class Library
*/
bool addBook(const Book& book);
Book& getBookById(const std::string& id);
/**
* A self-explanatory alias for addBook()
*/
bool addOrUpdateBook(const Book& book) { return addBook(book); }
/**
* Add a bookmark to the library.
*
* @param bookmark the book to add.
*/
void addBookmark(const Bookmark& bookmark);
/**
* Remove a bookmark
*
* @param zimId The zimId of the bookmark.
* @param url The url of the bookmark.
* @return True if the bookmark has been removed.
*/
bool removeBookmark(const std::string& zimId, const std::string& url);
/**
* Migrate all invalid bookmarks.
*
* All invalid bookmarks (ie pointing to unknown books, no check is made on bookmark pointing to
* invalid articles of valid book) will be migrated (if possible) to a better book.
* "Better book", will be determined using method `getBestTargetBookId`.
*
* @return A tuple<int, int>: <The number of bookmarks updated>, <Number of invalid bookmarks before migration was performed>.
*/
std::tuple<int, int> migrateBookmarks(MigrationMode migrationMode = ALLOW_DOWNGRADE);
/**
* Migrate all bookmarks associated to a specific book.
*
* All bookmarks associated to `sourceBookId` book will be migrated to a better book.
* "Better book", will be determined using method `getBestTargetBookId`.
*
* @param sourceBookId the source bookId of the bookmarks to migrate.
* @param migrationMode how we will find the best book.
* @return The number of bookmarks updated.
*/
int migrateBookmarks(const std::string& sourceBookId, MigrationMode migrationMode = UPGRADE_ONLY);
/**
* Migrate bookmarks
*
* Migrate all bookmarks pointing to `source` to `destination`.
*
* @param sourceBookId the source bookId of the bookmarks to migrate.
* @param targetBookId the destination bookId to migrate the bookmarks to.
* @return The number of bookmarks updated.
*/
int migrateBookmarks(const std::string& sourceBookId, const std::string& targetBookId);
/**
* Get the best available bookId for a bookmark.
*
* Given a bookmark, return the best available bookId.
* "best available bookId" is determined using heuristitcs based on book name, flavour and date.
*
* @param bookmark The bookmark to search the bookId for.
* @param migrationMode The migration mode to use.
* @return A bookId. Potentially empty string if no suitable book found.
*/
std::string getBestTargetBookId(const Bookmark& bookmark, MigrationMode migrationMode) const;
/**
* Get the best bookId for a combination of book's name, flavour and date.
*
* Given a bookName (mandatory), try to find the best book.
* If preferedFlavour is given, will try to find a book with the same flavour. If not found, return a book with a different flavour.
* If minDate is given, return a book newer than minDate. If not found, return a empty bookId.
*
* @param bookName The name of the book
* @param preferedFlavour The prefered flavour.
* @param minDate the minimal book date acceptable. Must be a string in the format "YYYY-MM-DD".
* @return A bookId corresponding to the query, or empty string if not found.
*/
std::string getBestTargetBookId(const std::string& bookName, const std::string& preferedFlavour="", const std::string& minDate="") const;
// XXX: This is a non-thread-safe operation
const Book& getBookById(const std::string& id) const;
// XXX: This is a non-thread-safe operation
const Book& getBookByPath(const std::string& path) const;
Book getBookByIdThreadSafe(const std::string& id) const;
std::shared_ptr<zim::Archive> getArchiveById(const std::string& id);
std::shared_ptr<ZimSearcher> getSearcherById(const std::string& id) {
return getSearcherByIds(BookIdSet{id});
}
std::shared_ptr<ZimSearcher> getSearcherByIds(const BookIdSet& ids);
/**
* Remove a book from the library.
@@ -79,9 +364,17 @@ class Library
* Write the library to a file.
*
* @param path the path of the file to write to.
* @return True if the library has been correctly save.
* @return True if the library has been correctly saved.
*/
bool writeToFile(const std::string& path);
bool writeToFile(const std::string& path) const;
/**
* Write the library bookmarks to a file.
*
* @param path the path of the file to write to.
* @return True if the library has been correctly saved.
*/
bool writeBookmarksToFile(const std::string& path) const;
/**
* Get the number of book in the library.
@@ -90,80 +383,129 @@ class Library
* @param remoteBooks If we must count remote books (books with an url)
* @return The number of books.
*/
unsigned int getBookCount(const bool localBooks, const bool remoteBooks);
unsigned int getBookCount(const bool localBooks, const bool remoteBooks) const;
/**
* Get all langagues of the books in the library.
* Get all languagues of the books in the library.
*
* @return A list of languages.
*/
std::vector<std::string> getBooksLanguages();
std::vector<std::string> getBooksLanguages() const;
/**
* Get all languagues of the books in the library with counts.
*
* @return A list of languages with the count of books in each language.
*/
AttributeCounts getBooksLanguagesWithCounts() const;
/**
* Get all categories of the books in the library.
*
* @return A list of categories.
*/
std::vector<std::string> getBooksCategories() const;
/**
* Get all book creators of the books in the library.
*
* @return A list of book creators.
*/
std::vector<std::string> getBooksCreators();
std::vector<std::string> getBooksCreators() const;
/**
* Get all book publishers of the books in the library.
*
* @return A list of book publishers.
*/
std::vector<std::string> getBooksPublishers();
std::vector<std::string> getBooksPublishers() const;
/**
* Get all bookmarks.
*
* @return A list of bookmarks
*/
const std::vector<kiwix::Bookmark> getBookmarks(bool onlyValidBookmarks = true) const;
/**
* Get all book ids of the books in the library.
*
* @return A list of book ids.
*/
std::vector<std::string> getBooksIds();
BookIdCollection getBooksIds() const;
/**
* Filter the library and generate a new one with the keep elements.
* Filter the library and return the id of the keep elements.
*
* This is equivalent to `listBookIds(ALL, UNSORTED, search)`.
*
* @param search List only books with search in the title or description.
* @return The list of bookIds corresponding to the query.
* @param filter The filter to use.
* @return The list of bookIds corresponding to the filter.
*/
std::vector<std::string> filter(const std::string& search);
BookIdCollection filter(const Filter& filter) const;
/**
* List books in the library.
* Sort (in place) bookIds using the given comparator.
*
* @param mode The mode of listing :
* - LOCAL  : list only local books (with a path).
* - REMOTE : list only remote books (with an url).
* - VALID  : list only valid books (without a path or with a
* path pointing to a valid zim file).
* - NOLOCAL : list only books without valid path.
* - NOREMOTE : list only books without url.
* - NOVALID : list only books not valid.
* - ALL : Do not do any filter (LOCAL or REMOTE)
* - Flags can be combined.
* @param sortBy Attribute to sort by the book list.
* @param search List only books with search in the title, description.
* @param language List only books in this language.
* @param creator List only books of this creator.
* @param publisher List only books of this publisher.
* @param maxSize Do not list book bigger than maxSize.
* Set to 0 to cancel this filter.
* @return The list of bookIds corresponding to the query.
* @param bookIds the list of book Ids to sort
* @param comparator how to sort the books
* @return The sorted list of books
*/
std::vector<std::string> listBooksIds(
int supportedListMode = ALL,
supportedListSortBy sortBy = UNSORTED,
const std::string& search = "",
const std::string& language = "",
const std::string& creator = "",
const std::string& publisher = "",
size_t maxSize = 0);
void sort(BookIdCollection& bookIds, supportedListSortBy sortBy, bool ascending) const;
/**
* Return the current revision of the library.
*
* The revision of the library is updated (incremented by one) by
* the addBook() and removeBookById() operations.
*
* @return Current revision of the library.
*/
Revision getRevision() const;
/**
* Remove books that have not been updated since the specified revision.
*
* @param rev the library revision to use
* @return Count of books that were removed by this operation.
*/
uint32_t removeBooksNotUpdatedSince(Revision rev);
friend class OPDSDumper;
friend class libXMLDumper;
private: // types
typedef const std::string& (Book::*BookStrPropMemFn)() const;
struct Entry : Book
{
Library::Revision lastUpdatedRevision = 0;
};
private: // functions
AttributeCounts getBookAttributeCounts(BookStrPropMemFn p) const;
std::vector<std::string> getBookPropValueSet(BookStrPropMemFn p) const;
BookIdCollection filterViaBookDB(const Filter& filter) const;
std::string getBestFromBookCollection(BookIdCollection books, const Bookmark& bookmark, MigrationMode migrationMode) const;
unsigned int getBookCount_not_protected(const bool localBooks, const bool remoteBooks) const;
void updateBookDB(const Book& book);
void dropCache(const std::string& bookId);
private: //data
mutable std::recursive_mutex m_mutex;
Library::Revision m_revision;
std::map<std::string, Entry> m_books;
using ArchiveCache = ConcurrentCache<std::string, std::shared_ptr<zim::Archive>>;
std::unique_ptr<ArchiveCache> mp_archiveCache;
using SearcherCache = MultiKeyCache<std::string, std::shared_ptr<ZimSearcher>>;
std::unique_ptr<SearcherCache> mp_searcherCache;
std::vector<kiwix::Bookmark> m_bookmarks;
std::unique_ptr<Xapian::WritableDatabase> m_bookDB;
};
// We don't need it anymore and we don't want to polute any other potential usage
// of `LIBKIWIX_NODISCARD` token.
#undef LIBKIWIX_NODISCARD
}
#endif
+56 -88
View File
@@ -22,10 +22,10 @@
#include "book.h"
#include "library.h"
#include "reader.h"
#include <string>
#include <vector>
#include <memory>
namespace pugi {
class xml_document;
@@ -34,60 +34,60 @@ class xml_document;
namespace kiwix
{
class LibraryManipulator {
public:
virtual ~LibraryManipulator() {}
virtual bool addBookToLibrary(Book book) = 0;
};
class LibraryManipulator
{
public: // functions
explicit LibraryManipulator(LibraryPtr library);
virtual ~LibraryManipulator();
class DefaultLibraryManipulator : public LibraryManipulator {
public:
DefaultLibraryManipulator(Library* library) :
library(library) {}
virtual ~DefaultLibraryManipulator() {}
bool addBookToLibrary(Book book) {
return library->addBook(book);
}
private:
kiwix::Library* library;
LibraryPtr getLibrary() const { return library; }
bool addBookToLibrary(const Book& book);
void addBookmarkToLibrary(const Bookmark& bookmark);
uint32_t removeBooksNotUpdatedSince(Library::Revision rev);
protected: // overrides
virtual void bookWasAddedToLibrary(const Book& book);
virtual void bookmarkWasAddedToLibrary(const Bookmark& bookmark);
virtual void booksWereRemovedFromLibrary();
private: // data
LibraryPtr library;
};
/**
* A tool to manage a `Library`.
*
* A `Manager` handle a internal `Library`.
* This `Library` can be retrived with `cloneLibrary` method.
*/
class Manager
{
public:
Manager(LibraryManipulator* manipulator);
Manager(Library* library);
~Manager();
public: // types
typedef std::vector<std::string> Paths;
public: // functions
explicit Manager(LibraryManipulator manipulator);
explicit Manager(LibraryPtr library);
/**
* Read a `library.xml` and add book in the file to the library.
*
* @param path The path to the `library.xml`.
* @param path The (utf8) path to the `library.xml`.
* @param readOnly Set if the libray path could be overwritten latter with
* updated content.
* @param trustLibrary use book metadata coming from XML.
* @return True if file has been properly parsed.
*/
bool readFile(const std::string& path, const bool readOnly = true);
bool readFile(const std::string& path, bool readOnly = true, bool trustLibrary = true);
/**
* Read a `library.xml` and add book in the file to the library.
* Sync the contents of the library with one or more `library.xml` files.
*
* @param nativePath The path of the `library.xml`
* @param UTF8Path The utf8 version (?) of the path. Also the path where the
* library will be writen i readOnly is False.
* @param readOnly Set if the libray path could be overwritten latter with
* updated content.
* @return True if file has been properly parsed.
* The metadata of the library files is trusted unconditionally.
* Any books not present in the input library.xml files are removed
* from the library.
*
* @param paths The (utf8) paths to the `library.xml` files.
*/
bool readFile(const std::string& nativePath,
const std::string& UTF8Path,
const bool readOnly = true);
void reload(const Paths& paths);
/**
* Load a library content store in the string.
@@ -100,7 +100,8 @@ class Manager
*/
bool readXml(const std::string& xml,
const bool readOnly = true,
const std::string& libraryPath = "");
const std::string& libraryPath = "",
bool trustLibrary = true);
/**
* Load a library content stored in a OPDS stream.
@@ -113,6 +114,15 @@ class Manager
*/
bool readOpds(const std::string& content, const std::string& urlHost);
/**
* Load a bookmark file.
*
* @param path The path of the file to read.
* @return True if the content has been properly parsed.
*/
bool readBookmarkFile(const std::string& path);
/**
* Add a book to the library.
*
@@ -146,53 +156,13 @@ class Manager
const bool checkMetaData = false);
/**
* Get the book corresponding to an id.
*
* @param[in] id The id of the book
* @param[out] book The book corresponding to the id.
* @return True if the book has been found.
* Add all books from the directory tree into the library.
*
* @param path The path of the directory to scan.
* @param verboseFlag Verbose logs flag.
*/
bool getBookById(const std::string& id, Book& book);
/**
* Update the "last open date" of a book
*
* @param id the id of the book.
* @return True if the book is in the library.
*/
bool updateBookLastOpenDateById(const std::string& id);
/**
* Remove (set to empty) paths of all books in the library.
*/
void removeBookPaths();
/**
* List books in the library.
*
* The books list will be available in public vector member `bookIdList`.
*
* @param mode The mode of listing :
* - LASTOPEN sort by last opened book.
* - LOCAL list only local file.
* - REMOTE list only remote file.
* @param sortBy Attribute to sort by the book list.
* @param maxSize Do not list book bigger than maxSize MiB.
* Set to 0 to cancel this filter.
* @param language List only books in this language.
* @param creator List only books of this creator.
* @param publisher List only books of this publisher.
* @param search List only books with search in the title, description or
* language.
* @return True
*/
bool listBooks(const supportedListMode mode,
const supportedListSortBy sortBy,
const unsigned int maxSize,
const std::string& language,
const std::string& creator,
const std::string& publisher,
const std::string& search);
void addBooksFromDirectory(const std::string& path,
const bool verboseFlag = false);
std::string writableLibraryPath;
@@ -202,18 +172,16 @@ class Manager
uint64_t m_itemsPerPage = 0;
protected:
kiwix::LibraryManipulator* manipulator;
bool mustDeleteManipulator;
kiwix::LibraryManipulator manipulator;
bool readBookFromPath(const std::string& path, Book* book);
bool parseXmlDom(const pugi::xml_document& doc,
const bool readOnly,
const std::string& libraryPath);
bool readOnly,
const std::string& libraryPath,
bool trustLibrary);
bool parseOpdsDom(const pugi::xml_document& doc,
const std::string& urlHost);
private:
void checkAndCleanBookPaths(Book& book, const std::string& libraryPath);
};
}
+9 -26
View File
@@ -1,35 +1,18 @@
headers = [
'book.h',
'bookmark.h',
'common.h',
'library.h',
'manager.h',
'opds_dumper.h',
'downloader.h',
'reader.h',
'entry.h',
'searcher.h'
'search_renderer.h',
'server.h',
'spelling_correction.h',
'kiwixserve.h',
'name_mapper.h',
'tools.h',
'version.h',
'i18n.h'
]
if xapian_dep.found()
headers += ['xapianSearcher.h']
endif
install_headers(headers, subdir:'kiwix')
install_headers(
'common/base64.h',
'common/networkTools.h',
'common/otherTools.h',
'common/pathTools.h',
'common/regexTools.h',
'common/stringTools.h',
subdir:'kiwix/common'
)
if has_ctpp2_dep
install_headers(
'ctpp2/CTPP2VMStringLoader.hpp',
subdir:'kiwix/ctpp2'
)
endif
+84
View File
@@ -0,0 +1,84 @@
/*
* Copyright 2019 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_NAMEMAPPER_H
#define KIWIX_NAMEMAPPER_H
#include <string>
#include <map>
#include <memory>
#include <mutex>
namespace kiwix
{
class Library;
class NameMapper {
public:
virtual ~NameMapper() = default;
virtual std::string getNameForId(const std::string& id) const = 0;
virtual std::string getIdForName(const std::string& name) const = 0;
};
class IdNameMapper : public NameMapper {
public:
virtual std::string getNameForId(const std::string& id) const { return id; };
virtual std::string getIdForName(const std::string& name) const { return name; };
};
class HumanReadableNameMapper : public NameMapper {
private:
std::map<std::string, std::string> m_idToName;
std::map<std::string, std::string> m_nameToId;
public:
HumanReadableNameMapper(const kiwix::Library& library, bool withAlias);
virtual ~HumanReadableNameMapper() = default;
virtual std::string getNameForId(const std::string& id) const;
virtual std::string getIdForName(const std::string& name) const;
private:
void mapName(const kiwix::Library& lib, std::string name, std::string id);
};
class UpdatableNameMapper : public NameMapper {
typedef std::shared_ptr<NameMapper> NameMapperHandle;
public:
UpdatableNameMapper(std::shared_ptr<Library> library, bool withAlias);
virtual std::string getNameForId(const std::string& id) const;
virtual std::string getIdForName(const std::string& name) const;
void update();
private:
NameMapperHandle currentNameMapper() const;
private:
mutable std::mutex mutex;
std::shared_ptr<Library> library;
NameMapperHandle nameMapper;
const bool withAlias;
};
}
#endif
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright 2021 Veloman Yunkan <veloman.yunkan@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,9 +17,17 @@
* MA 02110-1301, USA.
*/
package org.kiwix.kiwixlib;
#ifndef KIWIX_OPDS_CATALOG_H
#define KIWIX_OPDS_CATALOG_H
public class JNIKiwixBool
#include "library.h"
namespace kiwix
{
public boolean value;
}
std::string getSearchUrl(const Filter& f);
} // namespace kiwix
#endif // KIWIX_OPDS_CATALOG_H
-505
View File
@@ -1,505 +0,0 @@
/*
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_READER_H
#define KIWIX_READER_H
#include <stdio.h>
#include <zim/article.h>
#include <zim/file.h>
#include <zim/fileiterator.h>
#include <zim/zim.h>
#include <exception>
#include <map>
#include <sstream>
#include <string>
#include "common.h"
#include "entry.h"
#include "common/pathTools.h"
#include "common/stringTools.h"
using namespace std;
namespace kiwix
{
/**
* The Reader class is the class who allow to get an entry content from a zim
* file.
*/
class Reader
{
public:
/**
* Create a Reader to read a zim file specified by zimFilePath.
*
* @param zimFilePath The path to the zim file to read.
* The zim file can be splitted (.zimaa, .zimab, ...).
* In this case, the file path must still point to the
* unsplitted path as if the file were not splitted
* (.zim extesion).
*/
Reader(const string zimFilePath);
~Reader();
/**
* Get the number of "displayable" entries in the zim file.
*
* @return If the zim file has a /M/Counter metadata, return the number of
* entries with the 'text/html' MIMEtype specified in the metadata.
* Else return the number of entries in the 'A' namespace.
*/
unsigned int getArticleCount() const;
/**
* Get the number of media in the zim file.
*
* @return If the zim file has a /M/Counter metadata, return the number of
* entries with the 'image/jpeg', 'image/gif' and 'image/png' in
* the metadata.
* Else return the number of entries in the 'I' namespace.
*/
unsigned int getMediaCount() const;
/**
* Get the number of all entries in the zim file.
*
* @return Return the number of all the entries, whatever their MIMEtype or
* their namespace.
*/
unsigned int getGlobalCount() const;
/**
* Get the path of the zim file.
*
* @return the path of the zim file as given in the constructor.
*/
string getZimFilePath() const;
/**
* Get the Id of the zim file.
*
* @return The uuid stored in the zim file.
*/
string getId() const;
/**
* Get the url of a random page.
*
* Deprecated : Use `getRandomPage` instead.
*
* @return Url of a random page. The page is picked from all entries in
* the 'A' namespace.
* The main page is excluded from the potential results.
*/
DEPRECATED string getRandomPageUrl() const;
/**
* Get a random page.
*
* @return A random Entry. The entry is picked from all entries in
* the 'A' namespace.
* The main entry is excluded from the potential results.
*/
Entry getRandomPage() const;
/**
* Get the url of the first page.
*
* Deprecated : Use `getFirstPage` instead.
*
* @return Url of the first entry in the 'A' namespace.
*/
DEPRECATED string getFirstPageUrl() const;
/**
* Get the entry of the first page.
*
* @return The first entry in the 'A' namespace.
*/
Entry getFirstPage() const;
/**
* Get the url of the main page.
*
* Deprecated : Use `getMainPage` instead.
*
* @return Url of the main page as specified in the zim file.
*/
DEPRECATED string getMainPageUrl() const;
/**
* Get the entry of the main page.
*
* @return Entry of the main page as specified in the zim file.
*/
Entry getMainPage() const;
/**
* Get the content of a metadata.
*
* @param[in] name The name of the metadata.
* @param[out] value The value will be set to the content of the metadata.
* @return True if it was possible to get the content of the metadata.
*/
bool getMetatag(const string& name, string& value) const;
/**
* Get the title of the zim file.
*
* @return The title of zim file as specified in the zim metadata.
* If no title has been set, return a title computed from the
* file path.
*/
string getTitle() const;
/**
* Get the description of the zim file.
*
* @return The description of the zim file as specified in the zim metadata.
* If no description has been set, return the subtitle.
*/
string getDescription() const;
/**
* Get the language of the zim file.
*
* @return The language of the zim file as specified in the zim metadata.
*/
string getLanguage() const;
/**
* Get the name of the zim file.
*
* @return The name of the zim file as specified in the zim metadata.
*/
string getName() const;
/**
* Get the tags of the zim file.
*
* @return The tags of the zim file as specified in the zim metadata.
*/
string getTags() const;
/**
* Get the date of the zim file.
*
* @return The date of the zim file as specified in the zim metadata.
*/
string getDate() const;
/**
* Get the creator of the zim file.
*
* @return The creator of the zim file as specified in the zim metadata.
*/
string getCreator() const;
/**
* Get the publisher of the zim file.
*
* @return The publisher of the zim file as specified in the zim metadata.
*/
string getPublisher() const;
/**
* Get the origId of the zim file.
*
* The origId is only used in the case of patch zim file and is the Id
* of the original zim file.
*
* @return The origId of the zim file as specified in the zim metadata.
*/
string getOrigId() const;
/**
* Get the favicon of the zim file.
*
* @param[out] content The content of the favicon.
* @param[out] mimeType The mimeType of the favicon.
* @return True if a favicon has been found.
*/
bool getFavicon(string& content, string& mimeType) const;
/**
* Get an entry associated to an path.
*
* @param path The path of the entry.
* @return The entry.
* @throw NoEntry If no entry correspond to the path.
*/
Entry getEntryFromPath(const std::string& path) const;
/**
* Get an entry associated to an url encoded path.
*
* Equivalent to `getEntryFromPath(urlDecode(path));`
*
* @param path The url encoded path.
* @return The entry.
* @throw NoEntry If no entry correspond to the path.
*/
Entry getEntryFromEncodedPath(const std::string& path) const;
/**
* Get un entry associated to a title.
*
* @param title The title.
* @return The entry
* throw NoEntry If no entry correspond to the url.
*/
Entry getEntryFromTitle(const std::string& title) const;
/**
* Get the url of a page specified by a title.
*
* @param[in] title the title of the page.
* @param[out] url the url of the page.
* @return True if the page can be found.
*/
DEPRECATED bool getPageUrlFromTitle(const string& title, string& url) const;
/**
* Get the mimetype of a entry specified by a url.
*
* @param[in] url the url of the entry.
* @param[out] mimeType the mimeType of the entry.
* @return True if the mimeType has been found.
*/
DEPRECATED bool getMimeTypeByUrl(const string& url, string& mimeType) const;
/**
* Get the content of an entry specifed by a url.
*
* Alias to `getContentByEncodedUrl`
*/
DEPRECATED bool getContentByUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType) const;
/**
* Get the content of an entry specified by a url encoded url.
*
* Equivalent to getContentByDecodedUrl(urlDecode(url), ...).
*/
DEPRECATED bool getContentByEncodedUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType,
string& baseUrl) const;
/**
* Get the content of an entry specified by an url encoded url.
*
* Equivalent to getContentByEncodedUrl but without baseUrl.
*/
DEPRECATED bool getContentByEncodedUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType) const;
/**
* Get the content of an entry specified by a url.
*
* @param[in] url The url of the entry.
* @param[out] content The content of the entry.
* @param[out] title the title of the entry.
* @param[out] contentLength The size of the entry (size of content).
* @param[out] contentType The mimeType of the entry.
* @param[out] baseUrl Return the true url of the entry.
* If the specified entry is a redirection, contains
* the url of the targeted entry.
* @return True if the entry has been found.
*/
DEPRECATED bool getContentByDecodedUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType,
string& baseUrl) const;
/**
* Get the content of an entry specified by a url.
*
* Equivalent to getContentByDecodedUrl but withou the baseUrl.
*/
DEPRECATED bool getContentByDecodedUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType) const;
/**
* Search for entries with title starting with prefix (case sensitive).
*
* Suggestions are stored in an internal vector and can be retrieved using
* `getNextSuggestion` method.
*
* @param prefix The prefix to search.
* @param suggestionsCount How many suggestions to search for.
* @param reset If true, remove previous suggestions in the internal vector.
* If false, add suggestions to the internal vector
* (until internal vector size is suggestionCount (or no more
* suggestion))
* @return True if some suggestions where added to the internal vector.
*/
bool searchSuggestions(const string& prefix,
unsigned int suggestionsCount,
const bool reset = true);
/**
* Search for entries for the given prefix.
*
* If the zim file has a internal fulltext index, the suggestions will be
* searched using it.
* Else the suggestions will be search using `searchSuggestions` while trying
* to be smart about case sensitivity (using `getTitleVariants`).
*
* In any case, suggestions are stored in an internal vector and can be
* retrieved using `getNextSuggestion` method.
* The internal vector will be reset.
*
* @param prefix The prefix to search for.
* @param suggestionsCount How many suggestions to search for.
*/
bool searchSuggestionsSmart(const string& prefix,
unsigned int suggestionsCount);
/**
* Check if the url exists in the zim file.
*
* Deprecated : Use `pathExists` instead.
*
* @param url the url to check.
* @return True if the url exits in the zim file.
*/
DEPRECATED bool urlExists(const string& url) const;
/**
* Check if the path exists in the zim file.
*
* @param path the path to check.
* @return True if the path exists in the zim file.
*/
bool pathExists(const string& path) const;
/**
* Check if the zim file has a embedded fulltext index.
*
* @return True if the zim file has a embedded fulltext index
* and is not split (else the fulltext is not accessible).
*/
bool hasFulltextIndex() const;
/**
* Get potential case title variations for a title.
*
* @param title a title.
* @return the list of variantions.
*/
std::vector<std::string> getTitleVariants(const std::string& title) const;
/**
* Get the next suggestion title.
*
* @param[out] title the title of the suggestion.
* @return True if title has been set.
*/
bool getNextSuggestion(string& title);
/**
* Get the next suggestion title and url.
*
* @param[out] title the title of the suggestion.
* @param[out] url the url of the suggestion.
* @return True if title and url have been set.
*/
bool getNextSuggestion(string& title, string& url);
/**
* Get if we can check zim file integrity (has a checksum).
*
* @return True if zim file have a checksum.
*/
bool canCheckIntegrity() const;
/**
* Check is zim file is corrupted.
*
* @return True if zim file is corrupted.
*/
bool isCorrupted() const;
/**
* Parse a full url into a namespace and url.
*
* @param[in] url The full url ("/N/url").
* @param[out] ns The namespace (N).
* @param[out] title The url (url).
* @return True
*/
DEPRECATED bool parseUrl(const string& url, char* ns, string& title) const;
/**
* Return the total size of the zim file.
*
* If zim file is split, return the sum of all parts' size.
*
* @return Size of the size file is KiB.
*/
unsigned int getFileSize() const;
/**
* Get the zim file handler.
*
* @return The libzim file handler.
*/
zim::File* getZimFileHandler() const;
/**
* Get the zim article object associated to a url.
*
* @param[in] url The url of the article.
* @param[out] article The libzim article object.
* @return True if the url is good (article.good()).
*/
DEPRECATED bool getArticleObjectByDecodedUrl(const string& url,
zim::Article& article) const;
protected:
zim::File* zimFileHandler;
zim::size_type firstArticleOffset;
zim::size_type lastArticleOffset;
zim::size_type nsACount;
zim::size_type nsICount;
std::string zimFilePath;
std::vector<std::vector<std::string>> suggestions;
std::vector<std::vector<std::string>>::iterator suggestionsOffset;
private:
std::map<const std::string, unsigned int> parseCounterMetadata() const;
};
}
#endif
+121
View File
@@ -0,0 +1,121 @@
/*
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_SEARCH_RENDERER_H
#define KIWIX_SEARCH_RENDERER_H
#include <string>
#include <zim/search.h>
#include "library.h"
namespace kiwix
{
class NameMapper;
/**
* The SearcherRenderer class is used to render a search result to a html page.
*/
class SearchRenderer
{
public:
/**
* Construct a SearchRenderer from a SearchResultSet.
*
* @param srs The `SearchResultSet` to render.
* @param start The start offset used for the srs.
* @param estimatedResultCount The estimatedResultCount of the whole search
*/
SearchRenderer(zim::SearchResultSet srs, unsigned int start, unsigned int estimatedResultCount);
~SearchRenderer();
/**
* Set the search pattern used to do the search
*/
void setSearchPattern(const std::string& pattern);
/**
* Set the querystring used to select books
*/
void setSearchBookQuery(const std::string& bookQuery);
/**
* Set protocol prefix.
*/
void setProtocolPrefix(const std::string& prefix);
/**
* Set search protocol prefix.
*/
void setSearchProtocolPrefix(const std::string& prefix);
/**
* set result count per page
*/
void setPageLength(unsigned int pageLength){
this->pageLength = pageLength;
}
/**
* set user language
*/
void setUserLang(const std::string& lang){
this->userlang = lang;
}
/**
* Generate the html page with the resutls of the search.
*
* @param mapper The `NameMapper` to use to do the rendering.
* @param library The `Library` to use to look up book details for search results.
May be nullptr. In this case, bookName is not set in the rendered string.
* @return The html string
*/
std::string getHtml(const NameMapper& mapper, const Library* library);
/**
* Generate the xml page with the resutls of the search.
*
* @param mapper The `NameMapper` to use to do the rendering.
* @param library The `Library` to use to look up book details for search results.
May be nullptr. In this case, bookName is not set in the rendered string.
* @return The xml string
*/
std::string getXml(const NameMapper& mapper, const Library* library);
protected: // function
std::string renderTemplate(const std::string& tmpl_str, const NameMapper& mapper, const Library *library);
protected:
std::string beautifyInteger(const unsigned int number);
zim::SearchResultSet m_srs;
std::string searchBookQuery;
std::string searchPattern;
std::string protocolPrefix;
std::string searchProtocolPrefix;
unsigned int pageLength;
unsigned int estimatedResultCount;
unsigned int resultStart;
std::string userlang = "en";
};
}
#endif
-230
View File
@@ -1,230 +0,0 @@
/*
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_SEARCHER_H
#define KIWIX_SEARCHER_H
#include <stdio.h>
#include <stdlib.h>
#include <unicode/putil.h>
#include <algorithm>
#include <cctype>
#include <locale>
#include <string>
#include <vector>
#include <vector>
#include "common/pathTools.h"
#include "common/stringTools.h"
#include "kiwix_config.h"
using namespace std;
namespace kiwix
{
class Reader;
class Result
{
public:
virtual ~Result(){};
virtual std::string get_url() = 0;
virtual std::string get_title() = 0;
virtual int get_score() = 0;
virtual std::string get_snippet() = 0;
virtual std::string get_content() = 0;
virtual int get_wordCount() = 0;
virtual int get_size() = 0;
virtual int get_readerIndex() = 0;
};
struct SearcherInternal;
/**
* The Searcher class is reponsible to do different kind of search using the
* fulltext index.
*
* Historically, there are two kind of fulltext index :
* - The legacy one, is the external fulltext index. A directory stored outside
* of the zim file.
* - The new one, a embedded fulltext index in the zim file.
*
* Legacy external fulltext index has to be considered as obsolet format with
* less functionnalities:
* - No multi zim search ;
* - No geo_search ;
* - No suggestions search ;
*
* To reflect this, there is two Search creation "API":
* - One for the external fulltext index, using the constructor taking a
* xapianDirectoryPath) ;
* - One for the embedded fulltext index, using a "empty" constructor and the
* `add_reader` method".
*
* On top of that, the Searcher may (if compiled with ctpp2) be used to
* generate a html page for the search result. This use a template that need a
* humanReaderName. This feature is only used by kiwix-serve and this should be
* move outside of Searcher (and with a better API). If you don't use the html
* rendering (getHtml method), you better should simply ignore the different
* humanReadeableName attributes (or give an empty string).
*/
class Searcher
{
public:
/**
* The default constructor.
*
* @param humanReadableName The global zim's humanReadableName.
* Used to generate pagination links.
*/
Searcher(const string& humanReadableName = "");
/**
* The constructor for legacy external fulltext index.
*
* @param xapianDirectoryPath The path to the external index directory.
* @param reader The reader associated to the external index.
* It will be used retrive the article content or generate
* the snippet.
* @param humanReadableName The humanReadableName for the zim.
*/
Searcher(const string& xapianDirectoryPath,
Reader* reader,
const string& humanReadableName);
~Searcher();
/**
* Add a reader (containing embedded fulltext index) to the search.
*
* @param reader The Reader for the zim containing the fulltext index.
* @param humanReaderName The human readable name of the reader.
* @return true if the reader has been added.
* false if the reader cannot be added (no embedded fulltext index present)
*/
bool add_reader(Reader* reader, const std::string& humanReaderName);
/**
* Start a search on the zim associated to the Searcher.
*
* Search results should be retrived using the getNextResult method.
*
* @param search The search query.
* @param resultStart the start offset of the search results (used for pagination).
* @param resultEnd the end offset of the search results (used for pagination).
* @param verbose print some info on stdout if true.
*/
void search(std::string& search,
unsigned int resultStart,
unsigned int resultEnd,
const bool verbose = false);
/**
* Start a geographique search.
* The search return result for entry in a disc of center latitude/longitude
* and radius distance.
*
* Search results should be retrived using the getNextResult method.
*
* @param latitude The latitude of the center point.
* @param longitude The longitude of the center point.
* @param distance The radius of the disc.
* @param resultStart the start offset of the search results (used for pagination).
* @param resultEnd the end offset of the search results (used for pagination).
* @param verbose print some info on stdout if true.
*/
void geo_search(float latitude, float longitude, float distance,
unsigned int resultStart,
unsigned int resultEnd,
const bool verbose = false);
/**
* Start a suggestion search.
* The search made depend of the "version" of the embedded index.
* - If the index is newer enough and have a title namespace, the search is
* made in the titles only.
* - Else the search is made on the whole article content.
* In any case, the search is made "partial" (as adding '*' at the end of the query)
*
* @param search The search query.
* @param verbose print some info on stdout if true.
*/
void suggestions(std::string& search, const bool verbose = false);
/**
* Get the next result of a started search.
* This is the method to use to loop hover the search results.
*/
Result* getNextResult();
/**
* Restart the previous search.
* Next call to getNextResult will return the first result.
*/
void restart_search();
/**
* Get a estimation of the result count.
*/
unsigned int getEstimatedResultCount();
/**
* Set protocol prefix.
* Only used by getHtml.
*/
bool setProtocolPrefix(const std::string prefix);
/**
* Set search protocol prefix.
* Only used by getHtml.
*/
bool setSearchProtocolPrefix(const std::string prefix);
#ifdef ENABLE_CTPP2
/**
* Generate the html page with the resutls of the search.
*/
string getHtml();
#endif
protected:
std::string beautifyInteger(const unsigned int number);
void closeIndex();
void searchInIndex(string& search,
const unsigned int resultStart,
const unsigned int resultEnd,
const bool verbose = false);
std::vector<Reader*> readers;
std::vector<std::string> humanReaderNames;
SearcherInternal* internal;
std::string searchPattern;
std::string protocolPrefix;
std::string searchProtocolPrefix;
unsigned int resultCountPerPage;
unsigned int estimatedResultCount;
unsigned int resultStart;
unsigned int resultEnd;
std::string contentHumanReadableId;
private:
void reset();
};
}
#endif
+153
View File
@@ -0,0 +1,153 @@
/*
* Copyright 2019 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_SERVER_H
#define KIWIX_SERVER_H
#include <string>
#include <memory>
#include "tools.h"
namespace kiwix
{
class Library;
class NameMapper;
class InternalServer;
class Server {
public:
/**
* The default constructor.
*
* @param library The library to serve.
*/
Server(std::shared_ptr<Library> library, std::shared_ptr<NameMapper> nameMapper=nullptr);
virtual ~Server();
/**
* Start serving the content.
*/
bool start();
/**
* Stop the daemon.
*/
void stop();
/**
* Set the path of the root URL served by this server instance.
*/
void setRoot(const std::string& root);
/**
* Set the IP address on which to listen for incoming connections.
*
* Specifying a non-empty IP address requires that the IpMode is
* [set](@ref setIpMode()) to `IpMode::AUTO` (which is the default).
* Otherwise, [starting](@ref start()) the server will fail.
*/
void setAddress(const std::string& addr);
/**
* Set the port on which to listen for incoming connections.
*
* Default port is 80, but using it requires special privileges.
*/
void setPort(int port) { m_port = port; }
void setNbThreads(int threads) { m_nbThreads = threads; }
void setMultiZimSearchLimit(unsigned int limit) { m_multizimSearchLimit = limit; }
void setIpConnectionLimit(int limit) { m_ipConnectionLimit = limit; }
void setVerbose(bool verbose) { m_verbose = verbose; }
void setIndexTemplateString(const std::string& indexTemplateString) { m_indexTemplateString = indexTemplateString; }
void setTaskbar(bool withTaskbar, bool withLibraryButton)
{ m_withTaskbar = withTaskbar; m_withLibraryButton = withLibraryButton; }
void setBlockExternalLinks(bool blockExternalLinks)
{ m_blockExternalLinks = blockExternalLinks; }
void setCatalogOnlyMode(bool enable) { m_catalogOnlyMode = enable; }
void setContentServerUrl(std::string url) { m_contentServerUrl = url; }
/**
* Listen for incoming connections on all IP addresses of the specified
* IP protocol family.
*/
void setIpMode(IpMode mode) { m_ipMode = mode; }
/**
* Get the port on which the server listens for incoming connections
*/
int getPort() const;
/**
* Get the IPv4 and/or IPv6 address(es) on which the server can be
* contacted.
*
* The server may actually be listening on other IP addresses as well
* (see `setIpMode()`). The IP address(es) returned by this method
* represent the best-guess public IP address(es) accessible by the
* broadest set of clients.
*/
IpAddress getAddress() const;
/**
* Get the effective IpMode used by this server.
*
* The returned value may be different from the one configured via
* `setIpMode()`, since the server is expected to adjust to the
* constraints of the environment (e.g. `IpMode::ALL` can be converted
* to `IpMode::IPV4` on a system that does not support IPv6).
*/
IpMode getIpMode() const;
/**
* Get the list of HTTP URLs through which the server can be contacted.
*
* Each URL is composed of an IP address and optional port and includes
* the [root](@ref setRoot()) path component.
*
* In the current implementation at most 2 URLs may be returned - one
* for IPv4 and another for IPv6 protocol (whichever is available), as
* returned by `getAddress()`. Note, however, that the server may be
* also accessible via other IP-addresses/URLs (see `setIpMode()`).
*/
std::vector<std::string> getServerAccessUrls() const;
protected:
std::shared_ptr<Library> mp_library;
std::shared_ptr<NameMapper> mp_nameMapper;
std::string m_root = "";
IpAddress m_addr;
std::string m_indexTemplateString = "";
int m_port = 80;
int m_nbThreads = 1;
unsigned int m_multizimSearchLimit = 0;
bool m_verbose = false;
bool m_withTaskbar = true;
bool m_withLibraryButton = true;
bool m_blockExternalLinks = false;
IpMode m_ipMode = IpMode::AUTO;
int m_ipConnectionLimit = 0;
bool m_catalogOnlyMode = false;
std::string m_contentServerUrl;
std::unique_ptr<InternalServer> mp_server;
};
}
#endif
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2025 Veloman Yunkan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_SPELLING_CORRECTION_H
#define KIWIX_SPELLING_CORRECTION_H
#include <filesystem>
#include <memory>
#include <string>
#include <vector>
namespace zim
{
class Archive;
}
namespace Xapian
{
class Database;
}
namespace kiwix
{
class SpellingsDB
{
public: // functions
SpellingsDB(const zim::Archive& archive, std::filesystem::path cacheDirPath);
~SpellingsDB();
SpellingsDB(const SpellingsDB& ) = delete;
void operator=(const SpellingsDB& ) = delete;
std::vector<std::string> getSpellingCorrections(const std::string& word, uint32_t maxCount) const;
private: // data
std::unique_ptr<Xapian::Database> impl_;
};
} // namespace kiwix
#endif // KIWIX_SPELLING_CORRECTION_H
+274
View File
@@ -0,0 +1,274 @@
/*
* Copyright 2021 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_TOOLS_H
#define KIWIX_TOOLS_H
#include <string>
#include <vector>
#include <map>
#include <cstdint>
#include "common.h"
namespace kiwix
{
/**
* An IPv4 and/or IPv6 address.
*/
struct IpAddress
{
std::string addr; /**< IPv4 address */
std::string addr6; /**< IPv6 address */
};
typedef std::pair<std::string, std::string> LangNameCodePair;
typedef std::vector<LangNameCodePair> FeedLanguages;
typedef std::vector<std::string> FeedCategories;
/**
* Return the current directory.
*
* @return the current directory (utf8 encoded)
*/
std::string getCurrentDirectory();
/** Return the path of the executable
*
* Some application may be packaged in auto extractible archive (Appimage) and the
* real executable is different of the path of the archive.
* If `realPathOnly` is true, return the path of the real executable instead of the
* archive launched by the user.
*
* @param realPathOnly If we must return the real path of the executable.
* @return the path of the executable (utf8 encoded)
*/
std::string getExecutablePath(bool realPathOnly = false);
/** Tell if the path is a relative path.
*
* This function is provided as a small helper. It is probably better to use native tools
* to manipulate paths.
*
* @param path A utf8 encoded path.
* @return true if the path is relative.
*/
bool isRelativePath(const std::string& path);
/** Append a path to another one.
*
* This function is provided as a small helper. It is probably better to use native tools
* to manipulate paths.
*
* @param basePath the base path.
* @param relativePath a path to add to the base path, must be a relative path.
* @return The concatenation of the paths, using the right separator.
*/
std::string appendToDirectory(const std::string& basePath, const std::string& relativePath);
/** Remove the last element of a path.
*
* This function is provided as a small helper. It is probably better to use native tools
* to manipulate paths.
*
* @param path a path.
* @return The parent directory (or empty string if none).
*/
std::string removeLastPathElement(const std::string& path);
/** Get the last element of a path.
*
* This function is provided as a small helper. It is probably better to use native tools
* to manipulate paths.
*
* @param path a path.
* @return The base name of the path or empty string if none (ending with a separator).
*/
std::string getLastPathElement(const std::string& path);
/** Compute the absolute path of a relative path based on another one
*
* Equivalent to appendToDirectory followed by a normalization of the path.
*
* This function is provided as a small helper. It is probably better to use native tools
* to manipulate paths.
*
* @param path the base path (if empty, current directory is taken).
* @param relativePath the relative path.
* @return a absolute path.
*/
std::string computeAbsolutePath(const std::string& path, const std::string& relativePath);
/** Compute the relative path of a path relative to another one
*
* This function is provided as a small helper. It is probably better to use native tools
* to manipulate paths.
*
* @param path the base path.
* @param absolutePath the absolute path to find the relative path for.
* @return a relative path (pointing to absolutePath, relative to path).
*/
std::string computeRelativePath(const std::string& path, const std::string& absolutePath);
/** Sleep the current thread.
*
* This function is provided as a small helper. It is probably better to use native tools.
*
* @param milliseconds The number of milliseconds to wait for.
*/
void sleep(unsigned int milliseconds);
/** Split a string
*
* This function is provided as a small helper. It is probably better to use native tools.
*
* Assuming text = "foo:;bar;baz,oups;"
*
* split(text, ":;", true, true) => ["foo", ":", ";", "bar", ";", "baz,oups", ";"]
* split(text, ":;", true, false) => ["foo", "bar", "baz,oups"] (default)
* split(text, ":;", false, true) => ["foo", ":", "", ";", "bar", ";", "baz,oups", ";", ""]
* split(text, ":;", false, false) => ["foo", "", "bar", "baz,oups", ""]
*
* @param str The string to split.
* @param delims A string of potential delimiters.
* Each charater in the string can be a individual delimiters.
* @param dropEmpty true if empty part must be dropped from the result.
* @param keepDelim true if delimiter must be included from the result.
* @return a list of part (potentially containing delimiters)
*/
std::vector<std::string> split(const std::string& str, const std::string& delims, bool dropEmpty=true, bool keepDelim = false);
/** Convert language code from iso2 code to iso3
*
* This function is provided as a small helper. It is probably better to use native tools
* to manipulate locales.
*
* @param a2code a iso2 code string.
* @return the corresponding iso3 code.
* @throw std::out_of_range if iso2 code is not known.
*/
std::string converta2toa3(const std::string& a2code);
/** Extracts content from given file.
*
* This function provides content of a file provided it's path.
*
* @param path The absolute path provided in string format.
* @return Content of corresponding file in string format.
*/
std::string getFileContent(const std::string& path);
/** Checks if file exists.
*
* This function returns boolean stating if file exists.
*
* @param path The absolute path provided in string format.
* @return Boolean representing if file exists or not.
*/
bool fileExists(const std::string& path);
/** Checks if file is readable.
*
* This function returns boolean stating if file is readable.
*
* @param path The absolute path provided in string format.
* @return Boolean representing if file is readale or not.
*/
bool fileReadable(const std::string& path);
/** Provides mimetype from filename.
*
* This function provides mimetype from file-name.
*
* @param filename string containing filename.
* @return mimetype from filename in string format.
*/
std::string getMimeTypeForFile(const std::string& filename);
/** Provides all available network interfaces
*
* This function provides the available IPv4 and IPv6 network interfaces
* as a map from the interface name to its IPv4 and/or IPv6 address(es).
*/
std::map<std::string, IpAddress> getNetworkInterfacesIPv4Or6();
/** Provides all available IPv4 network interfaces
*
* This function provides the available IPv4 network interfaces
* as a map from the interface name to its IPv4 address.
*
* Provided for backward compatibility with libkiwix v13.1.0.
*/
std::map<std::string, std::string> getNetworkInterfaces();
/** Provides the best IP address
* This function provides the best IP addresses for both ipv4 and ipv6 protocols,
* in an IpAddress struct, based on the list given by getNetworkInterfacesIPv4Or6()
*/
IpAddress getBestPublicIps();
/** Provides the best IPv4 adddress
* Equivalent to getBestPublicIp(false). Provided for backward compatibility
* with libkiwix v13.1.0.
*/
std::string getBestPublicIp();
/** Converts file size to human readable format.
*
* This function will convert a number to its equivalent size using units.
*
* @param number file size in bytes.
* @return a human-readable string representation of the size, e.g., "2.3 KB", "1.8 MB", "5.2 GB".
*/
std::string beautifyFileSize(uint64_t number);
/**
* Load languages stored in an OPDS stream.
*
* @param content the OPDS stream.
* @return vector containing pairs of language code and their corresponding full language name.
*/
FeedLanguages readLanguagesFromFeed(const std::string& content);
/**
* Load categories stored in an OPDS stream .
*
* @param content the OPDS stream.
* @return vector containing category strings.
*/
FeedCategories readCategoriesFromFeed(const std::string& content);
/**
* Retrieve the full language name associated with a given ISO 639-3 language code.
*
* @param lang ISO 639-3 language code.
* @return full language name.
*/
std::string getLanguageSelfName(const std::string& lang);
/**
* Slugifies the filename by converting any characters reserved by the operating
* system to '_'. Note filename is only the file name and not a path.
*
* @param filename Valid UTF-8 encoded file name string.
* @return slugified string.
*/
std::string getSlugifiedFileName(const std::string& filename);
}
#endif // KIWIX_TOOLS_H
@@ -1,5 +1,5 @@
/*
* Copyright 2014 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright 2021 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,22 +17,18 @@
* MA 02110-1301, USA.
*/
#ifndef KIWIX_OTHERTOOLS_H
#define KIWIX_OTHERTOOLS_H
#ifndef KIWIX_VERSION_H
#define KIWIX_VERSION_H
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <pugixml.hpp>
#include <string>
#include <vector>
#include <iostream>
namespace kiwix
{
void sleep(unsigned int milliseconds);
std::string nodeToString(pugi::xml_node node);
std::string converta2toa3(const std::string& a2code);
typedef std::vector<std::pair<std::string, std::string>> LibVersions;
LibVersions getVersions();
void printVersions(std::ostream& out = std::cout);
}
#endif
#endif // KIWIX_VERSION_H
-98
View File
@@ -1,98 +0,0 @@
/*
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_XAPIAN_SEARCHER_H
#define KIWIX_XAPIAN_SEARCHER_H
#include <xapian.h>
#include "reader.h"
#include "searcher.h"
#include <map>
#include <string>
using namespace std;
namespace kiwix
{
class XapianSearcher;
class XapianResult : public Result
{
public:
XapianResult(XapianSearcher* searcher, Xapian::MSetIterator& iterator);
virtual ~XapianResult(){};
virtual std::string get_url();
virtual std::string get_title();
virtual int get_score();
virtual std::string get_snippet();
virtual std::string get_content();
virtual int get_wordCount();
virtual int get_size();
virtual int get_readerIndex() { return 0; };
private:
XapianSearcher* searcher;
Xapian::MSetIterator iterator;
Xapian::Document document;
};
class NoXapianIndexInZim : public exception
{
virtual const char* what() const throw()
{
return "There is no fulltext index in the zim file";
}
};
class XapianSearcher
{
friend class XapianResult;
public:
XapianSearcher(const string& xapianDirectoryPath, Reader* reader);
virtual ~XapianSearcher(){};
void searchInIndex(string& search,
const unsigned int resultStart,
const unsigned int resultEnd,
const bool verbose = false);
virtual Result* getNextResult();
void restart_search();
Xapian::MSet results;
protected:
void closeIndex();
void openIndex(const string& xapianDirectoryPath);
void setup_queryParser();
Reader* reader;
Xapian::Database readableDatabase;
std::string language;
std::string stopwords;
Xapian::QueryParser queryParser;
Xapian::Stem stemmer;
Xapian::SimpleStopper stopper;
Xapian::MSetIterator current_result;
std::map<std::string, int> valuesmap;
};
}
#endif
-10
View File
@@ -1,10 +0,0 @@
prefix=@prefix@
libdir=${prefix}/lib64
includedir=${prefix}/include
Name: libkiwix
Description: A library that contains a lot of things used by used by other kiwix programs
Version: @version@
Requires: @requires@
Libs: -L${libdir} -lkiwix @extra_libs@
Cflags: -I${includedir}/ @extra_cflags@
+96 -109
View File
@@ -1,135 +1,122 @@
project('kiwix-lib', 'cpp',
version : '3.0.2',
license : 'GPL',
default_options : ['c_std=c11', 'cpp_std=c++11', 'werror=true'])
project('libkiwix', 'cpp',
version : '14.2.0',
license : 'GPLv3+',
default_options : ['c_std=c11', 'cpp_std=c++17', 'werror=true'])
compiler = meson.get_compiler('cpp')
find_library_in_compiler = meson.version().version_compare('>=0.31.0')
static_deps = get_option('static-linkage') or get_option('default_library') == 'static'
extra_libs = []
static_deps = get_option('android') or get_option('default_library') == 'static'
if get_option('android')
extra_libs = ['-llog']
else
extra_libs = []
# Atomics as compiled by GCC or clang can lead to external references to
# functions depending on the type size and the platform. LLVM provides them in
# 'libcompiler_rt', which clang normally automatically links in, while GNU
# provides them in 'libatomic', which GCC *does not* link in automatically (but
# this is probably going to change, see
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81358). Regardless of the setup
# of the compiler driver itself (GCC or clang), we can thus assume that if some
# atomic references can't be resolved, then 'libatomic' is missing.
atomics_program = '''
#include <atomic>
#include <cstdint>
using namespace std;
int main() {
volatile atomic_bool a_b(true);
volatile atomic_ullong a_ull(-1);
// Next two lines are to cover atomic<socket_t> from 'httplib.h'.
volatile atomic<uint32_t> a_u32(-1);
volatile atomic<uint64_t> a_u64(-1);
return atomic_load(&a_b) == false && atomic_load(&a_ull) == 0 &&
atomic_load(&a_u32) == 0 && atomic_load(&a_u64) == 0;
}
'''
if not compiler.links(atomics_program,
name: 'compiler driver readily supports atomics')
libatomic = compiler.find_library('atomic')
compiler.links(atomics_program, name: 'atomics work with libatomic',
dependencies: libatomic, required: true)
extra_libs += ['-latomic']
endif
# C++ std::thread is implemented using pthread on Linux by GCC, and on FreeBSD
# for both GCC and LLVM.
if (host_machine.system() == 'linux' and compiler.get_id() == 'gcc') or \
host_machine.system() == 'freebsd'
thread_dep = dependency('threads')
else
thread_dep = dependency('', required:false)
endif
thread_dep = dependency('threads')
libicu_dep = dependency('icu-i18n', static:static_deps)
libzim_dep = dependency('libzim', version : '>=4.0.0', static:static_deps)
if libicu_dep.version().version_compare('>= 76')
libicu_deps = [libicu_dep, dependency('icu-uc', static:static_deps)]
else
libicu_deps = [libicu_dep]
endif
pugixml_dep = dependency('pugixml', static:static_deps)
libcurl_dep = dependency('libcurl', static:static_deps)
microhttpd_dep = dependency('libmicrohttpd', static:static_deps)
zlib_dep = dependency('zlib', static:static_deps)
xapian_dep = dependency('xapian-core', static:static_deps)
if compiler.has_header('mustache.hpp')
extra_include = []
elif compiler.has_header('mustache.hpp', args: '-I/usr/include/kainjow')
extra_include = ['/usr/include/kainjow']
else
error('Cannot found header mustache.hpp')
endif
libzim_dep = dependency('libzim', version:['>=9.4.0', '<10.0.0'], static:static_deps)
if not compiler.has_header_symbol('zim/zim.h', 'LIBZIM_WITH_XAPIAN', dependencies: libzim_dep)
error('Libzim seems to be compiled without Xapian. Xapian support is mandatory.')
endif
extra_cflags = ''
if target_machine.system() == 'windows' and static_deps
if host_machine.system() == 'windows' and static_deps
add_project_arguments('-DCURL_STATICLIB', language : 'cpp')
extra_cflags += '-DCURL_STATICLIB'
endif
ctpp2_include_path = ''
has_ctpp2_dep = false
ctpp2_prefix_install = get_option('ctpp2-install-prefix')
ctpp2_link_args = []
if ctpp2_prefix_install == ''
if compiler.has_header('ctpp2/CTPP2Logger.hpp')
if find_library_in_compiler
ctpp2_lib = compiler.find_library('ctpp2')
else
ctpp2_lib = find_library('ctpp2')
endif
ctpp2_link_args = ['-lctpp2']
if meson.is_cross_build() and host_machine.system() == 'windows'
if find_library_in_compiler
iconv_lib = compiler.find_library('iconv', required:false)
else
iconv_lib = find_library('iconv', required:false)
endif
if iconv_lib.found()
ctpp2_link_args += ['-liconv']
endif
endif
has_ctpp2_dep = true
ctpp2_dep = declare_dependency(link_args:ctpp2_link_args)
else
message('ctpp2/CTPP2Logger.hpp not found. Compiling without CTPP2 support')
endif
else
if not find_library_in_compiler
error('For custom ctpp2_prefix_install you need a meson version >=0.31.0')
endif
ctpp2_include_path = ctpp2_prefix_install + '/include'
ctpp2_include_args = ['-I'+ctpp2_include_path]
if compiler.has_header('ctpp2/CTPP2Logger.hpp', args:ctpp2_include_args)
ctpp2_include_dir = include_directories(ctpp2_include_path, is_system:true)
ctpp2_lib_path = join_paths(ctpp2_prefix_install, get_option('libdir'))
message(ctpp2_lib_path)
ctpp2_lib = compiler.find_library('ctpp2', dirs:ctpp2_lib_path, required:false)
if not ctpp2_lib.found()
ctpp2_lib_path = join_paths(ctpp2_prefix_install, 'lib')
message(ctpp2_lib_path)
ctpp2_lib = compiler.find_library('ctpp2', dirs:ctpp2_lib_path)
endif
ctpp2_link_args = ['-L'+ctpp2_lib_path, '-lctpp2']
if meson.is_cross_build() and host_machine.system() == 'windows'
iconv_lib = compiler.find_library('iconv', required:false)
if iconv_lib.found()
ctpp2_link_args += ['-liconv']
endif
endif
has_ctpp2_dep = true
ctpp2_dep = declare_dependency(include_directories:ctpp2_include_dir, link_args:ctpp2_link_args)
else
message('ctpp2/CTPP2Logger.hpp not found. Compiling without CTPP2 support')
endif
if host_machine.system() == 'windows'
add_project_arguments('-DNOMINMAX', language: 'cpp')
extra_libs += ['-liphlpapi']
endif
xapian_dep = dependency('xapian-core', required:false, static:static_deps)
all_deps = [thread_dep, libicu_dep, libzim_dep, xapian_dep, pugixml_dep, libcurl_dep]
if has_ctpp2_dep
all_deps += [ctpp2_dep]
endif
inc = include_directories('include')
conf = configuration_data()
conf.set('VERSION', '"@0@"'.format(meson.project_version()))
conf.set('ENABLE_CTPP2', has_ctpp2_dep)
if build_machine.system() == 'windows'
extra_link_args = ['-lshlwapi', '-lwinmm']
else
extra_link_args = []
extra_libs += ['-lshlwapi', '-lwinmm']
endif
# Dependencies as string
all_deps = [thread_dep, libzim_dep, pugixml_dep, libcurl_dep, microhttpd_dep, zlib_dep, xapian_dep]
# Dependencies as array
all_deps += libicu_deps
inc = include_directories('include', extra_include)
conf = configuration_data()
conf.set('LIBKIWIX_VERSION', '"@0@"'.format(meson.project_version()))
subdir('include')
subdir('scripts')
subdir('static')
subdir('src')
subdir('test')
pkg_requires = ['libzim', 'icu-i18n', 'pugixml', 'libcurl']
if xapian_dep.found()
pkg_requires += ['xapian-core']
if get_option('doc')
subdir('docs')
endif
if has_ctpp2_dep
extra_libs += ctpp2_link_args
if ctpp2_include_path != ''
extra_cflags = ' -I'+ctpp2_include_path
endif
endif
pkg_conf = configuration_data()
pkg_conf.set('prefix', get_option('prefix'))
pkg_conf.set('requires', ' '.join(pkg_requires))
pkg_conf.set('extra_libs', ' '.join(extra_libs))
pkg_conf.set('extra_cflags', extra_cflags)
pkg_conf.set('version', meson.project_version())
configure_file(output : 'kiwix.pc',
configuration : pkg_conf,
input : 'kiwix.pc.in',
install_dir: get_option('libdir')+'/pkgconfig'
)
pkg_mod = import('pkgconfig')
pkg_mod.generate(libraries : [libkiwix] + extra_libs,
version : meson.project_version(),
name : 'libkiwix',
filebase : 'libkiwix',
description : 'A library that contains useful primitives that Kiwix readers have in common',
extra_cflags: extra_cflags)
+4 -4
View File
@@ -1,4 +1,4 @@
option('ctpp2-install-prefix', type : 'string', value : '',
description : 'Prefix where ctpp libs has been installed')
option('android', type : 'boolean', value : false,
description : 'Do we make a kiwix-lib for android')
option('static-linkage', type : 'boolean', value : false,
description : 'Link statically with the dependencies.')
option('doc', type : 'boolean', value : false,
description : 'Build the documentations.')
-8
View File
@@ -1,8 +0,0 @@
#!/usr/bin/env bash
ctpp2c=$1
SOURCE=$(pwd)/$2
DEST=$3
$ctpp2c $SOURCE $DEST
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/bash
# Compute 'src' path
SCRIPT_DIR=$(dirname "$0")
REPO_DIR=$(readlink -f "$SCRIPT_DIR"/..)
DIRS="src include"
# Apply formating to all *.cpp and *.h files
cd "$REPO_DIR"
for FILE in $(find $DIRS -name '*.h' -o -name '*.cpp')
do
echo $FILE
clang-format -i -style=file "$FILE"
done
+148
View File
@@ -0,0 +1,148 @@
#!/usr/bin/env python3
'''
Copyright 2022 Veloman Yunkan <veloman.yunkan@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or any
later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
'''
import argparse
import os.path
import re
import json
def to_identifier(name):
ident = re.sub(r'[^0-9a-zA-Z]', '_', name)
if ident[0].isnumeric():
return "_"+ident
return ident
def lang_code(filename):
filename = os.path.basename(filename)
lang = to_identifier(os.path.splitext(filename)[0])
print(filename, '->', lang)
return lang
from string import Template
def expand_cxx_template(t, **kwargs):
return Template(t).substitute(**kwargs)
def cxx_string_literal(s):
# Taking advantage of the fact the JSON string escape rules match
# those of C++
return 'u8' + json.dumps(s)
string_table_cxx_template = '''
const I18nString $TABLE_NAME[] = {
$TABLE_ENTRIES
};
'''
lang_table_entry_cxx_template = '''
{
$LANG_STRING_LITERAL,
ARRAY_ELEMENT_COUNT($STRING_TABLE_NAME),
$STRING_TABLE_NAME
}'''
cxxfile_template = '''// This file is automatically generated. Do not modify it.
#include "server/i18n_utils.h"
namespace kiwix {
namespace i18n {
namespace
{
$STRING_DATA
} // unnamed namespace
#define ARRAY_ELEMENT_COUNT(a) (sizeof(a)/sizeof(a[0]))
extern const I18nStringTable stringTables[] = {
$LANG_TABLE
};
extern const size_t langCount = $LANG_COUNT;
} // namespace i18n
} // namespace kiwix
'''
class Resource:
def __init__(self, filename):
filename = filename.strip()
self.filename = filename
self.lang_code = lang_code(filename)
with open(filename, 'r', encoding='utf-8') as f:
self.data = f.read()
def get_string_table_name(self):
return "string_table_for_" + self.lang_code
def get_string_table(self):
table_entries = ",\n ".join(self.get_string_table_entries())
return expand_cxx_template(string_table_cxx_template,
TABLE_NAME=self.get_string_table_name(),
TABLE_ENTRIES=table_entries)
def get_string_table_entries(self):
d = json.loads(self.data)
for k in sorted(d.keys()):
if k != "@metadata":
key_string = cxx_string_literal(k)
value_string = cxx_string_literal(d[k])
yield '{ ' + key_string + ', ' + value_string + ' }'
def get_lang_table_entry(self):
return expand_cxx_template(lang_table_entry_cxx_template,
LANG_STRING_LITERAL=cxx_string_literal(self.lang_code),
STRING_TABLE_NAME=self.get_string_table_name())
def gen_c_file(resources):
string_data = []
lang_table = []
for r in resources:
string_data.append(r.get_string_table())
lang_table.append(r.get_lang_table_entry())
return expand_cxx_template(cxxfile_template,
STRING_DATA="\n".join(string_data),
LANG_TABLE=",\n ".join(lang_table),
LANG_COUNT=len(resources)
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--cxxfile',
required=True,
help='The Cpp file name to generate')
parser.add_argument('i18n_resource_files', nargs='+',
help='The list of resources to compile.')
args = parser.parse_args()
resources = [Resource(filename) for filename in args.i18n_resource_files]
with open(args.cxxfile, 'w') as f:
f.write(gen_c_file(resources))
+18
View File
@@ -0,0 +1,18 @@
.TH KIWIX-COMPILE-I18N "1" "January 2022" "Kiwix" "User Commands"
.SH NAME
kiwix-compile-i18n \- helper to compile Kiwix i18n (internationalization) data
.SH SYNOPSIS
\fBkiwix\-compile\-i18n\fR [\-h] \-\-cxxfile CXXFILE i18n_resource_files ...\fR
.SH DESCRIPTION
.TP
i18n_resource_files ...
The list of i18n resources to compile.
.TP
\fB\-h\fR, \fB\-\-help\fR
show a help message and exit
.TP
\fB\-\-cxxfile\fR CXXFILE
The Cpp file name to generate
.TP
.SH AUTHOR
Veloman Yunkan <veloman.yunkan@gmail.com>
+66 -16
View File
@@ -52,26 +52,60 @@ resource_getter_template = """
return RESOURCE::{identifier};
"""
resource_cacheid_getter_template = """
if (name == "{common_name}")
return "{cacheid}";
"""
resource_decl_template = """{namespaces_open}
extern const std::string {identifier};
{namespaces_close}"""
BINARY_RESOURCE_EXTENSIONS = {'.ico', '.png', '.ttf'}
TEXT_RESOURCE_EXTENSIONS = {
'.css',
'.html',
'.js',
'.json',
'.svg',
'.tmpl',
'.webmanifest',
'.xml',
}
if not BINARY_RESOURCE_EXTENSIONS.isdisjoint(TEXT_RESOURCE_EXTENSIONS):
raise RuntimeError(f"The following file type extensions are declared to be both binary and text: {BINARY_RESOURCE_EXTENSIONS.intersection(TEXT_RESOURCE_EXTENSIONS)}")
def is_binary_resource(filename):
_, extension = os.path.splitext(filename)
is_binary = extension in BINARY_RESOURCE_EXTENSIONS
is_text = extension in TEXT_RESOURCE_EXTENSIONS
if not is_binary and not is_text:
# all file type extensions of static resources must be listed
# in either BINARY_RESOURCE_EXTENSIONS or TEXT_RESOURCE_EXTENSIONS
raise RuntimeError(f"Unknown file type extension: {extension}")
return is_binary
class Resource:
def __init__(self, base_dirs, filename):
filename = filename.strip()
def __init__(self, base_dirs, filename, cacheid=None):
filename = filename
self.filename = filename
self.identifier = full_identifier(filename)
self.cacheid = cacheid
found = False
for base_dir in base_dirs:
try:
with open(os.path.join(base_dir, filename), 'rb') as f:
self.data = f.read()
if not is_binary_resource(filename):
self.data = self.data.replace(b"\r\n", b"\n")
found = True
break
except FileNotFoundError:
continue
if not found:
raise Exception("Impossible to found {}".format(filename))
raise Exception("Resource not found: {}".format(filename))
def dump_impl(self):
nb_row = len(self.data)//16 + (1 if len(self.data) % 16 else 0)
@@ -81,28 +115,34 @@ class Resource:
data_identifier="_".join([""]+self.identifier),
resource_content=",\n ".join(", ".join("{:#04x}".format(i) for i in r) for r in sliced),
resource_len=len(self.data),
namespaces_open=" ".join("namespace {} {{".format(id) for id in self.identifier[:-1]),
namespaces_open=" ".join("namespace {} {{".format(id) for id in self.identifier[:-1]),
namespaces_close=" ".join(["}"]*(len(self.identifier)-1)),
identifier=self.identifier[-1],
env_identifier="RES_"+"_".join(self.identifier)+"_PATH"
)
def dump_getter(self):
return resource_getter_template.format(
common_name=self.filename,
identifier="::".join(self.identifier)
)
def dump_cacheid_getter(self):
return resource_cacheid_getter_template.format(
common_name=self.filename,
cacheid=self.cacheid
)
def dump_decl(self):
return resource_decl_template.format(
namespaces_open=" ".join("namespace {} {{".format(id) for id in self.identifier[:-1]),
namespaces_open=" ".join("namespace {} {{".format(id) for id in self.identifier[:-1]),
namespaces_close=" ".join(["}"]*(len(self.identifier)-1)),
identifier=self.identifier[-1]
)
master_c_template = """//This file is automaically generated. Do not modify it.
master_c_template = """//This file is automatically generated. Do not modify it.
#include <stdlib.h>
#include <fstream>
@@ -113,7 +153,7 @@ static std::string init_resource(const char* name, const unsigned char* content,
char * resPath = getenv(name);
if (NULL == resPath)
return std::string(reinterpret_cast<const char*>(content), len);
std::ifstream ifs(resPath);
if (!ifs.good())
return std::string(reinterpret_cast<const char*>(content), len);
@@ -123,7 +163,12 @@ static std::string init_resource(const char* name, const unsigned char* content,
const std::string& getResource_{basename}(const std::string& name) {{
{RESOURCES_GETTER}
throw ResourceNotFound("Resource not found.");
throw ResourceNotFound("Resource not found: " + name);
}}
const char* getResourceCacheId_{basename}(const std::string& name) {{
{RESOURCE_CACHEID_GETTER}
return nullptr;
}}
{RESOURCES}
@@ -134,10 +179,11 @@ def gen_c_file(resources, basename):
return master_c_template.format(
RESOURCES="\n\n".join(r.dump_impl() for r in resources),
RESOURCES_GETTER="\n\n".join(r.dump_getter() for r in resources),
RESOURCE_CACHEID_GETTER="\n\n".join(r.dump_cacheid_getter() for r in resources if r.cacheid is not None),
include_file=basename,
basename=to_identifier(basename)
)
master_h_template = """//This file is automaically generated. Do not modify it.
@@ -159,8 +205,10 @@ class ResourceNotFound : public std::runtime_error {{
}};
const std::string& getResource_{basename}(const std::string& name);
const char* getResourceCacheId_{basename}(const std::string& name);
#define getResource(a) (getResource_{basename}(a))
#define getResourceCacheId(a) (getResourceCacheId_{basename}(a))
#endif // KIWIX_{BASENAME}
@@ -182,15 +230,17 @@ if __name__ == "__main__":
parser.add_argument('--source_dir',
help="Additional directory where to look for resources.",
action='append')
parser.add_argument('resource_file',
parser.add_argument('resource_files', nargs='+',
help='The list of resources to compile.')
args = parser.parse_args()
base_dir = os.path.dirname(os.path.realpath(args.resource_file))
source_dir = args.source_dir or []
with open(args.resource_file, 'r') as f:
resources = [Resource([base_dir]+source_dir, filename)
for filename in f.readlines()]
resources = []
for resfile in args.resource_files:
base_dir = os.path.dirname(os.path.realpath(resfile))
with open(resfile, 'r') as f:
resources += [Resource([base_dir]+source_dir, *line.strip().split())
for line in f.readlines()]
h_identifier = to_identifier(os.path.basename(args.hfile))
with open(args.hfile, 'w') as f:
+20
View File
@@ -0,0 +1,20 @@
.TH KIWIX-COMPILE-RESOURCES "1" "August 2017" "Kiwix" "User Commands"
.SH NAME
kiwix-compile-resources \- helper to compile and generate some Kiwix resources
.SH SYNOPSIS
\fBkiwix\-compile\-resources\fR [\-h] [\-\-cxxfile CXXFILE] [\-\-hfile HFILE] resource_file ...\fR
.SH DESCRIPTION
.TP
resource_file
The list of resources to compile.
.TP
\fB\-h\fR, \fB\-\-help\fR
show a help message and exit
.TP
\fB\-\-cxxfile\fR CXXFILE
The Cpp file name to generate
.TP
\fB\-\-hfile\fR HFILE
The h file name to generate
.SH AUTHOR
Matthieu Gautier <mgautier@kymeria.fr>
+135
View File
@@ -0,0 +1,135 @@
#!/usr/bin/env python3
'''
Copyright 2022 Veloman Yunkan <veloman.yunkan@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or any
later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
'''
import argparse
import hashlib
import os.path
import re
def read_resource_file(resource_file_path):
with open(resource_file_path, 'r') as f:
return [line.strip() for line in f]
def list_resources(resource_file_path):
for resource_path in read_resource_file(resource_file_path):
print(resource_path)
def compute_resource_revision(resource_path):
with open(os.path.join(OUT_DIR, resource_path), 'rb') as f:
return hashlib.sha1(f.read()).hexdigest()[:8]
resource_revisions = {}
def get_resource_revision(res):
if not res in resource_revisions:
preprocess_resource(res)
resource_revisions[res] = compute_resource_revision(res)
return resource_revisions[res]
RESOURCE_WITH_CACHEID_URL_PATTERN=r'(?P<pre>.*/(?P<resource>skin/[^"?]+)\?)KIWIXCACHEID(?P<post>[^"]*)'
def set_cacheid(resource_matchobj):
pre = resource_matchobj.group('pre')
resource = resource_matchobj.group('resource')
post = resource_matchobj.group('post')
cacheid = 'cacheid=' + get_resource_revision(resource)
return pre + cacheid + post
def preprocess_text(s):
if 'KIWIXCACHEID' in s:
s = re.sub(RESOURCE_WITH_CACHEID_URL_PATTERN, set_cacheid, s)
assert not 'KIWIXCACHEID' in s
return s
def get_preprocessed_resource(srcpath):
"""Get the transformed content of a resource
If the resource at srcpath is modified by preprocessing then this function
returns the transformed content of the resource. Otherwise it returns None.
"""
try:
with open(srcpath, 'r') as resource_file:
content = resource_file.read()
preprocessed_content = preprocess_text(content)
return preprocessed_content if preprocessed_content != content else None
except UnicodeDecodeError:
# It was a binary resource
return None
def symlink_resource(src, resource_path):
if os.path.exists(resource_path):
if os.path.islink(resource_path) and os.readlink(resource_path) == src:
return
os.remove(resource_path)
os.symlink(src, resource_path)
def preprocess_resource(resource_path):
print('Preprocessing', resource_path, '...')
resource_dir = os.path.dirname(resource_path)
if resource_dir != '':
os.makedirs(os.path.join(OUT_DIR, resource_dir), exist_ok=True)
srcpath = os.path.join(BASE_DIR, resource_path)
outpath = os.path.join(OUT_DIR, resource_path)
if os.path.exists(outpath):
os.remove(outpath)
preprocessed_content = get_preprocessed_resource(srcpath)
if preprocessed_content is None:
symlink_resource(srcpath, outpath)
else:
with open(outpath, 'w') as target:
print(preprocessed_content, end='', file=target)
def copy_resource_list_file(src_path, dst_path):
with open(src_path, 'r') as src:
with open(dst_path, 'w') as dst:
for line in src:
res = line.strip()
if line.startswith("skin/") and res in resource_revisions:
dst.write(res + " " + resource_revisions[res] + "\n")
else:
dst.write(line)
def preprocess_resources(resource_file_path):
resource_filename = os.path.basename(resource_file_path)
for resource in read_resource_file(resource_file_path):
if resource.startswith('skin/'):
get_resource_revision(resource)
else:
preprocess_resource(resource)
copy_resource_list_file(resource_file_path, os.path.join(OUT_DIR, resource_filename))
if __name__ == "__main__":
parser = argparse.ArgumentParser()
commands = parser.add_mutually_exclusive_group()
commands.add_argument('--list-all', action='store_true')
commands.add_argument('--preprocess', action='store_true')
parser.add_argument('--outdir')
parser.add_argument('resource_file')
args = parser.parse_args()
BASE_DIR = os.path.dirname(os.path.realpath(args.resource_file))
OUT_DIR = args.outdir
if args.list_all:
list_resources(args.resource_file)
elif args.preprocess:
preprocess_resources(args.resource_file)
+9 -1
View File
@@ -1,5 +1,13 @@
res_manager = find_program('kiwix-resources')
res_compiler = find_program('kiwix-compile-resources')
intermediate_ctpp2c = find_program('ctpp2c.sh')
install_data(res_compiler.path(), install_dir:get_option('bindir'))
install_man('kiwix-compile-resources.1')
i18n_compiler = find_program('kiwix-compile-i18n')
install_data(i18n_compiler.path(), install_dir:get_option('bindir'))
install_man('kiwix-compile-i18n.1')
-13
View File
@@ -1,13 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="kiwix.org.kiwixlib"
>
<application android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true"
>
</application>
</manifest>
-424
View File
@@ -1,424 +0,0 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <jni.h>
#include <zim/file.h>
#include <android/log.h>
#include "org_kiwix_kiwixlib_JNIKiwixReader.h"
#include "common/base64.h"
#include "reader.h"
#include "utils.h"
/* Kiwix Reader JNI functions */
JNIEXPORT jlong JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getNativeReader(
JNIEnv* env, jobject obj, jstring filename)
{
std::string cPath = jni2c(filename, env);
__android_log_print(ANDROID_LOG_INFO, "kiwix", "Attempting to create reader with: %s", cPath.c_str());
Lock l;
try {
kiwix::Reader* reader = new kiwix::Reader(cPath);
return reinterpret_cast<jlong>(new Handle<kiwix::Reader>(reader));
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_WARN, "kiwix", "Error opening ZIM file");
__android_log_print(ANDROID_LOG_WARN, "kiwix", e.what());
return 0;
}
}
JNIEXPORT void JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_dispose(JNIEnv* env, jobject obj)
{
Handle<kiwix::Reader>::dispose(env, obj);
}
#define READER (Handle<kiwix::Reader>::getHandle(env, obj))
/* Kiwix library functions */
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getMainPage(JNIEnv* env, jobject obj)
{
jstring url;
try {
std::string cUrl = READER->getMainPage().getPath();
url = c2jni(cUrl, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM main page");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
url = NULL;
}
return url;
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getId(JNIEnv* env, jobject obj)
{
jstring id;
try {
std::string cId = READER->getId();
id = c2jni(cId, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM id");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
id = NULL;
}
return id;
}
JNIEXPORT jint JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getFileSize(JNIEnv* env, jobject obj)
{
jint size;
try {
int cSize = READER->getFileSize();
size = c2jni(cSize);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM file size");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
}
return size;
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getCreator(JNIEnv* env, jobject obj)
{
jstring creator;
try {
std::string cCreator = READER->getCreator();
creator = c2jni(cCreator, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM creator");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
creator = NULL;
}
return creator;
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getPublisher(JNIEnv* env, jobject obj)
{
jstring publisher;
try {
std::string cPublisher = READER->getPublisher();
publisher = c2jni(cPublisher, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM publish");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
publisher = NULL;
}
return publisher;
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getName(JNIEnv* env, jobject obj)
{
jstring name;
try {
std::string cName = READER->getName();
name = c2jni(cName, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM name");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
name = NULL;
}
return name;
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getFavicon(JNIEnv* env, jobject obj)
{
jstring favicon;
try {
std::string cContent;
std::string cMime;
READER->getFavicon(cContent, cMime);
favicon = c2jni(
base64_encode(cContent),
env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM favicon");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
favicon = NULL;
}
return favicon;
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getDate(JNIEnv* env, jobject obj)
{
jstring date;
try {
std::string cDate = READER->getDate();
date = c2jni(cDate, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM date");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
date = NULL;
}
return date;
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getLanguage(JNIEnv* env, jobject obj)
{
jstring language;
try {
std::string cLanguage = READER->getLanguage();
language = c2jni(cLanguage, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM language");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
language = NULL;
}
return language;
}
JNIEXPORT jstring JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getMimeType(
JNIEnv* env, jobject obj, jstring url)
{
jstring mimeType;
std::string cUrl = jni2c(url, env);
try {
auto entry = READER->getEntryFromEncodedPath(cUrl);
auto cMimeType = entry.getMimetype();
mimeType = c2jni(cMimeType, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get mime-type for url: %s", cUrl.c_str());
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
mimeType = NULL;
}
return mimeType;
}
JNIEXPORT jbyteArray JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getContent(
JNIEnv* env, jobject obj, jstring url, jobject titleObj, jobject mimeTypeObj, jobject sizeObj)
{
/* Default values */
setStringObjValue("", titleObj, env);
setStringObjValue("", mimeTypeObj, env);
setIntObjValue(0, sizeObj, env);
jbyteArray data = env->NewByteArray(0);
/* Retrieve the content */
std::string cUrl = jni2c(url, env);
unsigned int cSize = 0;
try {
auto entry = READER->getEntryFromEncodedPath(cUrl);
entry = entry.getFinalEntry();
cSize = entry.getSize();
setIntObjValue(cSize, sizeObj, env);
data = env->NewByteArray(cSize);
env->SetByteArrayRegion(
data, 0, cSize, reinterpret_cast<const jbyte*>(entry.getBlob().data()));
setStringObjValue(entry.getMimetype(), mimeTypeObj, env);
setStringObjValue(entry.getTitle(), titleObj, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get content for url: %s", cUrl.c_str());
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
}
return data;
}
JNIEXPORT jbyteArray JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getContentPart(
JNIEnv* env, jobject obj, jstring url, jint offset, jint len, jobject sizeObj)
{
jbyteArray data = env->NewByteArray(0);
setIntObjValue(0, sizeObj, env);
/* Default values */
/* Retrieve the content */
std::string cUrl = jni2c(url, env);
unsigned int cOffset = jni2c(offset);
unsigned int cLen = jni2c(len);
try {
auto entry = READER->getEntryFromEncodedPath(cUrl);
entry = entry.getFinalEntry();
if (cLen == 0) {
setIntObjValue(entry.getSize(), sizeObj, env);
} else if (cOffset+cLen < entry.getSize()) {
auto blob = entry.getBlob(cOffset, cLen);
data = env->NewByteArray(cLen);
env->SetByteArrayRegion(
data, 0, cLen, reinterpret_cast<const jbyte*>(blob.data()));
setIntObjValue(cLen, sizeObj, env);
}
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get partial content for url: %s (%u : %u)", cUrl.c_str(), cOffset, cLen);
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
}
return data;
}
JNIEXPORT jobject JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getDirectAccessInformation(
JNIEnv* env, jobject obj, jstring url)
{
jclass classPair = env->FindClass("org/kiwix/kiwixlib/Pair");
jmethodID midPairinit = env->GetMethodID(classPair, "<init>", "()V");
jobject pair = env->NewObject(classPair, midPairinit);
setPairObjValue("", 0, pair, env);
std::string cUrl = jni2c(url, env);
try {
auto entry = READER->getEntryFromEncodedPath(cUrl);
entry = entry.getFinalEntry();
auto part_info = entry.getDirectAccessInfo();
setPairObjValue(part_info.first, part_info.second, pair, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get direct access info for url: %s", cUrl.c_str());
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
}
return pair;
}
JNIEXPORT jboolean JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_searchSuggestions(JNIEnv* env,
jobject obj,
jstring prefix,
jint count)
{
jboolean retVal = JNI_FALSE;
std::string cPrefix = jni2c(prefix, env);
unsigned int cCount = jni2c(count);
try {
if (READER->searchSuggestionsSmart(cPrefix, cCount)) {
retVal = JNI_TRUE;
}
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_WARN, "kiwix", "Unable to get search results for pattern: %s", cPrefix.c_str());
__android_log_print(ANDROID_LOG_WARN, "kiwix", e.what());
}
return retVal;
}
JNIEXPORT jboolean JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getNextSuggestion(JNIEnv* env,
jobject obj,
jobject titleObj)
{
jboolean retVal = JNI_FALSE;
std::string cTitle;
try {
if (READER->getNextSuggestion(cTitle)) {
setStringObjValue(cTitle, titleObj, env);
retVal = JNI_TRUE;
}
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_WARN, "kiwix", "Unable to get next suggestion");
__android_log_print(ANDROID_LOG_WARN, "kiwix", e.what());
}
return retVal;
}
JNIEXPORT jboolean JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getPageUrlFromTitle(JNIEnv* env,
jobject obj,
jstring title,
jobject urlObj)
{
std::string cTitle = jni2c(title, env);
try {
auto entry = READER->getEntryFromTitle(cTitle);
entry = entry.getFinalEntry();
setStringObjValue(entry.getPath(), urlObj, env);
return JNI_TRUE;
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_WARN, "kiwix", "Unable to get url for title %s: ", cTitle.c_str());
__android_log_print(ANDROID_LOG_WARN, "kiwix", e.what());
}
return JNI_FALSE;
}
JNIEXPORT jstring JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getTitle(
JNIEnv* env, jobject obj)
{
jstring title;
try {
std::string cTitle = READER->getTitle();
title = c2jni(cTitle, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get zim title");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
title = NULL;
}
return title;
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixReader_getDescription(JNIEnv* env, jobject obj)
{
jstring description;
try {
std::string cDescription = READER->getDescription();
description = c2jni(cDescription, env);
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get zim description");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
description = NULL;
}
return description;
}
JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getRandomPage(
JNIEnv* env, jobject obj, jobject urlObj)
{
jboolean retVal = JNI_FALSE;
std::string cUrl;
try {
std::string cUrl = READER->getRandomPage().getPath();
setStringObjValue(cUrl, urlObj, env);
retVal = JNI_TRUE;
} catch (std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get random page");
__android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what());
}
return retVal;
}
-124
View File
@@ -1,124 +0,0 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <zim/file.h>
#include "org_kiwix_kiwixlib_JNIKiwixSearcher.h"
#include "org_kiwix_kiwixlib_JNIKiwixSearcher_Result.h"
#include "reader.h"
#include "searcher.h"
#include "utils.h"
#define SEARCHER (Handle<kiwix::Searcher>::getHandle(env, obj))
#define RESULT (Handle<kiwix::Result>::getHandle(env, obj))
JNIEXPORT void JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixSearcher_dispose(JNIEnv* env, jobject obj)
{
Handle<kiwix::Searcher>::dispose(env, obj);
}
/* Kiwix Reader JNI functions */
JNIEXPORT jlong JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixSearcher_getNativeHandle(JNIEnv* env,
jobject obj)
{
kiwix::Searcher* searcher = new kiwix::Searcher();
return reinterpret_cast<jlong>(new Handle<kiwix::Searcher>(searcher));
}
/* Kiwix library functions */
JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_addReader(
JNIEnv* env, jobject obj, jobject reader)
{
auto searcher = SEARCHER;
searcher->add_reader(*(Handle<kiwix::Reader>::getHandle(env, reader)), "");
}
JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_search(
JNIEnv* env, jobject obj, jstring query, jint count)
{
std::string cquery = jni2c(query, env);
unsigned int ccount = jni2c(count);
SEARCHER->search(cquery, 0, ccount);
}
JNIEXPORT jobject JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixSearcher_getNextResult(JNIEnv* env,
jobject obj)
{
jobject result = nullptr;
kiwix::Result* cresult = SEARCHER->getNextResult();
if (cresult != nullptr) {
jclass resultclass
= env->FindClass("org/kiwix/kiwixlib/JNIKiwixSearcher$Result");
jmethodID ctor = env->GetMethodID(
resultclass, "<init>", "(Lorg/kiwix/kiwixlib/JNIKiwixSearcher;JLorg/kiwix/kiwixlib/JNIKiwixSearcher;)V");
result = env->NewObject(resultclass, ctor, obj, reinterpret_cast<jlong>(new Handle<kiwix::Result>(cresult)), obj);
}
return result;
}
JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_dispose(
JNIEnv* env, jobject obj)
{
Handle<kiwix::Result>::dispose(env, obj);
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_getUrl(JNIEnv* env,
jobject obj)
{
try {
return c2jni(RESULT->get_url(), env);
} catch (...) {
return nullptr;
}
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_getTitle(JNIEnv* env,
jobject obj)
{
try {
return c2jni(RESULT->get_title(), env);
} catch (...) {
return nullptr;
}
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_getSnippet(JNIEnv* env,
jobject obj)
{
return c2jni(RESULT->get_snippet(), env);
}
JNIEXPORT jstring JNICALL
Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_getContent(JNIEnv* env,
jobject obj)
{
return c2jni(RESULT->get_content(), env);
}
-26
View File
@@ -1,26 +0,0 @@
kiwix_jni = custom_target('jni',
input: ['org/kiwix/kiwixlib/JNIKiwix.java',
'org/kiwix/kiwixlib/JNIKiwixReader.java',
'org/kiwix/kiwixlib/JNIKiwixSearcher.java',
'org/kiwix/kiwixlib/JNIKiwixInt.java',
'org/kiwix/kiwixlib/JNIKiwixString.java',
'org/kiwix/kiwixlib/JNIKiwixBool.java',
'org/kiwix/kiwixlib/JNIKiwixException.java',
'org/kiwix/kiwixlib/Pair.java'],
output: ['org_kiwix_kiwixlib_JNIKiwix.h',
'org_kiwix_kiwixlib_JNIKiwixReader.h',
'org_kiwix_kiwixlib_JNIKiwixSearcher.h',
'org_kiwix_kiwixlib_JNIKiwixSearcher_Result.h'],
command:['javac', '-d', '@OUTDIR@', '-h', '@OUTDIR@', '@INPUT@']
)
kiwix_sources += [
'android/kiwix.cpp',
'android/kiwixreader.cpp',
'android/kiwixsearcher.cpp',
kiwix_jni]
install_subdir('org', install_dir: 'kiwix-lib/java')
install_subdir('res', install_dir: 'kiwix-lib')
install_data('AndroidManifest.xml', install_dir: 'kiwix-lib')
@@ -1,127 +0,0 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.kiwix.kiwixlib;
import org.kiwix.kiwixlib.JNIKiwixException;
import org.kiwix.kiwixlib.JNIKiwixString;
import org.kiwix.kiwixlib.JNIKiwixInt;
import org.kiwix.kiwixlib.JNIKiwixSearcher;
import org.kiwix.kiwixlib.Pair;
public class JNIKiwixReader
{
public native String getMainPage();
public native String getTitle();
public native String getId();
public native String getLanguage();
public native String getMimeType(String url);
public native byte[] getContent(String url,
JNIKiwixString title,
JNIKiwixString mimeType,
JNIKiwixInt size);
/**
* getContentPart.
*
* Get only a part of the content of the article.
* Return a byte array of `len` size starting from offset `offset`.
* Set `size` to the number of bytes read
* (`len` if everything is ok, 0 in case of error).
* If `len` == 0, no bytes are read but `size` is set to the total size of the
* article.
*/
public native byte[] getContentPart(String url,
int offest,
int len,
JNIKiwixInt size);
/**
* getDirectAccessInformation.
*
* Return information giving where the content is located in the zim file.
*
* Some contents (binary content) are stored uncompressed in the zim file.
* Knowing this information, it could be interesting to directly open
* the zim file (or zim part) and directly read the content from it (and so
* bypassing the libzim).
*
* Return a `Pair` (filename, offset) where the content is located.
*
* If the content cannot be directly accessed (content is compressed or zim
* file is cut in the middle of the content), the filename is an empty string
* and offset is zero.
*/
public native Pair getDirectAccessInformation(String url);
public native boolean searchSuggestions(String prefix, int count);
public native boolean getNextSuggestion(JNIKiwixString title);
public native boolean getPageUrlFromTitle(String title, JNIKiwixString url);
public native String getDescription();
public native String getDate();
public native String getFavicon();
public native String getCreator();
public native String getPublisher();
public native String getName();
public native int getFileSize();
public native int getArticleCount();
public native int getMediaCount();
public native boolean getRandomPage(JNIKiwixString url);
public JNIKiwixSearcher search(String query, int count)
{
JNIKiwixSearcher searcher = new JNIKiwixSearcher();
searcher.addKiwixReader(this);
searcher.search(query, count);
return searcher;
}
public JNIKiwixReader(String filename) throws JNIKiwixException
{
nativeHandle = getNativeReader(filename);
if (nativeHandle == 0) {
throw new JNIKiwixException("Cannot open zimfile "+filename);
}
}
public JNIKiwixReader() {
}
public native void dispose();
private native long getNativeReader(String filename);
private long nativeHandle;
}
@@ -1,67 +0,0 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.kiwix.kiwixlib;
import org.kiwix.kiwixlib.JNIKiwixReader;
import java.util.Vector;
public class JNIKiwixSearcher
{
public class Result
{
private long nativeHandle;
private JNIKiwixSearcher searcher;
public Result(long handle, JNIKiwixSearcher _searcher)
{
nativeHandle = handle;
searcher = _searcher;
}
public native String getUrl();
public native String getTitle();
public native String getContent();
public native String getSnippet();
public native void dispose();
}
public JNIKiwixSearcher()
{
nativeHandle = getNativeHandle();
usedReaders = new Vector();
}
public native void dispose();
private native long getNativeHandle();
private long nativeHandle;
private Vector usedReaders;
public native void addReader(JNIKiwixReader reader);
public void addKiwixReader(JNIKiwixReader reader)
{
addReader(reader);
usedReaders.addElement(reader);
};
public native void search(String query, int count);
public native Result getNextResult();
public native boolean hasMoreResult();
}
@@ -1,25 +0,0 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.kiwix.kiwixlib;
public class JNIKiwixString
{
public String value;
}
-26
View File
@@ -1,26 +0,0 @@
/*
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.kiwix.kiwixlib;
public class Pair
{
public String filename;
public int offset;
}
-3
View File
@@ -1,3 +0,0 @@
<resources>
<string name="app_name">Kiwix Lib</string>
</resources>
-150
View File
@@ -1,150 +0,0 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef _ANDROID_JNI_UTILS_H
#define _ANDROID_JNI_UTILS_H
#include <jni.h>
#include <pthread.h>
#include <string>
extern pthread_mutex_t globalLock;
inline jfieldID getHandleField(JNIEnv* env, jobject obj)
{
jclass c = env->GetObjectClass(obj);
// J is the type signature for long:
return env->GetFieldID(c, "nativeHandle", "J");
}
class Lock
{
protected:
pthread_mutex_t* lock;
public:
Lock() : lock(&globalLock) { pthread_mutex_lock(lock); }
Lock(const Lock&) = delete;
Lock& operator=(const Lock&) = delete;
Lock(Lock&& other) : lock(&globalLock) { other.lock = nullptr; }
virtual ~Lock()
{
if (lock) {
pthread_mutex_unlock(lock);
}
}
};
template <class T>
class LockedHandle;
template <class T>
class Handle
{
protected:
T* h;
public:
Handle(T* h) : h(h){};
// No destructor. This must and will be handled by dispose method.
static LockedHandle<T> getHandle(JNIEnv* env, jobject obj)
{
jlong handle = env->GetLongField(obj, getHandleField(env, obj));
return LockedHandle<T>(reinterpret_cast<Handle<T>*>(handle));
}
static void dispose(JNIEnv* env, jobject obj)
{
auto lHandle = getHandle(env, obj);
auto handle = lHandle.h;
delete handle->h;
delete handle;
}
friend class LockedHandle<T>;
};
template <class T>
struct LockedHandle : public Lock {
Handle<T>* h;
LockedHandle(Handle<T>* h) : h(h) {}
T* operator->() { return h->h; }
T* operator*() { return h->h; }
operator bool() const { return (h->h != nullptr); }
};
/* c2jni type conversion functions */
inline jboolean c2jni(const bool& val) { return val ? JNI_TRUE : JNI_FALSE; }
inline jstring c2jni(const std::string& val, JNIEnv* env)
{
return env->NewStringUTF(val.c_str());
}
inline jint c2jni(const int val) { return (jint)val; }
inline jint c2jni(const unsigned val) { return (unsigned)val; }
/* jni2c type conversion functions */
inline bool jni2c(const jboolean& val) { return val == JNI_TRUE; }
inline std::string jni2c(const jstring& val, JNIEnv* env)
{
const char* chars = env->GetStringUTFChars(val, 0);
std::string ret(chars);
env->ReleaseStringUTFChars(val, chars);
return ret;
}
inline int jni2c(const jint val) { return (int)val; }
/* Method to deal with variable passed by reference */
inline void setStringObjValue(const std::string& value,
const jobject obj,
JNIEnv* env)
{
jclass objClass = env->GetObjectClass(obj);
jfieldID objFid = env->GetFieldID(objClass, "value", "Ljava/lang/String;");
env->SetObjectField(obj, objFid, c2jni(value, env));
}
inline void setIntObjValue(const int value, const jobject obj, JNIEnv* env)
{
jclass objClass = env->GetObjectClass(obj);
jfieldID objFid = env->GetFieldID(objClass, "value", "I");
env->SetIntField(obj, objFid, value);
}
inline void setBoolObjValue(const bool value, const jobject obj, JNIEnv* env)
{
jclass objClass = env->GetObjectClass(obj);
jfieldID objFid = env->GetFieldID(objClass, "value", "Z");
env->SetIntField(obj, objFid, c2jni(value));
}
inline void setPairObjValue(const std::string& filename, const int offset,
const jobject obj, JNIEnv* env)
{
jclass objClass = env->GetObjectClass(obj);
jfieldID filenameFid = env->GetFieldID(objClass, "filename", "Ljava/lang/String;");
env->SetObjectField(obj, filenameFid, c2jni(filename, env));
jfieldID offsetFid = env->GetFieldID(objClass, "offset", "I");
env->SetIntField(obj, offsetFid, offset);
}
#endif // _ANDROID_JNI_UTILS_H
+183 -60
View File
@@ -2,28 +2,69 @@
#include "aria2.h"
#include "xmlrpc.h"
#include <iostream>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <thread>
#include <chrono>
#include <common/otherTools.h>
#include <common/pathTools.h>
#include <downloader.h> // For AriaError
#include "tools.h"
#include "tools/pathTools.h"
#include "tools/stringTools.h"
#include "tools/otherTools.h"
#include "downloader.h" // For AriaError
#ifdef _WIN32
# define ARIA2_CMD "aria2c.exe"
#else
# define ARIA2_CMD "aria2c"
# include <unistd.h>
#endif
#define LOG_ARIA_ERROR() \
{ \
std::cerr << "ERROR: aria2 RPC request failed. (" << res << ")." << std::endl; \
std::cerr << (curlErrorBuffer[0] ? curlErrorBuffer : curl_easy_strerror(res)) << std::endl; \
}
namespace kiwix {
Aria2::Aria2():
namespace {
void pauseAnyActiveDownloads(const std::string& ariaSessionFilePath)
{
std::ifstream inputFile(ariaSessionFilePath);
if ( !inputFile )
return;
std::ostringstream ss;
std::string line;
while ( std::getline(inputFile, line) ) {
if ( !startsWith(line, " pause=") ) {
ss << line << "\n";
}
if ( !line.empty() && line[0] != ' ' && line[0] != '#' ) {
ss << " pause=true\n";
}
}
std::ofstream outputFile(ariaSessionFilePath);
outputFile << ss.str();
}
} // unnamed namespace
Aria2::Aria2(std::string sessionFileDir):
mp_aria(nullptr),
m_port(42042),
m_secret("kiwixariarpc"),
mp_curl(nullptr),
m_lock(PTHREAD_MUTEX_INITIALIZER)
m_secret(getNewRpcSecret())
{
m_downloadDir = getDataDirectory();
std::vector<const char*> callCmd;
std::string rpc_port = "--rpc-listen-port=" + to_string(m_port);
std::string download_dir = "--dir=" + getDataDirectory();
std::string session_file = appendToDirectory(getDataDirectory(), "kiwix.session");
std::string session_file = appendToDirectory(sessionFileDir, "kiwix.session");
pauseAnyActiveDownloads(session_file);
std::string session = "--save-session=" + session_file;
std::string inputFile = "--input-file=" + session_file;
// std::string log_dir = "--log=\"" + logDir + "\"";
@@ -36,16 +77,21 @@ Aria2::Aria2():
std::string rpc_secret = "--rpc-secret=" + m_secret;
m_secret = "token:"+m_secret;
#ifdef _WIN32
callCmd.push_back("aria2c.exe");
#else
callCmd.push_back("aria2c");
#endif
std::string aria2cmd = appendToDirectory(
removeLastPathElement(getExecutablePath(true)),
ARIA2_CMD);
if (fileExists(aria2cmd)) {
// A local aria2c exe exists (packaged with kiwix-desktop), use it.
callCmd.push_back(aria2cmd.c_str());
} else {
// Try to use a potential installed aria2c.
callCmd.push_back(ARIA2_CMD);
}
callCmd.push_back("--follow-metalink=mem");
callCmd.push_back("--enable-rpc");
callCmd.push_back(rpc_secret.c_str());
callCmd.push_back(rpc_port.c_str());
callCmd.push_back(download_dir.c_str());
if (fileExists(session_file)) {
if (fileReadable(session_file)) {
callCmd.push_back(inputFile.c_str());
}
callCmd.push_back(session.c_str());
@@ -61,29 +107,45 @@ Aria2::Aria2():
callCmd.push_back("--max-concurrent-downloads=42");
callCmd.push_back("--rpc-max-request-size=6M");
callCmd.push_back("--file-allocation=none");
std::string launchCmd;
for (auto &cmd : callCmd) {
launchCmd.append(cmd).append(" ");
}
mp_aria = Subprocess::run(callCmd);
mp_curl = curl_easy_init();
curl_easy_setopt(mp_curl, CURLOPT_URL, "http://localhost/rpc");
curl_easy_setopt(mp_curl, CURLOPT_PORT, m_port);
curl_easy_setopt(mp_curl, CURLOPT_POST, 1L);
int watchdog = 50;
while(--watchdog) {
std::this_thread::sleep_for(std::chrono::microseconds(100));
auto res = curl_easy_perform(mp_curl);
CURL* p_curl = curl_easy_init();
char curlErrorBuffer[CURL_ERROR_SIZE];
curl_easy_setopt(p_curl, CURLOPT_URL, "http://localhost/rpc");
curl_easy_setopt(p_curl, CURLOPT_PORT, m_port);
curl_easy_setopt(p_curl, CURLOPT_POST, 1L);
curl_easy_setopt(p_curl, CURLOPT_ERRORBUFFER, curlErrorBuffer);
curl_easy_setopt(p_curl, CURLOPT_TIMEOUT_MS, 100);
typedef std::chrono::duration<double> Seconds;
const double MAX_WAITING_TIME_SECONDS = 1;
const auto t0 = std::chrono::steady_clock::now();
bool maxWaitingTimeWasExceeded = false;
CURLcode res = CURLE_OK;
while ( !maxWaitingTimeWasExceeded ) {
sleep(10);
curlErrorBuffer[0] = 0;
res = curl_easy_perform(p_curl);
if (res == CURLE_OK) {
break;
}
}
if (!watchdog) {
curl_easy_cleanup(mp_curl);
throw std::runtime_error("Cannot connect to aria2c rpc");
}
}
Aria2::~Aria2()
{
curl_easy_cleanup(mp_curl);
const auto dt = std::chrono::steady_clock::now() - t0;
const double elapsedTime = std::chrono::duration_cast<Seconds>(dt).count();
maxWaitingTimeWasExceeded = elapsedTime > MAX_WAITING_TIME_SECONDS;
}
curl_easy_cleanup(p_curl);
if ( maxWaitingTimeWasExceeded ) {
LOG_ARIA_ERROR();
throw std::runtime_error("Cannot connect to aria2c rpc. Aria2c launch cmd : " + launchCmd);
}
}
void Aria2::close()
@@ -94,47 +156,61 @@ void Aria2::close()
size_t write_callback_to_iss(char* ptr, size_t size, size_t nmemb, void* userdata)
{
auto str = static_cast<std::stringstream*>(userdata);
str->write(ptr, nmemb);
auto outStream = static_cast<std::stringstream*>(userdata);
outStream->write(ptr, nmemb);
return nmemb;
}
std::string Aria2::doRequest(const MethodCall& methodCall)
{
pthread_mutex_lock(&m_lock);
auto requestContent = methodCall.toString();
std::stringstream stringstream;
std::stringstream outStream;
CURLcode res;
curl_easy_setopt(mp_curl, CURLOPT_POSTFIELDSIZE, requestContent.size());
curl_easy_setopt(mp_curl, CURLOPT_POSTFIELDS, requestContent.c_str());
curl_easy_setopt(mp_curl, CURLOPT_WRITEFUNCTION, &write_callback_to_iss);
curl_easy_setopt(mp_curl, CURLOPT_WRITEDATA, &stringstream);
res = curl_easy_perform(mp_curl);
if (res == CURLE_OK) {
long response_code;
curl_easy_getinfo(mp_curl, CURLINFO_RESPONSE_CODE, &response_code);
pthread_mutex_unlock(&m_lock);
if (response_code != 200) {
throw std::runtime_error("Invalid return code from aria");
}
auto responseContent = stringstream.str();
MethodResponse response(responseContent);
if (response.isFault()) {
throw AriaError(response.getFault().getFaultString());
}
return responseContent;
long response_code;
char curlErrorBuffer[CURL_ERROR_SIZE];
CURL* p_curl = curl_easy_init();
curl_easy_setopt(p_curl, CURLOPT_URL, "http://localhost/rpc");
curl_easy_setopt(p_curl, CURLOPT_PORT, m_port);
curl_easy_setopt(p_curl, CURLOPT_POST, 1L);
curl_easy_setopt(p_curl, CURLOPT_ERRORBUFFER, curlErrorBuffer);
curl_easy_setopt(p_curl, CURLOPT_POSTFIELDSIZE, requestContent.size());
curl_easy_setopt(p_curl, CURLOPT_POSTFIELDS, requestContent.c_str());
curl_easy_setopt(p_curl, CURLOPT_WRITEFUNCTION, &write_callback_to_iss);
curl_easy_setopt(p_curl, CURLOPT_WRITEDATA, &outStream);
curlErrorBuffer[0] = 0;
res = curl_easy_perform(p_curl);
if (res != CURLE_OK) {
LOG_ARIA_ERROR();
curl_easy_cleanup(p_curl);
throw std::runtime_error("Cannot perform request");
}
pthread_mutex_unlock(&m_lock);
throw std::runtime_error("Cannot perform request");
curl_easy_getinfo(p_curl, CURLINFO_RESPONSE_CODE, &response_code);
curl_easy_cleanup(p_curl);
auto responseContent = outStream.str();
if (response_code != 200) {
std::cerr << "ERROR: Invalid return code (" << response_code << ") from aria :" << std::endl;
std::cerr << responseContent << std::endl;
throw std::runtime_error("Invalid return code from aria");
}
MethodResponse response(responseContent);
if (response.isFault()) {
throw AriaError(response.getFault().getFaultString());
}
return responseContent;
}
std::string Aria2::addUri(const std::vector<std::string>& uris)
std::string Aria2::addUri(const std::vector<std::string>& uris, const std::vector<std::pair<std::string, std::string>>& options)
{
MethodCall methodCall("aria2.addUri", m_secret);
auto uriParams = methodCall.newParamValue().getArray();
for (auto& uri : uris) {
uriParams.addValue().set(uri);
}
for (auto& option : options) {
methodCall.newParamValue().getStruct().addMember(option.first).getValue().set(option.second);
}
auto ret = doRequest(methodCall);
MethodResponse response(ret);
return response.getParamValue(0).getAsS();
@@ -153,12 +229,18 @@ std::string Aria2::tellStatus(const std::string& gid, const std::vector<std::str
return doRequest(methodCall);
}
std::string Aria2::getNewRpcSecret()
{
std::string uuid = gen_uuid("");
uuid.erase(std::remove(uuid.begin(), uuid.end(), '-'));
return uuid.substr(0, 9);
}
std::vector<std::string> Aria2::tellActive()
{
MethodCall methodCall("aria2.tellActive", m_secret);
auto statusArray = methodCall.newParamValue().getArray();
statusArray.addValue().set(std::string("gid"));
statusArray.addValue().set(std::string("following"));
auto responseContent = doRequest(methodCall);
MethodResponse response(responseContent);
std::vector<std::string> activeGID;
@@ -173,6 +255,27 @@ std::vector<std::string> Aria2::tellActive()
return activeGID;
}
std::vector<std::string> Aria2::tellWaiting()
{
MethodCall methodCall("aria2.tellWaiting", m_secret);
methodCall.newParamValue().set(0);
methodCall.newParamValue().set(99); // max number of downloads to be returned, don't know how to set this properly assumed that there will not be more than 99 paused downloads.
auto statusArray = methodCall.newParamValue().getArray();
statusArray.addValue().set(std::string("gid"));
auto responseContent = doRequest(methodCall);
MethodResponse response(responseContent);
std::vector<std::string> waitingGID;
int index = 0;
while(true) {
try {
auto structNode = response.getParamValue(0).getArray().getValue(index++).getStruct();
auto gidNode = structNode.getMember("gid");
waitingGID.push_back(gidNode.getValue().getAsS());
} catch (InvalidRPCNode& e) { break; }
}
return waitingGID;
}
void Aria2::saveSession()
{
MethodCall methodCall("aria2.saveSession", m_secret);
@@ -186,5 +289,25 @@ void Aria2::shutdown()
doRequest(methodCall);
}
void Aria2::pause(const std::string& gid)
{
MethodCall methodCall("aria2.pause", m_secret);
methodCall.newParamValue().set(gid);
doRequest(methodCall);
}
void Aria2::unpause(const std::string& gid)
{
MethodCall methodCall("aria2.unpause", m_secret);
methodCall.newParamValue().set(gid);
doRequest(methodCall);
}
void Aria2::remove(const std::string& gid)
{
MethodCall methodCall("aria2.remove", m_secret);
methodCall.newParamValue().set(gid);
doRequest(methodCall);
}
} // end namespace kiwix
+8 -8
View File
@@ -13,7 +13,6 @@
#include <memory>
#include <curl/curl.h>
#include <pthread.h>
namespace kiwix {
@@ -23,22 +22,23 @@ class Aria2
std::unique_ptr<Subprocess> mp_aria;
int m_port;
std::string m_secret;
std::string m_downloadDir;
CURL* mp_curl;
pthread_mutex_t m_lock;
std::string doRequest(const MethodCall& methodCall);
public:
Aria2();
virtual ~Aria2();
explicit Aria2(std::string sessionFileDir);
virtual ~Aria2() = default;
void close();
std::string addUri(const std::vector<std::string>& uri);
std::string addUri(const std::vector<std::string>& uri, const std::vector<std::pair<std::string, std::string>>& options = {});
std::string tellStatus(const std::string& gid, const std::vector<std::string>& statusKey);
static std::string getNewRpcSecret();
std::vector<std::string> tellActive();
std::vector<std::string> tellWaiting();
void saveSession();
void shutdown();
void pause(const std::string& gid);
void unpause(const std::string& gid);
void remove(const std::string& gid);
};
}; //end namespace kiwix
+167 -78
View File
@@ -18,78 +18,80 @@
*/
#include "book.h"
#include "reader.h"
#include "common/base64.h"
#include "common/regexTools.h"
#include "common/networkTools.h"
#include "tools.h"
#include "tools/base64.h"
#include "tools/regexTools.h"
#include "tools/networkTools.h"
#include "tools/otherTools.h"
#include "tools/stringTools.h"
#include "tools/pathTools.h"
#include "tools/archiveTools.h"
#include <zim/archive.h>
#include <zim/item.h>
#include <pugixml.hpp>
namespace kiwix
{
/* Constructor */
Book::Book() : m_readOnly(false)
Book::Book() :
m_pathValid(false),
m_readOnly(false)
{
}
/* Destructor */
Book::~Book()
{
}
Book::Illustrations Book::getIllustrations() const
{
return m_illustrations;
}
bool Book::update(const kiwix::Book& other)
{
if (m_readOnly)
return false;
m_readOnly = other.m_readOnly;
if (m_id != other.m_id)
return false;
if (m_path.empty()) {
m_path = other.m_path;
}
if (m_url.empty()) {
m_url = other.m_url;
}
if (m_tags.empty()) {
m_tags = other.m_tags;
}
if (m_name.empty()) {
m_name = other.m_name;
}
if (m_indexPath.empty()) {
m_indexPath = other.m_indexPath;
m_indexType = other.m_indexType;
}
if (m_faviconMimeType.empty()) {
m_favicon = other.m_favicon;
m_faviconMimeType = other.m_faviconMimeType;
}
*this = other;
return true;
}
void Book::update(const kiwix::Reader& reader)
{
m_path = reader.getZimFilePath();
m_id = reader.getId();
m_description = reader.getDescription();
m_language = reader.getLanguage();
m_date = reader.getDate();
m_creator = reader.getCreator();
m_publisher = reader.getPublisher();
m_title = reader.getTitle();
m_name = reader.getName();
m_tags = reader.getTags();
m_origId = reader.getOrigId();
m_articleCount = reader.getArticleCount();
m_mediaCount = reader.getMediaCount();
m_size = reader.getFileSize() << 10;
void Book::update(const zim::Archive& archive) {
m_path = archive.getFilename();
m_pathValid = true;
m_id = std::string(archive.getUuid());
m_title = getArchiveTitle(archive);
m_description = getMetaDescription(archive);
m_language = getMetaLanguage(archive);
m_creator = getMetaCreator(archive);
m_publisher = getMetaPublisher(archive);
m_date = getMetaDate(archive);
m_name = getMetaName(archive);
m_flavour = getMetaFlavour(archive);
m_tags = getMetaTags(archive);
m_category = getCategoryFromTags();
m_articleCount = archive.getArticleCount();
m_mediaCount = archive.getMediaCount();
m_size = static_cast<uint64_t>(getArchiveFileSize(archive)) << 10;
reader.getFavicon(m_favicon, m_faviconMimeType);
m_illustrations.clear();
for ( const auto& illustrationInfo : archive.getIllustrationInfos() ) {
const auto illustration = std::make_shared<Illustration>();
const zim::Item illustrationItem = archive.getIllustrationItem(illustrationInfo);
illustration->width = illustrationInfo.width;
illustration->height = illustrationInfo.height;
illustration->mimeType = illustrationItem.getMimetype();
illustration->data = illustrationItem.getData();
// NOTE: illustration->url is left uninitialized
m_illustrations.push_back(illustration);
}
}
#define ATTR(name) node.attribute(name).value()
@@ -101,36 +103,47 @@ void Book::updateFromXml(const pugi::xml_node& node, const std::string& baseDir)
path = computeAbsolutePath(baseDir, path);
}
m_path = path;
path = ATTR("indexPath");
if (!path.empty()) {
if (isRelativePath(path)) {
path = computeAbsolutePath(baseDir, path);
}
m_indexPath = path;
m_indexType = XAPIAN;
}
m_pathValid = fileReadable(path);
m_title = ATTR("title");
m_name = ATTR("name");
m_tags = ATTR("tags");
m_description = ATTR("description");
m_language = ATTR("language");
m_date = ATTR("date");
m_creator = ATTR("creator");
m_publisher = ATTR("publisher");
m_date = ATTR("date");
m_url = ATTR("url");
m_name = ATTR("name");
m_flavour = ATTR("flavour");
m_tags = ATTR("tags");
m_origId = ATTR("origId");
m_articleCount = strtoull(ATTR("articleCount"), 0, 0);
m_mediaCount = strtoull(ATTR("mediaCount"), 0, 0);
m_size = strtoull(ATTR("size"), 0, 0) << 10;
m_favicon = base64_decode(ATTR("favicon"));
m_faviconMimeType = ATTR("faviconMimeType");
const std::string faviconMimeType = ATTR("faviconMimeType");
const std::string faviconBase64EncodedData = ATTR("favicon");
if ( !faviconMimeType.empty() && !faviconBase64EncodedData.empty() ) {
const auto favicon = std::make_shared<Illustration>();
favicon->data = base64_decode(faviconBase64EncodedData);
favicon->mimeType = faviconMimeType;
favicon->url = ATTR("faviconUrl");
m_illustrations.assign(1, favicon);
}
try {
m_downloadId = ATTR("downloadId");
} catch(...) {}
const auto catattr = node.attribute("category");
m_category = catattr.empty() ? getCategoryFromTags() : catattr.value();
}
#undef ATTR
static std::string fromOpdsDate(const std::string& date)
{
//The opds date use the standard <YYYY>-<MM>-<DD>T<HH>:<mm>:<SS>Z
//and we want <YYYY>-<MM>-<DD>. That's easy, let's take the first 10 char
return date.substr(0, 10);
}
#define VALUE(name) node.child(name).child_value()
void Book::updateFromOpds(const pugi::xml_node& node, const std::string& urlHost)
{
@@ -138,11 +151,22 @@ void Book::updateFromOpds(const pugi::xml_node& node, const std::string& urlHost
if (!m_id.compare(0, 9, "urn:uuid:")) {
m_id.erase(0, 9);
}
// No path on opds.
m_title = VALUE("title");
m_description = VALUE("description");
m_description = VALUE("summary");
m_language = VALUE("language");
m_date = VALUE("updated");
m_creator = node.child("author").child("name").child_value();
m_publisher = node.child("publisher").child("name").child_value();
const std::string dcIssuedDate = VALUE("dc:issued");
m_date = dcIssuedDate.empty() ? VALUE("updated") : dcIssuedDate;
m_date = fromOpdsDate(m_date);
m_name = VALUE("name");
m_flavour = VALUE("flavour");
m_tags = VALUE("tags");
const auto catnode = node.child("category");
m_category = catnode.empty() ? getCategoryFromTags() : catnode.child_value();
m_articleCount = strtoull(VALUE("articleCount"), 0, 0);
m_mediaCount = strtoull(VALUE("mediaCount"), 0, 0);
for(auto linkNode = node.child("link"); linkNode;
linkNode = linkNode.next_sibling("link")) {
std::string rel = linkNode.attribute("rel").value();
@@ -152,19 +176,22 @@ void Book::updateFromOpds(const pugi::xml_node& node, const std::string& urlHost
m_size = strtoull(linkNode.attribute("length").value(), 0, 0);
}
if (rel == "http://opds-spec.org/image/thumbnail") {
m_faviconUrl = urlHost + linkNode.attribute("href").value();
m_faviconMimeType = linkNode.attribute("type").value();
const auto favicon = std::make_shared<Illustration>();
favicon->data.clear();
favicon->url = urlHost + linkNode.attribute("href").value();
favicon->mimeType = linkNode.attribute("type").value();
m_illustrations.assign(1, favicon);
}
}
}
#undef VALUE
std::string Book::getHumanReadableIdFromPath()
std::string Book::getHumanReadableIdFromPath() const
{
std::string id = m_path;
if (!id.empty()) {
kiwix::removeAccents(id);
id = kiwix::removeAccents(id);
#ifdef _WIN32
id = replaceRegex(id, "", "^.*\\\\");
@@ -186,22 +213,84 @@ void Book::setPath(const std::string& path)
: path;
}
void Book::setIndexPath(const std::string& indexPath)
const Book::Illustration Book::missingDefaultIllustration;
std::shared_ptr<const Book::Illustration> Book::getIllustration(unsigned int size) const
{
m_indexPath = isRelativePath(indexPath)
? computeAbsolutePath(getCurrentDirectory(), indexPath)
: indexPath;
for ( const auto& ilPtr : m_illustrations ) {
if (ilPtr->width == size && ilPtr->height == size) {
return ilPtr;
}
}
throw std::runtime_error("Cannot find illustration");
}
const Book::Illustration& Book::getDefaultIllustration() const
{
try {
return *getIllustration(48);
} catch (...) {
return missingDefaultIllustration;
}
}
const std::string& Book::Illustration::getData() const
{
if (data.empty() && !url.empty()) {
const std::lock_guard<std::mutex> l(mutex);
if ( data.empty() ) {
try {
data = download(url);
} catch(...) {
std::cerr << "Cannot download favicon from " << url << std::endl;
}
}
}
return data;
}
const std::string& Book::getFavicon() const {
if (m_favicon.empty() && !m_faviconUrl.empty()) {
try {
m_favicon = download(m_faviconUrl);
} catch(...) {
std::cerr << "Cannot download favicon from " << m_faviconUrl;
}
return getDefaultIllustration().getData();
}
const std::string& Book::getFaviconUrl() const
{
return getDefaultIllustration().url;
}
const std::string& Book::getFaviconMimeType() const
{
return getDefaultIllustration().mimeType;
}
std::string Book::getTagStr(const std::string& tagName) const {
return getTagValueFromTagList(convertTags(m_tags), tagName);
}
bool Book::getTagBool(const std::string& tagName) const {
return convertStrToBool(getTagStr(tagName));
}
std::string Book::getCategory() const
{
return m_category;
}
std::string Book::getCategoryFromTags() const
{
try
{
return getTagStr("category");
}
return m_favicon;
catch ( const std::out_of_range& )
{
return "";
}
}
const std::vector<std::string> Book::getLanguages() const
{
return kiwix::split(m_language, ",");
}
}
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright 2018 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "bookmark.h"
#include "book.h"
#include <pugixml.hpp>
namespace kiwix
{
/* Constructor */
Bookmark::Bookmark()
{
}
Bookmark::Bookmark(const Book& book, const std::string& path, const std::string& title):
m_bookId(book.getId()),
m_bookTitle(book.getTitle()),
m_bookName(book.getName()),
m_bookFlavour(book.getFlavour()),
m_url(path),
m_title(title),
m_language(book.getCommaSeparatedLanguages()),
m_date(book.getDate())
{}
/* Destructor */
Bookmark::~Bookmark()
{
}
void Bookmark::updateFromXml(const pugi::xml_node& node)
{
auto bookNode = node.child("book");
m_bookId = bookNode.child("id").child_value();
m_bookTitle = bookNode.child("title").child_value();
m_bookName = bookNode.child("name").child_value();
m_bookFlavour = bookNode.child("flavour").child_value();
m_language = bookNode.child("language").child_value();
m_date = bookNode.child("date").child_value();
m_title = node.child("title").child_value();
m_url = node.child("url").child_value();
}
}
-209
View File
@@ -1,209 +0,0 @@
/*
* Copyright 2012 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <common/networkTools.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <net/if.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#include <curl/curl.h>
#include <sstream>
#include <iostream>
std::map<std::string, std::string> kiwix::getNetworkInterfaces()
{
std::map<std::string, std::string> interfaces;
#ifdef _WIN32
SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
if (sd == (SOCKET)SOCKET_ERROR) {
std::cerr << "Failed to get a socket. Error " << WSAGetLastError()
<< std::endl;
return interfaces;
}
INTERFACE_INFO InterfaceList[20];
unsigned long nBytesReturned;
if (WSAIoctl(sd,
SIO_GET_INTERFACE_LIST,
0,
0,
&InterfaceList,
sizeof(InterfaceList),
&nBytesReturned,
0,
0)
== SOCKET_ERROR) {
std::cerr << "Failed calling WSAIoctl: error " << WSAGetLastError()
<< std::endl;
return interfaces;
}
int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
for (int i = 0; i < nNumInterfaces; ++i) {
sockaddr_in* pAddress;
pAddress = (sockaddr_in*)&(InterfaceList[i].iiAddress);
/* Add to the map */
std::string interfaceName = std::string(inet_ntoa(pAddress->sin_addr));
std::string interfaceIp = std::string(inet_ntoa(pAddress->sin_addr));
interfaces.insert(
std::pair<std::string, std::string>(interfaceName, interfaceIp));
}
#else
/* Get Network interfaces information */
char buf[16384];
struct ifconf ifconf;
int fd = socket(PF_INET, SOCK_DGRAM, 0); /* Only IPV4 */
ifconf.ifc_len = sizeof buf;
ifconf.ifc_buf = buf;
if (ioctl(fd, SIOCGIFCONF, &ifconf) != 0) {
perror("ioctl(SIOCGIFCONF)");
exit(EXIT_FAILURE);
}
/* Go through each interface */
int i;
size_t len;
struct ifreq* ifreq;
ifreq = ifconf.ifc_req;
for (i = 0; i < ifconf.ifc_len;) {
if (ifreq->ifr_addr.sa_family == AF_INET) {
/* Get the network interface ip */
char host[128] = {0};
const int error = getnameinfo(&(ifreq->ifr_addr),
sizeof ifreq->ifr_addr,
host,
sizeof host,
0,
0,
NI_NUMERICHOST);
if (!error) {
std::string interfaceName = std::string(ifreq->ifr_name);
std::string interfaceIp = std::string(host);
/* Add to the map */
interfaces.insert(
std::pair<std::string, std::string>(interfaceName, interfaceIp));
} else {
perror("getnameinfo()");
}
}
/* some systems have ifr_addr.sa_len and adjust the length that
* way, but not mine. weird */
#ifndef __linux__
len = IFNAMSIZ + ifreq->ifr_addr.sa_len;
#else
len = sizeof *ifreq;
#endif
ifreq = (struct ifreq*)((char*)ifreq + len);
i += len;
}
#endif
return interfaces;
}
std::string kiwix::getBestPublicIp()
{
std::map<std::string, std::string> interfaces = kiwix::getNetworkInterfaces();
#ifndef _WIN32
const char* const prioritizedNames[]
= {"eth0", "eth1", "wlan0", "wlan1", "en0", "en1"};
const int count = (sizeof prioritizedNames) / (sizeof prioritizedNames[0]);
for (int i = 0; i < count; ++i) {
std::map<std::string, std::string>::const_iterator it
= interfaces.find(prioritizedNames[i]);
if (it != interfaces.end()) {
return it->second;
}
}
#endif
for (std::map<std::string, std::string>::iterator iter = interfaces.begin();
iter != interfaces.end();
++iter) {
std::string interfaceIp = iter->second;
if (interfaceIp.length() >= 7 && interfaceIp.substr(0, 7) == "192.168") {
return interfaceIp;
}
}
for (std::map<std::string, std::string>::iterator iter = interfaces.begin();
iter != interfaces.end();
++iter) {
std::string interfaceIp = iter->second;
if (interfaceIp.length() >= 7 && interfaceIp.substr(0, 7) == "172.16.") {
return interfaceIp;
}
}
for (std::map<std::string, std::string>::iterator iter = interfaces.begin();
iter != interfaces.end();
++iter) {
std::string interfaceIp = iter->second;
if (interfaceIp.length() >= 3 && interfaceIp.substr(0, 3) == "10.") {
return interfaceIp;
}
}
return "127.0.0.1";
}
size_t write_callback_to_iss(char* ptr, size_t size, size_t nmemb, void* userdata)
{
auto str = static_cast<std::stringstream*>(userdata);
str->write(ptr, nmemb);
return nmemb;
}
std::string kiwix::download(const std::string& url) {
auto curl = curl_easy_init();
std::stringstream ss;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_callback_to_iss);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ss);
auto res = curl_easy_perform(curl);
if (res != CURLE_OK) {
curl_easy_cleanup(curl);
throw std::runtime_error("Cannot perform request");
}
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
curl_easy_cleanup(curl);
if (response_code != 200) {
throw std::runtime_error("Invalid return code from server");
}
return ss.str();
}
-300
View File
@@ -1,300 +0,0 @@
/*
* Copyright 2014 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <common/otherTools.h>
#include <map>
std::map<std::string, std::string> codeisomapping {
{ "af", "afg" },
{ "ax", "ala" },
{ "al", "alb" },
{ "dz", "dza" },
{ "as", "asm" },
{ "ad", "and" },
{ "ao", "ago" },
{ "ai", "aia" },
{ "aq", "ata" },
{ "ag", "atg" },
{ "ar", "arg" },
{ "am", "arm" },
{ "aw", "abw" },
{ "au", "aus" },
{ "at", "aut" },
{ "az", "aze" },
{ "bs", "bhs" },
{ "bh", "bhr" },
{ "bd", "bgd" },
{ "bb", "brb" },
{ "by", "blr" },
{ "be", "bel" },
{ "bz", "blz" },
{ "bj", "ben" },
{ "bm", "bmu" },
{ "bt", "btn" },
{ "bo", "bol" },
{ "ba", "bih" },
{ "bw", "bwa" },
{ "bv", "bvt" },
{ "br", "bra" },
{ "vg", "vgb" },
{ "io", "iot" },
{ "bn", "brn" },
{ "bg", "bgr" },
{ "bf", "bfa" },
{ "bi", "bdi" },
{ "kh", "khm" },
{ "cm", "cmr" },
{ "ca", "can" },
{ "cv", "cpv" },
{ "ky", "cym" },
{ "cf", "caf" },
{ "td", "tcd" },
{ "cl", "chl" },
{ "cn", "chn" },
{ "hk", "hkg" },
{ "mo", "mac" },
{ "cx", "cxr" },
{ "cc", "cck" },
{ "co", "col" },
{ "km", "com" },
{ "cg", "cog" },
{ "cd", "cod" },
{ "ck", "cok" },
{ "cr", "cri" },
{ "ci", "civ" },
{ "hr", "hrv" },
{ "cu", "cub" },
{ "cy", "cyp" },
{ "cz", "cze" },
{ "dk", "dnk" },
{ "dj", "dji" },
{ "dm", "dma" },
{ "do", "dom" },
{ "ec", "ecu" },
{ "eg", "egy" },
{ "sv", "slv" },
{ "gq", "gnq" },
{ "er", "eri" },
{ "ee", "est" },
{ "et", "eth" },
{ "fk", "flk" },
{ "fo", "fro" },
{ "fj", "fji" },
{ "fi", "fin" },
{ "fr", "fra" },
{ "gf", "guf" },
{ "pf", "pyf" },
{ "tf", "atf" },
{ "ga", "gab" },
{ "gm", "gmb" },
{ "ge", "geo" },
{ "de", "deu" },
{ "gh", "gha" },
{ "gi", "gib" },
{ "gr", "grc" },
{ "gl", "grl" },
{ "gd", "grd" },
{ "gp", "glp" },
{ "gu", "gum" },
{ "gt", "gtm" },
{ "gg", "ggy" },
{ "gn", "gin" },
{ "gw", "gnb" },
{ "gy", "guy" },
{ "ht", "hti" },
{ "hm", "hmd" },
{ "va", "vat" },
{ "hn", "hnd" },
{ "hu", "hun" },
{ "is", "isl" },
{ "in", "ind" },
{ "id", "idn" },
{ "ir", "irn" },
{ "iq", "irq" },
{ "ie", "irl" },
{ "im", "imn" },
{ "il", "isr" },
{ "it", "ita" },
{ "jm", "jam" },
{ "jp", "jpn" },
{ "je", "jey" },
{ "jo", "jor" },
{ "kz", "kaz" },
{ "ke", "ken" },
{ "ki", "kir" },
{ "kp", "prk" },
{ "kr", "kor" },
{ "kw", "kwt" },
{ "kg", "kgz" },
{ "la", "lao" },
{ "lv", "lva" },
{ "lb", "lbn" },
{ "ls", "lso" },
{ "lr", "lbr" },
{ "ly", "lby" },
{ "li", "lie" },
{ "lt", "ltu" },
{ "lu", "lux" },
{ "mk", "mkd" },
{ "mg", "mdg" },
{ "mw", "mwi" },
{ "my", "mys" },
{ "mv", "mdv" },
{ "ml", "mli" },
{ "mt", "mlt" },
{ "mh", "mhl" },
{ "mq", "mtq" },
{ "mr", "mrt" },
{ "mu", "mus" },
{ "yt", "myt" },
{ "mx", "mex" },
{ "fm", "fsm" },
{ "md", "mda" },
{ "mc", "mco" },
{ "mn", "mng" },
{ "me", "mne" },
{ "ms", "msr" },
{ "ma", "mar" },
{ "mz", "moz" },
{ "mm", "mmr" },
{ "na", "nam" },
{ "nr", "nru" },
{ "np", "npl" },
{ "nl", "nld" },
{ "an", "ant" },
{ "nc", "ncl" },
{ "nz", "nzl" },
{ "ni", "nic" },
{ "ne", "ner" },
{ "ng", "nga" },
{ "nu", "niu" },
{ "nf", "nfk" },
{ "mp", "mnp" },
{ "no", "nor" },
{ "om", "omn" },
{ "pk", "pak" },
{ "pw", "plw" },
{ "ps", "pse" },
{ "pa", "pan" },
{ "pg", "png" },
{ "py", "pry" },
{ "pe", "per" },
{ "ph", "phl" },
{ "pn", "pcn" },
{ "pl", "pol" },
{ "pt", "prt" },
{ "pr", "pri" },
{ "qa", "qat" },
{ "re", "reu" },
{ "ro", "rou" },
{ "ru", "rus" },
{ "rw", "rwa" },
{ "bl", "blm" },
{ "sh", "shn" },
{ "kn", "kna" },
{ "lc", "lca" },
{ "mf", "maf" },
{ "pm", "spm" },
{ "vc", "vct" },
{ "ws", "wsm" },
{ "sm", "smr" },
{ "st", "stp" },
{ "sa", "sau" },
{ "sn", "sen" },
{ "rs", "srb" },
{ "sc", "syc" },
{ "sl", "sle" },
{ "sg", "sgp" },
{ "sk", "svk" },
{ "si", "svn" },
{ "sb", "slb" },
{ "so", "som" },
{ "za", "zaf" },
{ "gs", "sgs" },
{ "ss", "ssd" },
{ "es", "esp" },
{ "lk", "lka" },
{ "sd", "sdn" },
{ "sr", "sur" },
{ "sj", "sjm" },
{ "sz", "swz" },
{ "se", "swe" },
{ "ch", "che" },
{ "sy", "syr" },
{ "tw", "twn" },
{ "tj", "tjk" },
{ "tz", "tza" },
{ "th", "tha" },
{ "tl", "tls" },
{ "tg", "tgo" },
{ "tk", "tkl" },
{ "to", "ton" },
{ "tt", "tto" },
{ "tn", "tun" },
{ "tr", "tur" },
{ "tm", "tkm" },
{ "tc", "tca" },
{ "tv", "tuv" },
{ "ug", "uga" },
{ "ua", "ukr" },
{ "ae", "are" },
{ "gb", "gbr" },
{ "us", "usa" },
{ "um", "umi" },
{ "uy", "ury" },
{ "uz", "uzb" },
{ "vu", "vut" },
{ "ve", "ven" },
{ "vn", "vnm" },
{ "vi", "vir" },
{ "wf", "wlf" },
{ "eh", "esh" },
{ "ye", "yem" },
{ "zm", "zmb" },
{ "zw", "zwe" }
};
void kiwix::sleep(unsigned int milliseconds)
{
#ifdef _WIN32
Sleep(milliseconds);
#else
usleep(1000 * milliseconds);
#endif
}
struct XmlStringWriter: pugi::xml_writer
{
std::string result;
virtual void write(const void* data, size_t size){
result.append(static_cast<const char*>(data), size);
}
};
std::string kiwix::nodeToString(pugi::xml_node node)
{
XmlStringWriter writer;
node.print(writer, " ");
return writer.result;
}
std::string kiwix::converta2toa3(const std::string& a2code){
return codeisomapping.at(a2code);
}
-335
View File
@@ -1,335 +0,0 @@
/*
* Copyright 2011-2014 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <common/pathTools.h>
#ifdef __APPLE__
#include <limits.h>
#include <mach-o/dyld.h>
#elif _WIN32
#include <direct.h>
#include <windows.h>
#include "shlwapi.h"
#define getcwd _getcwd // stupid MSFT "deprecation" warning
#endif
#ifdef _WIN32
#else
#include <unistd.h>
#endif
#ifdef _WIN32
const std::string SEPARATOR("\\");
#else
const std::string SEPARATOR("/");
#include <unistd.h>
#endif
#include <stdlib.h>
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
bool isRelativePath(const string& path)
{
#ifdef _WIN32
return path.empty() || path.substr(1, 2) == ":\\" ? false : true;
#else
return path.empty() || path.substr(0, 1) == "/" ? false : true;
#endif
}
string computeRelativePath(const string path, const string absolutePath)
{
std::vector<std::string> pathParts = kiwix::split(path, SEPARATOR);
std::vector<std::string> absolutePathParts
= kiwix::split(absolutePath, SEPARATOR);
unsigned int commonCount = 0;
while (commonCount < pathParts.size()
&& commonCount < absolutePathParts.size()
&& pathParts[commonCount] == absolutePathParts[commonCount]) {
commonCount++;
}
string relativePath;
#ifdef _WIN32
/* On Windows you have a token more because the root is represented
by a letter */
if (commonCount == 0) {
relativePath = ".." + SEPARATOR;
}
#endif
for (unsigned int i = commonCount; i < pathParts.size(); i++) {
relativePath += ".." + SEPARATOR;
}
for (unsigned int i = commonCount; i < absolutePathParts.size(); i++) {
relativePath += absolutePathParts[i];
relativePath += i + 1 < absolutePathParts.size() ? SEPARATOR : "";
}
return relativePath;
}
/* Warning: the relative path must be with slashes */
string computeAbsolutePath(const string path, const string relativePath)
{
string absolutePath;
if (path.empty()) {
char* path = NULL;
size_t size = 0;
#ifdef _WIN32
path = _getcwd(path, size);
#else
path = getcwd(path, size);
#endif
absolutePath = string(path) + SEPARATOR;
} else {
absolutePath = path.substr(path.length() - 1, 1) == SEPARATOR
? path
: path + SEPARATOR;
}
#if _WIN32
char* cRelativePath = _strdup(relativePath.c_str());
#else
char* cRelativePath = strdup(relativePath.c_str());
#endif
char* token = strtok(cRelativePath, "/");
while (token != NULL) {
if (string(token) == "..") {
absolutePath = removeLastPathElement(absolutePath, true, false);
token = strtok(NULL, "/");
} else if (strcmp(token, ".") && strcmp(token, "")) {
absolutePath += string(token);
token = strtok(NULL, "/");
if (token != NULL) {
absolutePath += SEPARATOR;
}
} else {
token = strtok(NULL, "/");
}
}
return absolutePath;
}
string removeLastPathElement(const string path,
const bool removePreSeparator,
const bool removePostSeparator)
{
string newPath = path;
size_t offset = newPath.find_last_of(SEPARATOR);
if (removePreSeparator &&
#ifndef _WIN32
offset != newPath.find_first_of(SEPARATOR) &&
#endif
offset == newPath.length() - 1) {
newPath = newPath.substr(0, offset);
offset = newPath.find_last_of(SEPARATOR);
}
newPath = removePostSeparator ? newPath.substr(0, offset)
: newPath.substr(0, offset + 1);
return newPath;
}
string appendToDirectory(const string& directoryPath, const string& filename)
{
string newPath = directoryPath + SEPARATOR + filename;
return newPath;
}
string getLastPathElement(const string& path)
{
return path.substr(path.find_last_of(SEPARATOR) + 1);
}
unsigned int getFileSize(const string& path)
{
#ifdef _WIN32
struct _stat filestatus;
_stat(path.c_str(), &filestatus);
#else
struct stat filestatus;
stat(path.c_str(), &filestatus);
#endif
return filestatus.st_size / 1024;
}
string getFileSizeAsString(const string& path)
{
ostringstream convert;
convert << getFileSize(path);
return convert.str();
}
string getFileContent(const string& path)
{
std::ifstream f(path, std::ios::in|std::ios::ate);
std::string content;
if (f.is_open()) {
auto size = f.tellg();
content.reserve(size);
f.seekg(0, std::ios::beg);
content.assign((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
}
return content;
}
bool fileExists(const string& path)
{
#ifdef _WIN32
return PathFileExists(path.c_str());
#else
bool flag = false;
fstream fin;
fin.open(path.c_str(), ios::in);
if (fin.is_open()) {
flag = true;
}
fin.close();
return flag;
#endif
}
bool makeDirectory(const string& path)
{
#ifdef _WIN32
int status = _mkdir(path.c_str());
#else
int status = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
return status == 0;
}
string makeTmpDirectory()
{
#ifdef _WIN32
char cbase[MAX_PATH+1];
int base_len = GetTempPath(MAX_PATH+1, cbase);
UUID uuid;
UuidCreate(&uuid);
char* dir_name;
UuidToString(&uuid, reinterpret_cast<unsigned char**>(&dir_name));
string dir(cbase, base_len);
dir += dir_name;
_mkdir(dir.c_str());
RpcStringFree(reinterpret_cast<unsigned char**>(&dir_name));
#else
string base = "/tmp";
auto _template = base + "/kiwix-lib_XXXXXX";
char* _template_array = new char[_template.size()+1];
memcpy(_template_array, _template.c_str(), _template.size());
string dir = mkdtemp(_template_array);
delete[] _template_array;
#endif
return dir;
}
/* Try to create a link and if does not work then make a copy */
bool copyFile(const string& sourcePath, const string& destPath)
{
try {
#ifndef _WIN32
if (link(sourcePath.c_str(), destPath.c_str()) != 0) {
#endif
std::ifstream infile(sourcePath.c_str(), std::ios_base::binary);
std::ofstream outfile(destPath.c_str(), std::ios_base::binary);
outfile << infile.rdbuf();
#ifndef _WIN32
}
#endif
} catch (exception& e) {
cerr << e.what() << endl;
return false;
}
return true;
}
string getExecutablePath()
{
char binRootPath[PATH_MAX];
#ifdef _WIN32
GetModuleFileName(NULL, binRootPath, PATH_MAX);
return std::string(binRootPath);
#elif __APPLE__
uint32_t max = (uint32_t)PATH_MAX;
_NSGetExecutablePath(binRootPath, &max);
return std::string(binRootPath);
#else
ssize_t size = readlink("/proc/self/exe", binRootPath, PATH_MAX);
if (size != -1) {
return std::string(binRootPath, size);
}
#endif
return "";
}
bool writeTextFile(const string& path, const string& content)
{
std::ofstream file;
file.open(path.c_str());
file << content;
file.close();
return true;
}
string getCurrentDirectory()
{
char* a_cwd = getcwd(NULL, 0);
string s_cwd(a_cwd);
free(a_cwd);
return s_cwd;
}
string getDataDirectory()
{
#ifdef _WIN32
char* cDataDir = ::getenv("APPDATA");
#else
char* cDataDir = ::getenv("KIWIX_DATA_DIR");
#endif
std::string dataDir = cDataDir==nullptr ? "" : cDataDir;
if (!dataDir.empty())
return dataDir;
#ifdef _WIN32
cDataDir = ::getenv("USERPROFILE");
dataDir = cDataDir==nullptr ? getCurrentDirectory() : cDataDir;
#else
cDataDir = ::getenv("XDG_DATA_HOME");
dataDir = cDataDir==nullptr ? "" : cDataDir;
if (dataDir.empty()) {
cDataDir = ::getenv("HOME");
dataDir = cDataDir==nullptr ? getCurrentDirectory() : cDataDir;
dataDir = appendToDirectory(dataDir, ".local");
dataDir = appendToDirectory(dataDir, "share");
}
#endif
return appendToDirectory(dataDir, "kiwix");
}
+1 -2
View File
@@ -1,4 +1,3 @@
#mesondefine VERSION
#mesondefine LIBKIWIX_VERSION
#mesondefine ENABLE_CTPP2
-210
View File
@@ -1,210 +0,0 @@
/*
* Copyright 2013 Renaud Gaudin <reg@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <ctpp2/CTPP2VMStringLoader.hpp>
namespace CTPP // C++ Template Engine
{
//
// Convert byte order
//
static void ConvertExecutable(VMExecutable * oCore)
{
// Code entry point
oCore -> entry_point = Swap32(oCore -> entry_point);
// Offset of code segment
oCore -> code_offset = Swap32(oCore -> code_offset);
// Code segment size
oCore -> code_size = Swap32(oCore -> code_size);
// Offset of static text segment
oCore -> syscalls_offset = Swap32(oCore -> syscalls_offset);
// Static text segment size
oCore -> syscalls_data_size = Swap32(oCore -> syscalls_data_size);
// Offset of static text index segment
oCore -> syscalls_index_offset = Swap32(oCore -> syscalls_index_offset);
// Static text index segment size
oCore -> syscalls_index_size = Swap32(oCore -> syscalls_index_size);
// Offset of static data segment
oCore -> static_data_offset = Swap32(oCore -> static_data_offset);
// Static data segment size
oCore -> static_data_data_size = Swap32(oCore -> static_data_data_size);
// Offset of static text segment
oCore -> static_text_offset = Swap32(oCore -> static_text_offset);
// Static text segment size
oCore -> static_text_data_size = Swap32(oCore -> static_text_data_size);
// Offset of static text index segment
oCore -> static_text_index_offset = Swap32(oCore -> static_text_index_offset);
// Static text index segment size
oCore -> static_text_index_size = Swap32(oCore -> static_text_index_size);
// Version 2.2+
// Offset of static data bit index
oCore -> static_data_bit_index_offset = Swap32(oCore -> static_data_bit_index_offset);
/// Offset of static data bit index
oCore -> static_data_bit_index_size = Swap32(oCore -> static_data_bit_index_size);
// Platform
oCore -> platform = Swap64(oCore -> platform);
// Ugly-jolly hack!
// ... dereferencing type-punned pointer will break strict-aliasing rules ...
UINT_64 iTMP;
memcpy(&iTMP, &(oCore -> ieee754double), sizeof(UINT_64));
iTMP = Swap64(iTMP);
memcpy(&(oCore -> ieee754double), &iTMP, sizeof(UINT_64));
// Cyclic Redundancy Check
oCore -> crc = 0;
// Convert data structures
// Convert code segment
VMInstruction * pInstructions = const_cast<VMInstruction *>(VMExecutable::GetCodeSeg(oCore));
UINT_32 iI = 0;
UINT_32 iSteps = oCore -> code_size / sizeof(VMInstruction);
for(iI = 0; iI < iSteps; ++iI)
{
pInstructions -> instruction = Swap32(pInstructions -> instruction);
pInstructions -> argument = Swap32(pInstructions -> argument);
pInstructions -> reserved = Swap64(pInstructions -> reserved);
++pInstructions;
}
// Convert syscalls index
TextDataIndex * pTextIndex = const_cast<TextDataIndex *>(VMExecutable::GetSyscallsIndexSeg(oCore));
iSteps = oCore -> syscalls_index_size / sizeof(TextDataIndex);
for(iI = 0; iI < iSteps; ++iI)
{
pTextIndex -> offset = Swap32(pTextIndex -> offset);
pTextIndex -> length = Swap32(pTextIndex -> length);
++pTextIndex;
}
// Convert static text index
pTextIndex = const_cast<TextDataIndex *>(VMExecutable::GetStaticTextIndexSeg(oCore));
iSteps = oCore -> static_text_index_size / sizeof(TextDataIndex);
for(iI = 0; iI < iSteps; ++iI)
{
pTextIndex -> offset = Swap32(pTextIndex -> offset);
pTextIndex -> length = Swap32(pTextIndex -> length);
++pTextIndex;
}
// Convert static data
StaticDataVar * pStaticDataVar = const_cast<StaticDataVar *>(VMExecutable::GetStaticDataSeg(oCore));
iSteps = oCore -> static_data_data_size / sizeof(StaticDataVar);
for(iI = 0; iI < iSteps; ++iI)
{
(*pStaticDataVar).i_data = Swap64((*pStaticDataVar).i_data);
++pStaticDataVar;
}
}
//
// Constructor
//
VMStringLoader::VMStringLoader(CCHAR_P rawContent, size_t rawContentSize)
{
oCore = (VMExecutable *)malloc(rawContentSize + 1);
memcpy(oCore, rawContent, rawContentSize);
if (oCore -> magic[0] == 'C' &&
oCore -> magic[1] == 'T' &&
oCore -> magic[2] == 'P' &&
oCore -> magic[3] == 'P')
{
// Check version
if (oCore -> version[0] >= 1)
{
// Platform-dependent data (byte order)
if (oCore -> platform == 0x4142434445464748ull)
{
#ifdef _DEBUG
fprintf(stderr, "Big/Little Endian conversion: Nothing to do\n");
#endif
// Nothing to do, only check crc
UINT_32 iCRC = oCore -> crc;
oCore -> crc = 0;
// Calculate CRC of file
// KELSON: next line used to refer to oStat.st_size
// changed it to rawContentSize
if (iCRC != crc32((UCCHAR_P)oCore, rawContentSize))
{
free(oCore);
throw CTPPLogicError("CRC checksum invalid");
}
}
// Platform-dependent data (byte order)
else if (oCore -> platform == 0x4847464544434241ull)
{
// Need to reconvert data
#ifdef _DEBUG
fprintf(stderr, "Big/Little Endian conversion: Need to reconvert core\n");
#endif
ConvertExecutable(oCore);
}
else
{
free(oCore);
throw CTPPLogicError("Conversion of middle-end architecture does not supported.");
}
// Check IEEE 754 format
if (oCore -> ieee754double != 15839800103804824402926068484019465486336.0)
{
free(oCore);
throw CTPPLogicError("IEEE 754 format is broken, cannot convert file");
}
}
pVMMemoryCore = new VMMemoryCore(oCore);
}
else
{
free(oCore);
throw CTPPLogicError("Not an CTPP bytecode file.");
}
}
//
// Get ready-to-run program
//
const VMMemoryCore * VMStringLoader::GetCore() const { return pVMMemoryCore; }
//
// A destructor
//
VMStringLoader::~VMStringLoader() throw()
{
delete pVMMemoryCore;
free(oCore);
}
} // namespace CTPP
// End.
+128 -25
View File
@@ -18,7 +18,9 @@
*/
#include "downloader.h"
#include "common/pathTools.h"
#include "tools.h"
#include "tools/pathTools.h"
#include "tools/stringTools.h"
#include <algorithm>
#include <thread>
@@ -28,7 +30,7 @@
#include "aria2.h"
#include "xmlrpc.h"
#include "common/otherTools.h"
#include "tools/otherTools.h"
#include <pugixml.hpp>
namespace kiwix
@@ -36,6 +38,8 @@ namespace kiwix
void Download::updateStatus(bool follow)
{
if (m_status == Download::K_REMOVED)
return;
static std::vector<std::string> statusKey = {"status", "files", "totalLength",
"completedLength", "followedBy",
"downloadSpeed", "verifiedLength"};
@@ -93,28 +97,78 @@ void Download::updateStatus(bool follow)
}
}
/* Constructor */
Downloader::Downloader() :
mp_aria(new Aria2())
void Download::resumeDownload()
{
for (auto gid : mp_aria->tellActive()) {
m_knownDownloads[gid] = std::unique_ptr<Download>(new Download(mp_aria, gid));
m_knownDownloads[gid]->updateStatus();
}
if (!m_followedBy.empty())
mp_aria->unpause(m_followedBy);
else
mp_aria->unpause(m_did);
updateStatus(true);
}
void Download::pauseDownload()
{
if (!m_followedBy.empty())
mp_aria->pause(m_followedBy);
else
mp_aria->pause(m_did);
updateStatus(true);
}
void Download::cancelDownload()
{
if (!m_followedBy.empty())
mp_aria->remove(m_followedBy);
else
mp_aria->remove(m_did);
m_status = Download::K_REMOVED;
}
/* Constructor */
Downloader::Downloader(std::string sessionFileDir) :
mp_aria(new Aria2(sessionFileDir))
{
try {
for (auto gid : mp_aria->tellWaiting()) {
m_knownDownloads[gid] = std::unique_ptr<Download>(new Download(mp_aria, gid));
m_knownDownloads[gid]->updateStatus(false);
}
} catch (std::exception& e) {
std::cerr << "aria2 tellWaiting failed : " << e.what() << std::endl;
}
try {
for (auto gid : mp_aria->tellActive()) {
if( m_knownDownloads.find(gid) == m_knownDownloads.end()) {
m_knownDownloads[gid] = std::unique_ptr<Download>(new Download(mp_aria, gid));
m_knownDownloads[gid]->updateStatus(false);
}
}
} catch (std::exception& e) {
std::cerr << "aria2 tellActive failed : " << e.what() << std::endl;
}
}
/* Destructor */
Downloader::~Downloader()
{
close();
}
void Downloader::close()
{
mp_aria->close();
if ( mp_aria ) {
try {
mp_aria->close();
} catch (const std::exception& err) {
std::cerr << "ERROR: Failed to save the downloader state: "
<< err.what() << std::endl;
}
mp_aria.reset();
}
}
std::vector<std::string> Downloader::getDownloadIds() {
std::vector<std::string> Downloader::getDownloadIds() const {
std::unique_lock<std::mutex> lock(m_lock);
std::vector<std::string> ret;
for(auto& p:m_knownDownloads) {
ret.push_back(p.first);
@@ -122,33 +176,82 @@ std::vector<std::string> Downloader::getDownloadIds() {
return ret;
}
Download* Downloader::startDownload(const std::string& uri)
namespace
{
bool downloadCanBeReused(const Download& d,
const std::string& uri,
const Downloader::Options& /*options*/)
{
const auto& uris = d.getUris();
const bool sameURI = std::find(uris.begin(), uris.end(), uri) != uris.end();
if ( !sameURI )
return false;
switch ( d.getStatus() ) {
case Download::K_ERROR:
case Download::K_UNKNOWN:
case Download::K_REMOVED:
return false;
case Download::K_ACTIVE:
case Download::K_WAITING:
case Download::K_PAUSED:
return true; // XXX: what if options are different?
case Download::K_COMPLETE:
return fileExists(d.getPath()); // XXX: what if options are different?
}
return false;
}
} // unnamed namespace
std::shared_ptr<Download> Downloader::startDownload(const std::string& uri, const std::string& downloadDir, Options options)
{
std::unique_lock<std::mutex> lock(m_lock);
options.erase(std::remove_if(options.begin(), options.end(), [](const auto& option) {
return option.first == "dir";
}), options.end());
options.push_back({"dir", downloadDir});
for (auto& p: m_knownDownloads) {
auto& d = p.second;
auto& uris = d->getUris();
if (std::find(uris.begin(), uris.end(), uri) != uris.end())
return d.get();
if ( downloadCanBeReused(*d, uri, options) )
return d;
}
std::vector<std::string> uris = {uri};
auto gid = mp_aria->addUri(uris);
m_knownDownloads[gid] = std::unique_ptr<Download>(new Download(mp_aria, gid));
return m_knownDownloads[gid].get();
auto gid = mp_aria->addUri(uris, options);
m_knownDownloads[gid] = std::make_shared<Download>(mp_aria, gid);
return m_knownDownloads[gid];
}
Download* Downloader::getDownload(const std::string& did)
std::shared_ptr<Download> Downloader::getDownload(const std::string& did)
{
std::unique_lock<std::mutex> lock(m_lock);
try {
return m_knownDownloads.at(did).get();
} catch(exception& e) {
for (auto gid : mp_aria->tellActive()) {
return m_knownDownloads.at(did);
} catch(std::exception& e) {
for (auto gid : mp_aria->tellWaiting()) {
if (gid == did) {
m_knownDownloads[gid] = std::unique_ptr<Download>(new Download(mp_aria, gid));
return m_knownDownloads[gid].get();
m_knownDownloads[gid] = std::make_shared<Download>(mp_aria, gid);
return m_knownDownloads[gid];
}
}
throw e;
for (auto gid : mp_aria->tellActive()) {
if (gid == did) {
m_knownDownloads[gid] = std::make_shared<Download>(mp_aria, gid);
return m_knownDownloads[gid];
}
}
throw;
}
}
size_t Downloader::getNbDownload() const {
std::unique_lock<std::mutex> lock(m_lock);
return m_knownDownloads.size();
}
}
-138
View File
@@ -1,138 +0,0 @@
/*
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "reader.h"
#include <time.h>
#include <zim/search.h>
namespace kiwix
{
Entry::Entry(zim::Article article)
: article(article)
{
}
#define RETURN_IF_INVALID(WHAT) if(!good()) { return (WHAT); }
std::string Entry::getPath() const
{
RETURN_IF_INVALID("");
return article.getLongUrl();
}
std::string Entry::getTitle() const
{
RETURN_IF_INVALID("");
return article.getTitle();
}
std::string Entry::getContent() const
{
RETURN_IF_INVALID("");
return article.getData();
}
zim::Blob Entry::getBlob(offset_type offset) const
{
RETURN_IF_INVALID(zim::Blob());
return article.getData(offset);
}
zim::Blob Entry::getBlob(offset_type offset, size_type size) const
{
RETURN_IF_INVALID(zim::Blob());
return article.getData(offset, size);
}
std::pair<std::string, offset_type> Entry::getDirectAccessInfo() const
{
RETURN_IF_INVALID(std::make_pair("", 0));
return article.getDirectAccessInformation();
}
size_type Entry::getSize() const
{
RETURN_IF_INVALID(0);
return article.getArticleSize();
}
std::string Entry::getMimetype() const
{
RETURN_IF_INVALID("");
try {
return article.getMimeType();
} catch (exception& e) {
return "application/octet-stream";
}
}
bool Entry::isRedirect() const
{
RETURN_IF_INVALID(false);
return article.isRedirect();
}
bool Entry::isLinkTarget() const
{
RETURN_IF_INVALID(false);
return article.isLinktarget();
}
bool Entry::isDeleted() const
{
RETURN_IF_INVALID(false);
return article.isDeleted();
}
Entry Entry::getRedirectEntry() const
{
RETURN_IF_INVALID(Entry());
if ( !article.isRedirect() ) {
throw NoEntry();
}
auto targeted_article = article.getRedirectArticle();
if ( !targeted_article.good()) {
throw NoEntry();
}
return targeted_article;
}
Entry Entry::getFinalEntry() const
{
RETURN_IF_INVALID(Entry());
if (final_article.good()) {
return final_article;
}
int loopCounter = 42;
final_article = article;
while (final_article.isRedirect() && loopCounter--) {
final_article = final_article.getRedirectArticle();
if ( !final_article.good()) {
throw NoEntry();
}
}
return final_article;
}
}
+144
View File
@@ -0,0 +1,144 @@
#include "html_dumper.h"
#include "libkiwix-resources.h"
#include "tools/otherTools.h"
#include "tools.h"
#include "tools/regexTools.h"
#include "server/i18n_utils.h"
namespace kiwix
{
/* Constructor */
HTMLDumper::HTMLDumper(const Library* library, const NameMapper* nameMapper)
: LibraryDumper(library, nameMapper)
{
}
/* Destructor */
HTMLDumper::~HTMLDumper()
{
}
namespace {
std::string humanFriendlyTitle(std::string title)
{
std::string humanFriendlyString = replaceRegex(title, "_", " ");
humanFriendlyString[0] = toupper(humanFriendlyString[0]);
return humanFriendlyString;
}
kainjow::mustache::object getLangTag(const std::vector<std::string>& bookLanguages) {
std::string langShortString = "";
std::string langFullString = "???";
//if more than 1 languages then show "mul" else show the language
if(bookLanguages.size() > 1) {
std::vector<std::string> mulLanguages;
langShortString = "mul";
for (const auto& lang : bookLanguages) {
const std::string fullLang = getLanguageSelfName(lang);
mulLanguages.push_back(fullLang);
}
langFullString = kiwix::join(mulLanguages, ",");
} else if(bookLanguages.size() == 1) {
langShortString = bookLanguages[0];
langFullString = getLanguageSelfName(langShortString);
}
kainjow::mustache::object langTag;
langTag["langShortString"] = langShortString;
langTag["langFullString"] = langFullString;
return langTag;
}
kainjow::mustache::list getTagList(std::string tags)
{
const auto tagsList = kiwix::split(tags, ";", true, false);
kainjow::mustache::list finalTagList;
for (auto tag : tagsList) {
if (tag[0] != '_')
finalTagList.push_back(kainjow::mustache::object{
{"tag", tag}
});
}
return finalTagList;
}
} // unnamed namespace
std::string HTMLDumper::dumpPlainHTML(kiwix::Filter filter) const
{
kainjow::mustache::list booksData;
const auto filteredBooks = library->filter(filter);
const auto searchQuery = filter.getQuery();
auto languages = getLanguageData();
auto categories = getCategoryData();
for (auto &category : categories) {
const auto categoryName = category.get("name")->string_value();
if (categoryName == filter.getCategory()) {
category["selected"] = true;
}
category["hf_name"] = humanFriendlyTitle(categoryName);
}
for (auto &language : languages) {
if (language.get("lang_code")->string_value() == filter.getLang()) {
language["selected"] = true;
}
}
for ( const auto& bookId : filteredBooks ) {
const auto bookObj = library->getBookById(bookId);
const auto bookTitle = bookObj.getTitle();
std::string contentId = "";
try {
contentId = urlEncode(nameMapper->getNameForId(bookId));
} catch (...) {}
const auto bookDescription = bookObj.getDescription();
const auto bookIconUrl = rootLocation + "/catalog/v2/illustration/" + bookId + "/?size=48";
const auto tags = bookObj.getTags();
const auto downloadAvailable = (bookObj.getUrl() != "");
const auto langTagObj = getLangTag(bookObj.getLanguages());
std::string faviconAttr = "style=background-image:url(" + bookIconUrl + ")";
booksData.push_back(kainjow::mustache::object{
{"id", contentId},
{"title", bookTitle},
{"description", bookDescription},
{"langTag", langTagObj},
{"faviconAttr", faviconAttr},
{"tagList", getTagList(tags)},
{"downloadAvailable", downloadAvailable}
});
}
auto getTranslation = i18n::GetTranslatedStringWithMsgId(m_userLang);
const auto translations = kainjow::mustache::object{
getTranslation("search"),
getTranslation("download"),
getTranslation("count-of-matching-books", {{"COUNT", to_string(filteredBooks.size())}}),
getTranslation("book-filtering-all-categories"),
getTranslation("book-filtering-all-languages"),
getTranslation("powered-by-kiwix-html"),
getTranslation("welcome-to-kiwix-server"),
getTranslation("preview-book"),
getTranslation("welcome-page-overzealous-filter", {{"URL", "?lang="}})
};
return render_template(
RESOURCE::templates::no_js_library_page_html,
kainjow::mustache::object{
{"root", rootLocation},
{"contentAccessUrl", onlyAsNonEmptyMustacheValue(contentAccessUrl)},
{"books", booksData },
{"searchQuery", searchQuery},
{"languages", languages},
{"categories", categories},
{"noResults", filteredBooks.size() == 0},
{"translations", translations}
}
);
}
} // namespace kiwix
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.fr>
* Copyright 2023 Nikhil Tanwar <2002nikhiltanwar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,14 +17,34 @@
* MA 02110-1301, USA.
*/
package org.kiwix.kiwixlib;
#ifndef KIWIX_HTML_DUMPER_H
#define KIWIX_HTML_DUMPER_H
import org.kiwix.kiwixlib.JNIKiwixReader;
import org.kiwix.kiwixlib.JNIKiwixString;
#include <string>
public class JNIKiwix
#include "library_dumper.h"
namespace kiwix
{
static { System.loadLibrary("kiwix"); }
public native void setDataDirectory(String icuDataDir);
/**
* A class to dump Library in HTML format.
*/
class HTMLDumper : public LibraryDumper
{
public:
HTMLDumper(const Library* library, const NameMapper* NameMapper);
~HTMLDumper();
/**
* Dump library in HTML
*
* @return HTML content
*/
std::string dumpPlainHTML(kiwix::Filter filter) const;
};
}
#endif // KIWIX_HTML_DUMPER_H
+82
View File
@@ -0,0 +1,82 @@
#include "kiwixserve.h"
#include "subprocess.h"
#ifdef _WIN32
# define KIWIXSERVE_CMD "kiwix-serve.exe"
# include <windows.h>
#else
# define KIWIXSERVE_CMD "kiwix-serve"
# include <unistd.h>
#endif
#include "tools.h"
#include "tools/pathTools.h"
#include "tools/stringTools.h"
namespace kiwix {
KiwixServe::KiwixServe(const std::string& libraryPath, int port)
: m_port(port),
m_libraryPath(libraryPath)
{
}
KiwixServe::~KiwixServe()
{
shutDown();
}
void KiwixServe::run()
{
#ifdef _WIN32
int pid = GetCurrentProcessId();
#else
pid_t pid = getpid();
#endif
std::vector<const char*> callCmd;
std::string kiwixServeCmd = appendToDirectory(
removeLastPathElement(getExecutablePath(true)),
KIWIXSERVE_CMD);
if (fileExists(kiwixServeCmd)) {
// A local kiwix-serve exe exists (packaged with kiwix-desktop), use it.
callCmd.push_back(kiwixServeCmd.c_str());
} else {
// Try to use a potential installed kiwix-serve.
callCmd.push_back(KIWIXSERVE_CMD);
}
std::string attachProcessOpt = "-a" + to_string(pid);
std::string portOpt = "-p" + to_string(m_port);
callCmd.push_back(attachProcessOpt.c_str());
callCmd.push_back(portOpt.c_str());
callCmd.push_back("-l");
callCmd.push_back(m_libraryPath.c_str());
mp_kiwixServe = Subprocess::run(callCmd);
}
void KiwixServe::shutDown()
{
if (mp_kiwixServe)
mp_kiwixServe->kill();
}
bool KiwixServe::isRunning()
{
if (mp_kiwixServe) {
return (mp_kiwixServe->isRunning());
}
return false;
}
int KiwixServe::setPort(int port)
{
if (port >= 1 && port <= 65535) {
m_port = port;
} else {
return -1;
}
return m_port;
}
}
+933 -221
View File
File diff suppressed because it is too large. Load diff
+61
View File
@@ -0,0 +1,61 @@
#include "library_dumper.h"
#include "tools/stringTools.h"
#include "tools/otherTools.h"
#include "tools.h"
namespace kiwix
{
/* Constructor */
LibraryDumper::LibraryDumper(const Library* library, const NameMapper* nameMapper)
: library(library),
nameMapper(nameMapper)
{
}
/* Destructor */
LibraryDumper::~LibraryDumper()
{
}
void LibraryDumper::setOpenSearchInfo(int totalResults, int startIndex, int count)
{
m_totalResults = totalResults;
m_startIndex = startIndex,
m_count = count;
}
kainjow::mustache::list LibraryDumper::getCategoryData() const
{
const auto now = gen_date_str();
kainjow::mustache::list categoryData;
for ( const auto& category : library->getBooksCategories() ) {
const auto urlencodedCategoryName = urlEncode(category);
categoryData.push_back(kainjow::mustache::object{
{"name", category},
{"urlencoded_name", urlencodedCategoryName},
{"updated", now},
{"id", gen_uuid(libraryId + "/categories/" + urlencodedCategoryName)}
});
}
return categoryData;
}
kainjow::mustache::list LibraryDumper::getLanguageData() const
{
const auto now = gen_date_str();
kainjow::mustache::list languageData;
for ( const auto& langAndBookCount : library->getBooksLanguagesWithCounts() ) {
const std::string languageCode = langAndBookCount.first;
const int bookCount = langAndBookCount.second;
const auto languageSelfName = getLanguageSelfName(languageCode);
languageData.push_back(kainjow::mustache::object{
{"lang_code", languageCode},
{"lang_self_name", languageSelfName},
{"book_count", to_string(bookCount)},
{"updated", now},
{"id", gen_uuid(libraryId + "/languages/" + languageCode)}
});
}
return languageData;
}
} // namespace kiwix
+32 -53
View File
@@ -1,4 +1,5 @@
/*
* Copyright 2023 Nikhil Tanwar <2002nikhiltanwar@gmail.com>
* Copyright 2017 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,58 +18,30 @@
* MA 02110-1301, USA.
*/
#ifndef KIWIX_OPDS_DUMPER_H
#define KIWIX_OPDS_DUMPER_H
#ifndef KIWIX_LIBRARY_DUMPER_H
#define KIWIX_LIBRARY_DUMPER_H
#include <time.h>
#include <sstream>
#include <string>
#include <pugixml.hpp>
#include "common/base64.h"
#include "common/pathTools.h"
#include "common/regexTools.h"
#include "library.h"
#include "reader.h"
using namespace std;
#include "name_mapper.h"
#include <mustache.hpp>
namespace kiwix
{
/**
* A tool to dump a `Library` into a opds stream.
* A base class to dump Library in various formats.
*
*/
class OPDSDumper
class LibraryDumper
{
public:
OPDSDumper() = default;
OPDSDumper(Library* library);
~OPDSDumper();
LibraryDumper(const Library* library, const NameMapper* NameMapper);
~LibraryDumper();
/**
* Dump the OPDS feed.
*
* @param id The id of the library.
* @return The OPDS feed.
*/
std::string dumpOPDSFeed(const std::vector<std::string>& bookIds);
/**
* Set the id of the opds stream.
*
* @param id the id to use.
*/
void setId(const std::string& id) { this->id = id;}
/**
* Set the title oft the opds stream.
*
* @param title the title to use.
*/
void setTitle(const std::string& title) { this->title = title; }
void setLibraryId(const std::string& id) { this->libraryId = id;}
/**
* Set the root location used when generating url.
@@ -78,11 +51,11 @@ class OPDSDumper
void setRootLocation(const std::string& rootLocation) { this->rootLocation = rootLocation; }
/**
* Set the search url.
* Set the URL for accessing book content
*
* @param searchUrl the search url to use.
* @param url the URL of the /content endpoint of the content server
*/
void setSearchDescriptionUrl(const std::string& searchDescriptionUrl) { this->searchDescriptionUrl = searchDescriptionUrl; }
void setContentAccessUrl(const std::string& url) { this->contentAccessUrl = url; }
/**
* Set some informations about the search results.
@@ -94,27 +67,33 @@ class OPDSDumper
void setOpenSearchInfo(int totalResult, int startIndex, int count);
/**
* Set the library to dump.
* Sets user default language
*
* @param library The library to dump.
* @param userLang the user language to be set
*/
void setLibrary(Library* library) { this->library = library; }
void setUserLanguage(std::string userLang) { this->m_userLang = userLang; }
/**
* Get the data of categories
*/
kainjow::mustache::list getCategoryData() const;
/**
* Get the data of languages
*/
kainjow::mustache::list getLanguageData() const;
protected:
kiwix::Library* library;
std::string id;
std::string title;
std::string date;
const kiwix::Library* const library;
const kiwix::NameMapper* const nameMapper;
std::string libraryId;
std::string rootLocation;
std::string searchDescriptionUrl;
std::string contentAccessUrl;
std::string m_userLang;
int m_totalResults;
int m_startIndex;
int m_count;
bool m_isSearchResult = false;
private:
pugi::xml_node handleBook(Book book, pugi::xml_node root_node);
};
}
#endif // KIWIX_OPDS_DUMPER_H
#endif // KIWIX_LIBRARY_DUMPER_H
+149
View File
@@ -0,0 +1,149 @@
/*
* Copyright 2017 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "libxml_dumper.h"
#include "book.h"
#include "tools.h"
#include "tools/base64.h"
#include "tools/stringTools.h"
#include "tools/otherTools.h"
namespace kiwix
{
/* Constructor */
LibXMLDumper::LibXMLDumper(const Library* library)
: library(library)
{
}
/* Destructor */
LibXMLDumper::~LibXMLDumper()
{
}
#define ADD_ATTRIBUTE(node, name, value) { (node).append_attribute((name)) = (value).c_str(); }
#define ADD_ATTR_NOT_EMPTY(node, name, value) { if (!(value).empty()) ADD_ATTRIBUTE(node, name, value); }
void LibXMLDumper::handleBook(Book book, pugi::xml_node root_node) {
if (book.readOnly())
return;
auto entry_node = root_node.append_child("book");
ADD_ATTRIBUTE(entry_node, "id", book.getId());
if (!book.getPath().empty()) {
ADD_ATTRIBUTE(entry_node, "path", computeRelativePath(baseDir, book.getPath()));
}
if (book.getOrigId().empty()) {
ADD_ATTR_NOT_EMPTY(entry_node, "title", book.getTitle());
ADD_ATTR_NOT_EMPTY(entry_node, "description", book.getDescription());
ADD_ATTR_NOT_EMPTY(entry_node, "language", book.getCommaSeparatedLanguages());
ADD_ATTR_NOT_EMPTY(entry_node, "creator", book.getCreator());
ADD_ATTR_NOT_EMPTY(entry_node, "publisher", book.getPublisher());
ADD_ATTR_NOT_EMPTY(entry_node, "name", book.getName());
ADD_ATTR_NOT_EMPTY(entry_node, "flavour", book.getFlavour());
ADD_ATTR_NOT_EMPTY(entry_node, "tags", book.getTags());
try {
auto defaultIllustration = book.getIllustration(48);
ADD_ATTR_NOT_EMPTY(entry_node, "faviconMimeType", defaultIllustration->mimeType);
ADD_ATTR_NOT_EMPTY(entry_node, "faviconUrl", defaultIllustration->url);
if (!defaultIllustration->getData().empty())
ADD_ATTRIBUTE(entry_node, "favicon", base64_encode(defaultIllustration->getData()));
} catch(...) {}
} else {
ADD_ATTRIBUTE(entry_node, "origId", book.getOrigId());
}
ADD_ATTR_NOT_EMPTY(entry_node, "date", book.getDate());
ADD_ATTR_NOT_EMPTY(entry_node, "url", book.getUrl());
if (book.getArticleCount())
ADD_ATTRIBUTE(entry_node, "articleCount", to_string(book.getArticleCount()));
if (book.getMediaCount())
ADD_ATTRIBUTE(entry_node, "mediaCount", to_string(book.getMediaCount()));
if (book.getSize())
ADD_ATTRIBUTE(entry_node, "size", to_string(book.getSize()>>10));
ADD_ATTR_NOT_EMPTY(entry_node, "downloadId", book.getDownloadId());
}
#define ADD_TEXT_ENTRY(node, child, value) (node).append_child((child)).append_child(pugi::node_pcdata).set_value((value).c_str())
void LibXMLDumper::handleBookmark(Bookmark bookmark, pugi::xml_node root_node) {
auto entry_node = root_node.append_child("bookmark");
auto book_node = entry_node.append_child("book");
try {
auto book = library->getBookByIdThreadSafe(bookmark.getBookId());
ADD_TEXT_ENTRY(book_node, "id", book.getId());
ADD_TEXT_ENTRY(book_node, "title", book.getTitle());
ADD_TEXT_ENTRY(book_node, "name", book.getName());
ADD_TEXT_ENTRY(book_node, "flavour", book.getFlavour());
ADD_TEXT_ENTRY(book_node, "language", book.getCommaSeparatedLanguages());
ADD_TEXT_ENTRY(book_node, "date", book.getDate());
} catch (...) {
ADD_TEXT_ENTRY(book_node, "id", bookmark.getBookId());
ADD_TEXT_ENTRY(book_node, "title", bookmark.getBookTitle());
ADD_TEXT_ENTRY(book_node, "name", bookmark.getBookName());
ADD_TEXT_ENTRY(book_node, "flavour", bookmark.getBookFlavour());
ADD_TEXT_ENTRY(book_node, "language", bookmark.getLanguage());
ADD_TEXT_ENTRY(book_node, "date", bookmark.getDate());
}
ADD_TEXT_ENTRY(entry_node, "title", bookmark.getTitle());
ADD_TEXT_ENTRY(entry_node, "url", bookmark.getUrl());
}
std::string LibXMLDumper::dumpLibXMLContent(const std::vector<std::string>& bookIds)
{
pugi::xml_document doc;
/* Add the library node */
pugi::xml_node libraryNode = doc.append_child("library");
libraryNode.append_attribute("version") = KIWIX_LIBRARY_VERSION;
if (library) {
for (auto& bookId: bookIds) {
handleBook(library->getBookById(bookId), libraryNode);
}
}
return nodeToString(libraryNode);
}
std::string LibXMLDumper::dumpLibXMLBookmark()
{
pugi::xml_document doc;
/* Add the library node */
pugi::xml_node bookmarksNode = doc.append_child("bookmarks");
if (library) {
for (auto& bookmark: library->getBookmarks(false)) {
handleBookmark(bookmark, bookmarksNode);
}
}
return nodeToString(bookmarksNode);
}
}
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright 2018 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_LIBXML_DUMPER_H
#define KIWIX_LIBXML_DUMPER_H
#include <string>
#include <vector>
#include <pugixml.hpp>
#include "library.h"
namespace kiwix
{
/**
* A tool to dump a `Library` into a basic library.xml
*
*/
class LibXMLDumper
{
public:
LibXMLDumper() = default;
LibXMLDumper(const Library* library);
~LibXMLDumper();
/**
* Dump the library.xml
*
* @param id The id of the library.
* @return The library.xml content.
*/
std::string dumpLibXMLContent(const std::vector<std::string>& bookIds);
/**
* Dump the bookmark of the library.
*
* @return The bookmark.xml content.
*/
std::string dumpLibXMLBookmark();
/**
* Set the base directory used.
*
* @param baseDir the base directory to use.
*/
void setBaseDir(const std::string& baseDir) { this->baseDir = baseDir; }
/**
* Set the library to dump.
*
* @param library The library to dump.
*/
void setLibrary(const Library* library) { this->library = library; }
protected:
const kiwix::Library* library;
std::string baseDir;
private:
void handleBook(Book book, pugi::xml_node root_node);
void handleBookmark(Bookmark bookmark, pugi::xml_node root_node);
};
}
#endif // KIWIX_OPDS_DUMPER_H
+199 -51
View File
@@ -19,35 +19,90 @@
#include "manager.h"
#include "tools.h"
#include "tools/pathTools.h"
#include <pugixml.hpp>
#include <filesystem>
#include <iostream>
#include <set>
#include <queue>
#include <cctype>
#include <algorithm>
namespace fs = std::filesystem;
namespace kiwix
{
/* Constructor */
Manager::Manager(LibraryManipulator* manipulator):
writableLibraryPath(""),
manipulator(manipulator),
mustDeleteManipulator(false)
{
}
Manager::Manager(Library* library) :
writableLibraryPath(""),
manipulator(new DefaultLibraryManipulator(library)),
mustDeleteManipulator(true)
{
}
////////////////////////////////////////////////////////////////////////////////
// LibraryManipulator
////////////////////////////////////////////////////////////////////////////////
/* Destructor */
Manager::~Manager()
LibraryManipulator::LibraryManipulator(LibraryPtr library)
: library(library)
{}
LibraryManipulator::~LibraryManipulator()
{}
bool LibraryManipulator::addBookToLibrary(const Book& book)
{
if (mustDeleteManipulator) {
delete manipulator;
const auto ret = library->addBook(book);
if ( ret ) {
bookWasAddedToLibrary(book);
}
return ret;
}
void LibraryManipulator::addBookmarkToLibrary(const Bookmark& bookmark)
{
library->addBookmark(bookmark);
bookmarkWasAddedToLibrary(bookmark);
}
uint32_t LibraryManipulator::removeBooksNotUpdatedSince(Library::Revision rev)
{
const auto n = library->removeBooksNotUpdatedSince(rev);
if ( n != 0 ) {
booksWereRemovedFromLibrary();
}
return n;
}
void LibraryManipulator::bookWasAddedToLibrary(const Book& book)
{
}
void LibraryManipulator::bookmarkWasAddedToLibrary(const Bookmark& bookmark)
{
}
void LibraryManipulator::booksWereRemovedFromLibrary()
{
}
////////////////////////////////////////////////////////////////////////////////
// Manager
////////////////////////////////////////////////////////////////////////////////
/* Constructor */
Manager::Manager(LibraryManipulator manipulator):
writableLibraryPath(""),
manipulator(manipulator)
{
}
Manager::Manager(LibraryPtr library) :
writableLibraryPath(""),
manipulator(LibraryManipulator(library))
{
}
bool Manager::parseXmlDom(const pugi::xml_document& doc,
const bool readOnly,
const std::string& libraryPath)
bool readOnly,
const std::string& libraryPath,
bool trustLibrary)
{
pugi::xml_node libraryNode = doc.child("library");
@@ -59,31 +114,28 @@ bool Manager::parseXmlDom(const pugi::xml_document& doc,
book.setReadOnly(readOnly);
book.updateFromXml(bookNode,
removeLastPathElement(libraryPath, true, false));
removeLastPathElement(libraryPath));
/* Update the book properties with the new importer */
if (libraryVersion.empty()
|| atoi(libraryVersion.c_str()) <= atoi(KIWIX_LIBRARY_VERSION)) {
if (!book.getPath().empty()) {
this->readBookFromPath(book.getPath(), &book);
}
if (!trustLibrary && !book.getPath().empty()) {
this->readBookFromPath(book.getPath(), &book);
}
manipulator->addBookToLibrary(book);
manipulator.addBookToLibrary(book);
}
return true;
}
bool Manager::readXml(const std::string& xml,
const bool readOnly,
const std::string& libraryPath)
bool readOnly,
const std::string& libraryPath,
bool trustLibrary)
{
pugi::xml_document doc;
pugi::xml_parse_result result
= doc.load_buffer_inplace((void*)xml.data(), xml.size());
= doc.load_buffer((void*)xml.data(), xml.size());
if (result) {
this->parseXmlDom(doc, readOnly, libraryPath);
this->parseXmlDom(doc, readOnly, libraryPath, trustLibrary);
}
return true;
@@ -112,7 +164,7 @@ bool Manager::parseOpdsDom(const pugi::xml_document& doc, const std::string& url
book.updateFromOpds(entryNode, urlHost);
/* Update the book properties with the new importer */
manipulator->addBookToLibrary(book);
manipulator.addBookToLibrary(book);
}
return true;
@@ -124,7 +176,7 @@ bool Manager::readOpds(const std::string& content, const std::string& urlHost)
{
pugi::xml_document doc;
pugi::xml_parse_result result
= doc.load_buffer_inplace((void*)content.data(), content.size());
= doc.load_buffer((void*)content.data(), content.size());
if (result) {
this->parseOpdsDom(doc, urlHost);
@@ -134,21 +186,22 @@ bool Manager::readOpds(const std::string& content, const std::string& urlHost)
return false;
}
bool Manager::readFile(const std::string& path, const bool readOnly)
{
return this->readFile(path, path, readOnly);
}
bool Manager::readFile(const std::string& nativePath,
const std::string& UTF8Path,
const bool readOnly)
bool Manager::readFile(
const std::string& path,
bool readOnly,
bool trustLibrary)
{
bool retVal = true;
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(nativePath.c_str());
#ifdef _WIN32
pugi::xml_parse_result result = doc.load_file(Utf8ToWide(path).c_str());
#else
pugi::xml_parse_result result = doc.load_file(path.c_str());
#endif
if (result) {
this->parseXmlDom(doc, readOnly, UTF8Path);
this->parseXmlDom(doc, readOnly, path, trustLibrary);
} else {
retVal = false;
}
@@ -157,7 +210,7 @@ bool Manager::readFile(const std::string& nativePath,
* able to know where to save the library if new content are
* available */
if (!readOnly) {
this->writableLibraryPath = UTF8Path;
this->writableLibraryPath = path;
}
return retVal;
@@ -174,19 +227,19 @@ std::string Manager::addBookFromPathAndGetId(const std::string& pathToOpen,
kiwix::Book book;
if (this->readBookFromPath(pathToOpen, &book)) {
if (pathToSave != pathToOpen) {
if (!pathToSave.empty() && pathToSave != pathToOpen) {
book.setPath(isRelativePath(pathToSave)
? computeAbsolutePath(
removeLastPathElement(writableLibraryPath, true, false),
removeLastPathElement(writableLibraryPath),
pathToSave)
: pathToSave);
}
if (!checkMetaData
|| (checkMetaData && !book.getTitle().empty() && !book.getLanguage().empty()
|| (!book.getTitle().empty() && !book.getLanguages().empty()
&& !book.getDate().empty())) {
book.setUrl(url);
manipulator->addBookToLibrary(book);
manipulator.addBookToLibrary(book);
return book.getId();
}
}
@@ -206,14 +259,69 @@ bool Manager::addBookFromPath(const std::string& pathToOpen,
.empty());
}
void Manager::addBooksFromDirectory(const std::string& path,
const bool verboseFlag)
{
std::set<std::string> iteratedDirs;
std::queue<std::string> dirQueue;
dirQueue.push(fs::absolute(path).u8string());
int totalBooksAdded = 0;
if (verboseFlag)
std::cout << "Adding books from the directory tree: " << dirQueue.front() << std::endl;
while (!dirQueue.empty()) {
const auto currentPath = dirQueue.front();
dirQueue.pop();
if (verboseFlag)
std::cout << "Visiting directory: " << currentPath << std::endl;
for (const auto& dirEntry : fs::directory_iterator(currentPath)) {
auto resolvedPath = dirEntry.path();
if (fs::is_symlink(dirEntry)) {
try {
resolvedPath = fs::canonical(dirEntry.path());
} catch (const std::exception& e) {
std::cerr << "Could not resolve symlink " << resolvedPath.u8string() << " to a valid path. Skipping..." << std::endl;
continue;
}
}
const std::string pathString = resolvedPath.u8string();
std::string resolvedPathExtension = resolvedPath.extension().u8string();
std::transform(resolvedPathExtension.begin(), resolvedPathExtension.end(), resolvedPathExtension.begin(),
[](unsigned char c){ return std::tolower(c); });
if (fs::is_directory(resolvedPath)) {
if (iteratedDirs.find(pathString) == iteratedDirs.end())
dirQueue.push(pathString);
else if (verboseFlag)
std::cout << "Already iterated over " << pathString << ". Skipping..." << std::endl;
} else if (resolvedPathExtension == ".zim" || resolvedPathExtension == ".zimaa") {
if (!this->addBookFromPath(pathString, pathString, "", false)) {
std::cerr << "Could not add " << pathString << " into the library." << std::endl;
} else if (verboseFlag) {
std::cout << "Added " << pathString << " into the library." << std::endl;
totalBooksAdded++;
}
} else if (verboseFlag) {
std::cout << "Skipped " << pathString << " - unsupported file type or permission denied." << std::endl;
}
}
iteratedDirs.insert(currentPath);
}
if (verboseFlag)
std::cout << "Traversal completed. Total books added: " << totalBooksAdded << std::endl;
}
bool Manager::readBookFromPath(const std::string& path, kiwix::Book* book)
{
std::string tmp_path = path;
if (isRelativePath(path)) {
tmp_path = computeAbsolutePath(getCurrentDirectory(), path);
}
try {
kiwix::Reader reader(path);
book->update(reader);
zim::Archive archive(tmp_path);
book->update(archive);
book->setPathValid(true);
} catch (const std::exception& e) {
std::cerr << "Invalid " << path << " : " << e.what() << std::endl;
book->setPathValid(false);
return false;
}
@@ -221,4 +329,44 @@ bool Manager::readBookFromPath(const std::string& path, kiwix::Book* book)
return true;
}
bool Manager::readBookmarkFile(const std::string& path)
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(path.c_str());
if (!result) {
return false;
}
pugi::xml_node libraryNode = doc.child("bookmarks");
for (pugi::xml_node node = libraryNode.child("bookmark"); node;
node = node.next_sibling("bookmark")) {
kiwix::Bookmark bookmark;
bookmark.updateFromXml(node);
manipulator.addBookmarkToLibrary(bookmark);
}
return true;
}
void Manager::reload(const Paths& paths)
{
const auto libRevision = manipulator.getLibrary()->getRevision();
for (std::string path : paths) {
if (!path.empty()) {
if ( kiwix::isRelativePath(path) )
path = kiwix::computeAbsolutePath(kiwix::getCurrentDirectory(), path);
if (!readFile(path, false, true)) {
throw std::runtime_error("Failed to load the XML library file '" + path + "'.");
}
}
}
manipulator.removeBooksNotUpdatedSince(libRevision);
}
}
+32 -29
View File
@@ -1,24 +1,41 @@
kiwix_sources = [
'book.cpp',
'bookmark.cpp',
'library.cpp',
'manager.cpp',
'libxml_dumper.cpp',
'opds_dumper.cpp',
'html_dumper.cpp',
'library_dumper.cpp',
'downloader.cpp',
'reader.cpp',
'entry.cpp',
'searcher.cpp',
'server.cpp',
'search_renderer.cpp',
'subprocess.cpp',
'aria2.cpp',
'common/base64.cpp',
'common/pathTools.cpp',
'common/regexTools.cpp',
'common/stringTools.cpp',
'common/networkTools.cpp',
'common/otherTools.cpp',
'xapian/htmlparse.cc',
'xapian/myhtmlparse.cc'
'tools/base64.cpp',
'tools/pathTools.cpp',
'tools/regexTools.cpp',
'tools/stringTools.cpp',
'tools/networkTools.cpp',
'tools/opdsParsingTools.cpp',
'tools/languageTools.cpp',
'tools/otherTools.cpp',
'tools/archiveTools.cpp',
'kiwixserve.cpp',
'name_mapper.cpp',
'server/byte_range.cpp',
'server/etag.cpp',
'server/request_context.cpp',
'server/response.cpp',
'server/internalServer.cpp',
'server/internalServer_catalog.cpp',
'server/i18n.cpp',
'opds_catalog.cpp',
'spelling_correction.cpp',
'version.cpp'
]
kiwix_sources += lib_resources
kiwix_sources += i18n_resources
if host_machine.system() == 'windows'
kiwix_sources += 'subprocess_windows.cpp'
@@ -26,32 +43,18 @@ else
kiwix_sources += 'subprocess_unix.cpp'
endif
if xapian_dep.found()
kiwix_sources += ['xapianSearcher.cpp']
endif
if get_option('android')
subdir('android')
install_dir = 'kiwix-lib/jniLibs/' + meson.get_cross_property('android_abi')
else
install_dir = get_option('libdir')
endif
if has_ctpp2_dep
kiwix_sources += ['ctpp2/CTPP2VMStringLoader.cpp']
endif
install_dir = get_option('libdir')
config_h = configure_file(output : 'kiwix_config.h',
configuration : conf,
input : 'config.h.in')
install_headers(config_h, subdir:'kiwix')
kiwixlib = library('kiwix',
libkiwix = library('kiwix',
kiwix_sources,
include_directories : inc,
dependencies : all_deps,
link_args: extra_libs,
version: meson.project_version(),
install: true,
install_dir: install_dir,
install_rpath: '$ORIGIN')
install_dir: install_dir)
+108
View File
@@ -0,0 +1,108 @@
/*
* Copyright 2019 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "name_mapper.h"
#include "library.h"
#include "tools/regexTools.h"
#include <iostream>
namespace kiwix {
HumanReadableNameMapper::HumanReadableNameMapper(const kiwix::Library& library, bool withAlias) {
for (auto& bookId: library.filter(kiwix::Filter())) {
auto& currentBook = library.getBookById(bookId);
auto bookName = currentBook.getHumanReadableIdFromPath();
m_idToName[bookId] = bookName;
mapName(library, bookName, bookId);
if (!withAlias)
continue;
auto aliasName = replaceRegex(bookName, "", "_[[:digit:]]{4}-[[:digit:]]{2}$");
if (aliasName != bookName) {
mapName(library, aliasName, bookId);
}
}
}
void HumanReadableNameMapper::mapName(const Library& library, std::string name, std::string bookId) {
if (m_nameToId.find(name) == m_nameToId.end()) {
m_nameToId[name] = bookId;
} else {
const auto& currentBook = library.getBookById(bookId);
auto alreadyPresentPath = library.getBookById(m_nameToId[name]).getPath();
std::cerr << "Path collision: '" << alreadyPresentPath
<< "' and '" << currentBook.getPath()
<< "' can't share the same URL path '" << name << "'."
<< " Therefore, only '" << alreadyPresentPath
<< "' will be served." << std::endl;
}
}
std::string HumanReadableNameMapper::getNameForId(const std::string& id) const {
return m_idToName.at(id);
}
std::string HumanReadableNameMapper::getIdForName(const std::string& name) const {
return m_nameToId.at(name);
}
////////////////////////////////////////////////////////////////////////////////
// UpdatableNameMapper
////////////////////////////////////////////////////////////////////////////////
UpdatableNameMapper::UpdatableNameMapper(LibraryPtr lib, bool withAlias)
: library(lib)
, withAlias(withAlias)
{
update();
}
void UpdatableNameMapper::update()
{
const auto newNameMapper = new HumanReadableNameMapper(*library, withAlias);
std::lock_guard<std::mutex> lock(mutex);
nameMapper.reset(newNameMapper);
}
UpdatableNameMapper::NameMapperHandle
UpdatableNameMapper::currentNameMapper() const
{
// Return a copy of the handle to the current NameMapper object. It will
// ensure that the object survives any call to UpdatableNameMapper::update()
// made before the completion of any pending operation on that object.
std::lock_guard<std::mutex> lock(mutex);
return nameMapper;
}
std::string UpdatableNameMapper::getNameForId(const std::string& id) const
{
// Ensure that the current nameMapper object survives a concurrent call
// to UpdatableNameMapper::update()
return currentNameMapper()->getNameForId(id);
}
std::string UpdatableNameMapper::getIdForName(const std::string& name) const
{
// Ensure that the current nameMapper object survives a concurrent call
// to UpdatableNameMapper::update()
return currentNameMapper()->getIdForName(name);
}
}
+74
View File
@@ -0,0 +1,74 @@
/*
* Copyright 2021 Veloman Yunkan <veloman.yunkan@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "opds_catalog.h"
#include "tools/stringTools.h"
#include <sstream>
namespace kiwix
{
namespace
{
const char opdsSearchEndpoint[] = "/catalog/v2/entries";
enum Separator { AMP };
std::ostringstream& operator<<(std::ostringstream& oss, Separator sep)
{
if ( oss.tellp() > 0 )
oss << "&";
return oss;
}
std::string buildSearchString(const Filter& f)
{
std::ostringstream oss;
if ( f.hasQuery() )
oss << AMP << "q=" << urlEncode(f.getQuery());
if ( f.hasCategory() )
oss << AMP << "category=" << urlEncode(f.getCategory());
if ( f.hasLang() )
oss << AMP << "lang=" << urlEncode(f.getLang());
if ( f.hasName() )
oss << AMP << "name=" << urlEncode(f.getName());
if ( !f.getAcceptTags().empty() )
oss << AMP << "tag=" << urlEncode(join(f.getAcceptTags(), ";"));
return oss.str();
}
} // unnamed namespace
std::string getSearchUrl(const Filter& f)
{
const std::string searchString = buildSearchString(f);
if ( searchString.empty() )
return opdsSearchEndpoint;
else
return opdsSearchEndpoint + ("?" + searchString);
}
} // namespace kiwix
+166 -88
View File
@@ -20,13 +20,18 @@
#include "opds_dumper.h"
#include "book.h"
#include <common/otherTools.h>
#include "libkiwix-resources.h"
#include <mustache.hpp>
#include "tools/stringTools.h"
#include "tools/otherTools.h"
namespace kiwix
{
/* Constructor */
OPDSDumper::OPDSDumper(Library* library)
: library(library)
OPDSDumper::OPDSDumper(const Library* library, const NameMapper* nameMapper)
: LibraryDumper(library, nameMapper)
{
}
/* Destructor */
@@ -34,104 +39,177 @@ OPDSDumper::~OPDSDumper()
{
}
std::string gen_date_str()
namespace
{
auto now = time(0);
auto tm = localtime(&now);
std::stringstream is;
is << std::setw(2) << std::setfill('0')
<< 1900+tm->tm_year << "-"
<< std::setw(2) << std::setfill('0') << tm->tm_mon << "-"
<< std::setw(2) << std::setfill('0') << tm->tm_mday << "T"
<< std::setw(2) << std::setfill('0') << tm->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << tm->tm_min << ":"
<< std::setw(2) << std::setfill('0') << tm->tm_sec << "Z";
return is.str();
const std::string XML_HEADER(R"(<?xml version="1.0" encoding="UTF-8"?>)");
typedef kainjow::mustache::data MustacheData;
typedef kainjow::mustache::list BooksData;
typedef kainjow::mustache::list IllustrationInfo;
IllustrationInfo getBookIllustrationInfo(const Book& book)
{
kainjow::mustache::list illustrations;
for ( const auto& illustration : book.getIllustrations() ) {
// For now, we are handling only sizexsize@1 illustration.
// So we can simply pass one size to mustache.
illustrations.push_back(kainjow::mustache::object{
{"icon_size", to_string(illustration->width)},
{"icon_mimetype", illustration->mimeType}
});
}
return illustrations;
}
void OPDSDumper::setOpenSearchInfo(int totalResults, int startIndex, int count)
std::string fullEntryXML(const Book& book,
const std::string& rootLocation,
const std::string& contentAccessUrl,
const std::string& contentId)
{
m_totalResults = totalResults;
m_startIndex = startIndex,
m_count = count;
m_isSearchResult = true;
const auto bookDate = book.getDate() + "T00:00:00Z";
const kainjow::mustache::object data{
{"root", rootLocation},
{"contentAccessUrl", onlyAsNonEmptyMustacheValue(contentAccessUrl)},
{"id", book.getId()},
{"name", book.getName()},
{"title", book.getTitle()},
{"description", book.getDescription()},
{"language", book.getCommaSeparatedLanguages()},
{"content_id", urlEncode(contentId)},
{"updated", bookDate}, // XXX: this should be the entry update datetime
{"book_date", bookDate},
{"category", book.getCategory()},
{"flavour", book.getFlavour()},
{"tags", book.getTags()},
{"article_count", to_string(book.getArticleCount())},
{"media_count", to_string(book.getMediaCount())},
{"author_name", book.getCreator()},
{"publisher_name", book.getPublisher()},
{"url", onlyAsNonEmptyMustacheValue(book.getUrl())},
{"size", to_string(book.getSize())},
{"icons", getBookIllustrationInfo(book)},
};
return render_template(RESOURCE::templates::catalog_v2_entry_xml, data);
}
#define ADD_TEXT_ENTRY(node, child, value) (node).append_child((child)).append_child(pugi::node_pcdata).set_value((value).c_str())
pugi::xml_node OPDSDumper::handleBook(Book book, pugi::xml_node root_node) {
auto entry_node = root_node.append_child("entry");
ADD_TEXT_ENTRY(entry_node, "title", book.getTitle());
ADD_TEXT_ENTRY(entry_node, "id", "urn:uuid:"+book.getId());
ADD_TEXT_ENTRY(entry_node, "icon", rootLocation + "/meta?name=favicon&content=" + book.getHumanReadableIdFromPath());
ADD_TEXT_ENTRY(entry_node, "updated", date);
ADD_TEXT_ENTRY(entry_node, "summary", book.getDescription());
auto content_node = entry_node.append_child("link");
content_node.append_attribute("type") = "text/html";
content_node.append_attribute("href") = (rootLocation + "/" + book.getHumanReadableIdFromPath()).c_str();
auto author_node = entry_node.append_child("author");
ADD_TEXT_ENTRY(author_node, "name", book.getCreator());
if (! book.getUrl().empty()) {
auto acquisition_link = entry_node.append_child("link");
acquisition_link.append_attribute("rel") = "http://opds-spec.org/acquisition/open-access";
acquisition_link.append_attribute("type") = "application/x-zim";
acquisition_link.append_attribute("href") = book.getUrl().c_str();
acquisition_link.append_attribute("length") = to_string(book.getSize()).c_str();
}
if (! book.getFaviconMimeType().empty() ) {
auto image_link = entry_node.append_child("link");
image_link.append_attribute("rel") = "http://opds-spec.org/image/thumbnail";
image_link.append_attribute("type") = book.getFaviconMimeType().c_str();
image_link.append_attribute("href") = (rootLocation + "/meta?name=favicon&content=" + book.getHumanReadableIdFromPath()).c_str();
}
return entry_node;
std::string partialEntryXML(const Book& book, const std::string& rootLocation)
{
const auto bookDate = book.getDate() + "T00:00:00Z";
const kainjow::mustache::object data{
{"root", rootLocation},
{"endpoint_root", rootLocation + "/catalog/v2"},
{"id", book.getId()},
{"title", book.getTitle()},
{"updated", bookDate}, // XXX: this should be the entry update datetime
};
const auto xmlTemplate = RESOURCE::templates::catalog_v2_partial_entry_xml;
return render_template(xmlTemplate, data);
}
string OPDSDumper::dumpOPDSFeed(const std::vector<std::string>& bookIds)
BooksData getBooksData(const Library* library,
const NameMapper* nameMapper,
const std::vector<std::string>& bookIds,
const std::string& rootLocation,
const std::string& contentAccessUrl,
bool partial)
{
date = gen_date_str();
pugi::xml_document doc;
auto root_node = doc.append_child("feed");
root_node.append_attribute("xmlns") = "http://www.w3.org/2005/Atom";
root_node.append_attribute("xmlns:opds") = "http://opds-spec.org/2010/catalog";
ADD_TEXT_ENTRY(root_node, "id", id);
ADD_TEXT_ENTRY(root_node, "title", title);
ADD_TEXT_ENTRY(root_node, "updated", date);
if (m_isSearchResult) {
ADD_TEXT_ENTRY(root_node, "totalResults", to_string(m_totalResults));
ADD_TEXT_ENTRY(root_node, "startIndex", to_string(m_startIndex));
ADD_TEXT_ENTRY(root_node, "itemsPerPage", to_string(m_count));
}
auto self_link_node = root_node.append_child("link");
self_link_node.append_attribute("rel") = "self";
self_link_node.append_attribute("href") = "";
self_link_node.append_attribute("type") = "application/atom+xml";
if (!searchDescriptionUrl.empty() ) {
auto search_link = root_node.append_child("link");
search_link.append_attribute("rel") = "search";
search_link.append_attribute("type") = "application/opensearchdescription+xml";
search_link.append_attribute("href") = searchDescriptionUrl.c_str();
}
if (library) {
for (auto& bookId: bookIds) {
handleBook(library->getBookById(bookId), root_node);
BooksData booksData;
for ( const auto& bookId : bookIds ) {
try {
const Book book = library->getBookByIdThreadSafe(bookId);
const std::string contentId = nameMapper->getNameForId(bookId);
const auto entryXML = partial
? partialEntryXML(book, rootLocation)
: fullEntryXML(book, rootLocation, contentAccessUrl, contentId);
booksData.push_back(kainjow::mustache::object{ {"entry", entryXML} });
} catch ( const std::out_of_range& ) {
// the book was removed from the library since its id was obtained
// ignore it
}
}
return nodeToString(root_node);
return booksData;
}
} // unnamed namespace
string OPDSDumper::dumpOPDSFeed(const std::vector<std::string>& bookIds, const std::string& query) const
{
const auto booksData = getBooksData(library, nameMapper, bookIds, rootLocation, contentAccessUrl, false);
const kainjow::mustache::object template_data{
{"date", gen_date_str()},
{"root", rootLocation},
{"feed_id", gen_uuid(libraryId + "/catalog/search?"+query)},
{"filter", onlyAsNonEmptyMustacheValue(query)},
{"totalResults", to_string(m_totalResults)},
{"startIndex", to_string(m_startIndex)},
{"itemsPerPage", to_string(m_count)},
{"books", booksData }
};
return render_template(RESOURCE::templates::catalog_entries_xml, template_data);
}
string OPDSDumper::dumpOPDSFeedV2(const std::vector<std::string>& bookIds, const std::string& query, bool partial) const
{
const auto endpointRoot = rootLocation + "/catalog/v2";
const auto booksData = getBooksData(library, nameMapper, bookIds, rootLocation, contentAccessUrl, partial);
const char* const endpoint = partial ? "/partial_entries" : "/entries";
const std::string url = endpoint + (query.empty() ? "" : "?" + query);
const kainjow::mustache::object template_data{
{"date", gen_date_str()},
{"endpoint_root", endpointRoot},
{"feed_id", gen_uuid(libraryId + endpoint + "?" + query)},
{"filter", onlyAsNonEmptyMustacheValue(query)},
{"self_url", url},
{"totalResults", to_string(m_totalResults)},
{"startIndex", to_string(m_startIndex)},
{"itemsPerPage", to_string(m_count)},
{"books", booksData }
};
return render_template(RESOURCE::templates::catalog_v2_entries_xml, template_data);
}
std::string OPDSDumper::dumpOPDSCompleteEntry(const std::string& bookId) const
{
const auto book = library->getBookById(bookId);
const std::string contentId = nameMapper->getNameForId(bookId);
return XML_HEADER
+ "\n"
+ fullEntryXML(book, rootLocation, contentAccessUrl, contentId);
}
std::string OPDSDumper::categoriesOPDSFeed() const
{
const auto now = gen_date_str();
kainjow::mustache::list categoryData = getCategoryData();
return render_template(
RESOURCE::templates::catalog_v2_categories_xml,
kainjow::mustache::object{
{"date", now},
{"endpoint_root", rootLocation + "/catalog/v2"},
{"feed_id", gen_uuid(libraryId + "/categories")},
{"categories", categoryData }
}
);
}
std::string OPDSDumper::languagesOPDSFeed() const
{
const auto now = gen_date_str();
kainjow::mustache::list languageData = getLanguageData();
return render_template(
RESOURCE::templates::catalog_v2_languages_xml,
kainjow::mustache::object{
{"date", now},
{"endpoint_root", rootLocation + "/catalog/v2"},
{"feed_id", gen_uuid(libraryId + "/languages")},
{"languages", languageData }
}
);
}
}
+91
View File
@@ -0,0 +1,91 @@
/*
* Copyright 2017 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef KIWIX_OPDS_DUMPER_H
#define KIWIX_OPDS_DUMPER_H
#include <time.h>
#include <sstream>
#include <string>
#include <pugixml.hpp>
#include "library.h"
#include "name_mapper.h"
#include "library_dumper.h"
using namespace std;
namespace kiwix
{
/**
* A tool to dump a `Library` into a opds stream.
*
*/
class OPDSDumper : public LibraryDumper
{
public:
OPDSDumper(const Library* library, const NameMapper* NameMapper);
~OPDSDumper();
/**
* Dump the OPDS feed.
*
* @param bookIds the ids of the books to include in the feed
* @param query the query used to obtain the list of book ids
* @return The OPDS feed.
*/
std::string dumpOPDSFeed(const std::vector<std::string>& bookIds, const std::string& query) const;
/**
* Dump the OPDS feed.
*
* @param bookIds the ids of the books to include in the feed
* @param query the query used to obtain the list of book ids
* @param partial whether the feed should include partial or complete entries
* @return The OPDS feed.
*/
std::string dumpOPDSFeedV2(const std::vector<std::string>& bookIds, const std::string& query, bool partial) const;
/**
* Dump the OPDS complete entry document.
*
* @param bookId the id of the book
* @return The OPDS complete entry document.
*/
std::string dumpOPDSCompleteEntry(const std::string& bookId) const;
/**
* Dump the categories OPDS feed.
*
* @return The OPDS feed.
*/
std::string categoriesOPDSFeed() const;
/**
* Dump the languages OPDS feed.
*
* @return The OPDS feed.
*/
std::string languagesOPDSFeed() const;
};
}
#endif // KIWIX_OPDS_DUMPER_H
-862
View File
@@ -1,862 +0,0 @@
/*
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "reader.h"
#include <time.h>
#include <zim/search.h>
inline char hi(char v)
{
char hex[] = "0123456789abcdef";
return hex[(v >> 4) & 0xf];
}
inline char lo(char v)
{
char hex[] = "0123456789abcdef";
return hex[v & 0xf];
}
std::string hexUUID(std::string in)
{
std::ostringstream out;
for (unsigned n = 0; n < 4; ++n) {
out << hi(in[n]) << lo(in[n]);
}
out << '-';
for (unsigned n = 4; n < 6; ++n) {
out << hi(in[n]) << lo(in[n]);
}
out << '-';
for (unsigned n = 6; n < 8; ++n) {
out << hi(in[n]) << lo(in[n]);
}
out << '-';
for (unsigned n = 8; n < 10; ++n) {
out << hi(in[n]) << lo(in[n]);
}
out << '-';
for (unsigned n = 10; n < 16; ++n) {
out << hi(in[n]) << lo(in[n]);
}
std::string op = out.str();
return op;
}
namespace kiwix
{
/* Constructor */
Reader::Reader(const string zimFilePath) : zimFileHandler(NULL)
{
string tmpZimFilePath = zimFilePath;
/* Remove potential trailing zimaa */
size_t found = tmpZimFilePath.rfind("zimaa");
if (found != string::npos && tmpZimFilePath.size() > 5
&& found == tmpZimFilePath.size() - 5) {
tmpZimFilePath.resize(tmpZimFilePath.size() - 2);
}
this->zimFileHandler = new zim::File(tmpZimFilePath);
if (this->zimFileHandler != NULL) {
this->firstArticleOffset
= this->zimFileHandler->getNamespaceBeginOffset('A');
this->lastArticleOffset = this->zimFileHandler->getNamespaceEndOffset('A');
this->nsACount = this->zimFileHandler->getNamespaceCount('A');
this->nsICount = this->zimFileHandler->getNamespaceCount('I');
this->zimFilePath = zimFilePath;
}
/* initialize random seed: */
srand(time(NULL));
}
/* Destructor */
Reader::~Reader()
{
if (this->zimFileHandler != NULL) {
delete this->zimFileHandler;
}
}
zim::File* Reader::getZimFileHandler() const
{
return this->zimFileHandler;
}
std::map<const std::string, unsigned int> Reader::parseCounterMetadata() const
{
std::map<const std::string, unsigned int> counters;
string mimeType, item, counterString;
unsigned int counter;
zim::Article article = this->zimFileHandler->getArticle('M', "Counter");
if (article.good()) {
stringstream ssContent(article.getData());
while (getline(ssContent, item, ';')) {
stringstream ssItem(item);
getline(ssItem, mimeType, '=');
getline(ssItem, counterString, '=');
if (!counterString.empty() && !mimeType.empty()) {
sscanf(counterString.c_str(), "%u", &counter);
counters.insert(pair<string, int>(mimeType, counter));
}
}
}
return counters;
}
/* Get the count of articles which can be indexed/displayed */
unsigned int Reader::getArticleCount() const
{
std::map<const std::string, unsigned int> counterMap
= this->parseCounterMetadata();
unsigned int counter = 0;
if (counterMap.empty()) {
counter = this->nsACount;
} else {
auto it = counterMap.find("text/html");
if (it != counterMap.end()) {
counter = it->second;
}
}
return counter;
}
/* Get the count of medias content in the ZIM file */
unsigned int Reader::getMediaCount() const
{
std::map<const std::string, unsigned int> counterMap
= this->parseCounterMetadata();
unsigned int counter = 0;
if (counterMap.empty()) {
counter = this->nsICount;
} else {
auto it = counterMap.find("image/jpeg");
if (it != counterMap.end()) {
counter += it->second;
}
it = counterMap.find("image/gif");
if (it != counterMap.end()) {
counter += it->second;
}
it = counterMap.find("image/png");
if (it != counterMap.end()) {
counter += it->second;
}
}
return counter;
}
/* Get the total of all items of a ZIM file, redirects included */
unsigned int Reader::getGlobalCount() const
{
return this->zimFileHandler->getCountArticles();
}
/* Return the UID of the ZIM file */
string Reader::getId() const
{
std::ostringstream s;
s << this->zimFileHandler->getFileheader().getUuid();
return s.str();
}
/* Return a page url from a title */
bool Reader::getPageUrlFromTitle(const string& title, string& url) const
{
try {
auto entry = getEntryFromTitle(title);
entry = entry.getFinalEntry();
url = entry.getPath();
return true;
} catch (NoEntry& e) {
return false;
}
}
/* Return an URL from a title */
string Reader::getRandomPageUrl() const
{
return getRandomPage().getPath();
}
Entry Reader::getRandomPage() const
{
if (!this->zimFileHandler) {
throw NoEntry();
}
zim::Article article;
std::string mainPagePath = this->getMainPage().getPath();
int watchdog = 42;
do {
auto idx = this->firstArticleOffset
+ (zim::size_type)((double)rand() / ((double)RAND_MAX + 1)
* this->nsACount);
article = zimFileHandler->getArticle(idx);
if (!watchdog--) {
throw NoEntry();
}
} while (!article.good() && article.getLongUrl() == mainPagePath);
return article;
}
/* Return the welcome page URL */
string Reader::getMainPageUrl() const
{
return getMainPage().getPath();
}
Entry Reader::getMainPage() const
{
if (!this->zimFileHandler) {
throw NoEntry();
}
string url = "";
zim::Article article;
if (this->zimFileHandler->getFileheader().hasMainPage())
{
article = zimFileHandler->getArticle(
this->zimFileHandler->getFileheader().getMainPage());
}
if (!article.good())
{
return getFirstPage();
}
return article;
}
bool Reader::getFavicon(string& content, string& mimeType) const
{
static const char* const paths[] = {"-/favicon.png", "I/favicon.png", "I/favicon", "-/favicon"};
for (auto &path: paths) {
try {
auto entry = getEntryFromPath(path);
entry = entry.getFinalEntry();
content = entry.getContent();
mimeType = entry.getMimetype();
return true;
} catch(NoEntry& e) {};
}
return false;
}
string Reader::getZimFilePath() const
{
return this->zimFilePath;
}
/* Return a metatag value */
bool Reader::getMetatag(const string& name, string& value) const
{
try {
auto entry = getEntryFromPath("M/"+name);
value = entry.getContent();
return true;
} catch(NoEntry& e) {
return false;
}
}
string Reader::getTitle() const
{
string value;
this->getMetatag("Title", value);
if (value.empty()) {
value = getLastPathElement(zimFileHandler->getFilename());
std::replace(value.begin(), value.end(), '_', ' ');
size_t pos = value.find(".zim");
value = value.substr(0, pos);
}
return value;
}
string Reader::getName() const
{
string value;
this->getMetatag("Name", value);
return value;
}
string Reader::getTags() const
{
string value;
this->getMetatag("Tags", value);
return value;
}
string Reader::getDescription() const
{
string value;
this->getMetatag("Description", value);
/* Mediawiki Collection tends to use the "Subtitle" name */
if (value.empty()) {
this->getMetatag("Subtitle", value);
}
return value;
}
string Reader::getLanguage() const
{
string value;
this->getMetatag("Language", value);
return value;
}
string Reader::getDate() const
{
string value;
this->getMetatag("Date", value);
return value;
}
string Reader::getCreator() const
{
string value;
this->getMetatag("Creator", value);
return value;
}
string Reader::getPublisher() const
{
string value;
this->getMetatag("Publisher", value);
return value;
}
string Reader::getOrigId() const
{
string value;
this->getMetatag("startfileuid", value);
if (value.empty()) {
return "";
}
std::string id = value;
std::string origID;
std::string temp = "";
unsigned int k = 0;
char tempArray[16] = "";
for (unsigned int i = 0; i < id.size(); i++) {
if (id[i] == '\n') {
tempArray[k] = atoi(temp.c_str());
temp = "";
k++;
} else {
temp += id[i];
}
}
origID = hexUUID(tempArray);
return origID;
}
/* Return the first page URL */
string Reader::getFirstPageUrl() const
{
return getFirstPage().getPath();
}
Entry Reader::getFirstPage() const
{
if (!this->zimFileHandler) {
throw NoEntry();
}
auto firstPageOffset = zimFileHandler->getNamespaceBeginOffset('A');
auto article = zimFileHandler->getArticle(firstPageOffset);
if (! article.good()) {
throw NoEntry();
}
return article;
}
bool _parseUrl(const string& url, char* ns, string& title)
{
/* Offset to visit the url */
unsigned int urlLength = url.size();
unsigned int offset = 0;
/* Ignore the first '/' */
if (url[offset] == '/')
offset++;
if (url[offset] == '/' || offset >= urlLength)
return false;
/* Get namespace */
*ns = url[offset++];
if (url[offset] != '/' || offset >= urlLength)
return false;
offset++;
if ( offset >= urlLength)
return false;
/* Get content title */
title = url.substr(offset, urlLength - offset);
return true;
}
bool Reader::parseUrl(const string& url, char* ns, string& title) const
{
return _parseUrl(url, ns, title);
}
Entry Reader::getEntryFromPath(const std::string& path) const
{
char ns = 0;
std::string short_url;
if (!this->zimFileHandler) {
throw NoEntry();
}
_parseUrl(path, &ns, short_url);
if (short_url.empty() && ns == 0) {
return getMainPage();
}
auto article = zimFileHandler->getArticle(ns, short_url);
if (!article.good()) {
throw NoEntry();
}
return article;
}
Entry Reader::getEntryFromEncodedPath(const std::string& path) const
{
return getEntryFromPath(urlDecode(path, true));
}
Entry Reader::getEntryFromTitle(const std::string& title) const
{
if (!this->zimFileHandler) {
throw NoEntry();
}
auto article = this->zimFileHandler->getArticleByTitle('A', title);
if (!article.good()) {
throw NoEntry();
}
return article;
}
/* Return article by url */
bool Reader::getArticleObjectByDecodedUrl(const string& url,
zim::Article& article) const
{
if (this->zimFileHandler == NULL) {
return false;
}
/* Parse the url */
char ns = 0;
string urlStr;
_parseUrl(url, &ns, urlStr);
/* Main page */
if (urlStr.empty() && ns == 0) {
_parseUrl(this->getMainPage().getPath(), &ns, urlStr);
}
/* Extract the content from the zim file */
article = zimFileHandler->getArticle(ns, urlStr);
return article.good();
}
/* Return the mimeType without the content */
bool Reader::getMimeTypeByUrl(const string& url, string& mimeType) const
{
try {
auto entry = getEntryFromPath(url);
mimeType = entry.getMimetype();
return true;
} catch (NoEntry& e) {
mimeType = "";
return false;
}
}
bool get_content_by_decoded_url(const Reader& reader,
const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType,
string& baseUrl)
{
content = "";
contentType = "";
contentLength = 0;
try {
auto entry = reader.getEntryFromPath(url);
entry = entry.getFinalEntry();
baseUrl = entry.getPath();
contentType = entry.getMimetype();
content = entry.getContent();
contentLength = entry.getSize();
title = entry.getTitle();
/* Try to set a stub HTML header/footer if necesssary */
if (contentType.find("text/html") != string::npos
&& content.find("<body") == std::string::npos
&& content.find("<BODY") == std::string::npos) {
content = "<html><head><title>" + title +
"</title><meta http-equiv=\"Content-Type\" content=\"text/html; "
"charset=utf-8\" /></head><body>" +
content + "</body></html>";
}
return true;
} catch (NoEntry& e) {
return false;
}
}
/* Get a content from a zim file */
bool Reader::getContentByUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType) const
{
std::string stubRedirectUrl;
return get_content_by_decoded_url(*this,
kiwix::urlDecode(url),
content,
title,
contentLength,
contentType,
stubRedirectUrl);
}
bool Reader::getContentByEncodedUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType,
string& baseUrl) const
{
return get_content_by_decoded_url(*this,
kiwix::urlDecode(url),
content,
title,
contentLength,
contentType,
baseUrl);
}
bool Reader::getContentByEncodedUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType) const
{
std::string stubRedirectUrl;
return get_content_by_decoded_url(*this,
kiwix::urlDecode(url),
content,
title,
contentLength,
contentType,
stubRedirectUrl);
}
bool Reader::getContentByDecodedUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType) const
{
std::string stubRedirectUrl;
return get_content_by_decoded_url(*this,
url,
content,
title,
contentLength,
contentType,
stubRedirectUrl);
}
bool Reader::getContentByDecodedUrl(const string& url,
string& content,
string& title,
unsigned int& contentLength,
string& contentType,
string& baseUrl) const
{
return get_content_by_decoded_url(*this,
url,
content,
title,
contentLength,
contentType,
baseUrl);
}
/* Check if an article exists */
bool Reader::urlExists(const string& url) const
{
return pathExists(url);
}
bool Reader::pathExists(const string& path) const
{
if (!zimFileHandler)
{
return false;
}
char ns = 0;
string titleStr;
_parseUrl(path, &ns, titleStr);
zim::File::const_iterator findItr = zimFileHandler->find(ns, titleStr);
return findItr != zimFileHandler->end() && findItr->getUrl() == titleStr;
}
/* Does the ZIM file has a fulltext index */
bool Reader::hasFulltextIndex() const
{
if (!zimFileHandler || zimFileHandler->is_multiPart() )
{
return false;
}
return ( pathExists("Z//fulltextIndex/xapian")
|| pathExists("X/fulltext/xapian"));
}
/* Search titles by prefix */
bool Reader::searchSuggestions(const string& prefix,
unsigned int suggestionsCount,
const bool reset)
{
bool retVal = false;
zim::File::const_iterator articleItr;
/* Reset the suggestions otherwise check if the suggestions number is less
* than the suggestionsCount */
if (reset) {
this->suggestions.clear();
this->suggestionsOffset = this->suggestions.begin();
} else {
if (this->suggestions.size() > suggestionsCount) {
return false;
}
}
/* Return if no prefix */
if (prefix.size() == 0) {
return false;
}
for (articleItr = zimFileHandler->findByTitle('A', prefix);
articleItr != zimFileHandler->end()
&& articleItr->getTitle().compare(0, prefix.size(), prefix) == 0
&& this->suggestions.size() < suggestionsCount;
++articleItr) {
/* Extract the interesting part of article title & url */
std::string normalizedArticleTitle
= kiwix::normalize(articleItr->getTitle());
std::string articleFinalUrl = "/A/" + articleItr->getUrl();
if (articleItr->isRedirect()) {
zim::Article article = *articleItr;
unsigned int loopCounter = 0;
while (article.isRedirect() && loopCounter++ < 42) {
article = article.getRedirectArticle();
}
articleFinalUrl = "/A/" + article.getUrl();
}
/* Go through all already found suggestions and skip if this
article is already in the suggestions list (with an other
title) */
bool insert = true;
std::vector<std::vector<std::string>>::iterator suggestionItr;
for (suggestionItr = this->suggestions.begin();
suggestionItr != this->suggestions.end();
suggestionItr++) {
int result = normalizedArticleTitle.compare((*suggestionItr)[2]);
if (result == 0 && articleFinalUrl.compare((*suggestionItr)[1]) == 0) {
insert = false;
break;
} else if (result < 0) {
break;
}
}
/* Insert if possible */
if (insert) {
std::vector<std::string> suggestion;
suggestion.push_back(articleItr->getTitle());
suggestion.push_back(articleFinalUrl);
suggestion.push_back(normalizedArticleTitle);
this->suggestions.insert(suggestionItr, suggestion);
}
/* Suggestions where found */
retVal = true;
}
/* Set the cursor to the begining */
this->suggestionsOffset = this->suggestions.begin();
return retVal;
}
std::vector<std::string> Reader::getTitleVariants(
const std::string& title) const
{
std::vector<std::string> variants;
variants.push_back(title);
variants.push_back(kiwix::ucFirst(title));
variants.push_back(kiwix::lcFirst(title));
variants.push_back(kiwix::toTitle(title));
return variants;
}
/* Try also a few variations of the prefix to have better results */
bool Reader::searchSuggestionsSmart(const string& prefix,
unsigned int suggestionsCount)
{
std::vector<std::string> variants = this->getTitleVariants(prefix);
bool retVal;
this->suggestions.clear();
this->suggestionsOffset = this->suggestions.begin();
/* Try to search in the title using fulltext search database */
const zim::Search* suggestionSearch
= this->getZimFileHandler()->suggestions(prefix, 0, suggestionsCount);
if (suggestionSearch->get_matches_estimated()) {
for (auto current = suggestionSearch->begin();
current != suggestionSearch->end();
current++) {
std::vector<std::string> suggestion;
suggestion.push_back(current->getTitle());
suggestion.push_back("/A/" + current->getUrl());
suggestion.push_back(kiwix::normalize(current->getTitle()));
this->suggestions.push_back(suggestion);
}
this->suggestionsOffset = this->suggestions.begin();
retVal = true;
} else {
for (std::vector<std::string>::iterator variantsItr = variants.begin();
variantsItr != variants.end();
variantsItr++) {
retVal = this->searchSuggestions(*variantsItr, suggestionsCount, false)
|| retVal;
}
}
return retVal;
}
/* Get next suggestion */
bool Reader::getNextSuggestion(string& title)
{
if (this->suggestionsOffset != this->suggestions.end()) {
/* title */
title = (*(this->suggestionsOffset))[0];
/* increment the cursor for the next call */
this->suggestionsOffset++;
return true;
}
return false;
}
bool Reader::getNextSuggestion(string& title, string& url)
{
if (this->suggestionsOffset != this->suggestions.end()) {
/* title */
title = (*(this->suggestionsOffset))[0];
url = (*(this->suggestionsOffset))[1];
/* increment the cursor for the next call */
this->suggestionsOffset++;
return true;
}
return false;
}
/* Check if the file has as checksum */
bool Reader::canCheckIntegrity() const
{
return this->zimFileHandler->getChecksum() != "";
}
/* Return true if corrupted, false otherwise */
bool Reader::isCorrupted() const
{
try {
if (this->zimFileHandler->verify() == true) {
return false;
}
} catch (exception& e) {
cerr << e.what() << endl;
return true;
}
return true;
}
/* Return the file size, works also for splitted files */
unsigned int Reader::getFileSize() const
{
zim::File* file = this->getZimFileHandler();
zim::offset_type size = 0;
if (file != NULL) {
size = file->getFilesize();
}
return (size / 1024);
}
}
+275
View File
@@ -0,0 +1,275 @@
/*
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <cmath>
#include "search_renderer.h"
#include "library.h"
#include "name_mapper.h"
#include "tools/archiveTools.h"
#include <zim/search.h>
#include <mustache.hpp>
#include "libkiwix-resources.h"
#include "tools/stringTools.h"
#include "server/i18n_utils.h"
namespace kiwix
{
namespace
{
ParameterizedMessage searchResultsPageTitleMsg(const std::string& searchPattern)
{
return ParameterizedMessage("search-results-page-title",
{{"SEARCH_PATTERN", searchPattern}}
);
}
ParameterizedMessage searchResultsPageHeaderMsg(const std::string& searchPattern,
const kainjow::mustache::data& r)
{
if ( r.get("count")->string_value() == "0" ) {
return ParameterizedMessage("empty-search-results-page-header",
{{"SEARCH_PATTERN", searchPattern}}
);
} else {
return ParameterizedMessage("search-results-page-header",
{
{"SEARCH_PATTERN", searchPattern},
{"START", r.get("startLabel")->string_value()},
{"END", r.get("end") ->string_value()},
{"COUNT", r.get("count")->string_value()},
}
);
}
}
} // unnamed namespace
/* Constructor */
SearchRenderer::SearchRenderer(zim::SearchResultSet srs,
unsigned int start, unsigned int estimatedResultCount)
: m_srs(srs),
protocolPrefix("zim://"),
searchProtocolPrefix("search://"),
estimatedResultCount(estimatedResultCount),
resultStart(start)
{}
/* Destructor */
SearchRenderer::~SearchRenderer() = default;
void SearchRenderer::setSearchPattern(const std::string& pattern)
{
searchPattern = pattern;
}
void SearchRenderer::setSearchBookQuery(const std::string& bookQuery)
{
searchBookQuery = bookQuery;
}
void SearchRenderer::setProtocolPrefix(const std::string& prefix)
{
this->protocolPrefix = prefix;
}
void SearchRenderer::setSearchProtocolPrefix(const std::string& prefix)
{
this->searchProtocolPrefix = prefix;
}
std::string extractValueFromQuery(const std::string& query, const std::string& key) {
const std::string p = key + "=";
const size_t i = query.find(p);
if (i == std::string::npos) {
return "";
}
std::string r = query.substr(i + p.size());
return r.substr(0, r.find("&"));
}
kainjow::mustache::data buildQueryData
(
const std::string& searchProtocolPrefix,
const std::string& pattern,
const std::string& bookQuery
) {
kainjow::mustache::data query;
query.set("pattern", kiwix::encodeDiples(pattern));
std::ostringstream ss;
ss << searchProtocolPrefix << "?pattern=" << urlEncode(pattern);
ss << "&" << bookQuery;
query.set("unpaginatedQuery", ss.str());
auto lang = extractValueFromQuery(bookQuery, "books.filter.lang");
if(!lang.empty()) {
query.set("lang", lang);
}
return query;
}
kainjow::mustache::data buildPagination(
unsigned int pageLength,
unsigned int resultsCount,
unsigned int resultsStart
)
{
assert(pageLength!=0);
kainjow::mustache::data pagination;
kainjow::mustache::data pages{kainjow::mustache::data::type::list};
if (resultsCount == 0) {
// Easy case
pagination.set("itemsPerPage", to_string(pageLength));
pagination.set("hasPages", false);
pagination.set("pages", pages);
return pagination;
}
// First we want to display pages starting at a multiple of `pageLength`
// so, let's calculate the start index of the current page.
auto currentPage = resultsStart/pageLength;
auto lastPage = ((resultsCount-1)/pageLength);
auto lastPageStart = lastPage*pageLength;
auto nbPages = lastPage + 1;
auto firstPageGenerated = currentPage > 4 ? currentPage-4 : 0;
auto lastPageGenerated = std::min(currentPage+4, lastPage);
if (nbPages != 1) {
if (firstPageGenerated!=0) {
kainjow::mustache::data page;
page.set("label", "");
page.set("start", to_string(0));
page.set("current", false);
pages.push_back(page);
}
for (auto i=firstPageGenerated; i<=lastPageGenerated; i++) {
kainjow::mustache::data page;
page.set("label", to_string(i+1));
page.set("start", to_string(i*pageLength));
page.set("current", bool(i == currentPage));
pages.push_back(page);
}
if (lastPageGenerated!=lastPage) {
kainjow::mustache::data page;
page.set("label", "");
page.set("start", to_string(lastPageStart));
page.set("current", false);
pages.push_back(page);
}
}
pagination.set("itemsPerPage", to_string(pageLength));
pagination.set("hasPages", firstPageGenerated < lastPageGenerated);
pagination.set("pages", pages);
return pagination;
}
std::string SearchRenderer::renderTemplate(const std::string& tmpl_str, const NameMapper& nameMapper, const Library* library)
{
const std::string absPathPrefix = protocolPrefix;
// Build the results list
kainjow::mustache::data items{kainjow::mustache::data::type::list};
for (auto it = m_srs.begin(); it != m_srs.end(); it++) {
kainjow::mustache::data result;
const std::string zim_id(it.getZimId());
const auto path = nameMapper.getNameForId(zim_id) + "/" + it.getPath();
result.set("title", it.getTitle());
result.set("absolutePath", absPathPrefix + urlEncode(path));
result.set("snippet", it.getSnippet());
if (library) {
const std::string bookTitle = library->getBookById(zim_id).getTitle();
const ParameterizedMessage bookInfoMsg("search-result-book-info",
{{"BOOK_TITLE", bookTitle}}
);
result.set("bookInfo", bookInfoMsg.getText(userlang)); // for HTML
result.set("bookTitle", bookTitle); // for XML
}
if (it.getWordCount() >= 0) {
const auto wordCountStr = kiwix::beautifyInteger(it.getWordCount());
const ParameterizedMessage wordCountMsg("word-count",
{{"COUNT", wordCountStr}}
);
result.set("wordCountInfo", wordCountMsg.getText(userlang)); // for HTML
result.set("wordCount", wordCountStr); // for XML
}
items.push_back(result);
}
kainjow::mustache::data results;
results.set("items", items);
results.set("count", kiwix::beautifyInteger(estimatedResultCount));
results.set("start", kiwix::beautifyInteger(resultStart));
results.set("startLabel", kiwix::beautifyInteger(resultStart+1));
results.set("end", kiwix::beautifyInteger(std::min(resultStart+pageLength, estimatedResultCount)));
// pagination
auto pagination = buildPagination(
pageLength,
estimatedResultCount,
resultStart
);
kainjow::mustache::data query = buildQueryData(
searchProtocolPrefix,
searchPattern,
searchBookQuery
);
const auto pageHeaderMsg = searchResultsPageHeaderMsg(searchPattern, results);
const kainjow::mustache::object allData{
{"PAGE_TITLE", searchResultsPageTitleMsg(searchPattern).getText(userlang)},
{"PAGE_HEADER", pageHeaderMsg.getText(userlang)},
{"searchProtocolPrefix", searchProtocolPrefix},
{"results", results},
{"pagination", pagination},
{"query", query},
};
kainjow::mustache::mustache tmpl(tmpl_str);
std::stringstream ss;
tmpl.render(allData, [&ss](const std::string& str) { ss << str; });
if (!tmpl.is_valid()) {
throw std::runtime_error("Error while rendering search results: " + tmpl.error_message());
}
return ss.str();
}
std::string SearchRenderer::getHtml(const NameMapper& mapper, const Library* library)
{
return renderTemplate(RESOURCE::templates::search_result_html, mapper, library);
}
std::string SearchRenderer::getXml(const NameMapper& mapper, const Library* library)
{
return renderTemplate(RESOURCE::templates::search_result_xml, mapper, library);
}
}
-465
View File
@@ -1,465 +0,0 @@
/*
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <cmath>
#include "searcher.h"
#include "reader.h"
#include "xapianSearcher.h"
#include <zim/search.h>
#ifdef ENABLE_CTPP2
#include <ctpp2/CDT.hpp>
#include <ctpp2/CTPP2FileLogger.hpp>
#include <ctpp2/CTPP2SimpleVM.hpp>
#include "ctpp2/CTPP2VMStringLoader.hpp"
#include "kiwixlib-resources.h"
using namespace CTPP;
#endif
#define MAX_SEARCH_LEN 140
namespace kiwix
{
class _Result : public Result
{
public:
_Result(zim::Search::iterator& iterator);
virtual ~_Result(){};
virtual std::string get_url();
virtual std::string get_title();
virtual int get_score();
virtual std::string get_snippet();
virtual std::string get_content();
virtual int get_wordCount();
virtual int get_size();
virtual int get_readerIndex();
private:
zim::Search::iterator iterator;
};
struct SearcherInternal {
const zim::Search* _search;
XapianSearcher* _xapianSearcher;
zim::Search::iterator current_iterator;
SearcherInternal() : _search(NULL), _xapianSearcher(NULL) {}
~SearcherInternal()
{
if (_search != NULL) {
delete _search;
}
if (_xapianSearcher != NULL) {
delete _xapianSearcher;
}
}
};
/* Constructor */
Searcher::Searcher(const string& xapianDirectoryPath,
Reader* reader,
const string& humanReadableName)
: internal(new SearcherInternal()),
searchPattern(""),
protocolPrefix("zim://"),
searchProtocolPrefix("search://?"),
resultCountPerPage(0),
estimatedResultCount(0),
resultStart(0),
resultEnd(0),
contentHumanReadableId(humanReadableName)
{
loadICUExternalTables();
if (!reader || !reader->hasFulltextIndex()) {
internal->_xapianSearcher = new XapianSearcher(xapianDirectoryPath, reader);
}
this->humanReaderNames.push_back(humanReadableName);
}
Searcher::Searcher(const std::string& humanReadableName)
: internal(new SearcherInternal()),
searchPattern(""),
protocolPrefix("zim://"),
searchProtocolPrefix("search://?"),
resultCountPerPage(0),
estimatedResultCount(0),
resultStart(0),
resultEnd(0),
contentHumanReadableId(humanReadableName)
{
loadICUExternalTables();
}
/* Destructor */
Searcher::~Searcher()
{
delete internal;
}
bool Searcher::add_reader(Reader* reader, const std::string& humanReadableName)
{
if (!reader->hasFulltextIndex()) {
return false;
}
this->readers.push_back(reader);
this->humanReaderNames.push_back(humanReadableName);
return true;
}
/* Search strings in the database */
void Searcher::search(std::string& search,
unsigned int resultStart,
unsigned int resultEnd,
const bool verbose)
{
this->reset();
if (verbose == true) {
cout << "Performing query `" << search << "'" << endl;
}
/* If resultEnd & resultStart inverted */
if (resultStart > resultEnd) {
resultEnd += resultStart;
resultStart = resultEnd - resultStart;
resultEnd -= resultStart;
}
/* Try to find results */
if (resultStart != resultEnd) {
/* Avoid big researches */
this->resultCountPerPage = resultEnd - resultStart;
if (this->resultCountPerPage > MAX_SEARCH_LEN) {
resultEnd = resultStart + MAX_SEARCH_LEN;
this->resultCountPerPage = MAX_SEARCH_LEN;
}
/* Perform the search */
this->searchPattern = search;
this->resultStart = resultStart;
this->resultEnd = resultEnd;
string unaccentedSearch = removeAccents(search);
if (internal->_xapianSearcher) {
internal->_xapianSearcher->searchInIndex(
unaccentedSearch, resultStart, resultEnd, verbose);
this->estimatedResultCount
= internal->_xapianSearcher->results.get_matches_estimated();
} else {
std::vector<const zim::File*> zims;
for (auto current = this->readers.begin(); current != this->readers.end();
current++) {
if ( (*current)->hasFulltextIndex() ) {
zims.push_back((*current)->getZimFileHandler());
}
}
zim::Search* search = new zim::Search(zims);
search->set_query(unaccentedSearch);
search->set_range(resultStart, resultEnd);
internal->_search = search;
internal->current_iterator = internal->_search->begin();
this->estimatedResultCount = internal->_search->get_matches_estimated();
}
}
return;
}
void Searcher::geo_search(float latitude, float longitude, float distance,
unsigned int resultStart,
unsigned int resultEnd,
const bool verbose)
{
this->reset();
if (verbose == true) {
cout << "Performing geo query `" << distance << "&(" << latitude << ";" << longitude << ")'" << endl;
}
/* If resultEnd & resultStart inverted */
if (resultStart > resultEnd) {
resultEnd += resultStart;
resultStart = resultEnd - resultStart;
resultEnd -= resultStart;
}
/* Try to find results */
if (resultStart == resultEnd) {
return;
}
if (internal->_xapianSearcher) {
return;
}
/* Avoid big researches */
this->resultCountPerPage = resultEnd - resultStart;
if (this->resultCountPerPage > MAX_SEARCH_LEN) {
resultEnd = resultStart + MAX_SEARCH_LEN;
this->resultCountPerPage = MAX_SEARCH_LEN;
}
/* Perform the search */
std::ostringstream oss;
oss << "Articles located less than " << distance << " meters of " << latitude << ";" << longitude;
this->searchPattern = oss.str();
this->resultStart = resultStart;
this->resultEnd = resultEnd;
std::vector<const zim::File*> zims;
for (auto current = this->readers.begin(); current != this->readers.end();
current++) {
zims.push_back((*current)->getZimFileHandler());
}
zim::Search* search = new zim::Search(zims);
search->set_query("");
search->set_georange(latitude, longitude, distance);
search->set_range(resultStart, resultEnd);
internal->_search = search;
internal->current_iterator = internal->_search->begin();
this->estimatedResultCount = internal->_search->get_matches_estimated();
}
void Searcher::restart_search()
{
if (internal->_xapianSearcher) {
internal->_xapianSearcher->restart_search();
} else if (internal->_search) {
internal->current_iterator = internal->_search->begin();
}
}
Result* Searcher::getNextResult()
{
if (internal->_xapianSearcher) {
return internal->_xapianSearcher->getNextResult();
} else if (internal->_search &&
internal->current_iterator != internal->_search->end()) {
Result* result = new _Result(internal->current_iterator);
internal->current_iterator++;
return result;
}
return NULL;
}
/* Reset the results */
void Searcher::reset()
{
this->estimatedResultCount = 0;
this->searchPattern = "";
return;
}
void Searcher::suggestions(std::string& search, const bool verbose)
{
this->reset();
if (verbose == true) {
cout << "Performing suggestion query `" << search << "`" << endl;
}
this->searchPattern = search;
this->resultStart = 0;
this->resultEnd = 10;
string unaccentedSearch = removeAccents(search);
if (internal->_xapianSearcher) {
/* [TODO] Suggestion on a external database ?
* We do not support that. */
this->estimatedResultCount = 0;
} else {
std::vector<const zim::File*> zims;
for (auto current = this->readers.begin(); current != this->readers.end();
current++) {
zims.push_back((*current)->getZimFileHandler());
}
zim::Search* search = new zim::Search(zims);
search->set_query(unaccentedSearch);
search->set_range(resultStart, resultEnd);
search->set_suggestion_mode(true);
internal->_search = search;
internal->current_iterator = internal->_search->begin();
this->estimatedResultCount = internal->_search->get_matches_estimated();
}
}
/* Return the result count estimation */
unsigned int Searcher::getEstimatedResultCount()
{
return this->estimatedResultCount;
}
bool Searcher::setProtocolPrefix(const std::string prefix)
{
this->protocolPrefix = prefix;
return true;
}
bool Searcher::setSearchProtocolPrefix(const std::string prefix)
{
this->searchProtocolPrefix = prefix;
return true;
}
_Result::_Result(zim::Search::iterator& iterator)
: iterator(iterator)
{
}
std::string _Result::get_url()
{
return iterator.get_url();
}
std::string _Result::get_title()
{
return iterator.get_title();
}
int _Result::get_score()
{
return iterator.get_score();
}
std::string _Result::get_snippet()
{
return iterator.get_snippet();
}
std::string _Result::get_content()
{
if (iterator->good()) {
return iterator->getData();
}
return "";
}
int _Result::get_size()
{
return iterator.get_size();
}
int _Result::get_wordCount()
{
return iterator.get_wordCount();
}
int _Result::get_readerIndex()
{
return iterator.get_fileIndex();
}
#ifdef ENABLE_CTPP2
string Searcher::getHtml()
{
SimpleVM oSimpleVM(
1024, //iIMaxFunctions (default value)
4096, //iIMaxArgStackSize (default value)
4096, //iIMaxCodeStackSize (default value)
10240 * 2 //iIMaxSteps (default*2)
);
// Fill data
CDT oData;
CDT resultsCDT(CDT::ARRAY_VAL);
this->restart_search();
Result* p_result = NULL;
while ((p_result = this->getNextResult())) {
CDT result;
result["title"] = p_result->get_title();
result["url"] = p_result->get_url();
result["snippet"] = p_result->get_snippet();
result["contentId"] = humanReaderNames[p_result->get_readerIndex()];
if (p_result->get_size() >= 0) {
result["size"] = kiwix::beautifyInteger(p_result->get_size());
}
if (p_result->get_wordCount() >= 0) {
result["wordCount"] = kiwix::beautifyInteger(p_result->get_wordCount());
}
resultsCDT.PushBack(result);
delete p_result;
}
this->restart_search();
oData["results"] = resultsCDT;
// pages
CDT pagesCDT(CDT::ARRAY_VAL);
unsigned int pageStart
= this->resultStart / this->resultCountPerPage >= 5
? this->resultStart / this->resultCountPerPage - 4
: 0;
unsigned int pageCount
= this->estimatedResultCount / this->resultCountPerPage + 1 - pageStart;
if (pageCount > 10) {
pageCount = 10;
} else if (pageCount == 1) {
pageCount = 0;
}
for (unsigned int i = pageStart; i < pageStart + pageCount; i++) {
CDT page;
page["label"] = i + 1;
page["start"] = i * this->resultCountPerPage;
page["end"] = (i + 1) * this->resultCountPerPage;
if (i * this->resultCountPerPage == this->resultStart) {
page["selected"] = true;
}
pagesCDT.PushBack(page);
}
oData["pages"] = pagesCDT;
oData["count"] = kiwix::beautifyInteger(this->estimatedResultCount);
oData["searchPattern"] = kiwix::encodeDiples(this->searchPattern);
oData["searchPatternEncoded"] = urlEncode(this->searchPattern);
oData["resultStart"] = this->resultStart + 1;
oData["resultEnd"] = (this->resultEnd > this->estimatedResultCount
? this->estimatedResultCount
: this->resultEnd);
oData["resultRange"] = this->resultCountPerPage;
oData["resultLastPageStart"]
= this->estimatedResultCount > this->resultCountPerPage
? std::round(this->estimatedResultCount / this->resultCountPerPage) * this->resultCountPerPage
: 0;
oData["protocolPrefix"] = this->protocolPrefix;
oData["searchProtocolPrefix"] = this->searchProtocolPrefix;
oData["contentId"] = this->contentHumanReadableId;
std::string template_ct2 = RESOURCE::results_ct2;
VMStringLoader oLoader(template_ct2.c_str(), template_ct2.size());
FileLogger oLogger(stderr);
// DEBUG only (write output to stdout)
// oSimpleVM.Run(oData, oLoader, stdout, oLogger);
std::string sResult;
oSimpleVM.Run(oData, oLoader, sResult, oLogger);
return sResult;
}
#endif
}
+143
View File
@@ -0,0 +1,143 @@
/*
* Copyright 2019 Matthieu Gautier <mgautier@kymeria.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "server.h"
#include "library.h"
#include "name_mapper.h"
#include <string>
#include <zim/item.h>
#include "server/internalServer.h"
namespace kiwix {
namespace
{
std::string makeServerUrl(std::string host, int port, std::string root)
{
const int httpDefaultPort = 80;
if (port == httpDefaultPort) {
return "http://" + host + root;
} else {
return "http://" + host + ":" + std::to_string(port) + root;
}
}
} // unnamed namespace
Server::Server(LibraryPtr library, std::shared_ptr<NameMapper> nameMapper) :
mp_library(library),
mp_nameMapper(nameMapper),
mp_server(nullptr)
{
}
Server::~Server() = default;
bool Server::start() {
mp_server.reset(new InternalServer(
mp_library,
mp_nameMapper,
m_addr,
m_port,
m_root,
m_nbThreads,
m_multizimSearchLimit,
m_verbose,
m_withTaskbar,
m_withLibraryButton,
m_blockExternalLinks,
m_ipMode,
m_indexTemplateString,
m_ipConnectionLimit,
m_catalogOnlyMode,
m_contentServerUrl));
if (mp_server->start()) {
// this syncs m_addr of InternalServer and Server as they may diverge
m_addr = mp_server->getAddress();
return true;
} else {
return false;
}
}
void Server::stop() {
if (mp_server) {
mp_server->stop();
mp_server.reset(nullptr);
}
}
void Server::setRoot(const std::string& root)
{
m_root = root;
while (!m_root.empty() && m_root.back() == '/')
m_root.pop_back();
while (!m_root.empty() && m_root.front() == '/')
m_root = m_root.substr(1);
m_root = m_root.empty() ? m_root : "/" + m_root;
}
void Server::setAddress(const std::string& addr)
{
m_addr.addr.clear();
m_addr.addr6.clear();
if (addr.empty()) return;
if (addr.find(':') != std::string::npos) { // IPv6
m_addr.addr6 = (addr[0] == '[') ? addr.substr(1, addr.length() - 2) : addr; // Remove brackets if any
} else {
m_addr.addr = addr;
}
}
int Server::getPort() const
{
return m_port;
}
IpAddress Server::getAddress() const
{
return m_addr;
}
IpMode Server::getIpMode() const
{
return mp_server->getIpMode();
}
std::vector<std::string> Server::getServerAccessUrls() const
{
std::vector<std::string> result;
if (!m_addr.addr.empty()) {
result.push_back(makeServerUrl(m_addr.addr, m_port, m_root));
}
if (!m_addr.addr6.empty()) {
result.push_back(makeServerUrl("[" + m_addr.addr6 + "]", m_port, m_root));
}
return result;
}
}
+127
View File
@@ -0,0 +1,127 @@
/*
* Copyright 2020 Veloman Yunkan <veloman.yunkan@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "byte_range.h"
#include "tools/stringTools.h"
#include <cassert>
#include <algorithm>
namespace kiwix {
namespace {
ByteRange parseByteRange(const std::string& rangeStr)
{
std::istringstream iss(rangeStr);
int64_t start, end = INT64_MAX;
if (iss >> start) {
if ( start < 0 ) {
if ( iss.eof() )
return ByteRange(-start);
} else {
char c;
if (iss >> c && c=='-') {
iss >> end; // if this fails, end is not modified, which is OK
if (iss.eof() && start <= end)
return ByteRange(ByteRange::PARSED, start, end);
}
}
}
return ByteRange(ByteRange::INVALID, 0, INT64_MAX);
}
} // unnamed namespace
ByteRange::ByteRange()
: kind_(NONE)
, first_(0)
, last_(INT64_MAX)
{}
ByteRange::ByteRange(Kind kind, int64_t first, int64_t last)
: kind_(kind)
, first_(first)
, last_(last)
{
assert(kind != NONE);
assert(first >= 0);
assert(last >= first || (first == 0 && last == -1));
}
ByteRange::ByteRange(int64_t suffix_length)
: kind_(PARSED)
, first_(-suffix_length)
, last_(INT64_MAX)
{
assert(suffix_length > 0);
}
int64_t ByteRange::first() const
{
assert(kind_ > PARSED);
return first_;
}
int64_t ByteRange::last() const
{
assert(kind_ > PARSED);
return last_;
}
int64_t ByteRange::length() const
{
assert(kind_ > PARSED);
return last_ + 1 - first_;
}
ByteRange ByteRange::parse(const std::string& rangeStr)
{
const std::string byteUnitSpec("bytes=");
if ( ! kiwix::startsWith(rangeStr, byteUnitSpec) )
return ByteRange(INVALID, 0, INT64_MAX);
return parseByteRange(rangeStr.substr(byteUnitSpec.size()));
}
ByteRange ByteRange::resolve(int64_t contentSize) const
{
if ( kind() == NONE )
return ByteRange(RESOLVED_FULL_CONTENT, 0, contentSize-1);
if ( kind() == INVALID )
return ByteRange(RESOLVED_UNSATISFIABLE, 0, contentSize-1);
const int64_t resolved_first = first_ < 0
? std::max(int64_t(0), contentSize + first_)
: first_;
const int64_t resolved_last = std::min(contentSize-1, last_);
if ( resolved_first > resolved_last )
return ByteRange(RESOLVED_UNSATISFIABLE, 0, contentSize-1);
return ByteRange(RESOLVED_PARTIAL_CONTENT, resolved_first, resolved_last);
}
} // namespace kiwix
Loaded 100 of 662 files, more files were not shown because too many files have changed in this diff. Show more