├── cps ├── tasks │ ├── __init__.py │ └── upload.py ├── static │ ├── favicon.ico │ ├── img │ │ ├── close.png │ │ ├── save.png │ │ ├── saved.png │ │ ├── star.png │ │ ├── loader.gif │ │ ├── settings.png │ │ ├── fullscreen.png │ │ ├── menu-icon.png │ │ ├── settings-s.png │ │ ├── apple-touch-icon.png │ │ ├── cancelfullscreen.png │ │ ├── annotator-glyph-sprite.png │ │ └── annotator-icon-sprite.png │ ├── css │ │ ├── img │ │ │ ├── clear.png │ │ │ └── loading.gif │ │ ├── fonts │ │ │ ├── fontello.eot │ │ │ ├── fontello.ttf │ │ │ ├── fontello.woff │ │ │ ├── GrandHotel-Regular.ttf │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ ├── images │ │ │ ├── black-10.png │ │ │ ├── black-25.png │ │ │ ├── black-33.png │ │ │ ├── patterns │ │ │ │ ├── credits.txt │ │ │ │ ├── tweed.png │ │ │ │ ├── woven.png │ │ │ │ ├── pool_table.png │ │ │ │ ├── rubber_grip.png │ │ │ │ ├── wood_pattern.png │ │ │ │ ├── tasky_pattern.png │ │ │ │ ├── textured_paper.png │ │ │ │ ├── wood_pattern_dark.png │ │ │ │ └── pinstriped_suit_vertical.png │ │ │ ├── caliblur │ │ │ │ ├── blur-dark.png │ │ │ │ ├── blur-light.png │ │ │ │ └── blur-noise.png │ │ │ └── icomoon │ │ │ │ ├── entypo-25px-000000 │ │ │ │ ├── PNG │ │ │ │ │ ├── arrow.png │ │ │ │ │ ├── cart.png │ │ │ │ │ ├── first.png │ │ │ │ │ ├── last.png │ │ │ │ │ ├── list.png │ │ │ │ │ ├── list2.png │ │ │ │ │ ├── loop.png │ │ │ │ │ ├── music.png │ │ │ │ │ ├── pause.png │ │ │ │ │ ├── play.png │ │ │ │ │ ├── shuffle.png │ │ │ │ │ └── volume.png │ │ │ │ └── SVG │ │ │ │ │ ├── arrow.svg │ │ │ │ │ ├── volume.svg │ │ │ │ │ ├── play.svg │ │ │ │ │ ├── loop.svg │ │ │ │ │ ├── pause.svg │ │ │ │ │ ├── first.svg │ │ │ │ │ ├── last.svg │ │ │ │ │ ├── list2.svg │ │ │ │ │ ├── music.svg │ │ │ │ │ ├── cart.svg │ │ │ │ │ ├── shuffle.svg │ │ │ │ │ └── list.svg │ │ │ │ ├── entypo-25px-ffffff │ │ │ │ ├── PNG │ │ │ │ │ ├── arrow.png │ │ │ │ │ ├── cart.png │ │ │ │ │ ├── first.png │ │ │ │ │ ├── last.png │ │ │ │ │ ├── list.png │ │ │ │ │ ├── list2.png │ │ │ │ │ ├── loop.png │ │ │ │ │ ├── music.png │ │ │ │ │ ├── pause.png │ │ │ │ │ ├── play.png │ │ │ │ │ ├── shuffle.png │ │ │ │ │ └── volume.png │ │ │ │ └── SVG │ │ │ │ │ ├── arrow.svg │ │ │ │ │ ├── volume.svg │ │ │ │ │ ├── play.svg │ │ │ │ │ ├── loop.svg │ │ │ │ │ ├── pause.svg │ │ │ │ │ ├── first.svg │ │ │ │ │ ├── last.svg │ │ │ │ │ ├── list2.svg │ │ │ │ │ ├── music.svg │ │ │ │ │ ├── cart.svg │ │ │ │ │ ├── shuffle.svg │ │ │ │ │ └── list.svg │ │ │ │ ├── free-25px-000000 │ │ │ │ ├── PNG │ │ │ │ │ └── spinner.png │ │ │ │ └── SVG │ │ │ │ │ └── spinner.svg │ │ │ │ ├── free-25px-ffffff │ │ │ │ ├── PNG │ │ │ │ │ └── spinner.png │ │ │ │ └── SVG │ │ │ │ │ └── spinner.svg │ │ │ │ └── credits.txt │ │ ├── libs │ │ │ └── images │ │ │ │ ├── grab.cur │ │ │ │ ├── shadow.png │ │ │ │ ├── grabbing.cur │ │ │ │ ├── loading-icon.gif │ │ │ │ ├── treeitem-collapsed.svg │ │ │ │ ├── treeitem-expanded.svg │ │ │ │ ├── toolbarButton-bookmark.svg │ │ │ │ ├── treeitem-collapsed-dark.svg │ │ │ │ ├── treeitem-expanded-dark.svg │ │ │ │ ├── toolbarButton-bookmark-dark.svg │ │ │ │ ├── secondaryToolbarButton-spreadNone.svg │ │ │ │ ├── annotation-noicon.svg │ │ │ │ ├── secondaryToolbarButton-rotateCcw.svg │ │ │ │ ├── secondaryToolbarButton-spreadNone-dark.svg │ │ │ │ ├── toolbarButton-menuArrow.svg │ │ │ │ ├── secondaryToolbarButton-firstPage.svg │ │ │ │ ├── secondaryToolbarButton-lastPage.svg │ │ │ │ ├── secondaryToolbarButton-rotateCcw-dark.svg │ │ │ │ ├── toolbarButton-menuArrow-dark.svg │ │ │ │ ├── secondaryToolbarButton-firstPage-dark.svg │ │ │ │ ├── secondaryToolbarButton-lastPage-dark.svg │ │ │ │ ├── secondaryToolbarButton-scrollHorizontal.svg │ │ │ │ ├── secondaryToolbarButton-scrollVertical.svg │ │ │ │ ├── secondaryToolbarButton-handTool.svg │ │ │ │ ├── secondaryToolbarButton-scrollHorizontal-dark.svg │ │ │ │ ├── secondaryToolbarButton-scrollVertical-dark.svg │ │ │ │ ├── secondaryToolbarButton-handTool-dark.svg │ │ │ │ ├── toolbarButton-viewAttachments.svg │ │ │ │ ├── toolbarButton-zoomOut.svg │ │ │ │ ├── toolbarButton-presentationMode.svg │ │ │ │ ├── toolbarButton-viewAttachments-dark.svg │ │ │ │ ├── toolbarButton-zoomOut-dark.svg │ │ │ │ ├── toolbarButton-zoomIn.svg │ │ │ │ ├── toolbarButton-presentationMode-dark.svg │ │ │ │ ├── findbarButton-next.svg │ │ │ │ ├── findbarButton-previous.svg │ │ │ │ ├── toolbarButton-zoomIn-dark.svg │ │ │ │ ├── annotation-insert.svg │ │ │ │ ├── toolbarButton-search.svg │ │ │ │ ├── annotation-check.svg │ │ │ │ ├── toolbarButton-viewOutline.svg │ │ │ │ ├── findbarButton-previous-dark.svg │ │ │ │ ├── annotation-newparagraph.svg │ │ │ │ ├── findbarButton-next-dark.svg │ │ │ │ ├── toolbarButton-search-dark.svg │ │ │ │ ├── secondaryToolbarButton-scrollWrapped.svg │ │ │ │ ├── secondaryToolbarButton-selectTool.svg │ │ │ │ ├── toolbarButton-viewOutline-dark.svg │ │ │ │ ├── secondaryToolbarButton-rotateCw.svg │ │ │ │ ├── toolbarButton-pageDown.svg │ │ │ │ ├── secondaryToolbarButton-scrollWrapped-dark.svg │ │ │ │ ├── secondaryToolbarButton-selectTool-dark.svg │ │ │ │ ├── toolbarButton-pageUp.svg │ │ │ │ ├── toolbarButton-pageDown-dark.svg │ │ │ │ ├── toolbarButton-secondaryToolbarToggle.svg │ │ │ │ ├── secondaryToolbarButton-rotateCw-dark.svg │ │ │ │ ├── toolbarButton-pageUp-dark.svg │ │ │ │ ├── toolbarButton-secondaryToolbarToggle-dark.svg │ │ │ │ ├── toolbarButton-print.svg │ │ │ │ ├── secondaryToolbarButton-documentProperties.svg │ │ │ │ ├── toolbarButton-print-dark.svg │ │ │ │ ├── toolbarButton-download.svg │ │ │ │ ├── toolbarButton-viewThumbnail.svg │ │ │ │ ├── secondaryToolbarButton-documentProperties-dark.svg │ │ │ │ ├── toolbarButton-sidebarToggle.svg │ │ │ │ ├── toolbarButton-download-dark.svg │ │ │ │ ├── toolbarButton-openFile.svg │ │ │ │ ├── secondaryToolbarButton-spreadOdd.svg │ │ │ │ ├── toolbarButton-viewLayers.svg │ │ │ │ ├── toolbarButton-viewThumbnail-dark.svg │ │ │ │ ├── toolbarButton-sidebarToggle-dark.svg │ │ │ │ ├── toolbarButton-openFile-dark.svg │ │ │ │ ├── toolbarButton-viewLayers-dark.svg │ │ │ │ ├── secondaryToolbarButton-spreadOdd-dark.svg │ │ │ │ ├── annotation-comment.svg │ │ │ │ ├── secondaryToolbarButton-spreadEven.svg │ │ │ │ ├── secondaryToolbarButton-spreadEven-dark.svg │ │ │ │ ├── annotation-paragraph.svg │ │ │ │ ├── annotation-note.svg │ │ │ │ ├── annotation-key.svg │ │ │ │ ├── loading.svg │ │ │ │ ├── loading-dark.svg │ │ │ │ └── annotation-help.svg │ │ ├── upload.css │ │ ├── caliBlur_override.css │ │ ├── listen.css │ │ └── popup.css │ ├── generic_cover.jpg │ └── js │ │ ├── libs │ │ ├── djvu_html5 │ │ │ ├── img │ │ │ │ ├── blank.jpg │ │ │ │ ├── status.png │ │ │ │ └── toolbar-buttons.png │ │ │ ├── djvu_html5 │ │ │ │ ├── clear.cache.gif │ │ │ │ └── compilation-mappings.txt │ │ │ └── djvu_worker │ │ │ │ ├── clear.cache.gif │ │ │ │ └── djvu_worker.nocache.js │ │ ├── tinymce │ │ │ └── skins │ │ │ │ ├── lightgray │ │ │ │ ├── img │ │ │ │ │ ├── anchor.gif │ │ │ │ │ ├── loader.gif │ │ │ │ │ ├── object.gif │ │ │ │ │ └── trans.gif │ │ │ │ └── fonts │ │ │ │ │ ├── tinymce.eot │ │ │ │ │ ├── tinymce.ttf │ │ │ │ │ ├── tinymce.woff │ │ │ │ │ ├── tinymce-small.eot │ │ │ │ │ ├── tinymce-small.ttf │ │ │ │ │ └── tinymce-small.woff │ │ │ │ ├── ui │ │ │ │ ├── oxide │ │ │ │ │ ├── fonts │ │ │ │ │ │ └── tinymce-mobile.woff │ │ │ │ │ ├── content.mobile.min.css │ │ │ │ │ └── skin.shadowdom.min.css │ │ │ │ └── oxide-dark │ │ │ │ │ ├── fonts │ │ │ │ │ └── tinymce-mobile.woff │ │ │ │ │ ├── content.mobile.min.css │ │ │ │ │ └── skin.shadowdom.min.css │ │ │ │ └── content │ │ │ │ ├── default │ │ │ │ └── content.min.css │ │ │ │ ├── writer │ │ │ │ └── content.min.css │ │ │ │ ├── dark │ │ │ │ └── content.min.css │ │ │ │ └── document │ │ │ │ └── content.min.css │ │ ├── bootstrap-datepicker │ │ │ └── locales │ │ │ │ ├── bootstrap-datepicker.ja.min.js │ │ │ │ ├── bootstrap-datepicker.zh_Hans_CN.min.js │ │ │ │ ├── bootstrap-datepicker.tr.min.js │ │ │ │ ├── bootstrap-datepicker.sv.min.js │ │ │ │ ├── bootstrap-datepicker.km.min.js │ │ │ │ ├── bootstrap-datepicker.cs.min.js │ │ │ │ ├── bootstrap-datepicker.pt_BR.min.js │ │ │ │ ├── bootstrap-datepicker.uk.min.js │ │ │ │ ├── bootstrap-datepicker.es.min.js │ │ │ │ ├── bootstrap-datepicker.de.min.js │ │ │ │ ├── bootstrap-datepicker.nl.min.js │ │ │ │ ├── bootstrap-datepicker.hu.min.js │ │ │ │ ├── bootstrap-datepicker.it.min.js │ │ │ │ ├── bootstrap-datepicker.ru.min.js │ │ │ │ ├── bootstrap-datepicker.el.min.js │ │ │ │ ├── bootstrap-datepicker.fi.min.js │ │ │ │ ├── bootstrap-datepicker.fr.min.js │ │ │ │ └── bootstrap-datepicker.pl.min.js │ │ ├── jquery.visible.min.js │ │ ├── bootstrap-select │ │ │ ├── defaults-nl.min.js │ │ │ ├── defaults-es.min.js │ │ │ ├── defaults-hu.min.js │ │ │ ├── defaults-pl.min.js │ │ │ ├── defaults-fi.min.js │ │ │ ├── defaults-sv.min.js │ │ │ ├── defaults-it.min.js │ │ │ ├── defaults-cs.min.js │ │ │ ├── defaults-zh_Hans_CN.min.js │ │ │ ├── defaults-de.min.js │ │ │ ├── defaults-tr.min.js │ │ │ ├── defaults-fr.min.js │ │ │ ├── defaults-ja.min.js │ │ │ ├── defaults-ru.min.js │ │ │ └── defaults-km.min.js │ │ ├── context.min.js │ │ ├── screenfull.min.js │ │ └── bootstrap-rating-input.min.js │ │ ├── shelforder.js │ │ ├── logviewer.js │ │ ├── reading │ │ └── epub.js │ │ └── filter_grid.js ├── templates │ ├── fragment.html │ ├── book_exists_flash.html │ ├── generate_kobo_auth_url.html │ ├── languages.html │ ├── osd.xml │ ├── shelf_edit.html │ ├── readdjvu.html │ ├── stats.html │ ├── remote_login.html │ ├── logviewer.html │ ├── http_error.html │ ├── json.txt │ ├── shelf_order.html │ ├── grid.html │ └── tasks.html ├── translations │ ├── cs │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── de │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── el │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── es │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── fi │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── fr │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── hu │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── it │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── ja │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── km │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── nl │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── pl │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── ru │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── sv │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── tr │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── uk │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ ├── pt_BR │ │ └── LC_MESSAGES │ │ │ └── messages.mo │ └── zh_Hans_CN │ │ └── LC_MESSAGES │ │ └── messages.mo ├── services │ └── __init__.py ├── converter.py ├── subproc_wrapper.py ├── debug_info.py ├── redirect.py └── error_handler.py ├── MANIFEST.in ├── .github └── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.md │ └── bug_report.md ├── babel.cfg ├── .gitattributes ├── .editorconfig ├── requirements.txt ├── .gitignore ├── optional-requirements.txt ├── setup.py ├── .eslintrc └── setup.cfg /cps/tasks/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | graft src/calibreweb 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /cps/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/favicon.ico -------------------------------------------------------------------------------- /cps/static/img/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/close.png -------------------------------------------------------------------------------- /cps/static/img/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/save.png -------------------------------------------------------------------------------- /cps/static/img/saved.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/saved.png -------------------------------------------------------------------------------- /cps/static/img/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/star.png -------------------------------------------------------------------------------- /cps/static/img/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/loader.gif -------------------------------------------------------------------------------- /cps/static/img/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/settings.png -------------------------------------------------------------------------------- /babel.cfg: -------------------------------------------------------------------------------- 1 | [python: **.py] 2 | [jinja2: **/templates/**.*ml] 3 | extensions=jinja2.ext.autoescape,jinja2.ext.with_ -------------------------------------------------------------------------------- /cps/static/css/img/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/img/clear.png -------------------------------------------------------------------------------- /cps/static/generic_cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/generic_cover.jpg -------------------------------------------------------------------------------- /cps/static/img/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/fullscreen.png -------------------------------------------------------------------------------- /cps/static/img/menu-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/menu-icon.png -------------------------------------------------------------------------------- /cps/static/img/settings-s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/settings-s.png -------------------------------------------------------------------------------- /cps/static/css/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/img/loading.gif -------------------------------------------------------------------------------- /cps/static/css/fonts/fontello.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/fonts/fontello.eot -------------------------------------------------------------------------------- /cps/static/css/fonts/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/fonts/fontello.ttf -------------------------------------------------------------------------------- /cps/static/css/fonts/fontello.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/fonts/fontello.woff -------------------------------------------------------------------------------- /cps/static/css/images/black-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/black-10.png -------------------------------------------------------------------------------- /cps/static/css/images/black-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/black-25.png -------------------------------------------------------------------------------- /cps/static/css/images/black-33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/black-33.png -------------------------------------------------------------------------------- /cps/static/css/images/patterns/credits.txt: -------------------------------------------------------------------------------- 1 | Patterns from subtlepatterns.com. 2 | "If you need more, that's where to get 'em." -------------------------------------------------------------------------------- /cps/static/css/libs/images/grab.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/libs/images/grab.cur -------------------------------------------------------------------------------- /cps/static/css/libs/images/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/libs/images/shadow.png -------------------------------------------------------------------------------- /cps/static/img/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/apple-touch-icon.png -------------------------------------------------------------------------------- /cps/static/img/cancelfullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/cancelfullscreen.png -------------------------------------------------------------------------------- /cps/static/css/libs/images/grabbing.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/libs/images/grabbing.cur -------------------------------------------------------------------------------- /cps/static/css/images/patterns/tweed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/patterns/tweed.png -------------------------------------------------------------------------------- /cps/static/css/images/patterns/woven.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/patterns/woven.png -------------------------------------------------------------------------------- /cps/static/img/annotator-glyph-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/annotator-glyph-sprite.png -------------------------------------------------------------------------------- /cps/static/img/annotator-icon-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/img/annotator-icon-sprite.png -------------------------------------------------------------------------------- /cps/static/css/fonts/GrandHotel-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/fonts/GrandHotel-Regular.ttf -------------------------------------------------------------------------------- /cps/static/css/images/caliblur/blur-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/caliblur/blur-dark.png -------------------------------------------------------------------------------- /cps/static/css/libs/images/loading-icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/libs/images/loading-icon.gif -------------------------------------------------------------------------------- /cps/static/css/libs/images/treeitem-collapsed.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/treeitem-expanded.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/djvu_html5/img/blank.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/djvu_html5/img/blank.jpg -------------------------------------------------------------------------------- /cps/static/js/libs/djvu_html5/img/status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/djvu_html5/img/status.png -------------------------------------------------------------------------------- /cps/templates/fragment.html: -------------------------------------------------------------------------------- 1 |
2 | {% block body %}{% endblock %} 3 |
4 | {% block js %}{% endblock %} 5 | -------------------------------------------------------------------------------- /cps/translations/cs/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/cs/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/de/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/de/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/el/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/el/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/es/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/es/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/fi/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/fi/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/fr/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/fr/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/hu/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/hu/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/it/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/it/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/ja/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/ja/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/km/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/km/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/nl/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/nl/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/pl/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/pl/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/ru/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/ru/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/sv/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/sv/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/tr/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/tr/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/translations/uk/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/uk/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/static/css/images/caliblur/blur-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/caliblur/blur-light.png -------------------------------------------------------------------------------- /cps/static/css/images/caliblur/blur-noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/caliblur/blur-noise.png -------------------------------------------------------------------------------- /cps/static/css/images/patterns/pool_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/patterns/pool_table.png -------------------------------------------------------------------------------- /cps/static/css/images/patterns/rubber_grip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/patterns/rubber_grip.png -------------------------------------------------------------------------------- /cps/static/css/images/patterns/wood_pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/patterns/wood_pattern.png -------------------------------------------------------------------------------- /cps/translations/pt_BR/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/pt_BR/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cps/static/css/images/patterns/tasky_pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/patterns/tasky_pattern.png -------------------------------------------------------------------------------- /cps/static/css/images/patterns/textured_paper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/patterns/textured_paper.png -------------------------------------------------------------------------------- /cps/static/css/images/patterns/wood_pattern_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/patterns/wood_pattern_dark.png -------------------------------------------------------------------------------- /cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | constants.py ident export-subst 2 | /test export-ignore 3 | cps/static/css/libs/* linguist-vendored 4 | cps/static/js/libs/* linguist-vendored 5 | -------------------------------------------------------------------------------- /cps/static/css/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /cps/static/css/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /cps/static/css/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /cps/static/js/libs/djvu_html5/img/toolbar-buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/djvu_html5/img/toolbar-buttons.png -------------------------------------------------------------------------------- /cps/static/css/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-bookmark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/djvu_html5/djvu_html5/clear.cache.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/djvu_html5/djvu_html5/clear.cache.gif -------------------------------------------------------------------------------- /cps/static/js/libs/djvu_html5/djvu_worker/clear.cache.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/djvu_html5/djvu_worker/clear.cache.gif -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/img/anchor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/img/anchor.gif -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/img/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/img/loader.gif -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/img/object.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/img/object.gif -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/img/trans.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/img/trans.gif -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | 8 | [*.{js,py}] 9 | indent_size = 4 10 | -------------------------------------------------------------------------------- /cps/static/css/images/patterns/pinstriped_suit_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/patterns/pinstriped_suit_vertical.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/arrow.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/cart.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/first.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/last.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/list.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/list2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/list2.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/loop.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/music.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/pause.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/play.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/arrow.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/cart.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/first.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/last.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/list.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/list2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/list2.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/loop.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/music.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/pause.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/play.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/free-25px-000000/PNG/spinner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/free-25px-000000/PNG/spinner.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/free-25px-ffffff/PNG/spinner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/free-25px-ffffff/PNG/spinner.png -------------------------------------------------------------------------------- /cps/static/css/libs/images/treeitem-collapsed-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/treeitem-expanded-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce.eot -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce.ttf -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce.woff -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/shuffle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/shuffle.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/PNG/volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-000000/PNG/volume.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/shuffle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/shuffle.png -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/css/images/icomoon/entypo-25px-ffffff/PNG/volume.png -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce-small.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce-small.eot -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce-small.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce-small.ttf -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce-small.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/lightgray/fonts/tinymce-small.woff -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/ui/oxide-dark/fonts/tinymce-mobile.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idalin/calibre-web/HEAD/cps/static/js/libs/tinymce/skins/ui/oxide-dark/fonts/tinymce-mobile.woff -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-bookmark-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/upload.css: -------------------------------------------------------------------------------- 1 | @media (min-device-width: 768px) { 2 | .upload-modal-dialog { 3 | position: absolute; 4 | top: 45%; 5 | left: 50%; 6 | transform: translate(-50%, -50%) !important; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-spreadNone.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/annotation-noicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /cps/templates/book_exists_flash.html: -------------------------------------------------------------------------------- 1 | 2 | {{entry.title|shortentitle}} 3 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-rotateCcw.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-spreadNone-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-menuArrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/djvu_html5/djvu_worker/djvu_worker.nocache.js: -------------------------------------------------------------------------------- 1 | self.$wnd=self;self.$doc=self;function djvu_worker(){var c='81EB501BD7AB47786C30D3175CE1EA2B',d='.cache.js',e='djvu_worker',f='';var b;try{b=c}catch(a){return}importScripts(b+d);gwtOnLoad(undefined,e,f)} 2 | djvu_worker(); -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/credits.txt: -------------------------------------------------------------------------------- 1 | SVG icons via Icomoon 2 | https://icomoon.io/app 3 | 4 | Icons used from the following sets: 5 | * Entypo - Creative Commons BY-SA 3.0 http://creativecommons.org/licenses/by-sa/3.0/us/ 6 | * IcoMoon - Free (GPL) http://www.gnu.org/licenses/gpl.html -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-firstPage.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-lastPage.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-rotateCcw-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-menuArrow-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-firstPage-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-lastPage-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-scrollHorizontal.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-scrollVertical.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-handTool.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-scrollHorizontal-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-scrollVertical-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/templates/generate_kobo_auth_url.html: -------------------------------------------------------------------------------- 1 | {% extends "fragment.html" %} 2 | {% block body %} 3 |
4 |

5 | {{_('Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):')}} 6 |

7 |

8 | {% if not warning %}api_endpoint={{kobo_auth_url}}{% else %}{{warning}}{% endif %} 9 |

10 |

11 |

12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-handTool-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-viewAttachments.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-zoomOut.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-presentationMode.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-viewAttachments-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-zoomOut-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/js/libs/djvu_html5/djvu_html5/compilation-mappings.txt: -------------------------------------------------------------------------------- 1 | 091ECB3AE852C68866FBC86AA8FCDB1F.cache.js 2 | user.agent ie8 3 | 4 | 1A420474460884E73E3288F783AD7024.cache.js 5 | user.agent ie10 6 | 7 | 3CFDA9D9AFA2798299BBAE243DB2E9B5.cache.js 8 | user.agent safari 9 | 10 | 564CB406D925C79CCD67EB98CA5AD4EF.cache.js 11 | user.agent gecko1_8 12 | 13 | A8305F17E026239876FCBC730B035A55.cache.js 14 | user.agent ie9 15 | 16 | Devmode:devmode.js -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-zoomIn.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ja.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.ja={days:["日曜","月曜","火曜","水曜","木曜","金曜","土曜"],daysShort:["日","月","火","水","木","金","土"],daysMin:["日","月","火","水","木","金","土"],months:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今日",format:"yyyy/mm/dd",titleFormat:"yyyy年mm月",clear:"クリア"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-presentationMode-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/findbarButton-next.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/findbarButton-previous.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-zoomIn-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Babel>=1.3, <2.9 2 | Flask-Babel>=0.11.1,<2.1.0 3 | Flask-Login>=0.3.2,<0.5.1 4 | Flask-Principal>=0.3.2,<0.5.1 5 | singledispatch>=3.4.0.0,<3.5.0.0 6 | backports_abc>=0.4 7 | Flask>=1.0.2,<1.2.0 8 | iso-639>=0.4.5,<0.5.0 9 | PyPDF3>=1.0.0,<1.0.4 10 | pytz>=2016.10 11 | requests>=2.11.1,<2.25.0 12 | SQLAlchemy>=1.3.0,<1.4.0 # oauth fails on 1.4+ due to import problems in flask_dance 13 | tornado>=4.1,<6.2 14 | Wand>=0.4.4,<0.7.0 15 | unidecode>=0.04.19,<1.2.0 16 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/annotation-insert.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-search.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Python ### 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # Distribution / packaging 8 | .Python 9 | env/ 10 | venv/ 11 | eggs/ 12 | dist/ 13 | executable/ 14 | build/ 15 | vendor/ 16 | .eggs/ 17 | *.egg-info/ 18 | .installed.cfg 19 | *.egg 20 | .pylint.d 21 | 22 | # calibre-web 23 | *.db 24 | *.log 25 | 26 | .idea/ 27 | *.bak 28 | *.log.* 29 | 30 | settings.yaml 31 | gdrive_credentials 32 | client_secrets.json 33 | gmail.json 34 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/annotation-check.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-viewOutline.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.zh_Hans_CN.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates["zh-CN"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["周日","周一","周二","周三","周四","周五","周六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今天",monthsTitle:"选择月份",clear:"清除",format:"yyyy-mm-dd",titleFormat:"yyyy年mm月",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/libs/images/findbarButton-previous-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/annotation-newparagraph.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/findbarButton-next-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-search-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-scrollWrapped.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-selectTool.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-viewOutline-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tr.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.tr={days:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],daysShort:["Pz","Pzt","Sal","Çrş","Prş","Cu","Cts"],daysMin:["Pz","Pzt","Sa","Çr","Pr","Cu","Ct"],months:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],monthsShort:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],today:"Bugün",clear:"Temizle",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sv.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.sv={days:["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],daysShort:["sön","mån","tis","ons","tor","fre","lör"],daysMin:["sö","må","ti","on","to","fr","lö"],months:["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],monthsShort:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],today:"Idag",format:"yyyy-mm-dd",weekStart:1,clear:"Rensa"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-rotateCw.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-pageDown.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.km.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.km={days:["អាទិត្យ","ចន្ទ","អង្គារ","ពុធ","ព្រហស្បតិ៍","សុក្រ","សៅរ៍"],daysShort:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍"],daysMin:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍"],months:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],monthsShort:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],today:"ថ្ងៃនេះ",clear:"សំអាត"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/caliBlur_override.css: -------------------------------------------------------------------------------- 1 | body.serieslist.grid-view div.container-fluid > div > div.col-sm-10::before { 2 | display: none; 3 | } 4 | 5 | .cover .badge { 6 | position: absolute; 7 | top: 0; 8 | left: 0; 9 | color: #fff; 10 | background-color: #cc7b19; 11 | border-radius: 0; 12 | padding: 0 8px; 13 | box-shadow: 0 0 4px rgba(0, 0, 0, 0.6); 14 | line-height: 24px; 15 | } 16 | 17 | .cover { 18 | box-shadow: 0 0 4px rgba(0, 0, 0, 0.6); 19 | } 20 | 21 | .cover .read { 22 | padding: 0 0; 23 | line-height: 15px; 24 | } 25 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.cs={days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota"],daysShort:["Ned","Pon","Úte","Stř","Čtv","Pát","Sob"],daysMin:["Ne","Po","Út","St","Čt","Pá","So"],months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],monthsShort:["Led","Úno","Bře","Dub","Kvě","Čer","Čnc","Srp","Zář","Říj","Lis","Pro"],today:"Dnes",clear:"Vymazat",monthsTitle:"Měsíc",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pt_BR.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates["pt-BR"]={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",monthsTitle:"Meses",clear:"Limpar",format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uk.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.uk={days:["Неділя","Понеділок","Вівторок","Середа","Четвер","П'ятниця","Субота"],daysShort:["Нед","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Cічень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],monthsShort:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],today:"Сьогодні",clear:"Очистити",format:"dd.mm.yyyy",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/volume.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/volume.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-scrollWrapped-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.es.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.es={days:["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"],daysShort:["Dom","Lun","Mar","Mié","Jue","Vie","Sáb"],daysMin:["Do","Lu","Ma","Mi","Ju","Vi","Sa"],months:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],monthsShort:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],today:"Hoy",monthsTitle:"Meses",clear:"Borrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-selectTool-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.de={days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fre","Sam"],daysMin:["So","Mo","Di","Mi","Do","Fr","Sa"],months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",monthsTitle:"Monate",clear:"Löschen",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.nl.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.nl={days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],daysShort:["zo","ma","di","wo","do","vr","za"],daysMin:["zo","ma","di","wo","do","vr","za"],months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthsShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],today:"Vandaag",monthsTitle:"Maanden",clear:"Wissen",weekStart:1,format:"dd-mm-yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-pageUp.svg: -------------------------------------------------------------------------------- 1 | 4 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hu.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.hu={days:["vasárnap","hétfő","kedd","szerda","csütörtök","péntek","szombat"],daysShort:["vas","hét","ked","sze","csü","pén","szo"],daysMin:["V","H","K","Sze","Cs","P","Szo"],months:["január","február","március","április","május","június","július","augusztus","szeptember","október","november","december"],monthsShort:["jan","feb","már","ápr","máj","jún","júl","aug","sze","okt","nov","dec"],today:"ma",weekStart:1,clear:"töröl",titleFormat:"yyyy. MM",format:"yyyy.mm.dd"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.it.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.it={days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],daysShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],daysMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthsShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],today:"Oggi",monthsTitle:"Mesi",clear:"Cancella",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ru.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.ru={days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],daysShort:["Вск","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Сегодня",clear:"Очистить",format:"dd.mm.yyyy",weekStart:1,monthsTitle:"Месяцы"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-pageDown-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-secondaryToolbarToggle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.el={days:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],daysShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],daysMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],months:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthsShort:["Ιαν","Φεβ","Μαρ","Απρ","Μάι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],today:"Σήμερα",clear:"Καθαρισμός",weekStart:1,format:"d/m/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fi.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.fi={days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai"],daysShort:["sun","maa","tii","kes","tor","per","lau"],daysMin:["su","ma","ti","ke","to","pe","la"],months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],monthsShort:["tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mar","jou"],today:"tänään",clear:"Tyhjennä",weekStart:1,format:"d.m.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-rotateCw-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fr.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.fr={days:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],daysShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],daysMin:["d","l","ma","me","j","v","s"],months:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthsShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],today:"Aujourd'hui",monthsTitle:"Mois",clear:"Effacer",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pl.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.pl={days:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],daysShort:["Niedz.","Pon.","Wt.","Śr.","Czw.","Piąt.","Sob."],daysMin:["Ndz.","Pn.","Wt.","Śr.","Czw.","Pt.","Sob."],months:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthsShort:["Sty.","Lut.","Mar.","Kwi.","Maj","Cze.","Lip.","Sie.","Wrz.","Paź.","Lis.","Gru."],today:"Dzisiaj",weekStart:1,clear:"Wyczyść",format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-pageUp-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-secondaryToolbarToggle-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/ui/oxide/content.mobile.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | .tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse} 8 | -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/ui/oxide-dark/content.mobile.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | .tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse} 8 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/loop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/loop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-print.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-documentProperties.svg: -------------------------------------------------------------------------------- 1 | 4 | 6 | 8 | 9 | 11 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-print-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-download.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-viewThumbnail.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-documentProperties-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-sidebarToggle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/tasks/upload.py: -------------------------------------------------------------------------------- 1 | from __future__ import division, print_function, unicode_literals 2 | 3 | from datetime import datetime 4 | from cps.services.worker import CalibreTask, STAT_FINISH_SUCCESS 5 | 6 | class TaskUpload(CalibreTask): 7 | def __init__(self, taskMessage): 8 | super(TaskUpload, self).__init__(taskMessage) 9 | self.start_time = self.end_time = datetime.now() 10 | self.stat = STAT_FINISH_SUCCESS 11 | self.progress = 1 12 | 13 | def run(self, worker_thread): 14 | """Upload task doesn't have anything to do, it's simply a way to add information to the task list""" 15 | 16 | @property 17 | def name(self): 18 | return "Upload" 19 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-download-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-openFile.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-spreadOdd.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-viewLayers.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-viewThumbnail-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-sidebarToggle-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/first.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/first.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-openFile-dark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/last.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/last.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/toolbarButton-viewLayers-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-spreadOdd-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/list2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/list2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/templates/languages.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

{{title}}

4 |
5 |
6 | {% for lang in languages %} 7 | {% if loop.index0 == (loop.length/2)|int and loop.length > 20 %} 8 |
9 |
10 | {% endif %} 11 |
12 |
{{lang_counter[loop.index0].bookcount}}
13 | 14 |
15 | {% endfor %} 16 |
17 |
18 | {% endblock %} 19 | 20 | -------------------------------------------------------------------------------- /cps/static/js/libs/jquery.visible.min.js: -------------------------------------------------------------------------------- 1 | !function(t){var i=t(window);t.fn.visible=function(t,e,o){if(!(this.length<1)){var r=this.length>1?this.eq(0):this,n=r.get(0),f=i.width(),h=i.height(),o=o?o:"both",l=e===!0?n.offsetWidth*n.offsetHeight:!0;if("function"==typeof n.getBoundingClientRect){var g=n.getBoundingClientRect(),u=g.top>=0&&g.top0&&g.bottom<=h,c=g.left>=0&&g.left0&&g.right<=f,v=t?u||s:u&&s,b=t?c||a:c&&a;if("both"===o)return l&&v&&b;if("vertical"===o)return l&&v;if("horizontal"===o)return l&&b}else{var d=i.scrollTop(),p=d+h,w=i.scrollLeft(),m=w+f,y=r.offset(),z=y.top,B=z+r.height(),C=y.left,R=C+r.width(),j=t===!0?B:z,q=t===!0?z:B,H=t===!0?R:C,L=t===!0?C:R;if("both"===o)return!!l&&p>=q&&j>=d&&m>=L&&H>=w;if("vertical"===o)return!!l&&p>=q&&j>=d;if("horizontal"===o)return!!l&&m>=L&&H>=w}}}}(jQuery); 2 | -------------------------------------------------------------------------------- /cps/templates/osd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{instance}} 4 | {{instance}} 5 | {{_('Calibre-Web eBook Catalog')}} 6 | Janeczku 7 | https://github.com/janeczku/calibre-web 8 | 10 | 12 | open 13 | {{lang}} 14 | UTF-8 15 | UTF-8 16 | 17 | -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/ui/oxide/skin.shadowdom.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;left:0;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;position:fixed;top:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox.tox-tinymce.tox-fullscreen{background-color:transparent;z-index:1200}.tox-shadowhost.tox-fullscreen{z-index:1200}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201} 8 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/music.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/music.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;left:0;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;position:fixed;top:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox.tox-tinymce.tox-fullscreen{background-color:transparent;z-index:1200}.tox-shadowhost.tox-fullscreen{z-index:1200}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201} 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for Calibre-Web 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | **Is your feature request related to a problem? Please describe.** 13 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 14 | 15 | **Describe the solution you'd like** 16 | A clear and concise description of what you want to happen. 17 | 18 | **Describe alternatives you've considered** 19 | A clear and concise description of any alternative solutions or features you've considered. 20 | 21 | **Additional context** 22 | Add any other context or screenshots about the feature request here. 23 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-nl.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Niets geselecteerd",noneResultsText:"Geen resultaten gevonden voor {0}",countSelectedText:"{0} van {1} geselecteerd",maxOptionsText:["Limiet bereikt ({n} {var} max)","Groep limiet bereikt ({n} {var} max)",["items","item"]],selectAllText:"Alles selecteren",deselectAllText:"Alles deselecteren",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-es.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,o){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return o(e)}):"object"==typeof module&&module.exports?module.exports=o(require("jquery")):o(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"No hay selecci\xf3n",noneResultsText:"No hay resultados {0}",countSelectedText:"Seleccionados {0} de {1}",maxOptionsText:["L\xedmite alcanzado ({n} {var} max)","L\xedmite del grupo alcanzado({n} {var} max)",["elementos","element"]],multipleSeparator:", ",selectAllText:"Seleccionar Todos",deselectAllText:"Desmarcar Todos"}}); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-hu.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"V\xe1lasszon!",noneResultsText:"Nincs tal\xe1lat {0}",countSelectedText:function(e,t){return"{0} elem kiv\xe1lasztva"},maxOptionsText:function(e,t){return["Legfeljebb {n} elem v\xe1laszthat\xf3","A csoportban legfeljebb {n} elem v\xe1laszthat\xf3"]},selectAllText:"Mind",deselectAllText:"Egyik sem",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/cart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/cart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-pl.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,n){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return n(e)}):"object"==typeof module&&module.exports?module.exports=n(require("jquery")):n(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Nic nie zaznaczono",noneResultsText:"Brak wynik\xf3w wyszukiwania {0}",countSelectedText:"Zaznaczono {0} z {1}",maxOptionsText:["Osi\u0105gni\u0119to limit ({n} {var} max)","Limit grupy osi\u0105gni\u0119ty ({n} {var} max)",["elementy","element"]],selectAllText:"Zaznacz wszystkie",deselectAllText:"Odznacz wszystkie",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-fi.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Ei valintoja",noneResultsText:"Ei hakutuloksia {0}",countSelectedText:function(e,t){return 1==e?"{0} valittu":"{0} valitut"},maxOptionsText:function(e,t){return["Valintojen maksimim\xe4\xe4r\xe4 ({n} saavutettu)","Ryhm\xe4n maksimim\xe4\xe4r\xe4 ({n} saavutettu)"]},selectAllText:"Valitse kaikki",deselectAllText:"Poista kaikki",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-sv.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Inget valt",noneResultsText:"Inget s\xf6kresultat matchar {0}",countSelectedText:function(e,t){return 1===e?"{0} alternativ valt":"{0} alternativ valda"},maxOptionsText:function(e,t){return["Gr\xe4ns uppn\xe5d (max {n} alternativ)","Gr\xe4ns uppn\xe5d (max {n} gruppalternativ)"]},selectAllText:"Markera alla",deselectAllText:"Avmarkera alla",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /optional-requirements.txt: -------------------------------------------------------------------------------- 1 | # GDrive Integration 2 | gevent>20.6.0,<21.2.0 3 | greenlet>=0.4.17,<1.1.0 4 | httplib2>=0.9.2,<0.18.0 5 | oauth2client>=4.0.0,<4.1.4 6 | uritemplate>=3.0.0,<3.1.0 7 | pyasn1-modules>=0.0.8,<0.3.0 8 | pyasn1>=0.1.9,<0.5.0 9 | PyDrive2>=1.3.1,<1.8.0 10 | PyYAML>=3.12 11 | rsa>=3.4.2,<4.1.0 12 | six>=1.10.0,<1.15.0 13 | 14 | # Gdrive and Gmail integration 15 | google-api-python-client>=1.7.11,<2.1.0 16 | 17 | # Gmail 18 | google-auth-oauthlib>=0.4.3,<0.5.0 19 | 20 | # goodreads 21 | goodreads>=0.3.2,<0.4.0 22 | python-Levenshtein>=0.12.0,<0.13.0 23 | 24 | # ldap login 25 | python-ldap>=3.0.0,<3.4.0 26 | Flask-SimpleLDAP>=1.4.0,<1.5.0 27 | 28 | #oauth 29 | Flask-Dance>=1.4.0,<4.1.0 30 | SQLAlchemy-Utils>=0.33.5,<0.38.0 31 | 32 | # extracting metadata 33 | lxml>=3.8.0,<4.7.0 34 | rarfile>=2.7 35 | 36 | # other 37 | natsort>=2.2.0,<7.1.0 38 | comicapi>= 2.2.0,<2.3.0 39 | 40 | #Kobo integration 41 | jsonschema>=3.2.0,<3.3.0 42 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-it.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Nessuna selezione",noneResultsText:"Nessun risultato per {0}",countSelectedText:function(e,t){return 1==e?"Selezionato {0} di {1}":"Selezionati {0} di {1}"},maxOptionsText:["Limite raggiunto ({n} {var} max)","Limite del gruppo raggiunto ({n} {var} max)",["elementi","elemento"]],multipleSeparator:", ",selectAllText:"Seleziona Tutto",deselectAllText:"Deseleziona Tutto"}}); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-cs.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,n){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return n(e)}):"object"==typeof module&&module.exports?module.exports=n(require("jquery")):n(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Vyberte ze seznamu",noneResultsText:"Pro hled\xe1n\xed {0} nebyly nalezeny \u017e\xe1dn\xe9 v\xfdsledky",countSelectedText:"Vybran\xe9 {0} z {1}",maxOptionsText:["Limit p\u0159ekro\u010den ({n} {var} max)","Limit skupiny p\u0159ekro\u010den ({n} {var} max)",["polo\u017eek","polo\u017eka"]],multipleSeparator:", ",selectAllText:"Vybrat v\u0161e",deselectAllText:"Zru\u0161it v\xfdb\u011br"}}); -------------------------------------------------------------------------------- /cps/static/css/libs/images/annotation-comment.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /cps/templates/shelf_edit.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
4 |

{{title}}

5 |
6 |
7 | 8 | 9 |
10 | {% if g.user.role_edit_shelfs() %} 11 |
12 | 15 |
16 | {% endif %} 17 | 18 | {% if shelf.id != None %} 19 | {{_('Cancel')}} 20 | {% endif %} 21 |
22 |
23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-000000/SVG/shuffle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/shuffle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-zh_Hans_CN.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u9879",noneResultsText:"\u6ca1\u6709\u627e\u5230\u5339\u914d\u9879",countSelectedText:"\u9009\u4e2d{1}\u4e2d\u7684{0}\u9879",maxOptionsText:["\u8d85\u51fa\u9650\u5236 (\u6700\u591a\u9009\u62e9{n}\u9879)","\u7ec4\u9009\u62e9\u8d85\u51fa\u9650\u5236(\u6700\u591a\u9009\u62e9{n}\u7ec4)"],multipleSeparator:", ",selectAllText:"\u5168\u9009",deselectAllText:"\u53d6\u6d88\u5168\u9009"}}); -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-spreadEven.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-de.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Bitte w\xe4hlen...",noneResultsText:"Keine Ergebnisse f\xfcr {0}",countSelectedText:function(e,t){return 1==e?"{0} Element ausgew\xe4hlt":"{0} Elemente ausgew\xe4hlt"},maxOptionsText:function(e,t){return[1==e?"Limit erreicht ({n} Element max.)":"Limit erreicht ({n} Elemente max.)",1==t?"Gruppen-Limit erreicht ({n} Element max.)":"Gruppen-Limit erreicht ({n} Elemente max.)"]},selectAllText:"Alles ausw\xe4hlen",deselectAllText:"Nichts ausw\xe4hlen",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-tr.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,i){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return i(e)}):"object"==typeof module&&module.exports?module.exports=i(require("jquery")):i(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Hi\xe7biri se\xe7ilmedi",noneResultsText:"Hi\xe7bir sonu\xe7 bulunamad\u0131 {0}",countSelectedText:function(e,i){return"{0} \xf6\u011fe se\xe7ildi"},maxOptionsText:function(e,i){return[1==e?"Limit a\u015f\u0131ld\u0131 (maksimum {n} say\u0131da \xf6\u011fe )":"Limit a\u015f\u0131ld\u0131 (maksimum {n} say\u0131da \xf6\u011fe)","Grup limiti a\u015f\u0131ld\u0131 (maksimum {n} say\u0131da \xf6\u011fe)"]},selectAllText:"T\xfcm\xfcn\xfc Se\xe7",deselectAllText:"Se\xe7iniz",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /cps/static/css/libs/images/secondaryToolbarButton-spreadEven-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-fr.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Aucune s\xe9lection",noneResultsText:"Aucun r\xe9sultat pour {0}",countSelectedText:function(e,t){return 1 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/entypo-25px-ffffff/SVG/list.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-ja.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093",noneResultsText:"'{0}'\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093",countSelectedText:"{0}/{1} \u9078\u629e\u4e2d",maxOptionsText:["\u9078\u629e\u4e0a\u9650\u6570\u3092\u8d85\u3048\u3066\u3044\u307e\u3059(\u6700\u5927{n}{var})","\u30b0\u30eb\u30fc\u30d7\u306e\u9078\u629e\u4e0a\u9650\u6570\u3092\u8d85\u3048\u3066\u3044\u307e\u3059(\u6700\u5927{n}{var})",["\u30a2\u30a4\u30c6\u30e0","\u30a2\u30a4\u30c6\u30e0"]],selectAllText:"\u5168\u3066\u9078\u629e",deselectAllText:"\u9078\u629e\u3092\u30af\u30ea\u30a2",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /cps/static/css/libs/images/annotation-paragraph.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/annotation-note.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 14 | 21 | 28 | 35 | 42 | 43 | -------------------------------------------------------------------------------- /cps/templates/readdjvu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Djvu HTML5 browser demo 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 |
27 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /cps/templates/stats.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

{{_('About')}} {{instance}}

4 |

{{instance}} powered by 5 | Calibre-Web. 6 |

7 |

{{_('Library Statistics')}}

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
{{bookcounter}}{{_('Books in this Library')}}
{{authorcounter}}{{_('Authors in this Library')}}
{{categorycounter}}{{_('Categories in this Library')}}
{{seriecounter}}{{_('Series in this Library')}}
28 | {% if g.user.role_admin() %} 29 |

{{_('System Statistics')}}

30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | {% for library,version in versions.items() %} 39 | {% if version %} 40 | 41 | 42 | 43 | 44 | {% endif %} 45 | {% endfor %} 46 | 47 |
{{_('Program Library')}}{{_('Installed Version')}}
{{library}}{{_(version)}}
48 | {% endif %} 49 | {% endblock %} 50 | -------------------------------------------------------------------------------- /cps/templates/remote_login.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
4 |

{{_('Magic Link - Authorise New Device')}}

5 |

6 | {{_('On another device, login and visit:')}} 7 |

{{verify_url}} 8 |

9 |

10 | {{_('Once verified, you will automatically be logged in on this device.')}} 11 |

12 |

13 | {{_('This verification link will expire in 10 minutes.')}} 14 |

15 |
16 | {% endblock %} 17 | 18 | {% block js %} 19 | 41 | {% endblock %} 42 | -------------------------------------------------------------------------------- /cps/templates/logviewer.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
4 | {% if log_enable %} 5 |
6 | {{logfiles[0]}}
7 | {% else %} 8 |
{{_("Stream output, can't be displayed")}}
9 | {% endif %} 10 | {% if accesslog_enable %} 11 |
12 | {{logfiles[1]}}
13 | {% endif %} 14 |
15 |
16 |
17 | {% if log_enable %} 18 | {{_('Download Calibre-Web Log')}} 19 | {% endif %} 20 | {% if accesslog_enable %} 21 | {{_('Download Access Log')}} 22 | {% endif %} 23 |
24 |
25 |
26 | 27 | {% endblock %} 28 | {% block js %} 29 | 30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/content/default/content.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem} 8 | -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/content/writer/content.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem auto;max-width:900px}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem} 8 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/annotation-key.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /cps/static/css/listen.css: -------------------------------------------------------------------------------- 1 | .sm2-bar-ui { 2 | font-size: 20px; 3 | } 4 | 5 | .sm2-bar-ui.compact { 6 | max-width: 90%; 7 | } 8 | 9 | .sm2-progress .sm2-progress-ball { 10 | width: 0.5333em; 11 | height: 1.9333em; 12 | border-radius: 0; 13 | } 14 | 15 | .sm2-progress .sm2-progress-track { 16 | height: 0.15em; 17 | background: white; 18 | } 19 | 20 | .sm2-bar-ui .sm2-main-controls, 21 | .sm2-bar-ui .sm2-playlist-drawer { 22 | background-color: transparent; 23 | } 24 | 25 | .sm2-bar-ui .sm2-inline-texture { 26 | background: transparent; 27 | } 28 | 29 | .rating .glyphicon-star { 30 | color: gray; 31 | } 32 | 33 | .rating .glyphicon-star.good { 34 | color: white; 35 | } 36 | 37 | body { 38 | overflow: hidden; 39 | background: #272b30; 40 | color: #aaa; 41 | } 42 | 43 | #main { 44 | position: absolute; 45 | width: 100%; 46 | height: 100%; 47 | } 48 | 49 | #area { 50 | width: 80%; 51 | height: 80%; 52 | margin: 5% auto; 53 | max-width: 1250px; 54 | overflow: hidden; 55 | } 56 | 57 | #area iframe { 58 | border: none; 59 | } 60 | 61 | #prev { 62 | left: 40px; 63 | } 64 | 65 | #next { 66 | right: 40px; 67 | } 68 | 69 | pre { 70 | display: block; 71 | margin: 1em 0; 72 | white-space: pre-wrap; 73 | word-wrap: break-word; 74 | font-family: -moz-fixed, sans-serif; 75 | column-count: 2; 76 | -webkit-columns: 2; 77 | -moz-columns: 2; 78 | column-gap: 20px; 79 | -moz-column-gap: 20px; 80 | -webkit-column-gap: 20px; 81 | position: relative; 82 | } 83 | -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/content/dark/content.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | body{background-color:#2f3742;color:#dfe0e4;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}a{color:#4099ff}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#6d737b}figure{display:table;margin:1rem auto}figure figcaption{color:#8a8f97;display:block;margin-top:.25rem;text-align:center}hr{border-color:#6d737b;border-style:solid;border-width:1px 0 0 0}code{background-color:#6d737b;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #6d737b;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #6d737b;margin-right:1.5rem;padding-right:1rem} 8 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-ru.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"\u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043e",noneResultsText:"\u0421\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0439 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e {0}",countSelectedText:"\u0412\u044b\u0431\u0440\u0430\u043d\u043e {0} \u0438\u0437 {1}",maxOptionsText:["\u0414\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442 \u043f\u0440\u0435\u0434\u0435\u043b ({n} {var} \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c)","\u0414\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442 \u043f\u0440\u0435\u0434\u0435\u043b \u0432 \u0433\u0440\u0443\u043f\u043f\u0435 ({n} {var} \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c)",["\u0448\u0442.","\u0448\u0442."]],doneButtonText:"\u0417\u0430\u043a\u0440\u044b\u0442\u044c",selectAllText:"\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435",deselectAllText:"\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u0441\u0435",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /cps/static/js/libs/tinymce/skins/content/document/content.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | @media screen{html{background:#f4f4f4;min-height:100%}}body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif}@media screen{body{background-color:#fff;box-shadow:0 0 4px rgba(0,0,0,.15);box-sizing:border-box;margin:1rem auto 0;max-width:820px;min-height:calc(100vh - 1rem);padding:4rem 6rem 6rem 6rem}}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure figcaption{color:#999;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem} 8 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/js/libs/context.min.js: -------------------------------------------------------------------------------- 1 | /*! intention.js v0.9.7.3 2 | * http://intentionjs.com/ 3 | * 4 | * context.js 5 | * 6 | * Copyright 2011, 2013 Dowjones and other contributors 7 | * Released under the MIT license 8 | * 9 | */ 10 | !function(){"use strict";var a=function(a,b){function c(a,b){var c=new Date,d=null;return function(e){var f=new Date;if(b>f-c){d&&window.clearTimeout(d);var g=function(b){return function(){a(b)}};return d=window.setTimeout(g(e),b),!1}a(e),c=f}}var d,e,f=new b;return f.responsive([{name:"base"}]).respond("base"),d=f.responsive({ID:"width",contexts:[{name:"standard",min:840},{name:"tablet",min:510},{name:"mobile",min:0}],matcher:function(a,b){return"string"==typeof a?a===b.name:a>=b.min},measure:function(b){return"string"==typeof b?b:a(window).width()}}),e=f.responsive({ID:"orientation",contexts:[{name:"portrait",rotation:0},{name:"landscape",rotation:90}],matcher:function(a,b){return a===b.rotation},measure:function(){var a=Math.abs(window.orientation);return a>0&&(a=180-a),a}}),f.responsive({ID:"touch",contexts:[{name:"touch"}],matcher:function(){return"ontouchstart"in window}}).respond(),f.responsive({ID:"highres",contexts:[{name:"highres"}],matcher:function(){return window.devicePixelRatio>1}}).respond(),a(window).on("resize",c(d.respond,100)).on("orientationchange",d.respond).on("orientationchange",e.respond),d.respond(),e.respond(),a(function(){f.elements(document)}),f};!function(a,b){"function"==typeof define&&define.amd?define("context",["jquery","intention"],b):a.intent=b(a.jQuery,a.Intention)}(this,function(b,c){return a(b,c)})}.call(this); -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug/Problem report 3 | about: Create a report to help us improve Calibre-Web 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | **Describe the bug/problem** 12 | A clear and concise description of what the bug is. If you are asking for support, please check our [Wiki](https://github.com/janeczku/calibre-web/wiki) if your question is already answered there. 13 | 14 | **To Reproduce** 15 | Steps to reproduce the behavior: 16 | 1. Go to '...' 17 | 2. Click on '....' 18 | 3. Scroll down to '....' 19 | 4. See error 20 | 21 | **Logfile** 22 | Add content of calibre-web.log file or the relevant error, try to reproduce your problem with "debug" log-level to get more output. 23 | 24 | **Expected behavior** 25 | A clear and concise description of what you expected to happen. 26 | 27 | **Screenshots** 28 | If applicable, add screenshots to help explain your problem. 29 | 30 | **Environment (please complete the following information):** 31 | - OS: [e.g. Windows 10/Raspberry Pi OS] 32 | - Python version: [e.g. python2.7] 33 | - Calibre-Web version: [e.g. 0.6.8 or 087c4c59 (git rev-parse --short HEAD)]: 34 | - Docker container: [None/Technosoft2000/LinuxServer]: 35 | - Special Hardware: [e.g. Rasperry Pi Zero] 36 | - Browser: [e.g. Chrome 83.0.4103.97, Safari 13.3.7, Firefox 68.0.1 ESR] 37 | 38 | **Additional context** 39 | Add any other context about the problem here. [e.g. access via reverse proxy, database background sync, special database location] 40 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/loading-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/free-25px-000000/SVG/spinner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cps/static/css/images/icomoon/free-25px-ffffff/SVG/spinner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) 5 | # Copyright (C) 2019 decentral1se 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | # 20 | # """Calibre-web distribution package setuptools installer.""" 21 | 22 | from setuptools import setup 23 | from setuptools import find_packages 24 | import os 25 | import re 26 | import codecs 27 | 28 | here = os.path.abspath(os.path.dirname(__file__)) 29 | 30 | def read(*parts): 31 | with codecs.open(os.path.join(here, *parts), 'r') as fp: 32 | return fp.read() 33 | 34 | def find_version(*file_paths): 35 | version_file = read(*file_paths) 36 | version_match = re.search(r"^STABLE_VERSION\s+=\s+{['\"]version['\"]:\s*['\"](.*)['\"]}", 37 | version_file, re.M) 38 | if version_match: 39 | return version_match.group(1) 40 | raise RuntimeError("Unable to find version string.") 41 | 42 | setup( 43 | packages=find_packages("src"), 44 | package_dir = {'': 'src'}, 45 | version=find_version("src", "calibreweb", "cps", "constants.py") 46 | ) 47 | -------------------------------------------------------------------------------- /cps/static/css/popup.css: -------------------------------------------------------------------------------- 1 | /* http://davidwalsh.name/css-tooltips */ 2 | 3 | /* base CSS element */ 4 | .popup { 5 | background: #eee; 6 | border: 1px solid #ccc; 7 | padding: 10px; 8 | border-radius: 8px; 9 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); 10 | position: fixed; 11 | max-width: 300px; 12 | font-size: 12px; 13 | display: none; 14 | margin-left: 2px; 15 | margin-top: 30px; 16 | } 17 | 18 | .popup.above { 19 | margin-top: -10px; 20 | } 21 | 22 | .popup.left { 23 | margin-left: -20px; 24 | } 25 | 26 | .popup.right { 27 | margin-left: 40px; 28 | } 29 | 30 | .pop_content { 31 | max-height: 225px; 32 | overflow-y: auto; 33 | } 34 | 35 | .pop_content > p { 36 | margin-top: 0; 37 | } 38 | 39 | /* below */ 40 | .popup::before { 41 | position: absolute; 42 | display: inline-block; 43 | border-bottom: 10px solid #eee; 44 | border-right: 10px solid transparent; 45 | border-left: 10px solid transparent; 46 | border-bottom-color: rgba(0, 0, 0, 0.2); 47 | left: 50%; 48 | top: -10px; 49 | margin-left: -6px; 50 | content: ''; 51 | } 52 | 53 | .popup::after { 54 | position: absolute; 55 | display: inline-block; 56 | border-bottom: 9px solid #eee; 57 | border-right: 9px solid transparent; 58 | border-left: 9px solid transparent; 59 | left: 50%; 60 | top: -9px; 61 | margin-left: -5px; 62 | content: ''; 63 | } 64 | 65 | /* above */ 66 | .popup.above::before { 67 | border-bottom: none; 68 | border-top: 10px solid #eee; 69 | border-top-color: rgba(0, 0, 0, 0.2); 70 | top: 100%; 71 | } 72 | 73 | .popup.above::after { 74 | border-bottom: none; 75 | border-top: 9px solid #eee; 76 | top: 100%; 77 | } 78 | 79 | .popup.left::before, 80 | .popup.left::after { 81 | left: 20px; 82 | } 83 | 84 | .popup.right::before, 85 | .popup.right::after { 86 | left: auto; 87 | right: 20px; 88 | } 89 | 90 | .popup.show, 91 | .popup.on { 92 | display: block; 93 | } 94 | -------------------------------------------------------------------------------- /cps/static/js/shelforder.js: -------------------------------------------------------------------------------- 1 | /* This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) 2 | * Copyright (C) 2018 jkrehm, OzzieIsaacs 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | /* global Sortable,sortTrue */ 19 | 20 | Sortable.create(sortTrue, { 21 | group: "sorting", 22 | sort: true 23 | }); 24 | 25 | // eslint-disable-next-line no-unused-vars 26 | function sendData(path) { 27 | var elements; 28 | var counter; 29 | var maxElements; 30 | var tmp = []; 31 | 32 | elements = $(".list-group-item"); 33 | maxElements = elements.length; 34 | 35 | var form = document.createElement("form"); 36 | form.setAttribute("method", "post"); 37 | form.setAttribute("action", path); 38 | 39 | for (counter = 0;counter < maxElements;counter++) { 40 | tmp[counter] = elements[counter].getAttribute("id"); 41 | var hiddenField = document.createElement("input"); 42 | hiddenField.setAttribute("type", "hidden"); 43 | hiddenField.setAttribute("name", elements[counter].getAttribute("id")); 44 | hiddenField.setAttribute("value", String(counter + 1)); 45 | form.appendChild(hiddenField); 46 | } 47 | document.body.appendChild(form); 48 | form.submit(); 49 | } 50 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-select/defaults-km.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) 3 | * 4 | * Copyright 2012-2020 SnapAppointments, LLC 5 | * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | 8 | !function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"\u1798\u17b7\u1793\u1798\u17b6\u1793\u17a2\u17d2\u179c\u17b8\u1794\u17b6\u1793\u1787\u17d2\u179a\u17be\u179f\u179a\u17be\u179f",noneResultsText:"\u1798\u17b7\u1793\u1798\u17b6\u1793\u179b\u1791\u17d2\u1792\u1795\u179b {0}",countSelectedText:function(e,t){return"{0} \u1792\u17b6\u178f\u17bb\u178a\u17c2\u179b\u1794\u17b6\u1793\u1787\u17d2\u179a\u17be\u179f"},maxOptionsText:function(e,t){return[1==e?"\u1788\u17b6\u1793\u178a\u179b\u17cb\u178a\u17c2\u1793\u1780\u17c6\u178e\u178f\u17cb ( {n} \u1792\u17b6\u178f\u17bb\u17a2\u178f\u17b7\u1794\u179a\u1798\u17b6)":"\u17a2\u178f\u17b7\u1794\u179a\u1798\u17b6\u1788\u17b6\u1793\u178a\u179b\u17cb\u178a\u17c2\u1793\u1780\u17c6\u178e\u178f\u17cb ( {n} \u1792\u17b6\u178f\u17bb)",1==t?"\u178a\u17c2\u1793\u1780\u17c6\u178e\u178f\u17cb\u1780\u17d2\u179a\u17bb\u1798\u1788\u17b6\u1793\u178a\u179b\u17cb ( {n} \u17a2\u178f\u17b7\u1794\u179a\u1798\u17b6\u1792\u17b6\u178f\u17bb)":"\u17a2\u178f\u17b7\u1794\u179a\u1798\u17b6\u1780\u17d2\u179a\u17bb\u1798\u1788\u17b6\u1793\u178a\u179b\u17cb\u178a\u17c2\u1793\u1780\u17c6\u178e\u178f\u17cb ( {n} \u1792\u17b6\u178f\u17bb)"]},selectAllText:"\u1787\u17d2\u179a\u17be\u179f\u200b\u1799\u1780\u200b\u1791\u17b6\u17c6\u1784\u17a2\u179f\u17cb",deselectAllText:"\u1798\u17b7\u1793\u1787\u17d2\u179a\u17be\u179f\u200b\u1799\u1780\u200b\u1791\u17b6\u17c6\u1784\u17a2\u179f",multipleSeparator:", "}}); -------------------------------------------------------------------------------- /cps/services/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) 4 | # Copyright (C) 2019 pwr 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | from __future__ import division, print_function, unicode_literals 20 | 21 | from .. import logger 22 | 23 | 24 | log = logger.create() 25 | 26 | 27 | try: from . import goodreads_support 28 | except ImportError as err: 29 | log.debug("Cannot import goodreads, showing authors-metadata will not work: %s", err) 30 | goodreads_support = None 31 | 32 | 33 | try: 34 | from . import simpleldap as ldap 35 | from .simpleldap import ldapVersion 36 | except ImportError as err: 37 | log.debug("Cannot import simpleldap, logging in with ldap will not work: %s", err) 38 | ldap = None 39 | ldapVersion = None 40 | 41 | try: 42 | from . import SyncToken as SyncToken 43 | kobo = True 44 | except ImportError as err: 45 | log.debug("Cannot import SyncToken, syncing books with Kobo Devices will not work: %s", err) 46 | kobo = None 47 | SyncToken = None 48 | 49 | try: 50 | from . import gmail 51 | except ImportError as err: 52 | log.debug("Cannot import gmail, sending books via Gmail Oauth2 Verification will not work: %s", err) 53 | gmail = None 54 | -------------------------------------------------------------------------------- /cps/templates/http_error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ instance }} | HTTP Error ({{ error_code }}) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% if g.current_theme == 1 %} 16 | 17 | {% endif %} 18 | 19 | 20 |
21 |
22 |
23 |

{{instance}}

24 |

{{ error_code }}

25 |

{{ error_name }}

26 |
27 |
28 |
29 |
30 | {% for element in error_stack %} 31 |
{{ element }}
32 | {% endfor %} 33 |
34 |
35 | {% if issue %} 36 |
37 | 40 |
41 | {% endif %} 42 | 43 |
44 | 47 |
48 | 49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /cps/templates/json.txt: -------------------------------------------------------------------------------- 1 | { 2 | "pubdate": "{{entry.pubdate}}", 3 | "title": "{{entry.title}}", 4 | "format_metadata": { 5 | {% for format in entry.data %} 6 | "{{format.format}}": { 7 | "mtime": "{{entry.last_modified}}", 8 | "size": {{format.uncompressed_size}}, 9 | "path": "" 10 | }{% if not loop.last %},{% endif %} 11 | {% endfor %} 12 | }, 13 | "formats": [ 14 | {% for format in entry.data %} 15 | "{{format.format}}"{% if not loop.last %},{% endif %} 16 | {% endfor %} 17 | ], 18 | "series": null, 19 | "cover": "{{url_for('opds.feed_get_cover', book_id=entry.id)}}", 20 | "languages": [ 21 | {% for lang in entry.languages %} 22 | "{{lang.lang_code}}"{% if not loop.last %},{% endif %} 23 | {% endfor %} 24 | ], 25 | "comments": "{% if entry.comments|length > 0 %}{{entry.comments[0].text.replace('"', '\\"')|safe}}{% endif %}", 26 | "tags": [ 27 | {% for tag in entry.tags %} 28 | "{{tag.name}}"{% if not loop.last %},{% endif %} 29 | {% endfor %} 30 | ], 31 | "application_id": {{entry.id}}, 32 | "series_index": {% if entry.series|length > 0 %}"{{entry.series_index}}"{% else %}null{% endif %}, 33 | "last_modified": "{{entry.last_modified}}", 34 | "author_sort": "{{entry.author_sort}}", 35 | "uuid": "{{entry.uuid}}", 36 | "timestamp": "{{entry.timestamp}}", 37 | "thumbnail": "{{url_for('opds.feed_get_cover', book_id=entry.id)}}", 38 | "main_format": { 39 | "{{entry.data[0].format|lower}}": "{{ url_for('opds.opds_download_link', book_id=entry.id, book_format=entry.data[0].format|lower)}}" 40 | }, 41 | "rating":{% if entry.ratings.__len__() > 0 %} "{{entry.ratings[0].rating}}.0"{% else %}0.0{% endif %}, 42 | "authors": [ 43 | {% for author in entry.authors %} 44 | "{{author.name.replace('|',',')}}"{% if not loop.last %},{% endif %} 45 | {% endfor %} 46 | ], 47 | "other_formats": { 48 | {% if entry.data.__len__() > 1 %} 49 | {% for format in entry.data[1:] %} 50 | "{{format.format|lower}}": "{{ url_for('opds.opds_download_link', book_id=entry.id, book_format=format.format|lower)}}"{% if not loop.last %},{% endif %} 51 | {% endfor %} 52 | {% endif %} }, 53 | "title_sort": "{{entry.sort}}" 54 | } 55 | -------------------------------------------------------------------------------- /cps/templates/shelf_order.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
4 |

{{title}}

5 |
{{_('Drag to Rearrange Order')}}
6 |
7 | {% for entry in entries %} 8 |
9 |
10 | 17 |
18 | {% if entry['visible'] %} 19 | {{entry['Books']['title']}} 20 | {% if entry['Books']['series']|length > 0 %} 21 |
22 | {{entry['Books']['series_index']}} - {{entry['Books']['series'][0].name}} 23 | {% endif %} 24 |
25 | {% for author in entry['Books']['author'] %} 26 | {{author.name.replace('|',',')}} 27 | {% if not loop.last %} 28 | & 29 | {% endif %} 30 | {% endfor %} 31 | {% else %} 32 | {{_('Hidden Book')}} 33 |
34 | {% endif %} 35 |
36 |
37 |
38 | {% endfor %} 39 |
40 | 41 | {{_('Back')}} 42 |
43 | {% endblock %} 44 | 45 | {% block js %} 46 | 47 | 48 | {% endblock %} 49 | -------------------------------------------------------------------------------- /cps/static/css/libs/images/annotation-help.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 16 | 18 | 21 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "jquery": true 5 | }, 6 | "globals": { 7 | "alert": true 8 | }, 9 | "rules": { 10 | "arrow-parens": 2, 11 | "block-scoped-var": 1, 12 | "brace-style": 2, 13 | "camelcase": 1, 14 | "comma-spacing": 2, 15 | "curly": [2, "multi-line", "consistent"], 16 | "eqeqeq": 2, 17 | "indent": [ 18 | 2, 19 | 4, 20 | { 21 | "SwitchCase": 1 22 | } 23 | ], 24 | "keyword-spacing": 2, 25 | "linebreak-style": 2, 26 | "new-cap": 2, 27 | "no-dupe-args": 2, 28 | "no-dupe-class-members": 2, 29 | "no-dupe-keys": 2, 30 | "no-duplicate-case": 2, 31 | "no-caller": 2, 32 | "no-class-assign": 2, 33 | "no-cond-assign": 2, 34 | "no-const-assign": 2, 35 | "no-console": 2, 36 | "no-debugger": 2, 37 | "no-delete-var": 2, 38 | "no-empty": 2, 39 | "no-eval": 2, 40 | "no-extend-native": 2, 41 | "no-extra-boolean-cast": 2, 42 | "no-extra-semi": 2, 43 | "no-fallthrough": [ 44 | 2, 45 | { 46 | "commentPattern": "break[\\s\\w]*omitted" 47 | } 48 | ], 49 | "no-implied-eval": 2, 50 | "no-invalid-regexp": 2, 51 | "no-irregular-whitespace": 2, 52 | "no-iterator": 2, 53 | "no-loop-func": 2, 54 | "no-mixed-operators": 2, 55 | "no-mixed-spaces-and-tabs": 2, 56 | "no-multi-str": 2, 57 | "no-new": 2, 58 | "no-obj-calls": 2, 59 | "no-octal": 2, 60 | "no-redeclare": 2, 61 | "no-regex-spaces": 2, 62 | "no-script-url": 2, 63 | "no-sparse-arrays": 2, 64 | "no-undef": 2, 65 | "no-undefined": 2, 66 | "no-unreachable": 2, 67 | "no-unsafe-negation": 2, 68 | "no-unused-vars": 2, 69 | "no-use-before-define": [ 70 | 2, 71 | { 72 | "classes": false, 73 | "functions": false 74 | } 75 | ], 76 | "quotes": [ 77 | 2, 78 | "double" 79 | ], 80 | "require-yield": 2, 81 | "semi": [ 82 | 2, 83 | "always" 84 | ], 85 | "space-before-blocks": 2, 86 | "space-infix-ops": 2, 87 | "space-unary-ops": 2, 88 | "use-isnan": 2, 89 | "valid-typeof": 2, 90 | "wrap-iife": [ 91 | 2, 92 | "any" 93 | ], 94 | "yield-star-spacing": 2 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /cps/static/js/libs/screenfull.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * screenfull 3 | * v4.2.0 - 2019-04-01 4 | * (c) Sindre Sorhus; MIT License 5 | */ 6 | 7 | !function(){"use strict";var u="undefined"!=typeof window&&void 0!==window.document?window.document:{},e="undefined"!=typeof module&&module.exports,t="undefined"!=typeof Element&&"ALLOW_KEYBOARD_INPUT"in Element,c=function(){for(var e,n=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],l=0,r=n.length,t={};l. 16 | */ 17 | 18 | // Upon loading load the logfile for the first option (event log) 19 | $(function() { 20 | if ($("#log_group input").length) { 21 | var element = $("#log_group input[type='radio']:checked").val(); 22 | init(element); 23 | } 24 | }); 25 | 26 | // After change the radio option load the corresponding log file 27 | $("#log_group input").on("change", function() { 28 | var element = $("#log_group input[type='radio']:checked").val(); 29 | init(element); 30 | }); 31 | 32 | 33 | // Handle reloading of the log file and display the content 34 | function init(logType) { 35 | var d = document.getElementById("renderer"); 36 | d.innerHTML = "loading ..."; 37 | 38 | $.ajax({ 39 | url: window.location.pathname + "/../../ajax/log/" + logType, 40 | datatype: "text", 41 | cache: false 42 | }) 43 | .done( function(data) { 44 | var text; 45 | $("#renderer").text(""); 46 | text = (data).split("\n"); 47 | // console.log(text.length); 48 | for (var i = 0; i < text.length; i++) { 49 | $("#renderer").append( "
" + _sanitize(text[i]) + "
" ); 50 | } 51 | }); 52 | } 53 | 54 | 55 | function _sanitize(t) { 56 | t = t 57 | .replace(/&/g, "&") 58 | .replace(/ /g, " ") 59 | .replace(//g, ">"); 61 | 62 | return t; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /cps/converter.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) 4 | # Copyright (C) 2016-2019 Ben Bennett, OzzieIsaacs 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | from __future__ import division, print_function, unicode_literals 20 | import os 21 | import re 22 | from flask_babel import gettext as _ 23 | 24 | from . import config, logger 25 | from .subproc_wrapper import process_wait 26 | 27 | 28 | log = logger.create() 29 | 30 | # _() necessary to make babel aware of string for translation 31 | _NOT_CONFIGURED = _('not configured') 32 | _NOT_INSTALLED = _('not installed') 33 | _EXECUTION_ERROR = _('Execution permissions missing') 34 | 35 | 36 | def _get_command_version(path, pattern, argument=None): 37 | if os.path.exists(path): 38 | command = [path] 39 | if argument: 40 | command.append(argument) 41 | try: 42 | for line in process_wait(command): 43 | if re.search(pattern, line): 44 | return line 45 | except Exception as ex: 46 | log.warning("%s: %s", path, ex) 47 | return _EXECUTION_ERROR 48 | return _NOT_INSTALLED 49 | 50 | 51 | def get_calibre_version(): 52 | return _get_command_version(config.config_converterpath, r'ebook-convert.*\(calibre', '--version') \ 53 | or _NOT_CONFIGURED 54 | 55 | 56 | def get_unrar_version(): 57 | return _get_command_version(config.config_rarfile_location, r'UNRAR.*\d') or _NOT_CONFIGURED 58 | 59 | def get_kepubify_version(): 60 | return _get_command_version(config.config_kepubifypath, r'kepubify\s','--version') or _NOT_CONFIGURED 61 | 62 | 63 | -------------------------------------------------------------------------------- /cps/static/js/libs/bootstrap-rating-input.min.js: -------------------------------------------------------------------------------- 1 | /** @link https://github.com/javiertoledo/bootstrap-rating-input */ 2 | !function(a){"use strict";function n(a){return"[data-value"+(a?"="+a:"")+"]"}function e(a,n,e){var i=e.activeIcon,t=e.inactiveIcon;a.removeClass(n?t:i).addClass(n?i:t)}function i(n,e){var i=a.extend({},s,n.data(),e);return i.inline=""===i.inline||i.inline,i.readonly=""===i.readonly||i.readonly,!1===i.clearable?i.clearableLabel="":i.clearableLabel=i.clearable,i.clearable=""===i.clearable||i.clearable,i}function t(n,e){if(e.inline)i=a('');else var i=a('
');i.addClass(n.attr("class")),i.removeClass("rating");for(var t=e.min;t<=e.max;t++)i.append('');return e.clearable&&!e.readonly&&i.append(" ").append(''+e.clearableLabel+""),i}var l="rating-clear",o="."+l,s={min:1,max:5,"empty-value":0,iconLib:"glyphicon",activeIcon:"glyphicon-star",inactiveIcon:"glyphicon-star-empty",clearable:!1,clearableIcon:"glyphicon-remove",clearableRemain:!1,inline:!1,readonly:!1},r=function(a,n){var e=this.$input=a;this.options=i(e,n);var l=this.$el=t(e,this.options);e.addClass("hidden").before(l),e.attr("type","hidden"),this.highlight(e.val())};r.VERSION="0.4.0",r.DEFAULTS=s,r.prototype={clear:function(){this.setValue(this.options["empty-value"])},setValue:function(a){this.highlight(a),this.updateInput(a)},highlight:function(a,i){var t=this.options,l=this.$el;if(a>=this.options.min&&a<=this.options.max){var s=l.find(n(a));e(s.prevAll("i").addBack(),!0,t),e(s.nextAll("i"),!1,t)}else e(l.find(n()),!1,t);i||(this.options.clearableRemain?l.find(o).removeClass("hidden"):a&&a!=this.options["empty-value"]?l.find(o).removeClass("hidden"):l.find(o).addClass("hidden"))},updateInput:function(a){var n=this.$input;n.val()!=a&&n.val(a).change()}},(a.fn.rating=function(e){return this.filter("input[type=number]").each(function(){var i=a(this),t=new r(i,"object"==typeof e&&e||{});t.options.readonly||(t.$el.on("mouseenter",n(),function(){t.highlight(a(this).data("value"),!0)}).on("mouseleave",n(),function(){t.highlight(i.val(),!0)}).on("click",n(),function(){t.setValue(a(this).data("value"))}).on("click",o,function(){t.clear()}),i.data("rating",t))})}).Constructor=r,a(function(){a("input.rating[type=number]").each(function(){a(this).rating()})})}(jQuery); 3 | -------------------------------------------------------------------------------- /cps/static/js/reading/epub.js: -------------------------------------------------------------------------------- 1 | /* global $, calibre, EPUBJS, ePubReader */ 2 | 3 | var reader; 4 | 5 | (function() { 6 | "use strict"; 7 | 8 | EPUBJS.filePath = calibre.filePath; 9 | EPUBJS.cssPath = calibre.cssPath; 10 | 11 | reader = ePubReader(calibre.bookUrl, { 12 | restore: true, 13 | bookmarks: calibre.bookmark ? [calibre.bookmark] : [] 14 | }); 15 | 16 | if (calibre.useBookmarks) { 17 | reader.on("reader:bookmarked", updateBookmark.bind(reader, "add")); 18 | reader.on("reader:unbookmarked", updateBookmark.bind(reader, "remove")); 19 | } else { 20 | $("#bookmark, #show-Bookmarks").remove(); 21 | } 22 | 23 | // Enable swipe support 24 | // I have no idea why swiperRight/swiperLeft from plugins is not working, events just don't get fired 25 | var touchStart = 0; 26 | var touchEnd = 0; 27 | 28 | reader.rendition.on('touchstart', function(event) { 29 | touchStart = event.changedTouches[0].screenX; 30 | }); 31 | reader.rendition.on('touchend', function(event) { 32 | touchEnd = event.changedTouches[0].screenX; 33 | if (touchStart < touchEnd) { 34 | if(reader.book.package.metadata.direction === "rtl") { 35 | reader.rendition.next(); 36 | } else { 37 | reader.rendition.prev(); 38 | } 39 | // Swiped Right 40 | } 41 | if (touchStart > touchEnd) { 42 | if(reader.book.package.metadata.direction === "rtl") { 43 | reader.rendition.prev(); 44 | } else { 45 | reader.rendition.next(); 46 | } 47 | // Swiped Left 48 | } 49 | }); 50 | 51 | /** 52 | * @param {string} action - Add or remove bookmark 53 | * @param {string|int} location - Location or zero 54 | */ 55 | function updateBookmark(action, location) { 56 | // Remove other bookmarks (there can only be one) 57 | if (action === "add") { 58 | this.settings.bookmarks.filter(function (bookmark) { 59 | return bookmark && bookmark !== location; 60 | }).map(function (bookmark) { 61 | this.removeBookmark(bookmark); 62 | }.bind(this)); 63 | } 64 | 65 | // Save to database 66 | $.ajax(calibre.bookmarkUrl, { 67 | method: "post", 68 | data: { bookmark: location || "" } 69 | }).fail(function (xhr, status, error) { 70 | alert(error); 71 | }); 72 | } 73 | })(); 74 | 75 | 76 | -------------------------------------------------------------------------------- /cps/templates/grid.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

{{_(title)}}

4 | 5 | 24 | 25 | {% if entries[0] %} 26 |
27 | {% for entry in entries %} 28 | 43 | {% endfor %} 44 |
45 | {% endif %} 46 | 47 | 48 | {% endblock %} 49 | {% block js %} 50 | 51 | {% endblock %} 52 | -------------------------------------------------------------------------------- /cps/static/js/filter_grid.js: -------------------------------------------------------------------------------- 1 | /* This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) 2 | * Copyright (C) 2018 OzzieIsaacs 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | var direction = $("#asc").data('order'); // 0=Descending order; 1= ascending order 19 | 20 | var $list = $("#list").isotope({ 21 | itemSelector: ".book", 22 | layoutMode: "fitRows", 23 | getSortData: { 24 | title: ".title", 25 | } 26 | }); 27 | 28 | $("#desc").click(function() { 29 | if (direction === 0) { 30 | return; 31 | } 32 | var page = $(this).data("id"); 33 | $.ajax({ 34 | method:"post", 35 | contentType: "application/json; charset=utf-8", 36 | dataType: "json", 37 | url: window.location.pathname + "/../../ajax/view", 38 | data: "{\"" + page + "\": {\"dir\": \"desc\"}}", 39 | }); 40 | $list.isotope({ 41 | sortBy: "name", 42 | sortAscending: true 43 | }); 44 | }); 45 | 46 | $("#asc").click(function() { 47 | if (direction === 1) { 48 | return; 49 | } 50 | var page = $(this).data("id"); 51 | $.ajax({ 52 | method:"post", 53 | contentType: "application/json; charset=utf-8", 54 | dataType: "json", 55 | url: window.location.pathname + "/../../ajax/view", 56 | data: "{\"" + page + "\": {\"dir\": \"asc\"}}", 57 | }); 58 | $list.isotope({ 59 | sortBy: "name", 60 | sortAscending: false 61 | }); 62 | }); 63 | 64 | $("#all").click(function() { 65 | // go through all elements and make them visible 66 | $list.isotope({ filter: function() { 67 | return true; 68 | } 69 | }); 70 | }); 71 | 72 | $(".char").click(function() { 73 | var character = this.innerText; 74 | $list.isotope({ filter: function() { 75 | return this.attributes["data-id"].value.charAt(0).toUpperCase() === character; 76 | } 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /cps/subproc_wrapper.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) 4 | # Copyright (C) 2018-2019 OzzieIsaacs 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | from __future__ import division, print_function, unicode_literals 20 | import sys 21 | import os 22 | import subprocess 23 | 24 | 25 | def process_open(command, quotes=(), env=None, sout=subprocess.PIPE, serr=subprocess.PIPE, newlines=True): 26 | # Linux py2.7 encode as list without quotes no empty element for parameters 27 | # linux py3.x no encode and as list without quotes no empty element for parameters 28 | # windows py2.7 encode as string with quotes empty element for parameters is okay 29 | # windows py 3.x no encode and as string with quotes empty element for parameters is okay 30 | # separate handling for windows and linux 31 | if os.name == 'nt': 32 | for key, element in enumerate(command): 33 | if key in quotes: 34 | command[key] = '"' + element + '"' 35 | exc_command = " ".join(command) 36 | if sys.version_info < (3, 0): 37 | exc_command = exc_command.encode(sys.getfilesystemencoding()) 38 | else: 39 | if sys.version_info < (3, 0): 40 | exc_command = [x.encode(sys.getfilesystemencoding()) for x in command] 41 | else: 42 | exc_command = [x for x in command] 43 | 44 | return subprocess.Popen(exc_command, shell=False, stdout=sout, stderr=serr, universal_newlines=newlines, env=env) # nosec 45 | 46 | 47 | def process_wait(command, serr=subprocess.PIPE): 48 | # Run command, wait for process to terminate, and return an iterator over lines of its output. 49 | newlines = os.name != 'nt' 50 | p = process_open(command, serr=serr, newlines=newlines) 51 | p.wait() 52 | for line in p.stdout.readlines(): 53 | if isinstance(line, bytes): 54 | line = line.decode('utf-8') 55 | yield line 56 | -------------------------------------------------------------------------------- /cps/debug_info.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) 4 | # Copyright (C) 2012-2019 cervinko, idalin, SiphonSquirrel, ouzklcn, akushsky, 5 | # OzzieIsaacs, bodybybuddha, jkrehm, matthazinski, janeczku 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | import shutil 21 | import glob 22 | import zipfile 23 | import json 24 | from io import BytesIO 25 | try: 26 | from StringIO import StringIO 27 | except ImportError: 28 | from io import StringIO 29 | 30 | import os 31 | 32 | from flask import send_file 33 | 34 | from . import logger, config 35 | from .about import collect_stats 36 | 37 | log = logger.create() 38 | 39 | def assemble_logfiles(file_name): 40 | log_list = sorted(glob.glob(file_name + '*'), reverse=True) 41 | wfd = StringIO() 42 | for f in log_list: 43 | with open(f, 'r') as fd: 44 | shutil.copyfileobj(fd, wfd) 45 | wfd.seek(0) 46 | return send_file(wfd, 47 | as_attachment=True, 48 | attachment_filename=os.path.basename(file_name)) 49 | 50 | def send_debug(): 51 | file_list = glob.glob(logger.get_logfile(config.config_logfile) + '*') 52 | file_list.extend(glob.glob(logger.get_accesslogfile(config.config_access_logfile) + '*')) 53 | for element in [logger.LOG_TO_STDOUT, logger.LOG_TO_STDERR]: 54 | if element in file_list: 55 | file_list.remove(element) 56 | memory_zip = BytesIO() 57 | with zipfile.ZipFile(memory_zip, 'w', compression=zipfile.ZIP_DEFLATED) as zf: 58 | zf.writestr('settings.txt', json.dumps(config.toDict())) 59 | zf.writestr('libs.txt', json.dumps(collect_stats())) 60 | for fp in file_list: 61 | zf.write(fp, os.path.basename(fp)) 62 | memory_zip.seek(0) 63 | return send_file(memory_zip, 64 | as_attachment=True, 65 | attachment_filename="Calibre-Web-debug-pack.zip") 66 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = calibreweb 3 | url = https://github.com/janeczku/calibre-web 4 | project_urls = 5 | Bug Tracker = https://github.com/janeczku/calibre-web/issues 6 | Release Management = https://github.com/janeczku/calibre-web/releases 7 | Documentation = https://github.com/janeczku/calibre-web/wiki 8 | Source Code = https://github.com/janeczku/calibre-web 9 | description = Web app for browsing, reading and downloading eBooks stored in a Calibre database. 10 | long_description = file: README.md 11 | long_description_content_type= text/markdown 12 | author = @OzzieIsaacs 13 | author_email = Ozzie.Fernandez.Isaacs@googlemail.com 14 | maintainer = @OzzieIsaacs 15 | license = GPLv3+ 16 | license_file = LICENSE 17 | classifiers = 18 | Development Status :: 5 - Production/Stable 19 | License :: OSI Approved :: GNU Affero General Public License v3 20 | Programming Language :: Python :: 3 21 | Programming Language :: Python :: 3.5 22 | Programming Language :: Python :: 3.6 23 | Programming Language :: Python :: 3.7 24 | Operating System :: OS Independent 25 | keywords = 26 | calibre 27 | calibre-web 28 | library 29 | python_requires = >=3.0 30 | 31 | [options.entry_points] 32 | console_scripts = 33 | cps = calibreweb:main 34 | [options] 35 | include_package_data = True 36 | install_requires = 37 | Babel>=1.3, <2.9 38 | Flask-Babel>=0.11.1,<2.1.0 39 | Flask-Login>=0.3.2,<0.5.1 40 | Flask-Principal>=0.3.2,<0.5.1 41 | singledispatch>=3.4.0.0,<3.5.0.0 42 | backports_abc>=0.4 43 | Flask>=1.0.2,<1.2.0 44 | iso-639>=0.4.5,<0.5.0 45 | PyPDF3>=1.0.0,<1.0.4 46 | pytz>=2016.10 47 | requests>=2.11.1,<2.25.0 48 | SQLAlchemy>=1.3.0,<1.4.0 49 | tornado>=4.1,<6.2 50 | Wand>=0.4.4,<0.7.0 51 | unidecode>=0.04.19,<1.2.0 52 | 53 | [options.extras_require] 54 | gdrive = 55 | google-api-python-client>=1.7.11,<1.13.0 56 | gevent>20.6.0,<21.2.0 57 | greenlet>=0.4.17,<1.1.0 58 | httplib2>=0.9.2,<0.18.0 59 | oauth2client>=4.0.0,<4.1.4 60 | uritemplate>=3.0.0,<3.1.0 61 | pyasn1-modules>=0.0.8,<0.3.0 62 | pyasn1>=0.1.9,<0.5.0 63 | PyDrive2>=1.3.1,<1.8.0 64 | PyYAML>=3.12 65 | rsa>=3.4.2,<4.1.0 66 | six>=1.10.0,<1.15.0 67 | goodreads = 68 | goodreads>=0.3.2,<0.4.0 69 | python-Levenshtein>=0.12.0,<0.13.0 70 | ldap = 71 | python-ldap>=3.0.0,<3.4.0 72 | Flask-SimpleLDAP>=1.4.0,<1.5.0 73 | oauth = 74 | Flask-Dance>=1.4.0,<3.1.0 75 | SQLAlchemy-Utils>=0.33.5,<0.37.0 76 | metadata = 77 | lxml>=3.8.0,<4.7.0 78 | rarfile>=2.7 79 | comics = 80 | natsort>=2.2.0,<7.1.0 81 | comicapi>= 2.1.3,<2.2.0 82 | kobo = 83 | jsonschema>=3.2.0,<3.3.0 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /cps/redirect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Flask License 4 | # 5 | # Copyright © 2010 by the Pallets team. 6 | # 7 | # Some rights reserved. 8 | 9 | # Redistribution and use in source and binary forms of the software as well as 10 | # documentation, with or without modification, are permitted provided that the 11 | # following conditions are met: 12 | # 13 | # Redistributions of source code must retain the above copyright notice, this list of conditions 14 | # and the following disclaimer. 15 | # Redistributions in binary form must reproduce the above copyright notice, this list of conditions 16 | # and the following disclaimer in the documentation and/or other materials provided with the distribution. 17 | # Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products 18 | # derived from this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR 21 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 22 | # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26 | # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | # http://flask.pocoo.org/snippets/62/ 29 | 30 | from __future__ import division, print_function, unicode_literals 31 | try: 32 | from urllib.parse import urlparse, urljoin 33 | except ImportError: 34 | from urlparse import urlparse, urljoin 35 | 36 | from flask import request, url_for, redirect 37 | 38 | 39 | def is_safe_url(target): 40 | ref_url = urlparse(request.host_url) 41 | test_url = urlparse(urljoin(request.host_url, target)) 42 | return test_url.scheme in ('http', 'https') and ref_url.netloc == test_url.netloc 43 | 44 | 45 | def get_redirect_target(): 46 | for target in request.values.get('next'), request.referrer: 47 | if not target: 48 | continue 49 | if is_safe_url(target): 50 | return target 51 | 52 | 53 | def redirect_back(endpoint, **values): 54 | target = request.form['next'] 55 | if not target or not is_safe_url(target): 56 | target = url_for(endpoint, **values) 57 | return redirect(target) 58 | -------------------------------------------------------------------------------- /cps/error_handler.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) 4 | # Copyright (C) 2018-2020 OzzieIsaacs 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | import traceback 20 | from flask import render_template 21 | from werkzeug.exceptions import default_exceptions 22 | try: 23 | from werkzeug.exceptions import FailedDependency 24 | except ImportError: 25 | from werkzeug.exceptions import UnprocessableEntity as FailedDependency 26 | 27 | from . import config, app, logger, services 28 | 29 | 30 | log = logger.create() 31 | 32 | # custom error page 33 | def error_http(error): 34 | return render_template('http_error.html', 35 | error_code="Error {0}".format(error.code), 36 | error_name=error.name, 37 | issue=False, 38 | instance=config.config_calibre_web_title 39 | ), error.code 40 | 41 | 42 | def internal_error(error): 43 | return render_template('http_error.html', 44 | error_code="Internal Server Error", 45 | error_name=str(error), 46 | issue=True, 47 | error_stack=traceback.format_exc().split("\n"), 48 | instance=config.config_calibre_web_title 49 | ), 500 50 | 51 | def init_errorhandler(): 52 | # http error handling 53 | for ex in default_exceptions: 54 | if ex < 500: 55 | app.register_error_handler(ex, error_http) 56 | elif ex == 500: 57 | app.register_error_handler(ex, internal_error) 58 | 59 | 60 | if services.ldap: 61 | # Only way of catching the LDAPException upon logging in with LDAP server down 62 | @app.errorhandler(services.ldap.LDAPException) 63 | # pylint: disable=unused-variable 64 | def handle_exception(e): 65 | log.debug('LDAP server not accessible while trying to login to opds feed') 66 | return error_http(FailedDependency()) 67 | 68 | -------------------------------------------------------------------------------- /cps/templates/tasks.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block header %} 3 | 4 | {% endblock %} 5 | {% block body %} 6 |
7 |

{{_('Tasks')}}

8 | 9 | 10 | 11 | {% if g.user.role_admin() %} 12 | 13 | {% endif %} 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
{{_('User')}}{{_('Task')}}{{_('Status')}}{{_('Progress')}}{{_('Run Time')}}{{_('Start Time')}}
24 | 26 |
27 | {% endblock %} 28 | {% block js %} 29 | 30 | 57 | 58 | {% endblock %} 59 | --------------------------------------------------------------------------------