Compare commits

...

2375 Commits

Author SHA1 Message Date
Nikhil Tanwar
42a2ce2534 fixup! fixup! fixup! fixup! Introduce Manager::addBooksFromDirectory() 2025-11-30 20:05:44 +01:00
Nikhil Tanwar
3945dda5d0 fixup! fixup! fixup! Introduce Manager::addBooksFromDirectory() 2025-11-30 20:05:44 +01:00
Nikhil Tanwar
d65dd859da fixup! fixup! Introduce Manager::addBooksFromDirectory() 2025-11-30 20:05:44 +01:00
Nikhil Tanwar
d94d2c1e8a Remove skipInvalid flag
skipInvalid=false makes little sense, if an invalid book is found, we can simply choose to ignore it rather stopping the whole operation midway.
2025-11-30 20:05:44 +01:00
Nikhil Tanwar
a20b135f80 fixup! Introduce Manager::addBooksFromDirectory() 2025-11-30 20:05:44 +01:00
Nikhil Tanwar
6d520a8aa7 Introduce Manager::addBooksFromDirectory()
Added a function to load books from a directory. Requires rootPath to iterate over.
2025-11-30 20:05:44 +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](e4a4b2f961)
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
Matthieu Gautier
9fa7d78ba1 Merge pull request #176 from kiwix/win_relpath
Win relpath
2018-11-03 12:33:14 +01:00
Matthieu Gautier
57d3552b97 New version 3.0.2 2018-11-03 12:20:13 +01:00
Matthieu Gautier
d4ecda40ff Use the correct separator when computing relativePath. 2018-11-03 12:18:54 +01:00
Matthieu Gautier
802df71410 Merge pull request #175 from kiwix/fix
Fix
2018-11-02 17:32:22 +01:00
Matthieu Gautier
4d904c4d8b New version 3.0.1 2018-11-02 17:10:05 +01:00
Matthieu Gautier
9ab44e6a5f Get information about the total number of book of a search.
When we do a search and paging the result, we need to display to the
user the total number of book, not only the `itemsPerPage`.

So, we need to parse correctly the xml to keep information of the total
number of book.
2018-11-02 17:04:55 +01:00
Matthieu Gautier
5f4c04e79e Fix use of getAsI when parsing download rpc.
The value is store as a string in in the xml, so we cannot use getAsI.
We have to get the string and parse it to an int.
We cannot use strtoull because android stdc++ lib doesn't have it.

We have to implement our how parseFromString function using a
istringstream.
2018-11-02 17:03:03 +01:00
Matthieu Gautier
360c913230 Merge pull request #174 from kiwix/new_version
New version 3.0.0
2018-10-31 14:47:48 +01:00
Matthieu Gautier
a60ffe78d5 New version 3.0.0 2018-10-31 14:35:22 +01:00
Matthieu Gautier
b977b08683 Merge pull request #173 from kiwix/subprocess_windows
Subprocess windows
2018-10-31 14:04:21 +01:00
Matthieu Gautier
bb07ff5610 Do not add NULL at end of commandLine on Windows. 2018-10-31 13:56:42 +01:00
Matthieu Gautier
1787e30440 Better launch of the aria2 process.
By setting the ApplicationName to NULL, CreateProcessW will
search for the application in the path.
2018-10-31 13:56:42 +01:00
Matthieu Gautier
ccb3d8639d Use correct name for aria2c on windows. 2018-10-30 18:43:30 +01:00
Matthieu Gautier
5ed095531e Correctly set pkgconfig file for static curl linking. 2018-10-30 12:59:30 +01:00
Matthieu Gautier
29e554b47b Include pthread 2018-10-29 14:30:35 +01:00
Matthieu Gautier
68dc4d40b5 Include windows.h before synchapi.h 2018-10-29 12:20:00 +01:00
Matthieu Gautier
8dbc34e9ae Merge pull request #172 from kiwix/alpha2toalpha3
Alpha2toalpha3
2018-10-26 14:27:55 +02:00
Matthieu Gautier
2682fa8f9c Remove unecessary variable or output. 2018-10-26 14:19:10 +02:00
Matthieu Gautier
a22f962722 Correctly store the size of the book in the library.
`reader.getFileSize()` return ko.
2018-10-26 14:18:40 +02:00
Matthieu Gautier
a1876e3b27 Add a method converta2toa3 to convert language code alpha2 to alpha3.
Qt give use alpha2 language code but we use alpha3.
2018-10-26 14:18:06 +02:00
Matthieu Gautier
50b7e5664a Merge pull request #171 from kiwix/remoteContentManager
Remote content manager
2018-10-24 16:48:52 +02:00
Matthieu Gautier
ad654ead08 Do not force the download port to be 80.
We may want to use url with port != 80.
2018-10-24 11:56:38 +02:00
Matthieu Gautier
c6206edfb4 Do not always download the favicon of a book. Download as needed.
When parsing a opds feed, the favicon is a url, not a dataurl.
If we download the favicon all the times, it may take a lot of time to
parse the feed.

We store the url and download the favicon only when needed (when displayed)
2018-10-24 11:56:05 +02:00
Matthieu Gautier
c20ae18bff An opds feed can also be the openSearch result.
We must be able to set the correct entry in the feed for a searchResult.
2018-10-24 11:51:38 +02:00
Matthieu Gautier
b1508c0b98 Better listBooksIds supported mode.
Only have REMOTE or LOCAL is a bit restrictive. By using flags a user
can specify for complex request.
2018-10-24 11:50:11 +02:00
Matthieu Gautier
2d59e12a4d Merge pull request #170 from kiwix/content_manager
Content manager
2018-10-24 11:18:14 +02:00
Matthieu Gautier
1b44eb33f3 [TRAVIS] Last osx version of travis already have python3 installed. 2018-10-24 11:07:10 +02:00
Matthieu Gautier
34021994cd Fix for Android
- No std::to_string. We have to implement it with a ostringstream
- No pthread_cancel. So we use pthread_kill to send a signal to the thread.
2018-10-24 10:48:53 +02:00
Matthieu Gautier
910ce5f10d Fix for Windows
- "winsock2.h" needs to be included before "windows.h". But if a
  compilation unit include "windows.h" and after "networkTools.h", we
  fails and it is complicated to handle. The include must not be in the
  header but in the cpp
- windows define some ERROR macro. It is a pitty but we cannot use `ERROR`
  in our enum.
- If build statically using mingw we need to define `CURL_STATICLIB`
2018-10-24 10:47:12 +02:00
Matthieu Gautier
c66c7e9c20 Store the size of the book in OPDSFeed. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
ad69fdd8c0 Move the download method from the downloader to networkTools.
The download method is a simple method to download content.
It use curl to download the content instead of aria.
2018-10-24 10:47:12 +02:00
Matthieu Gautier
a73ef23f6e Keep the book size in byte in memory (instead of in kb)
We keep the size in kb in library.xml for compatibility.
2018-10-24 10:47:12 +02:00
Matthieu Gautier
fe6d5fa93e Store the downloadId in the book (and in the library). 2018-10-24 10:47:12 +02:00
Matthieu Gautier
43ff8565d1 Add a Download class to encapsulate a aria2 download. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
f718c4c472 Add a LibraryManipulator.
Library client (kiwix-desktop) need to know when a book is added to
library by the manager. By using a LibraryManipulator, we can do
dependency injection.
2018-10-24 10:47:12 +02:00
Matthieu Gautier
8176a6eded Be more resilient to potential aria2 error. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
bb1f777078 Store the aria2 session and recover from it. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
829c34dd69 Store in the book instance if the given path is valid.
The path may exist and not be valid if the zim file is not truncated
(ie, interrupted download)
2018-10-24 10:47:12 +02:00
Matthieu Gautier
9c0f9696ed Better beautifyInteger and beautifyFileSize. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
be6dc01b4f Add few helper methods to xmlrpc objects. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
18fc5cb4df Correctly set the aria2 secret rpc. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
996829e4d7 Allow a OPDSDumper to dump only a subset of the library. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
5128861136 Remove default value for book pointer of readBookFromPath.
This is a nonsense to accept NULL pointer here.
2018-10-24 10:47:12 +02:00
Matthieu Gautier
7804bf2276 Reimplement listBooksIds.
No real improvement.
2018-10-24 10:47:12 +02:00
Matthieu Gautier
99e313f915 Clean includes of manager.h 2018-10-24 10:47:12 +02:00
Matthieu Gautier
839320d5e7 Move the Book class in its own source file. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
1e8f85eaff Rename methods title() into getTitle().
Same for all attributes.
2018-10-24 10:47:12 +02:00
Matthieu Gautier
e0704b3b21 Move the initialization code of a book from xml|opds into Book. 2018-10-24 10:47:12 +02:00
Matthieu Gautier
57fbb98bca Do not store the favicon base64 encoded in the book.
The fact that the favicon is base64 encoded in a storage detail.
2018-10-24 10:47:12 +02:00
Matthieu Gautier
c7f9218350 base64_encode takes a string instead of a char* 2018-10-24 10:47:12 +02:00
Matthieu Gautier
66a9a69480 Move the code updating a book from a reader in the Book class. 2018-09-06 18:30:37 +02:00
Matthieu Gautier
04b05dd68b Remove removeBookById from the Manager.
Use the same method of the `Library`.
2018-09-06 18:30:37 +02:00
Matthieu Gautier
aa6772b345 Remove the "last" book functionnality.
- This is not used by any application.
- This is application specific and should not be stored in the library
  (who is a list of book).
2018-09-06 18:30:37 +02:00
Matthieu Gautier
efae3e0d2f Do not make the Manager responsible to create the Library.
The `Manager` manage a library already existing.
This avoid the Library clone stuff.
2018-09-06 18:30:37 +02:00
Matthieu Gautier
bba3c252e4 Make the member of the book protected.
It is up to the book to manage its attribute.

Also remove the `absolutePath` (and `indexAbsolutePath`). The `Book::path` is always stored
absolute.
The fact that the path can be stored absolute or relative in the
`library.xml` is not relevant for the book.
2018-09-06 18:30:37 +02:00
Matthieu Gautier
57ac6f0305 Use a map to store the Library's books.
Having the books sorted is useless.
We handle books by id not by index.
2018-09-06 18:30:37 +02:00
Matthieu Gautier
541fb0cfd1 Remove the "current" book functionnality.
- This is not used by any application.
- This is application specific and should not be stored in the library
  (who is a list of book).
2018-09-06 18:30:37 +02:00
Matthieu Gautier
c9eac04050 Make the Library`s book vector private.
Move a lot of methods from Manager to Library. Because books is private
and thoses methods are better in Library.
2018-09-06 18:30:37 +02:00
Matthieu Gautier
741c67786a Add update method to Book. 2018-09-06 18:30:37 +02:00
Matthieu Gautier
db9000f706 Make the downloader use the aria2c wrapper instead of the aria2 library. 2018-09-06 18:30:34 +02:00
Matthieu Gautier
0a93cb0872 Add aria2 downloader using subprocess aria2c. 2018-09-06 18:29:49 +02:00
Matthieu Gautier
f4846c1ac8 Add a tool's function to get the data directory.
The data directory is where kiwix application should store data.
2018-08-29 15:28:52 +02:00
Matthieu Gautier
9b516ac35d Add a small wrapper around pugixml do handle xmprpc. 2018-08-29 15:28:52 +02:00
Matthieu Gautier
79b780b75b Move the function to convert from xml_node to string in otherTools.
This can be usefull elsewhere than in opds_dumper
2018-08-29 15:28:52 +02:00
Matthieu Gautier
f3dd83907d Add backend to launch subprocess.
The windows backend is not tested.
2018-08-29 15:28:52 +02:00
Matthieu Gautier
c351e7ccf1 Merge pull request #168 from kiwix/java_jdk8+
Update jni build script to java jdk 8+.
2018-08-20 17:53:39 +02:00
Matthieu Gautier
7c634738dd Update jni build script to java jdk 8+.
With jdk8, `javac` has an option `-h` to generate the header files of
native classes.
So there is no need to run `javah` several times.

As there is now only one command to run (`javac`), there is no need for
the wrapper script `gen_kiwix.sh`.

Fix #167
2018-08-20 12:17:29 +02:00
Matthieu Gautier
4378c52c27 Merge pull request #165 from kiwix/new_version
New version 2.0.2
2018-08-03 21:39:11 +02:00
Matthieu Gautier
790fa99143 New version 2.0.2 2018-08-03 19:37:21 +02:00
Matthieu Gautier
db6717e199 Merge pull request #164 from kiwix/windows
Windows
2018-08-03 19:31:31 +02:00
Matthieu Gautier
bf2188af14 [Windows] Add extra link arguments to build test on windows. 2018-08-03 19:22:39 +02:00
Matthieu Gautier
fd9b6569af Include unistd.h only on unix platform. 2018-08-03 19:22:39 +02:00
Matthieu Gautier
3cf58b5f5b Make libaria2 an optional dependency.
We don't compile libaria2 on Windows.
2018-08-03 19:22:39 +02:00
Matthieu Gautier
182be5d124 Merge pull request #163 from kiwix/android_better_log
[Android] Better error message when failing to read in zim file.
2018-07-31 13:48:11 +02:00
Matthieu Gautier
dbcc9140b9 [Android] Better error message when failing to read in zim file.
Let's print the exception's message to allow us to better understand
what went wrong.
2018-07-31 11:49:44 +02:00
Matthieu Gautier
d46aff00d1 Merge pull request #159 from kiwix/mhutti1/kiwixlib-fixes
Various kiwixlib fixes
2018-07-27 10:47:21 +02:00
mhutti1
d61580f599 Set JNI values to NULL on error 2018-07-27 10:11:24 +02:00
mhutti1
3227b29c90 Follow redirects in favicons 2018-07-27 10:11:24 +02:00
Matthieu Gautier
4cb55e1eef Merge pull request #161 from kiwix/new_dep_arrchive_root
New deps archives now contains the BUILD_${PLATFORM} directory.
2018-07-27 10:10:42 +02:00
Matthieu Gautier
9ec3358119 New deps archives now contains the BUILD_${PLATFORM} directory. 2018-07-27 09:36:35 +02:00
Kelson
cf21f1793c Merge pull request #158 from kiwix/compilation_fix
Use -llog only for Android
2018-07-07 22:08:11 +02:00
Kelson
c0d5e091d3 Small update of the README 2018-07-07 21:15:48 +02:00
Kelson
620f1b5e13 Use -llog only for Android 2018-07-07 20:19:34 +02:00
Kelson
1e8e897f4a Merge pull request #155 from kiwix/mhutti1/jni-corrupt-zim
JNI better log & stop crashing if exception thrown at ZIM file opening
2018-06-29 22:13:16 +02:00
Isaac Hutt
76ca4b0cee Add -llog 2018-06-29 16:57:32 +02:00
mhutti1
709baae934 Convert all JNI cerrs to Android log messages 2018-06-29 16:35:11 +02:00
mhutti1
ea8cd9f1a9 Correctly pass 0 through JNI if ZIM file is corrupted 2018-06-29 15:30:13 +02:00
Kelson
452e7f8883 Merge pull request #152 from kiwix/updated_readme
Update README
2018-06-25 06:14:36 +02:00
Emmanuel Engelhart
a66b178633 Update README 2018-06-24 22:16:16 +02:00
Matthieu Gautier
0c26b08dce Merge pull request #149 from kiwix/version_2.0.1
New version 2.0.1
2018-06-15 18:22:04 +02:00
Matthieu Gautier
2a03147662 New version 2.0.1 2018-06-15 18:07:51 +02:00
Matthieu Gautier
1164cf7444 Merge pull request #150 from kiwix/gcc4.8
[TRAVIS] Compile using the default compiler version 4.8.
2018-06-15 18:07:22 +02:00
Matthieu Gautier
6ef2d5ff4b [TRAVIS] Compile using the default compiler version 4.8. 2018-06-15 08:47:28 +02:00
Matthieu Gautier
3a00c4d671 Merge pull request #147 from kiwix/icu_namespace
Icu namespace
2018-06-11 15:21:30 +02:00
Matthieu Gautier
5025ee4963 Fix icudt version.
We have move to icu version 58 a while ago.
2018-06-11 14:38:32 +02:00
Matthieu Gautier
9aaf82a36d Explicitly use icu namespace.
Fix #145
2018-06-11 14:36:34 +02:00
Kelson
2e38aa796f Merge pull request #141 from kiwix/mhutti1/url-decoding
Decode reserved characters in URLs
2018-06-01 11:28:37 +02:00
mhutti1
fa99cce68d Decode reserved characters in URLs 2018-05-20 18:41:39 +01:00
Matthieu Gautier
fc6a0bcea2 Merge pull request #140 from kiwix/no_stopwords_resources
Remove unused static resources.
2018-05-15 11:37:35 +02:00
Matthieu Gautier
622d2fc23d Remove unused static resources.
Stop words are not use anymore since a long time now that indexing has
been moved to libzim. No need to embedded them in kiwix-lib.
2018-05-15 11:30:30 +02:00
Matthieu Gautier
48933a3b3e Merge pull request #139 from kiwix/fix_parseUrl
Fix parse url
2018-05-14 18:33:59 +02:00
Matthieu Gautier
c0b1c6013e Fix parsing of url
Fix kiwix/kiwix-tools#193
2018-05-14 17:41:05 +02:00
Matthieu Gautier
433a47c3fe Add unittest structure.
No tests, just everything to add tests later.
2018-05-14 17:40:43 +02:00
335 changed files with 42279 additions and 8637 deletions

12
.codecov.yml Normal file
View File

@@ -0,0 +1,12 @@
codecov:
notify:
require_ci_to_pass: yes
coverage:
status:
project:
default:
threshold: 1%
ignore:
- "test"

12
.github/FUNDING.yml vendored Normal file
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
.github/stale.yml vendored Normal file
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
.github/workflows/ci.yml vendored Normal file
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-2022
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
.github/workflows/package.yml vendored Normal file
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
.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
.idea/
*.swp
subprojects/googletest-release*
*.class
build/
.vscode/
builddir/
.cache/
.clangd/

21
.readthedocs.yaml Normal file
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

View File

@@ -1,43 +0,0 @@
language: cpp
dist: trusty
sudo: false
cache: ccache
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then eval "${MATRIX_EVAL}"; fi
- PATH=$PATH:$HOME/bin
- ${CXX} --version
install: travis/install_deps.sh
script: travis/compile.sh
env:
global:
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
matrix:
- PLATFORM="native_static"
- PLATFORM="native_dyn"
- PLATFORM="win32_static"
- PLATFORM="win32_dyn"
- PLATFORM="android_arm"
- PLATFORM="android_arm64"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
- 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

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

635
ChangeLog
View File

@@ -1,3 +1,638 @@
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
===============
* Use the correct path separator when computing relativePath on Windows.
kiwix-lib 3.0.1
===============
* Small fix about parsing the opdsStream.
kiwix-lib 3.0.0
===============
* Change the downloader to use aria2 using a separated process (with rpc)
instead of using the libaria2. This simplify a lot the link process to
libaria2 on Windows.
- kiwix-lib doesn't depend on libaria2 anymore.
- kiwix-lib now depends on libcurl.
* [API break] Library class API has been updated :
- Books are referenced by id, not index. A lot of methods have been
updated this way.
- Books "list" is now private.
- There is no more "current" book.
- listBooksIds's filters have been updated.
* [API break] Book class API has been updated :
- Move the definition of Book in `book.h`.
- Use getter/setter methods instead public members.
- Size (getSize/setSize) is now returned in bytes, not kB.
- Dependending of how the book has been initialized (opdsfeed), the
faviconUrl may be stored in the book, the favicon being downloaded when
using `getFavicon`.
- The path (and indexPath) are always absolute path.
- Book has now a downloadId, corresponding to the aria2 download id (if
exists)
* [API break] Manager class API has been updated :
- The manager is mainly use to fill a Libray from a "library.xml" file or
opds feed. Other operations (has removeBookById, setBookPath, filter, ...)
have been removed.
- The manager use a intermediate class (LibraryManipulator) to add book to
the library. This dependency injection allow caller code to hook the add
of a book to the library.
- The manager work on a existing Library. It doesn't how a internal
Library.
* [API break] OpdsDumper class API has been updated :
- dumpOPDSFeed method now take the list of bookIds to dump instead of
dumping all books in the library.
- OpdsDumper can now dump openSearch result information (total result
count, start index, ...).
* [API break] Common tools API has been updated :
- `base64_encode` and `base64_decode` take std::string as arguments.
- New `download` function in networkTools.h using libcurl.
- New `getDataDirectory` function in pathTools.
- Better `beautifyInteger` and `beautifyFileSize` functions.
- New `nodeToString` function serializing a pugi::xml_node to a string.
- New `converta2toa3` function to convert alpha2 language code to aplha3
language code.
kiwix-lib 2.0.2
===============
* [Android] Forward c++ errors message de Java world.
* Follow redirection of favicon.
* Make aria2 dependency optional.
* Inculde unistd.h only on unix platform.
kiwix-lib 2.0.1
===============
* Fix parsing of url.
* Remove unused static resources.
* Correctly decode reserved characters in URLs.
* Explicitly use icu namespace to allow use of packaged icu lib.
kiwix-lib 2.0.0
===============

258
README.md
View File

@@ -1,121 +1,239 @@
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 compiled/cross-compiled on/for many
sytems, the following documentation explains how to do it on POSIX
ones. It is primarly though 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/
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.
`libkiwix` 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.
Environnement
Environment
-------------
The Kiwix library builds using [Meson](http://mesonbuild.com/) version
0.34 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:
* Automake
* Libtool
* Virtualenv
* Pkg-config
* [Meson](https://mesonbuild.com/)
* [Ninja](https://ninja-build.org/)
* [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/)
Then install Meson itself:
```
virtualenv -p python3 ./ # Create virtualenv
source bin/activate # Activate the virtualenv
pip3 install meson # Install Meson
hash -r # Refresh bash paths
```
Finally download and build Ninja locally:
```
git clone git://github.com/ninja-build/ninja.git
cd ninja
git checkout release
./configure.py --bootstrap
mkdir ../bin
cp ninja ../bin
cd ..
```
These tools should be packaged if you use a cutting edge operating
system. If not, have a look to the [Troubleshooting](#Troubleshooting)
section.
Compilation
-----------
Once all dependencies are installed, you can compile kiwix-lib with:
```
mkdir build
Once all dependencies are installed, you can compile the Libkiwix
with:
```bash
meson . build
cd build
ninja
ninja -C build
```
By default, it will compile dynamic linked libraries. If you want
statically linked libraries, you can add `--default-library=static`
option to the Meson command.
By default, it will compile dynamic linked libraries. All binary files
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 libraries you just have compiled on your
system, here we go:
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
where you want to install the libraries. After the installation
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`).
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 ->
```
ninja install
<!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
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
./configure.py --bootstrap
mkdir ../bin
cp ninja ../bin
cd ..
```
You might need to run the command as root, depending where you want to
install the libraries.
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
debian/changelog vendored Normal file
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
debian/control vendored Normal file
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
debian/copyright vendored Normal file
View File

@@ -0,0 +1 @@
See COPYING in the repository root.

4
debian/libkiwix-dev.install vendored Normal file
View File

@@ -0,0 +1,4 @@
usr/include
usr/lib/*/libkiwix.so
usr/lib/*/pkgconfig
usr/bin

2
debian/libkiwix-dev.manpages vendored Normal file
View File

@@ -0,0 +1,2 @@
usr/share/man/man1/kiwix-compile-resources.1*
usr/share/man/man1/kiwix-compile-i18n.1*

1
debian/libkiwix14.install vendored Normal file
View File

@@ -0,0 +1 @@
usr/lib/*/libkiwix.so.*

8
debian/rules vendored Executable file
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
debian/source/format vendored Normal file
View File

@@ -0,0 +1 @@
3.0 (native)

2
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
api
xml

68
docs/conf.py Normal file
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 = '2022, 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
docs/index.rst Normal file
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
docs/meson.build Normal file
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
docs/requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
breathe
exhale
sphinx_rtd_theme

15
docs/usage.rst Normal file
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.

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

162
include/book.h Normal file
View File

@@ -0,0 +1,162 @@
/*
* 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_BOOK_H
#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
{
class OPDSDumper;
/**
* A class to store information about a book (a zim file)
*/
class Book
{
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 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() 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& getTitle() const { return m_title; }
const std::string& getDescription() const { return m_description; }
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; }
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 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; }
void setCreator(const std::string& creator) { m_creator = creator; }
void setPublisher(const std::string& publisher) { m_publisher = publisher; }
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 setDownloadId(const std::string& downloadId) { m_downloadId = downloadId; }
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 = 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 = 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;
};
}
#endif

86
include/bookmark.h Normal file
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

View File

@@ -16,6 +16,7 @@
namespace kiwix {
enum class IpMode { IPV4, IPV6, ALL, AUTO }; // AUTO: Server decides the protocol
typedef zim::size_type size_type;
typedef zim::offset_type offset_type;

View File

@@ -1,4 +0,0 @@
#include <string>
std::string base64_encode(unsigned char const* , unsigned int len);
std::string base64_decode(std::string const& s);

View File

@@ -1,63 +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();
bool writeTextFile(const string& path, const string& content);
#endif

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.

View File

@@ -21,13 +21,16 @@
#define KIWIX_DOWNLOADER_H
#include <string>
#include <aria2/aria2.h>
#include <pthread.h>
#include <vector>
#include <map>
#include <memory>
#include <stdexcept>
#include <mutex>
namespace kiwix
{
class Aria2;
struct DownloadedFile {
DownloadedFile()
: success(false) {}
@@ -35,35 +38,194 @@ struct DownloadedFile {
std::string path;
};
class AriaError : public std::runtime_error {
public:
AriaError(const std::string& message) : std::runtime_error(message) {}
};
/**
* 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;
Download() :
m_status(K_UNKNOWN) {}
Download(std::shared_ptr<Aria2> p_aria, std::string did)
: mp_aria(p_aria),
m_status(K_UNKNOWN),
m_did(did) {};
/**
* 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;
StatusResult m_status;
std::string m_did = "";
std::string m_followedBy = "";
uint64_t m_totalLength;
uint64_t m_completedLength;
uint64_t m_downloadSpeed;
uint64_t m_verifiedLength;
std::vector<std::string> m_uris;
std::string m_path;
};
/**
* 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();
~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 a content.
* Start a new download.
*
* @param url the url to download
* @return the content downloaded.
* 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.
*/
DownloadedFile download(const std::string& url);
std::shared_ptr<Download> startDownload(const std::string& uri, const std::string& downloadDir, Options options = {});
private:
static pthread_mutex_t globalLock;
/**
* 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);
aria2::Session* session;
DownloadedFile* fileHandle;
std::string tmpDir;
/**
* Get the number of downloads currently managed.
*/
size_t getNbDownload() const;
static int downloadEventCallback(aria2::Session* session,
aria2::DownloadEvent event,
aria2::A2Gid gid,
void* userData);
/**
* 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;
};
}

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
include/i18n.h Normal file
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

View File

@@ -22,4 +22,4 @@
#include "library.h"
#endif
#endif

30
include/kiwixserve.h Normal file
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_

View File

@@ -20,78 +20,232 @@
#ifndef KIWIX_LIBRARY_H
#define KIWIX_LIBRARY_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stack>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <mutex>
#include <zim/archive.h>
#include <zim/search.h>
#include "common/regexTools.h"
#include "common/stringTools.h"
#include "book.h"
#include "bookmark.h"
#include "common.h"
#define KIWIX_LIBRARY_VERSION "20110515"
using namespace std;
namespace Xapian {
class WritableDatabase;
};
namespace kiwix
{
enum supportedIndexType { UNKNOWN, XAPIAN };
class OPDSDumper;
class Library;
/**
* A class to store information about a book (a zim file)
*/
class Book
{
public:
Book();
~Book();
static bool sortByLastOpen(const Book& a, const Book& b);
static bool sortByTitle(const Book& a, const Book& b);
static bool sortBySize(const Book& a, const Book& b);
static bool sortByDate(const Book& a, const Book& b);
static bool sortByCreator(const Book& a, const Book& b);
static bool sortByPublisher(const Book& a, const Book& b);
static bool sortByLanguage(const Book& a, const Book& b);
string getHumanReadableIdFromPath();
string id;
string path;
string pathAbsolute;
string last;
string indexPath;
string indexPathAbsolute;
supportedIndexType indexType;
string title;
string description;
string language;
string creator;
string publisher;
string date;
string url;
string name;
string tags;
string origId;
string articleCount;
string mediaCount;
bool readOnly;
string size;
string favicon;
string faviconMimeType;
enum supportedListSortBy { UNSORTED, TITLE, SIZE, DATE, CREATOR, PUBLISHER };
enum supportedListMode {
ALL = 0,
LOCAL = 1,
REMOTE = 1 << 1,
NOLOCAL = 1 << 2,
NOREMOTE = 1 << 3,
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>
{
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();
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.
*
@@ -104,27 +258,254 @@ class Library
*/
bool addBook(const Book& book);
/**
* 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.
*
* @param bookIndex the index of the book to remove.
* @return True
* @param id the id of the book to remove.
* @return True if the book were in the lirbrary and has been removed.
*/
bool removeBookByIndex(const unsigned int bookIndex);
vector<kiwix::Book> books;
bool removeBookById(const std::string& id);
/*
* 'current' is the variable storing the current content/book id
* in the library. This is used to be able to load per default a
* content. As Kiwix may work with many library XML files, you may
* have "current" defined many time with different values. The
* last XML file read has the priority, Although we do not have an
* library object for each file, we want to be able to fallback to
* an 'old' current book if the one which should be load
* failed. That is the reason why we need a stack here
/**
* Write the library to a file.
*
* @param path the path of the file to write to.
* @return True if the library has been correctly saved.
*/
stack<string> current;
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.
*
* @param localBooks If we must count local books (books with a path).
* @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) const;
/**
* Get all languagues of the books in the library.
*
* @return A list of languages.
*/
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() const;
/**
* Get all book publishers of the books in the library.
*
* @return A list of book publishers.
*/
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.
*/
BookIdCollection getBooksIds() const;
/**
* Filter the library and return the id of the keep elements.
*
* @param filter The filter to use.
* @return The list of bookIds corresponding to the filter.
*/
BookIdCollection filter(const Filter& filter) const;
/**
* Sort (in place) bookIds using the given comparator.
*
* @param bookIds the list of book Ids to sort
* @param comparator how to sort the books
* @return The sorted list of books
*/
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

View File

@@ -20,60 +20,74 @@
#ifndef KIWIX_MANAGER_H
#define KIWIX_MANAGER_H
#include <time.h>
#include <sstream>
#include <string>
#include <pugixml.hpp>
#include "common/base64.h"
#include "common/pathTools.h"
#include "common/regexTools.h"
#include "book.h"
#include "library.h"
#include "reader.h"
using namespace std;
#include <string>
#include <vector>
#include <memory>
namespace pugi {
class xml_document;
}
namespace kiwix
{
enum supportedListMode { LASTOPEN, REMOTE, LOCAL };
enum supportedListSortBy { TITLE, SIZE, DATE, CREATOR, PUBLISHER };
class LibraryManipulator
{
public: // functions
explicit LibraryManipulator(LibraryPtr library);
virtual ~LibraryManipulator();
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();
~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 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 string nativePath,
const string UTF8Path,
const bool readOnly = true);
void reload(const Paths& paths);
/**
* Load a library content store in the string.
@@ -84,9 +98,10 @@ class Manager
* @param libraryPath The library path (used to resolve relative path)
* @return True if the content has been properly parsed.
*/
bool readXml(const string& xml,
bool readXml(const std::string& xml,
const bool readOnly = true,
const string libraryPath = "");
const std::string& libraryPath = "",
bool trustLibrary = true);
/**
* Load a library content stored in a OPDS stream.
@@ -97,69 +112,16 @@ class Manager
* @param libraryPath The library path (used to resolve relative path)
* @return True if the content has been properly parsed.
*/
bool readOpds(const string& content, const std::string& urlHost);
/**
* Write the library to a file.
*
* @param path the path of the file to write.
* @return True.
*/
bool writeFile(const string path);
bool readOpds(const std::string& content, const std::string& urlHost);
/**
* Remove a book from the library.
* Load a bookmark file.
*
* @param bookIndex the index of the book to remove
* @return True
* @param path The path of the file to read.
* @return True if the content has been properly parsed.
*/
bool removeBookByIndex(const unsigned int bookIndex);
/**
* Remove a book from the library.
*
* @param id the id of the book to remove.
* @return True if the book were in the library.
*/
bool removeBookById(const string id);
/**
* Set the current book.
*
* @param id The id to add to the stack of current books.
* If id is empty, remove the current book from the stack.
* @return True
*/
bool setCurrentBookId(const string id);
/**
* Get the current book id.
*
* @return The id of the current book (or empty string if no current book).
*/
string getCurrentBookId() const;
/**
* Set the path of the external fulltext index associated to a book.
*
* @param id The id of the book to set.
* @param path The path of the external fullext index.
* @param supportedIndexType The type of the fulltext index.
* @return True if the book is in the library.
*/
bool setBookIndex(const string id,
const string path,
const supportedIndexType type = XAPIAN);
/**
* Set the path of the zim file associated to a book.
*
* @param id The id of the book to set.
* @param path The path of the zim file.
* @return True if the book is in the library.
*/
bool setBookPath(const string id, const string path);
bool readBookmarkFile(const std::string& path);
/**
* Add a book to the library.
@@ -172,9 +134,9 @@ class Manager
* @return The id of the book if the book has been added to the library.
* Else, an empty string.
*/
string addBookFromPathAndGetId(const string pathToOpen,
const string pathToSave = "",
const string url = "",
std::string addBookFromPathAndGetId(const std::string& pathToOpen,
const std::string& pathToSave = "",
const std::string& url = "",
const bool checkMetaData = false);
/**
@@ -188,137 +150,38 @@ class Manager
* @return True if the book has been added to the library.
*/
bool addBookFromPath(const string pathToOpen,
const string pathToSave = "",
const string url = "",
bool addBookFromPath(const std::string& pathToOpen,
const std::string& pathToSave = "",
const std::string& url = "",
const bool checkMetaData = false);
/**
* Clone and return the internal library.
*
* @return A clone of the library.
* Add all books from the directory tree into the library.
*
* @param path The path of the directory to scan.
* @param verboseFlag Verbose logs flag.
*/
Library cloneLibrary();
void addBooksFromDirectory(const std::string& path,
const bool verboseFlag = 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.
*/
bool getBookById(const string id, Book& book);
std::string writableLibraryPath;
/**
* Get the current book.
*
* @param[out] The current book.
* @return True if there is a current book.
*/
bool getCurrentBook(Book& book);
/**
* Get the number of book in the library.
*
* @param localBooks If we must count local books (books with a path).
* @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);
/**
* 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 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 string language,
const string creator,
const string publisher,
const string search);
/**
* Filter the library and generate a new one with the keep elements.
*
* @param search List only books with search in the title or description.
* @return A `Library`.
*/
Library filter(const string& search);
/**
* Get all langagues of the books in the library.
*
* @return A list of languages.
*/
vector<string> getBooksLanguages();
/**
* Get all book creators of the books in the library.
*
* @return A list of book creators.
*/
vector<string> getBooksCreators();
/**
* Get all book publishers of the books in the library.
*
* @return A list of book publishers.
*/
vector<string> getBooksPublishers();
/**
* Get all book ids of the books in the library.
*
* @return A list of book ids.
*/
vector<string> getBooksIds();
string writableLibraryPath;
vector<std::string> bookIdList;
bool m_hasSearchResult = false;
uint64_t m_totalBooks = 0;
uint64_t m_startIndex = 0;
uint64_t m_itemsPerPage = 0;
protected:
kiwix::Library library;
kiwix::LibraryManipulator manipulator;
bool readBookFromPath(const string path, Book* book = NULL);
bool readBookFromPath(const std::string& path, Book* book);
bool parseXmlDom(const pugi::xml_document& doc,
const bool readOnly,
const 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 string& libraryPath);
};
}

View File

@@ -1,34 +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
include/name_mapper.h Normal file
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

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 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,18 +17,17 @@
* MA 02110-1301, USA.
*/
#ifndef KIWIX_OTHERTOOLS_H
#define KIWIX_OTHERTOOLS_H
#ifndef KIWIX_OPDS_CATALOG_H
#define KIWIX_OPDS_CATALOG_H
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include "library.h"
namespace kiwix
{
void sleep(unsigned int milliseconds);
}
#endif
std::string getSearchUrl(const Filter& f);
} // namespace kiwix
#endif // KIWIX_OPDS_CATALOG_H

View File

@@ -1,107 +0,0 @@
/*
* 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 "common/base64.h"
#include "common/pathTools.h"
#include "common/regexTools.h"
#include "library.h"
#include "reader.h"
using namespace std;
namespace kiwix
{
/**
* A tool to dump a `Library` into a opds stream.
*
*/
class OPDSDumper
{
public:
OPDSDumper() = default;
OPDSDumper(Library library);
~OPDSDumper();
/**
* Dump the OPDS feed.
*
* @param id The id of the library.
* @return The OPDS feed.
*/
std::string dumpOPDSFeed();
/**
* 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; }
/**
* Set the root location used when generating url.
*
* @param rootLocation the root location to use.
*/
void setRootLocation(const std::string& rootLocation) { this->rootLocation = rootLocation; }
/**
* Set the search url.
*
* @param searchUrl the search url to use.
*/
void setSearchDescriptionUrl(const std::string& searchDescriptionUrl) { this->searchDescriptionUrl = searchDescriptionUrl; }
/**
* Set the library to dump.
*
* @param library The library to dump.
*/
void setLibrary(Library library) { this->library = library; }
protected:
kiwix::Library library;
std::string id;
std::string title;
std::string date;
std::string rootLocation;
std::string searchDescriptionUrl;
private:
pugi::xml_node handleBook(Book book, pugi::xml_node root_node);
};
}
#endif // KIWIX_OPDS_DUMPER_H

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
include/search_renderer.h Normal file
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

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

95
include/server.h Normal file
View File

@@ -0,0 +1,95 @@
/*
* 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();
/**
* Serve the content.
*/
bool start();
/**
* Stop the daemon.
*/
void stop();
void setRoot(const std::string& root);
void setAddress(const std::string& addr);
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; }
void setIpMode(IpMode mode) { m_ipMode = mode; }
int getPort() const;
IpAddress getAddress() const;
IpMode getIpMode() const;
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

View File

@@ -1,6 +1,5 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.fr>
* 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
@@ -18,27 +17,42 @@
* MA 02110-1301, USA.
*/
#include <jni.h>
#include "org_kiwix_kiwixlib_JNIKiwix.h"
#ifndef KIWIX_SPELLING_CORRECTION_H
#define KIWIX_SPELLING_CORRECTION_H
#include <iostream>
#include <filesystem>
#include <memory>
#include <string>
#include <vector>
#include "unicode/putil.h"
#include "utils.h"
pthread_mutex_t globalLock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_setDataDirectory(
JNIEnv* env, jobject obj, jstring dirStr)
namespace zim
{
std::string cPath = jni2c(dirStr, env);
Lock l;
try {
u_setDataDirectory(cPath.c_str());
} catch (...) {
std::cerr << "Unable to set data directory " << cPath << std::endl;
}
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

271
include/tools.h Normal file
View File

@@ -0,0 +1,271 @@
/*
* 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
{
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

View File

@@ -1,6 +1,5 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.fr>
* 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
@@ -18,14 +17,18 @@
* MA 02110-1301, USA.
*/
package org.kiwix.kiwixlib;
#ifndef KIWIX_VERSION_H
#define KIWIX_VERSION_H
import org.kiwix.kiwixlib.JNIKiwixReader;
import org.kiwix.kiwixlib.JNIKiwixString;
#include <string>
#include <vector>
#include <iostream>
public class JNIKiwix
namespace kiwix
{
static { System.loadLibrary("kiwix"); }
public native void setDataDirectory(String icuDataDir);
typedef std::vector<std::pair<std::string, std::string>> LibVersions;
LibVersions getVersions();
void printVersions(std::ostream& out = std::cout);
}
#endif // KIWIX_VERSION_H

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

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@

View File

@@ -1,117 +1,122 @@
project('kiwix-lib', 'cpp',
version : '2.0.0',
license : 'GPL',
default_options : ['c_std=c11', 'cpp_std=c++11', 'werror=true'])
project('libkiwix', 'cpp',
version : '14.1.1',
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'
# 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>
thread_dep = dependency('threads')
libicu_dep = dependency('icu-i18n', static:static_deps)
libzim_dep = dependency('libzim', version : '>=3.3.0', static:static_deps)
pugixml_dep = dependency('pugixml', static:static_deps)
libaria2_dep = dependency('libaria2', static:static_deps)
using namespace std;
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
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
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
thread_dep = dependency('', required:false)
endif
xapian_dep = dependency('xapian-core', required:false, static:static_deps)
all_deps = [thread_dep, libicu_dep, libzim_dep, xapian_dep, pugixml_dep, libaria2_dep]
if has_ctpp2_dep
all_deps += [ctpp2_dep]
libicu_dep = dependency('icu-i18n', 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
inc = include_directories('include')
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 host_machine.system() == 'windows' and static_deps
add_project_arguments('-DCURL_STATICLIB', language : 'cpp')
extra_cflags += '-DCURL_STATICLIB'
endif
if host_machine.system() == 'windows'
add_project_arguments('-DNOMINMAX', language: 'cpp')
extra_libs += ['-liphlpapi']
endif
if build_machine.system() == 'windows'
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('VERSION', '"@0@"'.format(meson.project_version()))
conf.set('ENABLE_CTPP2', has_ctpp2_dep)
conf.set('LIBKIWIX_VERSION', '"@0@"'.format(meson.project_version()))
subdir('include')
subdir('scripts')
subdir('static')
subdir('src')
pkg_requires = ['libzim', 'icu-i18n', 'pugixml', 'libaria2']
if xapian_dep.found()
pkg_requires += ['xapian-core']
subdir('test')
if get_option('doc')
subdir('docs')
endif
extra_libs = []
extra_cflags = ''
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)

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.')

View File

@@ -1,8 +0,0 @@
#!/usr/bin/env bash
ctpp2c=$1
SOURCE=$(pwd)/$2
DEST=$3
$ctpp2c $SOURCE $DEST

14
scripts/format_code.sh Executable file
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
scripts/kiwix-compile-i18n Executable file
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))

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>

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:

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
scripts/kiwix-resources Executable file
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)

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')

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>

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env bash
set -e
BUILD_PATH=$(pwd)
echo "javac -d $BUILD_PATH/src/android $@"
javac -d $BUILD_PATH/src/android/ "$@"
cd $BUILD_PATH/src/android
echo "javah -jni org.kiwix.kiwixlib"
javah -jni org.kiwix.kiwixlib.JNIKiwix
javah -jni org.kiwix.kiwixlib.JNIKiwixReader
javah -jni org.kiwix.kiwixlib.JNIKiwixSearcher
cd $BUILD_PATH

View File

@@ -1,399 +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 "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);
Lock l;
kiwix::Reader* reader = nullptr;
try {
reader = new kiwix::Reader(cPath);
} catch (...) {
std::cerr << "Unable to load ZIM " << cPath << std::endl;
reader = NULL;
}
return reinterpret_cast<jlong>(new Handle<kiwix::Reader>(reader));
}
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::cerr << "Unable to get ZIM main page" << std::endl;
}
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::cerr << "Unable to get ZIM id" << std::endl;
}
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::cerr << "Unable to get ZIM file size" << std::endl;
}
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::cerr << "Unable to get ZIM creator" << std::endl;
}
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::cerr << "Unable to get ZIM creator" << std::endl;
}
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::cerr << "Unable to get ZIM name" << std::endl;
}
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(reinterpret_cast<const unsigned char*>(cContent.c_str()),
cContent.length()),
env);
} catch (...) {
std::cerr << "Unable to get ZIM favicon" << std::endl;
}
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::cerr << "Unable to get ZIM date" << std::endl;
}
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::cerr << "Unable to get ZIM language" << std::endl;
}
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::cerr << "Unable to get mime-type for url " << cUrl << std::endl;
}
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::cerr << "Unable to get content for url " << cUrl << std::endl;
}
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::cerr << "Unable to get partial content for url " << cUrl
<< "(" << cOffset << ":" << cLen << ")" << std::endl;
}
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::cerr << "Unable to locate direct access information for url " << cUrl
<< std::endl;
}
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::cerr << "Unable to search suggestions for pattern " << cPrefix
<< std::endl;
}
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::cerr << "Unable to get next suggestion" << std::endl;
}
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::cerr << "Unable to get URL for title " << cTitle << std::endl;
}
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::cerr << "Unable to get ZIM title" << std::endl;
}
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::cerr << "Unable to get ZIM description" << std::endl;
}
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::cerr << "Unable to get random page" << std::endl;
}
return retVal;
}

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);
}

View File

@@ -1,28 +0,0 @@
jni_generator = find_program('gen_kiwix.sh')
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:[jni_generator, '@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')

View File

@@ -1,27 +0,0 @@
/*
* Copyright (C) 2017 Matthieu Gautier <mgautier@kymeria.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 JNIKiwixException extends Exception
{
public JNIKiwixException(String message) {
super(message);
}
}

View File

@@ -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;
}

View File

@@ -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();
}

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;
}

View File

@@ -1,3 +0,0 @@
<resources>
<string name="app_name">Kiwix Lib</string>
</resources>

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

313
src/aria2.cpp Normal file
View File

@@ -0,0 +1,313 @@
#include "aria2.h"
#include "xmlrpc.h"
#include <iostream>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <thread>
#include <chrono>
#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 {
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(getNewRpcSecret())
{
std::vector<const char*> callCmd;
std::string rpc_port = "--rpc-listen-port=" + to_string(m_port);
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 + "\"";
#ifdef _WIN32
int pid = GetCurrentProcessId();
#else
pid_t pid = getpid();
#endif
std::string stop_with_pid = "--stop-with-process=" + to_string(pid);
std::string rpc_secret = "--rpc-secret=" + m_secret;
m_secret = "token:"+m_secret;
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());
if (fileReadable(session_file)) {
callCmd.push_back(inputFile.c_str());
}
callCmd.push_back(session.c_str());
// callCmd.push_back(log_dir.c_str());
callCmd.push_back("--auto-save-interval=10");
callCmd.push_back(stop_with_pid.c_str());
callCmd.push_back("--allow-overwrite=true");
callCmd.push_back("--dht-entry-point=router.bittorrent.com:6881");
callCmd.push_back("--dht-entry-point6=router.bittorrent.com:6881");
callCmd.push_back("--quiet=true");
callCmd.push_back("--bt-enable-lpd=true");
callCmd.push_back("--always-resume=true");
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);
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;
}
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()
{
saveSession();
shutdown();
}
size_t write_callback_to_iss(char* ptr, size_t size, size_t nmemb, void* userdata)
{
auto outStream = static_cast<std::stringstream*>(userdata);
outStream->write(ptr, nmemb);
return nmemb;
}
std::string Aria2::doRequest(const MethodCall& methodCall)
{
auto requestContent = methodCall.toString();
std::stringstream outStream;
CURLcode res;
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");
}
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, 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();
}
std::string Aria2::tellStatus(const std::string& gid, const std::vector<std::string>& statusKey)
{
MethodCall methodCall("aria2.tellStatus", m_secret);
methodCall.newParamValue().set(gid);
if (!statusKey.empty()) {
auto statusArray = methodCall.newParamValue().getArray();
for (auto& key : statusKey) {
statusArray.addValue().set(key);
}
}
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"));
auto responseContent = doRequest(methodCall);
MethodResponse response(responseContent);
std::vector<std::string> activeGID;
int index = 0;
while(true) {
try {
auto structNode = response.getParamValue(0).getArray().getValue(index++).getStruct();
auto gidNode = structNode.getMember("gid");
activeGID.push_back(gidNode.getValue().getAsS());
} catch (InvalidRPCNode& e) { break; }
}
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);
doRequest(methodCall);
std::cout << "session saved" << std::endl;
}
void Aria2::shutdown()
{
MethodCall methodCall("aria2.shutdown", m_secret);
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

46
src/aria2.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef KIWIXLIB_ARIA2_H_
#define KIWIXLIB_ARIA2_H_
#ifdef _WIN32
// winsock2.h need to be included before windows.h (included by curl.h)
# include <winsock2.h>
#endif
#include "subprocess.h"
#include "xmlrpc.h"
#include <memory>
#include <curl/curl.h>
namespace kiwix {
class Aria2
{
private:
std::unique_ptr<Subprocess> mp_aria;
int m_port;
std::string m_secret;
std::string doRequest(const MethodCall& methodCall);
public:
explicit Aria2(std::string sessionFileDir);
virtual ~Aria2() = default;
void close();
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
#endif // KIWIXLIB_ARIA2_H_

296
src/book.cpp Normal file
View File

@@ -0,0 +1,296 @@
/*
* 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 "book.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_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;
if (m_id != other.m_id)
return false;
*this = other;
return true;
}
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;
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()
void Book::updateFromXml(const pugi::xml_node& node, const std::string& baseDir)
{
m_id = ATTR("id");
std::string path = ATTR("path");
if (isRelativePath(path)) {
path = computeAbsolutePath(baseDir, path);
}
m_path = path;
m_pathValid = fileReadable(path);
m_title = ATTR("title");
m_description = ATTR("description");
m_language = ATTR("language");
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;
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)
{
m_id = VALUE("id");
if (!m_id.compare(0, 9, "urn:uuid:")) {
m_id.erase(0, 9);
}
// No path on opds.
m_title = VALUE("title");
m_description = VALUE("summary");
m_language = VALUE("language");
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();
if (rel == "http://opds-spec.org/acquisition/open-access") {
m_url = linkNode.attribute("href").value();
m_size = strtoull(linkNode.attribute("length").value(), 0, 0);
}
if (rel == "http://opds-spec.org/image/thumbnail") {
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() const
{
std::string id = m_path;
if (!id.empty()) {
id = kiwix::removeAccents(id);
#ifdef _WIN32
id = replaceRegex(id, "", "^.*\\\\");
#else
id = replaceRegex(id, "", "^.*/");
#endif
id = replaceRegex(id, "", "\\.zim[a-z]*$");
id = replaceRegex(id, "_", " ");
id = replaceRegex(id, "plus", "\\+");
}
return id;
}
void Book::setPath(const std::string& path)
{
m_path = isRelativePath(path)
? computeAbsolutePath(getCurrentDirectory(), path)
: path;
}
const Book::Illustration Book::missingDefaultIllustration;
std::shared_ptr<const Book::Illustration> Book::getIllustration(unsigned int size) const
{
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;
}
}
}
return data;
}
const std::string& Book::getFavicon() const {
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");
}
catch ( const std::out_of_range& )
{
return "";
}
}
const std::vector<std::string> Book::getLanguages() const
{
return kiwix::split(m_language, ",");
}
}

61
src/bookmark.cpp Normal file
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();
}
}

View File

@@ -1,162 +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>
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";
}

View File

@@ -1,29 +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>
void kiwix::sleep(unsigned int milliseconds)
{
#ifdef _WIN32
Sleep(milliseconds);
#else
usleep(1000 * milliseconds);
#endif
}

View File

@@ -1,312 +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
#define SEPARATOR "\\"
#else
#define 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]) {
if (!pathParts[commonCount].empty()) {
commonCount++;
}
}
string relativePath;
#ifdef _WIN32
/* On Windows you have a token more because the root is represented
by a letter */
if (commonCount == 0) {
relativePath = "../";
}
#endif
for (unsigned int i = commonCount; i < pathParts.size(); i++) {
relativePath += "../";
}
for (unsigned int i = commonCount; i < absolutePathParts.size(); i++) {
relativePath += absolutePathParts[i];
relativePath += i + 1 < absolutePathParts.size() ? "/" : "";
}
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;
}

View File

@@ -1,93 +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 <common/regexTools.h>
std::map<std::string, RegexMatcher*> regexCache;
RegexMatcher* buildRegex(const std::string& regex)
{
RegexMatcher* matcher;
std::map<std::string, RegexMatcher*>::iterator itr = regexCache.find(regex);
/* Regex is in cache */
if (itr != regexCache.end()) {
matcher = itr->second;
}
/* Regex needs to be parsed (and cached) */
else {
UErrorCode status = U_ZERO_ERROR;
UnicodeString uregex = UnicodeString(regex.c_str());
matcher = new RegexMatcher(uregex, UREGEX_CASE_INSENSITIVE, status);
regexCache[regex] = matcher;
}
return matcher;
}
/* todo */
void freeRegexCache()
{
}
bool matchRegex(const std::string& content, const std::string& regex)
{
ucnv_setDefaultName("UTF-8");
UnicodeString ucontent = UnicodeString(content.c_str());
RegexMatcher* matcher = buildRegex(regex);
matcher->reset(ucontent);
return matcher->find();
}
std::string replaceRegex(const std::string& content,
const std::string& replacement,
const std::string& regex)
{
ucnv_setDefaultName("UTF-8");
UnicodeString ucontent = UnicodeString(content.c_str());
UnicodeString ureplacement = UnicodeString(replacement.c_str());
RegexMatcher* matcher = buildRegex(regex);
matcher->reset(ucontent);
UErrorCode status = U_ZERO_ERROR;
UnicodeString uresult = matcher->replaceAll(ureplacement, status);
std::string tmp;
uresult.toUTF8String(tmp);
return tmp;
}
std::string appendToFirstOccurence(const std::string& content,
const std::string regex,
const std::string& replacement)
{
ucnv_setDefaultName("UTF-8");
UnicodeString ucontent = UnicodeString(content.c_str());
UnicodeString ureplacement = UnicodeString(replacement.c_str());
RegexMatcher* matcher = buildRegex(regex);
matcher->reset(ucontent);
if (matcher->find()) {
UErrorCode status = U_ZERO_ERROR;
ucontent.insert(matcher->end(status), ureplacement);
std::string tmp;
ucontent.toUTF8String(tmp);
return tmp;
}
return content;
}

View File

@@ -1,4 +1,3 @@
#mesondefine VERSION
#mesondefine LIBKIWIX_VERSION
#mesondefine ENABLE_CTPP2

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.

View File

@@ -18,95 +18,240 @@
*/
#include "downloader.h"
#include "common/pathTools.h"
#include "tools.h"
#include "tools/pathTools.h"
#include "tools/stringTools.h"
#include <algorithm>
#include <thread>
#include <chrono>
#include <unistd.h>
#include <iostream>
#include "aria2.h"
#include "xmlrpc.h"
#include "tools/otherTools.h"
#include <pugixml.hpp>
namespace kiwix
{
pthread_mutex_t Downloader::globalLock = PTHREAD_MUTEX_INITIALIZER;
/* Constructor */
Downloader::Downloader()
void Download::updateStatus(bool follow)
{
aria2::SessionConfig config;
config.downloadEventCallback = Downloader::downloadEventCallback;
config.userData = this;
tmpDir = makeTmpDirectory();
aria2::KeyVals options;
options.push_back(std::pair<std::string, std::string>("dir", tmpDir));
session = aria2::sessionNew(options, config);
if (m_status == Download::K_REMOVED)
return;
static std::vector<std::string> statusKey = {"status", "files", "totalLength",
"completedLength", "followedBy",
"downloadSpeed", "verifiedLength"};
std::string strStatus;
if(follow && !m_followedBy.empty()) {
strStatus = mp_aria->tellStatus(m_followedBy, statusKey);
} else {
strStatus = mp_aria->tellStatus(m_did, statusKey);
}
// std::cout << strStatus << std::endl;
MethodResponse response(strStatus);
if (response.isFault()) {
m_status = Download::K_UNKNOWN;
return;
}
auto structNode = response.getParams().getParam(0).getValue().getStruct();
auto _status = structNode.getMember("status").getValue().getAsS();
auto status = _status == "active" ? Download::K_ACTIVE
: _status == "waiting" ? Download::K_WAITING
: _status == "paused" ? Download::K_PAUSED
: _status == "error" ? Download::K_ERROR
: _status == "complete" ? Download::K_COMPLETE
: _status == "removed" ? Download::K_REMOVED
: Download::K_UNKNOWN;
if (status == K_COMPLETE) {
try {
auto followedByMember = structNode.getMember("followedBy");
m_followedBy = followedByMember.getValue().getArray().getValue(0).getAsS();
if (follow) {
status = K_ACTIVE;
updateStatus(true);
return;
}
} catch (InvalidRPCNode& e) { }
}
m_status = status;
m_totalLength = extractFromString<uint64_t>(structNode.getMember("totalLength").getValue().getAsS());
m_completedLength = extractFromString<uint64_t>(structNode.getMember("completedLength").getValue().getAsS());
m_downloadSpeed = extractFromString<uint64_t>(structNode.getMember("downloadSpeed").getValue().getAsS());
try {
auto verifiedLengthValue = structNode.getMember("verifiedLength").getValue();
m_verifiedLength = extractFromString<uint64_t>(verifiedLengthValue.getAsS());
} catch (InvalidRPCNode& e) { m_verifiedLength = 0; }
auto filesMember = structNode.getMember("files");
auto fileStruct = filesMember.getValue().getArray().getValue(0).getStruct();
m_path = fileStruct.getMember("path").getValue().getAsS();
auto urisArray = fileStruct.getMember("uris").getValue().getArray();
int index = 0;
m_uris.clear();
while(true) {
try {
auto uriNode = urisArray.getValue(index++).getStruct().getMember("uri");
m_uris.push_back(uriNode.getValue().getAsS());
} catch(InvalidRPCNode& e) { break; }
}
}
void Download::resumeDownload()
{
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()
{
aria2::sessionFinal(session);
rmdir(tmpDir.c_str());
close();
}
int Downloader::downloadEventCallback(aria2::Session* session,
aria2::DownloadEvent event,
aria2::A2Gid gid,
void* userData)
void Downloader::close()
{
Downloader* downloader = static_cast<Downloader*>(userData);
auto fileHandle = downloader->fileHandle;
auto dh = aria2::getDownloadHandle(session, gid);
if (!dh) {
return 0;
}
switch (event) {
case aria2::EVENT_ON_DOWNLOAD_COMPLETE:
{
if (dh->getNumFiles() > 0) {
auto f = dh->getFile(1);
fileHandle->path = f.path;
fileHandle->success = true;
}
}
break;
case aria2::EVENT_ON_DOWNLOAD_ERROR:
{
fileHandle->success = false;
}
break;
default:
break;
}
aria2::deleteDownloadHandle(dh);
return 0;
}
DownloadedFile Downloader::download(const std::string& url) {
pthread_mutex_lock(&globalLock);
DownloadedFile fileHandle;
try {
std::vector<std::string> uris = {url};
aria2::KeyVals options;
aria2::A2Gid gid;
int ret;
DownloadedFile fileHandle;
ret = aria2::addUri(session, &gid, uris, options);
if (ret < 0) {
std::cerr << "Failed to download" << std::endl;
} else {
this->fileHandle = &fileHandle;
aria2::run(session, aria2::RUN_DEFAULT);
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;
}
} catch (...) {};
this->fileHandle = nullptr;
pthread_mutex_unlock(&globalLock);
return fileHandle;
mp_aria.reset();
}
}
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);
}
return ret;
}
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;
if ( downloadCanBeReused(*d, uri, options) )
return d;
}
std::vector<std::string> uris = {uri};
auto gid = mp_aria->addUri(uris, options);
m_knownDownloads[gid] = std::make_shared<Download>(mp_aria, gid);
return m_knownDownloads[gid];
}
std::shared_ptr<Download> Downloader::getDownload(const std::string& did)
{
std::unique_lock<std::mutex> lock(m_lock);
try {
return m_knownDownloads.at(did);
} catch(std::exception& e) {
for (auto gid : mp_aria->tellWaiting()) {
if (gid == did) {
m_knownDownloads[gid] = std::make_shared<Download>(mp_aria, gid);
return m_knownDownloads[gid];
}
}
for (auto gid : mp_aria->tellActive()) {
if (gid == did) {
m_knownDownloads[gid] = std::make_shared<Download>(mp_aria, gid);
return m_knownDownloads[gid];
}
}
throw e;
}
}
size_t Downloader::getNbDownload() const {
std::unique_lock<std::mutex> lock(m_lock);
return m_knownDownloads.size();
}
}

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
src/html_dumper.cpp Normal file
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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 Emmanuel Engelhart <kelson@kiwix.org>
* 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
@@ -17,9 +17,34 @@
* MA 02110-1301, USA.
*/
package org.kiwix.kiwixlib;
#ifndef KIWIX_HTML_DUMPER_H
#define KIWIX_HTML_DUMPER_H
public class JNIKiwixBool
#include <string>
#include "library_dumper.h"
namespace kiwix
{
public boolean value;
/**
* 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
src/kiwixserve.cpp Normal file
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;
}
}

View File

File diff suppressed because it is too large Load Diff

61
src/library_dumper.cpp Normal file
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

99
src/library_dumper.h Normal file
View File

@@ -0,0 +1,99 @@
/*
* 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
* 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_LIBRARY_DUMPER_H
#define KIWIX_LIBRARY_DUMPER_H
#include <string>
#include "library.h"
#include "name_mapper.h"
#include <mustache.hpp>
namespace kiwix
{
/**
* A base class to dump Library in various formats.
*
*/
class LibraryDumper
{
public:
LibraryDumper(const Library* library, const NameMapper* NameMapper);
~LibraryDumper();
void setLibraryId(const std::string& id) { this->libraryId = id;}
/**
* Set the root location used when generating url.
*
* @param rootLocation the root location to use.
*/
void setRootLocation(const std::string& rootLocation) { this->rootLocation = rootLocation; }
/**
* Set the URL for accessing book content
*
* @param url the URL of the /content endpoint of the content server
*/
void setContentAccessUrl(const std::string& url) { this->contentAccessUrl = url; }
/**
* Set some informations about the search results.
*
* @param totalResult the total number of results of the search.
* @param startIndex the start index of the result.
* @param count the number of result of the current set (or page).
*/
void setOpenSearchInfo(int totalResult, int startIndex, int count);
/**
* Sets user default language
*
* @param userLang the user language to be set
*/
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:
const kiwix::Library* const library;
const kiwix::NameMapper* const nameMapper;
std::string libraryId;
std::string rootLocation;
std::string contentAccessUrl;
std::string m_userLang;
int m_totalResults;
int m_startIndex;
int m_count;
};
}
#endif // KIWIX_LIBRARY_DUMPER_H

149
src/libxml_dumper.cpp Normal file
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
src/libxml_dumper.h Normal file
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

View File

@@ -18,87 +18,124 @@
*/
#include "manager.h"
#include "downloader.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
{
////////////////////////////////////////////////////////////////////////////////
// LibraryManipulator
////////////////////////////////////////////////////////////////////////////////
LibraryManipulator::LibraryManipulator(LibraryPtr library)
: library(library)
{}
LibraryManipulator::~LibraryManipulator()
{}
bool LibraryManipulator::addBookToLibrary(const Book& book)
{
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() : writableLibraryPath("")
Manager::Manager(LibraryManipulator manipulator):
writableLibraryPath(""),
manipulator(manipulator)
{
}
/* Destructor */
Manager::~Manager()
Manager::Manager(LibraryPtr library) :
writableLibraryPath(""),
manipulator(LibraryManipulator(library))
{
}
bool Manager::parseXmlDom(const pugi::xml_document& doc,
const bool readOnly,
const string libraryPath)
bool readOnly,
const std::string& libraryPath,
bool trustLibrary)
{
pugi::xml_node libraryNode = doc.child("library");
if (strlen(libraryNode.attribute("current").value()))
this->setCurrentBookId(libraryNode.attribute("current").value());
string libraryVersion = libraryNode.attribute("version").value();
std::string libraryVersion = libraryNode.attribute("version").value();
for (pugi::xml_node bookNode = libraryNode.child("book"); bookNode;
bookNode = bookNode.next_sibling("book")) {
bool ok = true;
kiwix::Book book;
book.readOnly = readOnly;
book.id = bookNode.attribute("id").value();
book.path = bookNode.attribute("path").value();
book.last = (std::string(bookNode.attribute("last").value()) != "undefined"
? bookNode.attribute("last").value()
: "");
book.indexPath = bookNode.attribute("indexPath").value();
book.indexType = XAPIAN;
book.title = bookNode.attribute("title").value();
book.name = bookNode.attribute("name").value();
book.tags = bookNode.attribute("tags").value();
book.description = bookNode.attribute("description").value();
book.language = bookNode.attribute("language").value();
book.date = bookNode.attribute("date").value();
book.creator = bookNode.attribute("creator").value();
book.publisher = bookNode.attribute("publisher").value();
book.url = bookNode.attribute("url").value();
book.origId = bookNode.attribute("origId").value();
book.articleCount = bookNode.attribute("articleCount").value();
book.mediaCount = bookNode.attribute("mediaCount").value();
book.size = bookNode.attribute("size").value();
book.favicon = bookNode.attribute("favicon").value();
book.faviconMimeType = bookNode.attribute("faviconMimeType").value();
book.setReadOnly(readOnly);
book.updateFromXml(bookNode,
removeLastPathElement(libraryPath));
/* Check absolute and relative paths */
this->checkAndCleanBookPaths(book, libraryPath);
/* Update the book properties with the new importer */
if (libraryVersion.empty()
|| atoi(libraryVersion.c_str()) <= atoi(KIWIX_LIBRARY_VERSION)) {
if (!book.path.empty()) {
ok = this->readBookFromPath(book.pathAbsolute);
}
}
if (ok) {
library.addBook(book);
if (!trustLibrary && !book.getPath().empty()) {
this->readBookFromPath(book.getPath(), &book);
}
manipulator.addBookToLibrary(book);
}
return true;
}
bool Manager::readXml(const string& xml,
const bool readOnly,
const string libraryPath)
bool Manager::readXml(const std::string& xml,
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;
@@ -110,40 +147,24 @@ bool Manager::parseOpdsDom(const pugi::xml_document& doc, const std::string& url
{
pugi::xml_node libraryNode = doc.child("feed");
try {
m_totalBooks = strtoull(libraryNode.child("totalResults").child_value(), 0, 0);
m_startIndex = strtoull(libraryNode.child("startIndex").child_value(), 0, 0);
m_itemsPerPage = strtoull(libraryNode.child("itemsPerPage").child_value(), 0, 0);
m_hasSearchResult = true;
} catch(...) {
m_hasSearchResult = false;
}
for (pugi::xml_node entryNode = libraryNode.child("entry"); entryNode;
entryNode = entryNode.next_sibling("entry")) {
kiwix::Book book;
book.readOnly = false;
book.id = entryNode.child("id").child_value();
book.title = entryNode.child("title").child_value();
book.description = entryNode.child("summary").child_value();
book.language = entryNode.child("language").child_value();
book.date = entryNode.child("updated").child_value();
book.creator = entryNode.child("author").child("name").child_value();
for(pugi::xml_node linkNode = entryNode.child("link"); linkNode;
linkNode = linkNode.next_sibling("link")) {
std::string rel = linkNode.attribute("rel").value();
if (rel == "http://opds-spec.org/image/thumbnail") {
auto faviconUrl = urlHost + linkNode.attribute("href").value();
auto downloader = Downloader();
auto fileHandle = downloader.download(faviconUrl);
if (fileHandle.success) {
auto content = getFileContent(fileHandle.path);
book.favicon = base64_encode((const unsigned char*)content.data(), content.size());
book.faviconMimeType = linkNode.attribute("type").value();
} else {
std::cerr << "Cannot get favicon content from " << faviconUrl << std::endl;
}
} else if (rel == "http://opds-spec.org/acquisition/open-access") {
book.url = linkNode.attribute("href").value();
}
}
book.setReadOnly(false);
book.updateFromOpds(entryNode, urlHost);
/* Update the book properties with the new importer */
library.addBook(book);
manipulator.addBookToLibrary(book);
}
return true;
@@ -151,11 +172,11 @@ bool Manager::parseOpdsDom(const pugi::xml_document& doc, const std::string& url
bool Manager::readOpds(const string& content, const std::string& urlHost)
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);
@@ -165,21 +186,22 @@ bool Manager::readOpds(const string& content, const std::string& urlHost)
return false;
}
bool Manager::readFile(const string path, const bool readOnly)
{
return this->readFile(path, path, readOnly);
}
bool Manager::readFile(const string nativePath,
const 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;
}
@@ -188,155 +210,37 @@ bool Manager::readFile(const 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;
}
bool Manager::writeFile(const string path)
{
pugi::xml_document doc;
/* Add the library node */
pugi::xml_node libraryNode = doc.append_child("library");
if (!getCurrentBookId().empty()) {
libraryNode.append_attribute("current") = getCurrentBookId().c_str();
}
if (!library.version.empty())
libraryNode.append_attribute("version") = library.version.c_str();
/* Add each book */
std::vector<kiwix::Book>::iterator itr;
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (!itr->readOnly) {
this->checkAndCleanBookPaths(*itr, path);
pugi::xml_node bookNode = libraryNode.append_child("book");
bookNode.append_attribute("id") = itr->id.c_str();
if (!itr->path.empty()) {
bookNode.append_attribute("path") = itr->path.c_str();
}
if (!itr->last.empty() && itr->last != "undefined") {
bookNode.append_attribute("last") = itr->last.c_str();
}
if (!itr->indexPath.empty())
bookNode.append_attribute("indexPath") = itr->indexPath.c_str();
if (!itr->indexPath.empty() || !itr->indexPathAbsolute.empty()) {
if (itr->indexType == XAPIAN) {
bookNode.append_attribute("indexType") = "xapian";
}
}
if (itr->origId.empty()) {
if (!itr->title.empty())
bookNode.append_attribute("title") = itr->title.c_str();
if (!itr->name.empty())
bookNode.append_attribute("name") = itr->name.c_str();
if (!itr->tags.empty())
bookNode.append_attribute("tags") = itr->tags.c_str();
if (!itr->description.empty())
bookNode.append_attribute("description") = itr->description.c_str();
if (!itr->language.empty())
bookNode.append_attribute("language") = itr->language.c_str();
if (!itr->creator.empty())
bookNode.append_attribute("creator") = itr->creator.c_str();
if (!itr->publisher.empty())
bookNode.append_attribute("publisher") = itr->publisher.c_str();
if (!itr->favicon.empty())
bookNode.append_attribute("favicon") = itr->favicon.c_str();
if (!itr->faviconMimeType.empty())
bookNode.append_attribute("faviconMimeType")
= itr->faviconMimeType.c_str();
}
if (!itr->date.empty()) {
bookNode.append_attribute("date") = itr->date.c_str();
}
if (!itr->url.empty()) {
bookNode.append_attribute("url") = itr->url.c_str();
}
if (!itr->origId.empty())
bookNode.append_attribute("origId") = itr->origId.c_str();
if (!itr->articleCount.empty())
bookNode.append_attribute("articleCount") = itr->articleCount.c_str();
if (!itr->mediaCount.empty())
bookNode.append_attribute("mediaCount") = itr->mediaCount.c_str();
if (!itr->size.empty()) {
bookNode.append_attribute("size") = itr->size.c_str();
}
}
}
/* saving file */
doc.save_file(path.c_str());
return true;
}
bool Manager::setCurrentBookId(const string id)
{
if (library.current.empty() || library.current.top() != id) {
if (id.empty() && !library.current.empty()) {
library.current.pop();
} else {
library.current.push(id);
}
}
return true;
}
string Manager::getCurrentBookId() const
{
return library.current.empty() ? "" : library.current.top();
}
/* Add a book to the library. Return empty string if failed, book id otherwise
*/
string Manager::addBookFromPathAndGetId(const string pathToOpen,
const string pathToSave,
const string url,
const bool checkMetaData)
std::string Manager::addBookFromPathAndGetId(const std::string& pathToOpen,
const std::string& pathToSave,
const std::string& url,
const bool checkMetaData)
{
kiwix::Book book;
if (this->readBookFromPath(pathToOpen, &book)) {
if (pathToSave != pathToOpen) {
book.path = pathToSave;
book.pathAbsolute
= isRelativePath(pathToSave)
if (!pathToSave.empty() && pathToSave != pathToOpen) {
book.setPath(isRelativePath(pathToSave)
? computeAbsolutePath(
removeLastPathElement(writableLibraryPath, true, false),
removeLastPathElement(writableLibraryPath),
pathToSave)
: pathToSave;
: pathToSave);
}
if (!checkMetaData
|| (checkMetaData && !book.title.empty() && !book.language.empty()
&& !book.date.empty())) {
book.url = url;
library.addBook(book);
return book.id;
|| (!book.getTitle().empty() && !book.getLanguages().empty()
&& !book.getDate().empty())) {
book.setUrl(url);
manipulator.addBookToLibrary(book);
return book.getId();
}
}
@@ -345,9 +249,9 @@ string Manager::addBookFromPathAndGetId(const string pathToOpen,
/* Wrapper over Manager::addBookFromPath which return a bool instead of a string
*/
bool Manager::addBookFromPath(const string pathToOpen,
const string pathToSave,
const string url,
bool Manager::addBookFromPath(const std::string& pathToOpen,
const std::string& pathToSave,
const std::string& url,
const bool checkMetaData)
{
return !(
@@ -355,380 +259,114 @@ bool Manager::addBookFromPath(const string pathToOpen,
.empty());
}
bool Manager::readBookFromPath(const string path, kiwix::Book* book)
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();
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 = new kiwix::Reader(path);
if (book != NULL) {
book->path = path;
book->pathAbsolute = path;
book->id = reader->getId();
book->description = reader->getDescription();
book->language = reader->getLanguage();
book->date = reader->getDate();
book->creator = reader->getCreator();
book->publisher = reader->getPublisher();
book->title = reader->getTitle();
book->name = reader->getName();
book->tags = reader->getTags();
book->origId = reader->getOrigId();
std::ostringstream articleCountStream;
articleCountStream << reader->getArticleCount();
book->articleCount = articleCountStream.str();
std::ostringstream mediaCountStream;
mediaCountStream << reader->getMediaCount();
book->mediaCount = mediaCountStream.str();
ostringstream convert;
convert << reader->getFileSize();
book->size = convert.str();
string favicon;
string faviconMimeType;
if (reader->getFavicon(favicon, faviconMimeType)) {
book->favicon = base64_encode(
reinterpret_cast<const unsigned char*>(favicon.c_str()),
favicon.length());
book->faviconMimeType = faviconMimeType;
}
}
delete reader;
zim::Archive archive(tmp_path);
book->update(archive);
book->setPathValid(true);
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
book->setPathValid(false);
return false;
}
return true;
}
bool Manager::removeBookByIndex(const unsigned int bookIndex)
bool Manager::readBookmarkFile(const std::string& path)
{
return this->library.removeBookByIndex(bookIndex);
}
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(path.c_str());
bool Manager::removeBookById(const string id)
{
unsigned int bookIndex = 0;
std::vector<kiwix::Book>::iterator itr;
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (itr->id == id) {
return this->library.removeBookByIndex(bookIndex);
}
bookIndex++;
}
return false;
}
vector<string> Manager::getBooksLanguages()
{
std::vector<string> booksLanguages;
std::vector<kiwix::Book>::iterator itr;
std::map<string, bool> booksLanguagesMap;
std::sort(
library.books.begin(), library.books.end(), kiwix::Book::sortByLanguage);
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (booksLanguagesMap.find(itr->language) == booksLanguagesMap.end()) {
if (itr->origId.empty()) {
booksLanguagesMap[itr->language] = true;
booksLanguages.push_back(itr->language);
}
}
}
return booksLanguages;
}
vector<string> Manager::getBooksCreators()
{
std::vector<string> booksCreators;
std::vector<kiwix::Book>::iterator itr;
std::map<string, bool> booksCreatorsMap;
std::sort(
library.books.begin(), library.books.end(), kiwix::Book::sortByCreator);
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (booksCreatorsMap.find(itr->creator) == booksCreatorsMap.end()) {
if (itr->origId.empty()) {
booksCreatorsMap[itr->creator] = true;
booksCreators.push_back(itr->creator);
}
}
}
return booksCreators;
}
vector<string> Manager::getBooksIds()
{
std::vector<string> booksIds;
std::vector<kiwix::Book>::iterator itr;
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
booksIds.push_back(itr->id);
}
return booksIds;
}
vector<string> Manager::getBooksPublishers()
{
std::vector<string> booksPublishers;
std::vector<kiwix::Book>::iterator itr;
std::map<string, bool> booksPublishersMap;
std::sort(
library.books.begin(), library.books.end(), kiwix::Book::sortByPublisher);
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (booksPublishersMap.find(itr->publisher) == booksPublishersMap.end()) {
if (itr->origId.empty()) {
booksPublishersMap[itr->publisher] = true;
booksPublishers.push_back(itr->publisher);
}
}
}
return booksPublishers;
}
kiwix::Library Manager::cloneLibrary()
{
return this->library;
}
bool Manager::getCurrentBook(Book& book)
{
string currentBookId = getCurrentBookId();
if (currentBookId.empty()) {
if (!result) {
return false;
} else {
getBookById(currentBookId, book);
return true;
}
}
bool Manager::getBookById(const string id, Book& book)
{
std::vector<kiwix::Book>::iterator itr;
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (itr->id == id) {
book = *itr;
return true;
}
}
return false;
}
bool Manager::updateBookLastOpenDateById(const string id)
{
std::vector<kiwix::Book>::iterator itr;
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (itr->id == id) {
char unixdate[12];
sprintf(unixdate, "%d", (int)time(NULL));
itr->last = unixdate;
return true;
}
}
return false;
}
pugi::xml_node libraryNode = doc.child("bookmarks");
bool Manager::setBookIndex(const string id,
const string path,
const supportedIndexType type)
{
std::vector<kiwix::Book>::iterator itr;
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (itr->id == id) {
itr->indexPath = path;
itr->indexPathAbsolute
= isRelativePath(path)
? computeAbsolutePath(
removeLastPathElement(writableLibraryPath, true, false),
path)
: path;
itr->indexType = type;
return true;
}
}
for (pugi::xml_node node = libraryNode.child("bookmark"); node;
node = node.next_sibling("bookmark")) {
kiwix::Bookmark bookmark;
return false;
}
bookmark.updateFromXml(node);
bool Manager::setBookPath(const string id, const string path)
{
std::vector<kiwix::Book>::iterator itr;
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (itr->id == id) {
itr->path = path;
itr->pathAbsolute
= isRelativePath(path)
? computeAbsolutePath(
removeLastPathElement(writableLibraryPath, true, false),
path)
: path;
return true;
}
}
return false;
}
void Manager::removeBookPaths()
{
std::vector<kiwix::Book>::iterator itr;
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
itr->path = "";
itr->pathAbsolute = "";
}
}
unsigned int Manager::getBookCount(const bool localBooks,
const bool remoteBooks)
{
unsigned int result = 0;
std::vector<kiwix::Book>::iterator itr;
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if ((!itr->path.empty() && localBooks)
|| (itr->path.empty() && remoteBooks)) {
result++;
}
}
return result;
}
bool Manager::listBooks(const supportedListMode mode,
const supportedListSortBy sortBy,
const unsigned int maxSize,
const string language,
const string creator,
const string publisher,
const string search)
{
this->bookIdList.clear();
std::vector<kiwix::Book>::iterator itr;
/* Sort */
if (sortBy == TITLE) {
std::sort(
library.books.begin(), library.books.end(), kiwix::Book::sortByTitle);
} else if (sortBy == SIZE) {
std::sort(
library.books.begin(), library.books.end(), kiwix::Book::sortBySize);
} else if (sortBy == DATE) {
std::sort(
library.books.begin(), library.books.end(), kiwix::Book::sortByDate);
} else if (sortBy == CREATOR) {
std::sort(
library.books.begin(), library.books.end(), kiwix::Book::sortByCreator);
} else if (sortBy == PUBLISHER) {
std::sort(library.books.begin(),
library.books.end(),
kiwix::Book::sortByPublisher);
}
/* Special sort for LASTOPEN */
if (mode == LASTOPEN) {
std::sort(library.books.begin(),
library.books.end(),
kiwix::Book::sortByLastOpen);
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
if (!itr->last.empty()) {
this->bookIdList.push_back(itr->id);
}
}
} else {
/* Generate the list of book id */
for (itr = library.books.begin(); itr != library.books.end(); ++itr) {
bool ok = true;
if (mode == LOCAL && itr->path.empty()) {
ok = false;
}
if (ok == true && mode == REMOTE
&& (!itr->path.empty() || itr->url.empty())) {
ok = false;
}
if (ok == true && maxSize != 0
&& (unsigned int)atoi(itr->size.c_str()) > maxSize * 1024 * 1024) {
ok = false;
}
if (ok == true && !language.empty()
&& !matchRegex(itr->language, language)) {
ok = false;
}
if (ok == true && !creator.empty() && itr->creator != creator) {
ok = false;
}
if (ok == true && !publisher.empty() && itr->publisher != publisher) {
ok = false;
}
if ((ok == true && !search.empty())
&& !(matchRegex(itr->title, "\\Q" + search + "\\E")
|| matchRegex(itr->description, "\\Q" + search + "\\E")
|| matchRegex(itr->language, "\\Q" + search + "\\E"))) {
ok = false;
}
if (ok == true) {
this->bookIdList.push_back(itr->id);
}
}
manipulator.addBookmarkToLibrary(bookmark);
}
return true;
}
Library Manager::filter(const std::string& search) {
Library library;
if (search.empty()) {
return library;
}
for(auto book:this->library.books) {
if (matchRegex(book.title, "\\Q" + search + "\\E")
|| matchRegex(book.description, "\\Q" + search + "\\E")) {
library.addBook(book);
}
}
return library;
}
void Manager::checkAndCleanBookPaths(Book& book, const string& libraryPath)
void Manager::reload(const Paths& paths)
{
if (!book.path.empty()) {
if (isRelativePath(book.path)) {
book.pathAbsolute = computeAbsolutePath(
removeLastPathElement(libraryPath, true, false), book.path);
} else {
book.pathAbsolute = book.path;
book.path = computeRelativePath(
removeLastPathElement(libraryPath, true, false), book.pathAbsolute);
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 + "'.");
}
}
}
if (!book.indexPath.empty()) {
if (isRelativePath(book.indexPath)) {
book.indexPathAbsolute = computeAbsolutePath(
removeLastPathElement(libraryPath, true, false), book.indexPath);
} else {
book.indexPathAbsolute = book.indexPath;
book.indexPath
= computeRelativePath(removeLastPathElement(libraryPath, true, false),
book.indexPathAbsolute);
}
}
manipulator.removeBooksNotUpdatedSince(libRevision);
}
}

View File

@@ -1,48 +1,60 @@
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',
'common/base64.cpp',
'common/pathTools.cpp',
'common/regexTools.cpp',
'common/stringTools.cpp',
'common/networkTools.cpp',
'common/otherTools.cpp',
'xapian/htmlparse.cc',
'xapian/myhtmlparse.cc'
'server.cpp',
'search_renderer.cpp',
'subprocess.cpp',
'aria2.cpp',
'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 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')
if host_machine.system() == 'windows'
kiwix_sources += 'subprocess_windows.cpp'
else
install_dir = get_option('libdir')
kiwix_sources += 'subprocess_unix.cpp'
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
src/name_mapper.cpp Normal file
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
src/opds_catalog.cpp Normal file
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

View File

@@ -18,12 +18,20 @@
*/
#include "opds_dumper.h"
#include "book.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 */
@@ -31,105 +39,177 @@ OPDSDumper::~OPDSDumper()
{
}
struct xml_string_writer: pugi::xml_writer
namespace
{
std::string result;
virtual void write(const void* data, size_t size)
{
result.append(static_cast<const char*>(data), size);
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;
}
std::string node_to_string(pugi::xml_node node)
std::string fullEntryXML(const Book& book,
const std::string& rootLocation,
const std::string& contentAccessUrl,
const std::string& contentId)
{
xml_string_writer writer;
node.print(writer, " ");
return writer.result;
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);
}
std::string gen_date_str()
std::string partialEntryXML(const Book& book, const std::string& rootLocation)
{
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 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);
}
#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.title);
ADD_TEXT_ENTRY(entry_node, "id", "urn:uuid:"+book.id);
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.description);
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.creator);
if (! book.url.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.url.c_str();
}
if (! book.faviconMimeType.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.faviconMimeType.c_str();
image_link.append_attribute("href") = (rootLocation + "/meta?name=favicon&content=" + book.getHumanReadableIdFromPath()).c_str();
}
return entry_node;
}
string OPDSDumper::dumpOPDSFeed()
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);
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();
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
}
}
for (auto book: library.books) {
handleBook(book, root_node);
}
return booksData;
}
return node_to_string(root_node);
} // 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
src/opds_dumper.h Normal file
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

View File

@@ -1,865 +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);
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 '/' */
while ((offset < urlLength) && (url[offset] == '/')) {
offset++;
}
/* Get namespace */
while ((offset < urlLength) && (url[offset] != '/')) {
*ns = url[offset];
offset++;
}
/* Ignore the '/' */
while ((offset < urlLength) && (url[offset] == '/')) {
offset++;
}
/* Get content title */
unsigned int titleOffset = offset;
while (offset < urlLength) {
offset++;
}
/* unescape title */
title = url.substr(titleOffset, offset - titleOffset);
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));
}
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);
}
}

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