Commit a00d93a2 authored by Ozzieisaacs's avatar Ozzieisaacs

Working again (basically)

parent 561d40f8
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
base_path = os.path.dirname(os.path.abspath(__file__))
# Insert local directories into path
sys.path.append(base_path)
sys.path.append(os.path.join(base_path, 'cps'))
sys.path.append(os.path.join(base_path, 'vendor'))
from cps.server import Server
from cps import create_app
from cps.web import web
from cps import Server
if __name__ == '__main__':
app = create_app()
app.register_blueprint(web)
Server.startServer()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# import logging
# from logging.handlers import SMTPHandler, RotatingFileHandler
# import os
from flask import Flask# , request, current_app
from flask_login import LoginManager
from flask_babel import Babel # , lazy_gettext as _l
import cache_buster
from reverseproxy import ReverseProxied
import logging
from logging.handlers import RotatingFileHandler
from flask_principal import Principal
# from flask_sqlalchemy import SQLAlchemy
import os
import ub
from ub import Config, Settings
import cPickle
# Normal
babel = Babel()
lm = LoginManager()
lm.login_view = 'web.login'
lm.anonymous_user = ub.Anonymous
ub_session = ub.session
# ub_session.start()
config = Config()
import db
with open(os.path.join(config.get_main_dir, 'cps/translations/iso639.pickle'), 'rb') as f:
language_table = cPickle.load(f)
searched_ids = {}
from worker import WorkerThread
global_WorkerThread = WorkerThread()
from server import server
Server = server()
def create_app():
app = Flask(__name__)
app.wsgi_app = ReverseProxied(app.wsgi_app)
cache_buster.init_cache_busting(app)
formatter = logging.Formatter(
"[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s")
try:
file_handler = RotatingFileHandler(config.get_config_logfile(), maxBytes=50000, backupCount=2)
except IOError:
file_handler = RotatingFileHandler(os.path.join(config.get_main_dir, "calibre-web.log"),
maxBytes=50000, backupCount=2)
# ToDo: reset logfile value in config class
file_handler.setFormatter(formatter)
app.logger.addHandler(file_handler)
app.logger.setLevel(config.config_log_level)
app.logger.info('Starting Calibre Web...')
logging.getLogger("book_formats").addHandler(file_handler)
logging.getLogger("book_formats").setLevel(config.config_log_level)
Principal(app)
lm.init_app(app)
babel.init_app(app)
app.secret_key = os.getenv('SECRET_KEY', 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT')
Server.init_app(app)
db.setup_db()
global_WorkerThread.start()
# app.config.from_object(config_class)
# db.init_app(app)
# login.init_app(app)
return app
......@@ -24,7 +24,7 @@ from sqlalchemy.orm import *
import os
import re
import ast
from ub import config
from cps import config
import ub
import sys
......
......@@ -27,7 +27,7 @@ except ImportError:
gdrive_support = False
import os
from ub import config
from cps import config
import cli
import shutil
from flask import Response, stream_with_context
......
......@@ -20,14 +20,13 @@
import db
import ub
from cps import config
from flask import current_app as app
from tempfile import gettempdir
import sys
import os
import re
import unicodedata
# from io import BytesIO
import worker
import time
from flask import send_from_directory, make_response, redirect, abort
......@@ -41,9 +40,10 @@ try:
import gdriveutils as gd
except ImportError:
pass
import web
# import web
import random
from subproc_wrapper import process_open
import ub
try:
import unidecode
......@@ -51,11 +51,6 @@ try:
except ImportError:
use_unidecode = False
# Global variables
# updater_thread = None
global_WorkerThread = worker.WorkerThread()
global_WorkerThread.start()
def update_download(book_id, user_id):
check = ub.session.query(ub.Downloads).filter(ub.Downloads.user_id == user_id).filter(ub.Downloads.book_id ==
......@@ -73,7 +68,7 @@ def convert_book_format(book_id, calibrepath, old_book_format, new_book_format,
error_message = _(u"%(format)s format not found for book id: %(book)d", format=old_book_format, book=book_id)
app.logger.error("convert_book_format: " + error_message)
return error_message
if ub.config.config_use_google_drive:
if config.config_use_google_drive:
df = gd.getFileFromEbooksFolder(book.path, data.name + "." + old_book_format.lower())
if df:
datafile = os.path.join(calibrepath, book.path, data.name + u"." + old_book_format.lower())
......@@ -133,7 +128,7 @@ def check_send_to_kindle(entry):
"""
if len(entry.data):
bookformats=list()
if ub.config.config_ebookconverter == 0:
if config.config_ebookconverter == 0:
# no converter - only for mobi and pdf formats
for ele in iter(entry.data):
if 'MOBI' in ele.format:
......@@ -156,11 +151,11 @@ def check_send_to_kindle(entry):
bookformats.append({'format': 'Azw3','convert':0,'text':_('Send %(format)s to Kindle',format='Azw3')})
if 'PDF' in formats:
bookformats.append({'format': 'Pdf','convert':0,'text':_('Send %(format)s to Kindle',format='Pdf')})
if ub.config.config_ebookconverter >= 1:
if config.config_ebookconverter >= 1:
if 'EPUB' in formats and not 'MOBI' in formats:
bookformats.append({'format': 'Mobi','convert':1,
'text':_('Convert %(orig)s to %(format)s and send to Kindle',orig='Epub',format='Mobi')})
if ub.config.config_ebookconverter == 2:
if config.config_ebookconverter == 2:
if 'EPUB' in formats and not 'AZW3' in formats:
bookformats.append({'format': 'Azw3','convert':1,
'text':_('Convert %(orig)s to %(format)s and send to Kindle',orig='Epub',format='Azw3')})
......@@ -407,21 +402,21 @@ def generate_random_password():
################################## External interface
def update_dir_stucture(book_id, calibrepath, first_author = None):
if ub.config.config_use_google_drive:
if config.config_use_google_drive:
return update_dir_structure_gdrive(book_id, first_author)
else:
return update_dir_structure_file(book_id, calibrepath, first_author)
def delete_book(book, calibrepath, book_format):
if ub.config.config_use_google_drive:
if config.config_use_google_drive:
return delete_book_gdrive(book, book_format)
else:
return delete_book_file(book, calibrepath, book_format)
def get_book_cover(cover_path):
if ub.config.config_use_google_drive:
if config.config_use_google_drive:
try:
if not web.is_gdrive_ready():
return send_from_directory(os.path.join(os.path.dirname(__file__), "static"), "generic_cover.jpg")
......@@ -437,7 +432,7 @@ def get_book_cover(cover_path):
# traceback.print_exc()
return send_from_directory(os.path.join(os.path.dirname(__file__), "static"),"generic_cover.jpg")
else:
return send_from_directory(os.path.join(ub.config.config_calibre_dir, cover_path), "cover.jpg")
return send_from_directory(os.path.join(config.config_calibre_dir, cover_path), "cover.jpg")
# saves book cover to gdrive or locally
......@@ -447,7 +442,7 @@ def save_cover(url, book_path):
web.app.logger.error("Cover is no jpg file, can't save")
return False
if ub.config.config_use_google_drive:
if config.config_use_google_drive:
tmpDir = gettempdir()
f = open(os.path.join(tmpDir, "uploaded_cover.jpg"), "wb")
f.write(img.content)
......@@ -456,7 +451,7 @@ def save_cover(url, book_path):
web.app.logger.info("Cover is saved on Google Drive")
return True
f = open(os.path.join(ub.config.config_calibre_dir, book_path, "cover.jpg"), "wb")
f = open(os.path.join(config.config_calibre_dir, book_path, "cover.jpg"), "wb")
f.write(img.content)
f.close()
web.app.logger.info("Cover is saved")
......@@ -464,7 +459,7 @@ def save_cover(url, book_path):
def do_download_file(book, book_format, data, headers):
if ub.config.config_use_google_drive:
if config.config_use_google_drive:
startTime = time.time()
df = gd.getFileFromEbooksFolder(book.path, data.name + "." + book_format)
web.app.logger.debug(time.time() - startTime)
......@@ -473,7 +468,7 @@ def do_download_file(book, book_format, data, headers):
else:
abort(404)
else:
filename = os.path.join(ub.config.config_calibre_dir, book.path)
filename = os.path.join(config.config_calibre_dir, book.path)
if not os.path.isfile(os.path.join(filename, data.name + "." + book_format)):
# ToDo: improve error handling
web.app.logger.error('File not found: %s' % os.path.join(filename, data.name + "." + book_format))
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
# Copyright (C) 2018-2019 OzzieIsaacs, cervinko, jkrehm, bodybybuddha, ok11,
# andy29485, idalin, Kyosfonica, wuqi, Kennyl, lemmsh,
# falgh1, grunjol, csitko, ytils, xybydy, trasba, vrabe,
# ruben-herold, marblepebble, JackED42, SiphonSquirrel,
# apetresc, nanu-c, mutschler
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from math import ceil
# simple pagination for the feed
class Pagination(object):
def __init__(self, page, per_page, total_count):
self.page = int(page)
self.per_page = int(per_page)
self.total_count = int(total_count)
@property
def next_offset(self):
return int(self.page * self.per_page)
@property
def previous_offset(self):
return int((self.page - 2) * self.per_page)
@property
def last_offset(self):
last = int(self.total_count) - int(self.per_page)
if last < 0:
last = 0
return int(last)
@property
def pages(self):
return int(ceil(self.total_count / float(self.per_page)))
@property
def has_prev(self):
return self.page > 1
@property
def has_next(self):
return self.page < self.pages
# right_edge: last right_edges count of all pages are shown as number, means, if 10 pages are paginated -> 9,10 shwn
# left_edge: first left_edges count of all pages are shown as number -> 1,2 shwn
# left_current: left_current count below current page are shown as number, means if current page 5 -> 3,4 shwn
# left_current: right_current count above current page are shown as number, means if current page 5 -> 6,7 shwn
def iter_pages(self, left_edge=2, left_current=2,
right_current=4, right_edge=2):
last = 0
left_current = self.page - left_current - 1
right_current = self.page + right_current + 1
right_edge = self.pages - right_edge
for num in range(1, (self.pages + 1)):
if num <= left_edge or (left_current < num < right_current) or num > right_edge:
if last + 1 != num:
yield None
yield num
last = num
......@@ -22,7 +22,7 @@ from socket import error as SocketError
import sys
import os
import signal
import web
from cps import config, global_WorkerThread
try:
from gevent.pywsgi import WSGIServer
......@@ -42,82 +42,81 @@ class server:
wsgiserver = None
restart= False
app = None
def __init__(self):
signal.signal(signal.SIGINT, self.killServer)
signal.signal(signal.SIGTERM, self.killServer)
def init_app(self,application):
self.app = application
def start_gevent(self):
try:
ssl_args = dict()
certfile_path = web.ub.config.get_config_certfile()
keyfile_path = web.ub.config.get_config_keyfile()
certfile_path = config.get_config_certfile()
keyfile_path = config.get_config_keyfile()
if certfile_path and keyfile_path:
if os.path.isfile(certfile_path) and os.path.isfile(keyfile_path):
ssl_args = {"certfile": certfile_path,
"keyfile": keyfile_path}
else:
web.app.logger.info('The specified paths for the ssl certificate file and/or key file seem to be broken. Ignoring ssl. Cert path: %s | Key path: %s' % (certfile_path, keyfile_path))
self.app.logger.info('The specified paths for the ssl certificate file and/or key file seem to be broken. Ignoring ssl. Cert path: %s | Key path: %s' % (certfile_path, keyfile_path))
if os.name == 'nt':
self.wsgiserver= WSGIServer(('0.0.0.0', web.ub.config.config_port), web.app, spawn=Pool(), **ssl_args)
self.wsgiserver= WSGIServer(('0.0.0.0', config.config_port), self.app, spawn=Pool(), **ssl_args)
else:
self.wsgiserver = WSGIServer(('', web.ub.config.config_port), web.app, spawn=Pool(), **ssl_args)
web.py3_gevent_link = self.wsgiserver
self.wsgiserver = WSGIServer(('', config.config_port), self.app, spawn=Pool(), **ssl_args)
self.wsgiserver.serve_forever()
except SocketError:
try:
web.app.logger.info('Unable to listen on \'\', trying on IPv4 only...')
self.wsgiserver = WSGIServer(('0.0.0.0', web.ub.config.config_port), web.app, spawn=Pool(), **ssl_args)
web.py3_gevent_link = self.wsgiserver
self.app.logger.info('Unable to listen on \'\', trying on IPv4 only...')
self.wsgiserver = WSGIServer(('0.0.0.0', config.config_port), self.app, spawn=Pool(), **ssl_args)
self.wsgiserver.serve_forever()
except (OSError, SocketError) as e:
web.app.logger.info("Error starting server: %s" % e.strerror)
self.app.logger.info("Error starting server: %s" % e.strerror)
print("Error starting server: %s" % e.strerror)
web.helper.global_WorkerThread.stop()
global_WorkerThread.stop()
sys.exit(1)
except Exception:
web.app.logger.info("Unknown error while starting gevent")
self.app.logger.info("Unknown error while starting gevent")
def startServer(self):
if gevent_present:
web.app.logger.info('Starting Gevent server')
self.app.logger.info('Starting Gevent server')
# leave subprocess out to allow forking for fetchers and processors
self.start_gevent()
else:
try:
ssl = None
web.app.logger.info('Starting Tornado server')
certfile_path = web.ub.config.get_config_certfile()
keyfile_path = web.ub.config.get_config_keyfile()
self.app.logger.info('Starting Tornado server')
certfile_path = config.get_config_certfile()
keyfile_path = config.get_config_keyfile()
if certfile_path and keyfile_path:
if os.path.isfile(certfile_path) and os.path.isfile(keyfile_path):
ssl = {"certfile": certfile_path,
"keyfile": keyfile_path}
else:
web.app.logger.info('The specified paths for the ssl certificate file and/or key file seem to be broken. Ignoring ssl. Cert path: %s | Key path: %s' % (certfile_path, keyfile_path))
self.app.logger.info('The specified paths for the ssl certificate file and/or key file seem to be broken. Ignoring ssl. Cert path: %s | Key path: %s' % (certfile_path, keyfile_path))
# Max Buffersize set to 200MB
http_server = HTTPServer(WSGIContainer(web.app),
http_server = HTTPServer(WSGIContainer(self.app),
max_buffer_size = 209700000,
ssl_options=ssl)
http_server.listen(web.ub.config.config_port)
http_server.listen(config.config_port)
self.wsgiserver=IOLoop.instance()
self.wsgiserver.start()
# wait for stop signal
self.wsgiserver.close(True)
except SocketError as e:
web.app.logger.info("Error starting server: %s" % e.strerror)
self.app.logger.info("Error starting server: %s" % e.strerror)
print("Error starting server: %s" % e.strerror)
web.helper.global_WorkerThread.stop()
global_WorkerThread.stop()
sys.exit(1)
# ToDo: Somehow caused by circular import under python3 refactor
if sys.version_info > (3, 0):
self.restart = web.py3_restart_Typ
if self.restart == True:
web.app.logger.info("Performing restart of Calibre-Web")
web.helper.global_WorkerThread.stop()
self.app.logger.info("Performing restart of Calibre-Web")
global_WorkerThread.stop()
if os.name == 'nt':
arguments = ["\"" + sys.executable + "\""]
for e in sys.argv:
......@@ -126,26 +125,17 @@ class server:
else:
os.execl(sys.executable, sys.executable, *sys.argv)
else:
web.app.logger.info("Performing shutdown of Calibre-Web")
web.helper.global_WorkerThread.stop()
self.app.logger.info("Performing shutdown of Calibre-Web")
global_WorkerThread.stop()
sys.exit(0)
def setRestartTyp(self,starttyp):
self.restart = starttyp
# ToDo: Somehow caused by circular import under python3 refactor
web.py3_restart_Typ = starttyp
def killServer(self, signum, frame):
self.stopServer()
def stopServer(self):
# ToDo: Somehow caused by circular import under python3 refactor
if sys.version_info > (3, 0):
if not self.wsgiserver:
if gevent_present:
self.wsgiserver = web.py3_gevent_link
else:
self.wsgiserver = IOLoop.instance()
if self.wsgiserver:
if gevent_present:
self.wsgiserver.close()
......@@ -155,10 +145,6 @@ class server:
@staticmethod
def getNameVersion():
if gevent_present:
return {'Gevent':'v'+geventVersion}
return {'Gevent':'v' + geventVersion}
else:
return {'Tornado':'v'+tornadoVersion}
# Start Instance of Server
Server=server()
......@@ -18,7 +18,7 @@
{% for user in content %}
{% if not user.role_anonymous() or config.config_anonbrowse %}
<tr>
<td><a href="{{url_for('edit_user', user_id=user.id)}}">{{user.nickname}}</a></td>
<td><a href="{{url_for('web.edit_user', user_id=user.id)}}">{{user.nickname}}</a></td>
<td>{{user.email}}</td>
<td>{{user.kindle_mail}}</td>
<td>{{user.downloads.count()}}</td>
......@@ -30,7 +30,7 @@
{% endif %}
{% endfor %}
</table>
<div class="btn btn-default" id="admin_new_user"><a href="{{url_for('new_user')}}">{{_('Add new user')}}</a></div>
<div class="btn btn-default" id="admin_new_user"><a href="{{url_for('web.new_user')}}">{{_('Add new user')}}</a></div>
</div>
</div>
......@@ -53,7 +53,7 @@
<td class="hidden-xs">{{email.mail_from}}</td>
</tr>
</table>
<div class="btn btn-default" id="admin_edit_email"><a href="{{url_for('edit_mailsettings')}}">{{_('Change SMTP settings')}}</a></div>
<div class="btn btn-default" id="admin_edit_email"><a href="{{url_for('web.edit_mailsettings')}}">{{_('Change SMTP settings')}}</a></div>
</div>
</div>
......@@ -96,8 +96,8 @@
<div class="col-xs-6 col-sm-5">{% if config.config_remote_login %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</div>
</div>
</div>
<div class="btn btn-default"><a id="basic_config" href="{{url_for('configuration')}}">{{_('Basic Configuration')}}</a></div>
<div class="btn btn-default"><a id="view_config" href="{{url_for('view_configuration')}}">{{_('UI Configuration')}}</a></div>
<div class="btn btn-default"><a id="basic_config" href="{{url_for('web.configuration')}}">{{_('Basic Configuration')}}</a></div>
<div class="btn btn-default"><a id="view_config" href="{{url_for('web.view_configuration')}}">{{_('UI Configuration')}}</a></div>
</div>
</div>
......
......@@ -6,7 +6,7 @@
<div class="col-sm-3 col-lg-3 col-xs-12">
<div class="cover">
{% if book.has_cover %}
<img src="{{ url_for('get_cover', book_id=book.id) }}" alt="{{ book.title }}"/>
<img src="{{ url_for('web.get_cover', book_id=book.id) }}" alt="{{ book.title }}"/>
{% else %}
<img src="{{ url_for('static', filename='generic_cover.jpg') }}" alt="{{ book.title }}"/>
{% endif %}
......@@ -19,7 +19,7 @@
<div class="text-center more-stuff"><h4>{{_('Delete formats:')}}</h4>
{% for file in book.data %}
<div class="form-group">
<a href="{{ url_for('delete_book', book_id=book.id, book_format=file.format) }}" class="btn btn-danger" type="button">{{_('Delete')}} - {{file.format}}</a>
<a href="{{ url_for('web.delete_book', book_id=book.id, book_format=file.format) }}" class="btn btn-danger" type="button">{{_('Delete')}} - {{file.format}}</a>
</div>
{% endfor %}
</div>
......@@ -28,7 +28,7 @@
{% if source_formats|length > 0 and conversion_formats|length > 0 %}
<div class="text-center more-stuff"><h4>{{_('Convert book format:')}}</h4>
<form class="padded-bottom" action="{{ url_for('convert_bookformat', book_id=book.id) }}" method="post" id="book_convert_frm">
<form class="padded-bottom" action="{{ url_for('web.convert_bookformat', book_id=book.id) }}" method="post" id="book_convert_frm">
<div class="form-group">
<div class="text-left">
<label class="control-label" for="book_format_from">{{_('Convert from:')}}</label>
......@@ -53,7 +53,7 @@
{% endif %}
</div>
<form role="form" action="{{ url_for('edit_book', book_id=book.id) }}" method="post" enctype="multipart/form-data" id="book_edit_frm">
<form role="form" action="{{ url_for('web.edit_book', book_id=book.id) }}" method="post" enctype="multipart/form-data" id="book_edit_frm">
<div class="col-sm-9 col-xs-12">
<div class="form-group">
<label for="book_title">{{_('Book Title')}}</label>
......@@ -175,7 +175,7 @@
</div>
<a href="#" id="get_meta" class="btn btn-default" data-toggle="modal" data-target="#metaModal">{{_('Get metadata')}}</a>
<button type="submit" id="submit" class="btn btn-default">{{_('Submit')}}</button>
<a href="{{ url_for('show_book', book_id=book.id) }}" class="btn btn-default">{{_('Back')}}</a>
<a href="{{ url_for('web.show_book', book_id=book.id) }}" class="btn btn-default">{{_('Back')}}</a>
</div>
</form>
......@@ -196,7 +196,7 @@
</div>
<div class="modal-footer">
<a href="{{ url_for('delete_book', book_id=book.id) }}" class="btn btn-danger">{{_('Delete')}}</a>
<a href="{{ url_for('web.delete_book', book_id=book.id) }}" class="btn btn-danger">{{_('Delete')}}</a>
<button type="button" class="btn btn-default" data-dismiss="modal">{{_('Back')}}</button>
</div>
</div>
......
This diff is collapsed.
......@@ -8,21 +8,21 @@
{% for entry in random %}
<div class="col-sm-3 col-lg-2 col-xs-6 book" id="books_rand">
<div class="cover">
<a href="{{ url_for('show_book', book_id=entry.id) }}" data-toggle="modal" data-target="#bookDetailsModal" data-remote="false">
<a href="{{ url_for('web.show_book', book_id=entry.id) }}" data-toggle="modal" data-target="#bookDetailsModal" data-remote="false">
{% if entry.has_cover %}
<img src="{{ url_for('get_cover', book_id=entry.id) }}" alt="{{ entry.title }}" />
<img src="{{ url_for('web.get_cover', book_id=entry.id) }}" alt="{{ entry.title }}" />
{% else %}
<img src="{{ url_for('static', filename='generic_cover.jpg') }}" alt="{{ entry.title }}" />
{% endif %}
</a>
</div>
<div class="meta">
<a href="{{ url_for('show_book', book_id=entry.id) }}" data-toggle="modal" data-target="#bookDetailsModal" data-remote="false">
<a href="{{ url_for('web.show_book', book_id=entry.id) }}" data-toggle="modal" data-target="#bookDetailsModal" data-remote="false">
<p class="title">{{entry.title|shortentitle}}</p>
</a>
<p class="author">
{% for author in entry.authors %}
<a href="{{url_for('author', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
<a href="{{url_for('web.author', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
{% if not loop.last %}
&amp;
{% endif %}
......@@ -53,21 +53,21 @@
{% for entry in entries %}
<div class="col-sm-3 col-lg-2 col-xs-6 book" id="books">
<div class="cover">
<a href="{{ url_for('show_book', book_id=entry.id) }}" data-toggle="modal" data-target="#bookDetailsModal" data-remote="false">
<a href="{{ url_for('web.show_book', book_id=entry.id) }}" data-toggle="modal" data-target="#bookDetailsModal" data-remote="false">
{% if entry.has_cover %}
<img src="{{ url_for('get_cover', book_id=entry.id) }}" alt="{{ entry.title }}"/>
<img src="{{ url_for('web.get_cover', book_id=entry.id) }}" alt="{{ entry.title }}"/>
{% else %}
<img src="{{ url_for('static', filename='generic_cover.jpg') }}" alt="{{ entry.title }}" />
{% endif %}
</a>
</div>
<div class="meta">
<a href="{{ url_for('show_book', book_id=entry.id) }}" data-toggle="modal" data-target="#bookDetailsModal" data-remote="false">
<a href="{{ url_for('web.show_book', book_id=entry.id) }}" data-toggle="modal" data-target="#bookDetailsModal" data-remote="false">
<p class="title">{{entry.title|shortentitle}}</p>
</a>
<p class="author">
{% for author in entry.authors %}
<a href="{{url_for('author', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
<a href="{{url_for('web.author', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a>
{% if not loop.last %}
&amp;
{% endif %}
......
This diff is collapsed.
{% extends "layout.html" %}
{% block body %}
<div class="col-sm-8">
<form role="form" id="search" action="{{ url_for('advanced_search') }}" method="GET">
<form role="form" id="search" action="{{ url_for('web.advanced_search') }}" method="GET">
<div class="form-group">
<label for="book_title">{{_('Book Title')}}</label>
<input type="text" class="form-control" name="book_title" id="book_title" value="">
......
......@@ -5,7 +5,7 @@
{% block body %}
<div class="discover">
<h2>{{_('Tasks list')}}</h2>
<table class="table table-no-bordered" id="table" data-url="{{ url_for('get_email_status_json') }}" data-sort-name="starttime" data-sort-order="asc">
<table class="table table-no-bordered" id="table" data-url="{{ url_for('web.get_email_status_json') }}" data-sort-name="starttime" data-sort-order="asc">
<thead>
<tr>
{% if g.user.role_admin() %}
......@@ -38,7 +38,7 @@
setInterval(function() {
$.ajax({
method:"get",
url: "{{ url_for('get_email_status_json')}}",
url: "{{ url_for('web.get_email_status_json')}}",
async: true,
timeout: 900,
success:function(data){
......
......@@ -23,7 +23,6 @@ from sqlalchemy import exc
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import *
from flask_login import AnonymousUserMixin
from flask_dance.consumer.backend.sqla import OAuthConsumerMixin
import sys
import os
import logging
......@@ -69,6 +68,10 @@ AUTO_UPDATE_STABLE = 1
UPDATE_NIGHTLY = 2
AUTO_UPDATE_NIGHTLY = 4
engine = create_engine('sqlite:///{0}'.format(cli.settingspath), echo=False)
Base = declarative_base()
class UserBase:
@property
......@@ -171,13 +174,13 @@ class UserBase:
return '<User %r>' % self.nickname
#Login via LDAP method
@staticmethod
''''@staticmethod
def try_login(username, password):
conn = get_ldap_connection()
conn.simple_bind_s(
config.config_ldap_dn.replace("%s", username),
password
)
)'''
# Baseclass for Users in Calibre-Web, settings which are depending on certain users are stored here. It is derived from
# User Base (all access methods are declared there)
......@@ -197,11 +200,11 @@ class User(UserBase, Base):
default_language = Column(String(3), default="all")
mature_content = Column(Boolean, default=True)
'''
class OAuth(OAuthConsumerMixin, Base):
provider_user_id = Column(String(256))
user_id = Column(Integer, ForeignKey(User.id))
user = relationship(User)
user = relationship(User)'''
# Class for anonymous user is derived from User base and completly overrides methods and properties for the
......@@ -815,7 +818,7 @@ def delete_download(book_id):
session.commit()
# Generate user Guest (translated text), as anoymous user, no rights
def create_anonymous_user():
def create_anonymous_user(session):
user = User()
user.nickname = "Guest"
user.email = 'no@email'
......@@ -852,7 +855,7 @@ Session = sessionmaker()
Session.configure(bind=engine)
session = Session()
# generate database and admin and guest user, if no database is existing
if not os.path.exists(cli.settingspath):
try:
Base.metadata.create_all(engine)
......@@ -865,13 +868,3 @@ else:
Base.metadata.create_all(engine)
migrate_Database()
clean_database()
#get LDAP connection
def get_ldap_connection():
import ldap
conn = ldap.initialize('ldap://{}'.format(config.config_ldap_provider_url))
return conn
# Generate global Settings Object accessible from every file
config = Config()
searched_ids = {}
......@@ -28,7 +28,8 @@ from io import BytesIO
import os
import sys
import shutil
from ub import config, UPDATE_STABLE
from cps import config
from ub import UPDATE_STABLE
from tempfile import gettempdir
import datetime
import json
......
This diff is collapsed.
......@@ -27,11 +27,11 @@ import socket
import sys
import os
from email.generator import Generator
import web
from cps import config, db # , app
# import web
from flask_babel import gettext as _
import re
import gdriveutils as gd
# import subprocess
# import gdriveutils as gd
from subproc_wrapper import process_open
......@@ -70,8 +70,8 @@ RET_SUCCESS = 1
# it in MIME Base64 encoded to
def get_attachment(bookpath, filename):
"""Get file as MIMEBase message"""
calibrepath = web.config.config_calibre_dir
if web.ub.config.config_use_google_drive:
calibrepath = config.config_calibre_dir
if config.config_use_google_drive:
df = gd.getFileFromEbooksFolder(bookpath, filename)
if df:
datafile = os.path.join(calibrepath, bookpath, filename)
......@@ -90,8 +90,8 @@ def get_attachment(bookpath, filename):
data = file_.read()
file_.close()
except IOError as e:
web.app.logger.exception(e) # traceback.print_exc()
web.app.logger.error(u'The requested file could not be read. Maybe wrong permissions?')
# web.app.logger.exception(e) # traceback.print_exc()
# web.app.logger.error(u'The requested file could not be read. Maybe wrong permissions?')
return None
attachment = MIMEBase('application', 'octet-stream')
......@@ -235,7 +235,7 @@ class WorkerThread(threading.Thread):
curr_task = self.queue[self.current]['taskType']
filename = self._convert_ebook_format()
if filename:
if web.ub.config.config_use_google_drive:
if config.config_use_google_drive:
gd.updateGdriveCalibreFromLocal()
if curr_task == TASK_CONVERT:
self.add_email(self.queue[self.current]['settings']['subject'], self.queue[self.current]['path'],
......@@ -254,8 +254,8 @@ class WorkerThread(threading.Thread):
# if it does - mark the conversion task as complete and return a success
# this will allow send to kindle workflow to continue to work
if os.path.isfile(file_path + format_new_ext):
web.app.logger.info("Book id %d already converted to %s", bookid, format_new_ext)
cur_book = web.db.session.query(web.db.Books).filter(web.db.Books.id == bookid).first()
# web.app.logger.info("Book id %d already converted to %s", bookid, format_new_ext)
cur_book = db.session.query(db.Books).filter(db.Books.id == bookid).first()
self.queue[self.current]['path'] = file_path
self.queue[self.current]['title'] = cur_book.title
self._handleSuccess()
......@@ -264,23 +264,23 @@ class WorkerThread(threading.Thread):
web.app.logger.info("Book id %d - target format of %s does not exist. Moving forward with convert.", bookid, format_new_ext)
# check if converter-executable is existing
if not os.path.exists(web.ub.config.config_converterpath):
if not os.path.exists(config.config_converterpath):
# ToDo Text is not translated
self._handleError(u"Convertertool %s not found" % web.ub.config.config_converterpath)
self._handleError(u"Convertertool %s not found" % config.config_converterpath)
return
try:
# check which converter to use kindlegen is "1"
if format_old_ext == '.epub' and format_new_ext == '.mobi':
if web.ub.config.config_ebookconverter == 1:
if config.config_ebookconverter == 1:
'''if os.name == 'nt':
command = web.ub.config.config_converterpath + u' "' + file_path + u'.epub"'
if sys.version_info < (3, 0):
command = command.encode(sys.getfilesystemencoding())
else:'''
command = [web.ub.config.config_converterpath, file_path + u'.epub']
command = [config.config_converterpath, file_path + u'.epub']
quotes = (1)
if web.ub.config.config_ebookconverter == 2:
if config.config_ebookconverter == 2:
# Linux py2.7 encode as list without quotes no empty element for parameters
# linux py3.x no encode and as list without quotes no empty element for parameters
# windows py2.7 encode as string with quotes empty element for parameters is okay
......@@ -293,11 +293,11 @@ class WorkerThread(threading.Thread):
if sys.version_info < (3, 0):
command = command.encode(sys.getfilesystemencoding())
else:'''
command = [web.ub.config.config_converterpath, (file_path + format_old_ext),
command = [config.config_converterpath, (file_path + format_old_ext),
(file_path + format_new_ext)]
index = 3
if web.ub.config.config_calibre:
parameters = web.ub.config.config_calibre.split(" ")
if config.config_calibre:
parameters = config.config_calibre.split(" ")
for param in parameters:
command.append(param)
quotes.append(index)
......@@ -308,7 +308,7 @@ class WorkerThread(threading.Thread):
self._handleError(_(u"Ebook-converter failed: %(error)s", error=e))
return
if web.ub.config.config_ebookconverter == 1:
if config.config_ebookconverter == 1:
nextline = p.communicate()[0]
# Format of error message (kindlegen translates its output texts):
# Error(prcgen):E23006: Language not recognized in metadata.The dc:Language field is mandatory.Aborting.
......@@ -336,24 +336,24 @@ class WorkerThread(threading.Thread):
# 0 = Info(prcgen):I1036: Mobi file built successfully
# 1 = Info(prcgen):I1037: Mobi file built with WARNINGS!
# 2 = Info(prcgen):I1038: MOBI file could not be generated because of errors!
if (check < 2 and web.ub.config.config_ebookconverter == 1) or \
(check == 0 and web.ub.config.config_ebookconverter == 2):
cur_book = web.db.session.query(web.db.Books).filter(web.db.Books.id == bookid).first()
if (check < 2 and config.config_ebookconverter == 1) or \
(check == 0 and config.config_ebookconverter == 2):
cur_book = db.session.query(db.Books).filter(db.Books.id == bookid).first()
if os.path.isfile(file_path + format_new_ext):
new_format = web.db.Data(name=cur_book.data[0].name,
new_format = db.Data(name=cur_book.data[0].name,
book_format=self.queue[self.current]['settings']['new_book_format'].upper(),
book=bookid, uncompressed_size=os.path.getsize(file_path + format_new_ext))
cur_book.data.append(new_format)
web.db.session.commit()
db.session.commit()
self.queue[self.current]['path'] = cur_book.path
self.queue[self.current]['title'] = cur_book.title
if web.ub.config.config_use_google_drive:
if config.config_use_google_drive:
os.remove(file_path + format_old_ext)
self._handleSuccess()
return file_path + format_new_ext
else:
error_message = format_new_ext.upper() + ' format not found on disk'
web.app.logger.info("ebook converter failed with error while converting book")
# web.app.logger.info("ebook converter failed with error while converting book")
if not error_message:
error_message = 'Ebook converter failed with unknown error'
self._handleError(error_message)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment