def book_fmt(ctx, rd, library_id, db, book_id, fmt): mdata = db.format_metadata(book_id, fmt) if not mdata: raise NoSuchFormat() mtime = mdata['mtime'] update_metadata = fmt in update_metadata_in_fmts extra_etag_data = '' if update_metadata: mi = db.get_metadata(book_id) mtime = max(mtime, mi.last_modified) # Get any plugboards for the Content server plugboards = db.pref('plugboards') if plugboards: cpb = find_plugboard(plugboard_content_server_value, fmt, plugboards) if cpb: # Transform the metadata via the plugboard newmi = mi.deepcopy_metadata() newmi.template_to_attribute(mi, cpb) mi = newmi extra_etag_data = repr(cpb) else: mi = db.get_proxy_metadata(book_id) def copy_func(dest): db.copy_format_to(book_id, fmt, dest) if update_metadata: set_metadata(dest, mi, fmt) dest.seek(0) rd.outheaders['Content-Disposition'] = 'attachment; filename="%s"' % book_filename(rd, book_id, mi, fmt) return create_file_copy(ctx, rd, 'fmt', library_id, book_id, fmt, mtime, copy_func, extra_etag_data=extra_etag_data)
def get_format(self, id, format): format = format.upper() fm = self.db.format_metadata(id, format, allow_cache=False) if not fm: raise cherrypy.HTTPError( 404, 'book: %d does not have format: %s' % (id, format)) update_metadata = format in {'MOBI', 'EPUB', 'AZW3'} mi = newmi = self.db.get_metadata(id, index_is_id=True, cover_as_data=True, get_cover=update_metadata) cherrypy.response.headers['Last-Modified'] = \ self.last_modified(max(fm['mtime'], mi.last_modified)) fmt = self.db.format(id, format, index_is_id=True, as_file=True, mode='rb') if fmt is None: raise cherrypy.HTTPError( 404, 'book: %d does not have format: %s' % (id, format)) mt = guess_type('dummy.' + format.lower())[0] if mt is None: mt = 'application/octet-stream' cherrypy.response.headers['Content-Type'] = mt if format.lower() in plugboard_content_server_formats: # Get any plugboards for the content server plugboards = self.db.prefs.get('plugboards', {}) cpb = find_plugboard(plugboard_content_server_value, format.lower(), plugboards) if cpb: # Transform the metadata via the plugboard newmi = mi.deepcopy_metadata() newmi.template_to_attribute(mi, cpb) if update_metadata: # Write the updated file from calibre.ebooks.metadata.meta import set_metadata set_metadata(fmt, newmi, format.lower()) fmt.seek(0) fmt.seek(0, 2) cherrypy.response.headers['Content-Length'] = fmt.tell() fmt.seek(0) au = authors_to_string( newmi.authors if newmi.authors else [_('Unknown')]) title = newmi.title if newmi.title else _('Unknown') fname = u'%s - %s_%s.%s' % (title[:30], au[:30], id, format.lower()) fname = ascii_filename(fname).replace('"', '_') cherrypy.response.headers['Content-Disposition'] = \ b'attachment; filename="%s"'%fname cherrypy.response.body = fmt cherrypy.response.timeout = 3600 return fmt
def get_format(self, id, format): format = format.upper() fm = self.db.format_metadata(id, format, allow_cache=False) if not fm: raise cherrypy.HTTPError(404, 'book: %d does not have format: %s'%(id, format)) update_metadata = format in {'MOBI', 'EPUB', 'AZW3'} mi = newmi = self.db.get_metadata( id, index_is_id=True, cover_as_data=True, get_cover=update_metadata) cherrypy.response.headers['Last-Modified'] = \ self.last_modified(max(fm['mtime'], mi.last_modified)) fmt = self.db.format(id, format, index_is_id=True, as_file=True, mode='rb') if fmt is None: raise cherrypy.HTTPError(404, 'book: %d does not have format: %s'%(id, format)) mt = guess_type('dummy.'+format.lower())[0] if mt is None: mt = 'application/octet-stream' cherrypy.response.headers['Content-Type'] = mt if format.lower() in plugboard_content_server_formats: # Get any plugboards for the content server plugboards = self.db.prefs.get('plugboards', {}) cpb = find_plugboard(plugboard_content_server_value, format.lower(), plugboards) if cpb: # Transform the metadata via the plugboard newmi = mi.deepcopy_metadata() newmi.template_to_attribute(mi, cpb) if update_metadata: # Write the updated file from calibre.ebooks.metadata.meta import set_metadata set_metadata(fmt, newmi, format.lower()) fmt.seek(0) fmt.seek(0, 2) cherrypy.response.headers['Content-Length'] = fmt.tell() fmt.seek(0) ua = cherrypy.request.headers.get('User-Agent', '').strip() have_kobo_browser = self.is_kobo_browser(ua) file_extension = "kepub.epub" if have_kobo_browser and format.lower() == "kepub" else format au = authors_to_string(newmi.authors if newmi.authors else [_('Unknown')]) title = newmi.title if newmi.title else _('Unknown') fname = u'%s - %s_%s.%s'%(title[:30], au[:30], id, file_extension.lower()) fname = ascii_filename(fname).replace('"', '_') cherrypy.response.headers['Content-Disposition'] = \ b'attachment; filename="%s"'%fname cherrypy.response.body = fmt cherrypy.response.timeout = 3600 return fmt
def get_format(self, id, format): format = format.upper() fm = self.db.format_metadata(id, format, allow_cache=False) if not fm: raise web.HTTPError( 404, 'book: %d does not have format: %s' % (id, format)) mi = newmi = self.db.get_metadata(id, index_is_id=True) self.set_header('Last-Modified', self.last_modified(max(fm['mtime'], mi.last_modified))) fmt = self.db.format(id, format, index_is_id=True, as_file=True, mode='rb') if fmt is None: raise web.HTTPError( 404, 'book: %d does not have format: %s' % (id, format)) mt = guess_type('dummy.' + format.lower())[0] if mt is None: mt = 'application/octet-stream' self.set_header('Content-Type', mt) if format == 'EPUB': # Get the original metadata # Get any EPUB plugboards for the content server plugboards = self.db.prefs.get('plugboards', {}) cpb = find_plugboard(plugboard_content_server_value, 'epub', plugboards) if cpb: # Transform the metadata via the plugboard newmi = mi.deepcopy_metadata() newmi.template_to_attribute(mi, cpb) if format in ('MOBI', 'EPUB'): # Write the updated file set_metadata(fmt, newmi, format.lower()) fmt.seek(0) fmt.seek(0, 2) self.set_header('Content-Lenght', fmt.tell()) fmt.seek(0) au = authors_to_string( newmi.authors if newmi.authors else [_('Unknown')]) title = newmi.title if newmi.title else _('Unknown') fname = u'%s - %s_%s.%s' % (title[:30], au[:30], id, format.lower()) fname = ascii_filename(fname).replace('"', '_') self.set_header('Content-Disposition', b'attachment; filename="%s"' % fname) return fmt
def book_fmt(ctx, rd, library_id, db, book_id, fmt): mdata = db.format_metadata(book_id, fmt) if not mdata: raise NoSuchFormat() mtime = mdata['mtime'] update_metadata = fmt in update_metadata_in_fmts extra_etag_data = '' if update_metadata: mi = db.get_metadata(book_id) mtime = max(mtime, mi.last_modified) # Get any plugboards for the Content server plugboards = db.pref('plugboards') if plugboards: cpb = find_plugboard(plugboard_content_server_value, fmt, plugboards) if cpb: # Transform the metadata via the plugboard newmi = mi.deepcopy_metadata() newmi.template_to_attribute(mi, cpb) mi = newmi extra_etag_data = repr(cpb) else: mi = db.get_proxy_metadata(book_id) def copy_func(dest): db.copy_format_to(book_id, fmt, dest) if update_metadata: set_metadata(dest, mi, fmt) dest.seek(0) au = authors_to_string(mi.authors or [_('Unknown')]) title = mi.title or _('Unknown') ext = fmt if ext == 'kepub' and 'Kobo Touch' in rd.inheaders.get('User-Agent', ''): ext = 'kepub.epub' fname = '%s - %s_%s.%s' % (title[:30], au[:30], book_id, ext) fname = ascii_filename(fname).replace('"', '_') rd.outheaders['Content-Disposition'] = 'attachment; filename="%s"' % fname return create_file_copy(ctx, rd, 'fmt', library_id, book_id, fmt, mtime, copy_func, extra_etag_data=extra_etag_data)
def book_fmt(ctx, rd, library_id, db, book_id, fmt): mdata = db.format_metadata(book_id, fmt) if not mdata: raise NoSuchFormat() mtime = mdata['mtime'] update_metadata = fmt in update_metadata_in_fmts extra_etag_data = '' if update_metadata: mi = db.get_metadata(book_id) mtime = max(mtime, mi.last_modified) # Get any plugboards for the Content server plugboards = db.pref('plugboards') if plugboards: cpb = find_plugboard(plugboard_content_server_value, fmt, plugboards) if cpb: # Transform the metadata via the plugboard newmi = mi.deepcopy_metadata() newmi.template_to_attribute(mi, cpb) mi = newmi extra_etag_data = repr(cpb) else: mi = db.get_proxy_metadata(book_id) def copy_func(dest): db.copy_format_to(book_id, fmt, dest) if update_metadata: if not mi.cover_data or not mi.cover_data[-1]: cdata = db.cover(book_id) if cdata: mi.cover_data = ('jpeg', cdata) set_metadata(dest, mi, fmt) dest.seek(0) rd.outheaders[ 'Content-Disposition'] = '''attachment; filename="%s"; filename*=utf-8''%s''' % ( book_filename(rd, book_id, mi, fmt), book_filename(rd, book_id, mi, fmt, as_encoded_unicode=True)) return create_file_copy(ctx, rd, 'fmt', library_id, book_id, fmt, mtime, copy_func, extra_etag_data=extra_etag_data)
def collection_finished(self): self.do_one = self.do_one_write ensure_unique_components(self.collected_data) self.ids_to_write = iter(self.collected_data) self.pd.title = _('Copying files and writing metadata...') if self.opts.update_metadata else _( 'Copying files...') self.pd.max = len(self.collected_data) self.pd.value = 0 if self.opts.update_metadata: all_fmts = {fmt for data in itervalues(self.collected_data) for fmt in data[2]} plugboards_cache = {fmt:find_plugboard(plugboard_save_to_disk_value, fmt, self.plugboards) for fmt in all_fmts} self.pool = Pool(name='SaveToDisk') if self.pool is None else self.pool try: self.pool.set_common_data(plugboards_cache) except Failure as err: error_dialog(self.pd, _('Critical failure'), _( 'Could not save books to disk, click "Show details" for more information'), det_msg=unicode_type(err.failure_message) + '\n' + unicode_type(err.details), show=True) self.pd.canceled = True self.do_one_signal.emit()
def book_fmt(ctx, rd, library_id, db, book_id, fmt): mdata = db.format_metadata(book_id, fmt) if not mdata: raise NoSuchFormat() mtime = mdata['mtime'] update_metadata = fmt in update_metadata_in_fmts extra_etag_data = '' if update_metadata: mi = db.get_metadata(book_id) mtime = max(mtime, mi.last_modified) # Get any plugboards for the content server plugboards = db.pref('plugboards') if plugboards: cpb = find_plugboard(plugboard_content_server_value, fmt, plugboards) if cpb: # Transform the metadata via the plugboard newmi = mi.deepcopy_metadata() newmi.template_to_attribute(mi, cpb) mi = newmi extra_etag_data = repr(cpb) else: mi = db.get_proxy_metadata(book_id) def copy_func(dest): db.copy_format_to(book_id, fmt, dest) if update_metadata: set_metadata(dest, mi, fmt) dest.seek(0) au = authors_to_string(mi.authors or [_('Unknown')]) title = mi.title or _('Unknown') ext = fmt if ext == 'kepub' and 'Kobo Touch' in rd.inheaders.get('User-Agent', ''): ext = 'kepub.epub' fname = '%s - %s_%s.%s' % (title[:30], au[:30], book_id, ext) fname = ascii_filename(fname).replace('"', '_') rd.outheaders['Content-Disposition'] = 'attachment; filename="%s"' % fname return create_file_copy(ctx, rd, 'fmt', library_id, book_id, fmt, mtime, copy_func, extra_etag_data=extra_etag_data)
def writing_finished(self): if not self.opts.update_metadata: self.metadata_data = {} if not self.metadata_data: self.updating_metadata_finished() return self.pd.title = _('Updating metadata...') self.pd.max = len(self.metadata_data) self.pd.value = 0 all_fmts = {path.rpartition(os.extsep)[-1] for d in self.metadata_data.itervalues() for path in d['fmts']} plugboards_cache = {fmt:find_plugboard(plugboard_save_to_disk_value, fmt, self.plugboards) for fmt in all_fmts} self.server = server = Server() if self.server is None else self.server tasks = server.split(list(self.metadata_data)) self.jobs = set() for i, book_ids in enumerate(tasks): data = {book_id:self.metadata_data[book_id] for j, book_id in book_ids} job = ParallelJob('save_book', 'Save books (job %d of %d)' % (i+1, len(tasks)), lambda x, y:x, args=(data, plugboards_cache)) self.jobs.add(job) server.add_job(job) self.do_one = self.do_one_update self.do_one_signal.emit()
def book_fmt(ctx, rd, library_id, db, book_id, fmt): mdata = db.format_metadata(book_id, fmt) if not mdata: raise NoSuchFormat() mtime = mdata["mtime"] update_metadata = fmt in update_metadata_in_fmts extra_etag_data = "" if update_metadata: mi = db.get_metadata(book_id) mtime = max(mtime, mi.last_modified) # Get any plugboards for the content server plugboards = db.pref("plugboards") if plugboards: cpb = find_plugboard(plugboard_content_server_value, fmt, plugboards) if cpb: # Transform the metadata via the plugboard newmi = mi.deepcopy_metadata() newmi.template_to_attribute(mi, cpb) mi = newmi extra_etag_data = repr(cpb) else: mi = db.get_proxy_metadata(book_id) def copy_func(dest): db.copy_format_to(book_id, fmt, dest) if update_metadata: set_metadata(dest, mi, fmt) dest.seek(0) au = authors_to_string(mi.authors or [_("Unknown")]) title = mi.title or _("Unknown") fname = "%s - %s_%s.%s" % (title[:30], au[:30], book_id, fmt) fname = ascii_filename(fname).replace('"', "_") rd.outheaders["Content-Disposition"] = 'attachment; filename="%s"' % fname return create_file_copy(ctx, rd, "fmt", library_id, book_id, fmt, mtime, copy_func, extra_etag_data=extra_etag_data)
def new_device_changed(self, txt): self.current_device = None if txt == '': self.clear_fields(edit_boxes=False) return self.clear_fields(edit_boxes=True) self.current_device = unicode_type(txt) if self.current_format in self.current_plugboards and \ self.current_device in self.current_plugboards[self.current_format]: error_dialog(self, '', _('That format and device already has a plugboard.'), show=True) self.new_device.setCurrentIndex(0) return # If we have a specific format/device combination, check if a more # general combination matches. if self.current_format != plugboard_any_format_value and \ self.current_device != plugboard_any_device_value: if find_plugboard(self.current_device, self.current_format, self.current_plugboards): if not question_dialog( self.gui, _('Possibly override plugboard?'), _('A more general plugboard already exists for ' 'that format and device. ' 'Are you sure you want to add the new plugboard?')): self.new_device.setCurrentIndex(0) return # If we have a specific format, check if we are adding a possibly- # covered plugboard if self.current_format != plugboard_any_format_value: if self.current_format in self.current_plugboards: if self.current_device == plugboard_any_device_value: if not question_dialog( self.gui, _('Add possibly overridden plugboard?'), _('More specific device plugboards exist for ' 'that format. ' 'Are you sure you want to add the new plugboard?' )): self.new_device.setCurrentIndex(0) return # We are adding an 'any format' entry. Check if we are adding a specific # device and if so, does some other plugboard match that device. elif self.current_device != plugboard_any_device_value: for fmt in self.current_plugboards: if find_plugboard(self.current_device, fmt, self.current_plugboards): if not question_dialog( self.gui, _('Really add plugboard?'), _('A different plugboard matches that format and ' 'device combination. ' 'Are you sure you want to add the new plugboard?' )): self.new_device.setCurrentIndex(0) return # We are adding an any format/any device entry, which will be overridden # by any other entry. Ask if such entries exist. elif len(self.current_plugboards): if not question_dialog( self.gui, _('Add possibly overridden plugboard?'), _('More specific format and device plugboards ' 'already exist. ' 'Are you sure you want to add the new plugboard?')): self.new_device.setCurrentIndex(0) return if self.current_format != plugboard_any_format_value and \ self.current_device in self.device_to_formats_map: allowable_formats = self.device_to_formats_map[self.current_device] if self.current_format not in allowable_formats: error_dialog( self, '', _('The {0} device does not support the {1} format.' ).format(self.current_device, self.current_format), show=True) self.new_device.setCurrentIndex(0) return if self.current_format == plugboard_any_format_value and \ self.current_device == plugboard_content_server_value: warning_dialog( self, '', _('The {0} device supports only the {1} format(s).').format( plugboard_content_server_value, ', '.join(plugboard_content_server_formats)), show=True) self.set_fields()
def new_device_changed(self, txt): self.current_device = None if txt == '': self.clear_fields(edit_boxes=False) return self.clear_fields(edit_boxes=True) self.current_device = unicode(txt) if self.current_format in self.current_plugboards and \ self.current_device in self.current_plugboards[self.current_format]: error_dialog(self, '', _('That format and device already has a plugboard.'), show=True) self.new_device.setCurrentIndex(0) return # If we have a specific format/device combination, check if a more # general combination matches. if self.current_format != plugboard_any_format_value and \ self.current_device != plugboard_any_device_value: if find_plugboard(self.current_device, self.current_format, self.current_plugboards): if not question_dialog(self.gui, _('Possibly override plugboard?'), _('A more general plugboard already exists for ' 'that format and device. ' 'Are you sure you want to add the new plugboard?')): self.new_device.setCurrentIndex(0) return # If we have a specific format, check if we are adding a possibly- # covered plugboard if self.current_format != plugboard_any_format_value: if self.current_format in self.current_plugboards: if self.current_device == plugboard_any_device_value: if not question_dialog(self.gui, _('Add possibly overridden plugboard?'), _('More specific device plugboards exist for ' 'that format. ' 'Are you sure you want to add the new plugboard?')): self.new_device.setCurrentIndex(0) return # We are adding an 'any format' entry. Check if we are adding a specific # device and if so, does some other plugboard match that device. elif self.current_device != plugboard_any_device_value: for fmt in self.current_plugboards: if find_plugboard(self.current_device, fmt, self.current_plugboards): if not question_dialog(self.gui, _('Really add plugboard?'), _('A different plugboard matches that format and ' 'device combination. ' 'Are you sure you want to add the new plugboard?')): self.new_device.setCurrentIndex(0) return # We are adding an any format/any device entry, which will be overridden # by any other entry. Ask if such entries exist. elif len(self.current_plugboards): if not question_dialog(self.gui, _('Add possibly overridden plugboard?'), _('More specific format and device plugboards ' 'already exist. ' 'Are you sure you want to add the new plugboard?')): self.new_device.setCurrentIndex(0) return if self.current_format != plugboard_any_format_value and \ self.current_device in self.device_to_formats_map: allowable_formats = self.device_to_formats_map[self.current_device] if self.current_format not in allowable_formats: error_dialog(self, '', _('The {0} device does not support the {1} format.'). format(self.current_device, self.current_format), show=True) self.new_device.setCurrentIndex(0) return if self.current_format == plugboard_any_format_value and \ self.current_device == plugboard_content_server_value: warning_dialog(self, '', _('The {0} device supports only the {1} format(s).'). format(plugboard_content_server_value, ', '.join(plugboard_content_server_formats)), show=True) self.set_fields()
def new_device_changed(self, txt): self.current_device = None if txt == "": self.clear_fields(edit_boxes=False) return self.clear_fields(edit_boxes=True) self.current_device = unicode(txt) if ( self.current_format in self.current_plugboards and self.current_device in self.current_plugboards[self.current_format] ): error_dialog(self, "", _("That format and device already has a plugboard."), show=True) self.new_device.setCurrentIndex(0) return # If we have a specific format/device combination, check if a more # general combination matches. if self.current_format != plugboard_any_format_value and self.current_device != plugboard_any_device_value: if find_plugboard(self.current_device, self.current_format, self.current_plugboards): if not question_dialog( self.gui, _("Possibly override plugboard?"), _( "A more general plugboard already exists for " "that format and device. " "Are you sure you want to add the new plugboard?" ), ): self.new_device.setCurrentIndex(0) return # If we have a specific format, check if we are adding a possibly- # covered plugboard if self.current_format != plugboard_any_format_value: if self.current_format in self.current_plugboards: if self.current_device == plugboard_any_device_value: if not question_dialog( self.gui, _("Add possibly overridden plugboard?"), _( "More specific device plugboards exist for " "that format. " "Are you sure you want to add the new plugboard?" ), ): self.new_device.setCurrentIndex(0) return # We are adding an 'any format' entry. Check if we are adding a specific # device and if so, does some other plugboard match that device. elif self.current_device != plugboard_any_device_value: for fmt in self.current_plugboards: if find_plugboard(self.current_device, fmt, self.current_plugboards): if not question_dialog( self.gui, _("Really add plugboard?"), _( "A different plugboard matches that format and " "device combination. " "Are you sure you want to add the new plugboard?" ), ): self.new_device.setCurrentIndex(0) return # We are adding an any format/any device entry, which will be overridden # by any other entry. Ask if such entries exist. elif len(self.current_plugboards): if not question_dialog( self.gui, _("Add possibly overridden plugboard?"), _( "More specific format and device plugboards " "already exist. " "Are you sure you want to add the new plugboard?" ), ): self.new_device.setCurrentIndex(0) return if self.current_format != plugboard_any_format_value and self.current_device in self.device_to_formats_map: allowable_formats = self.device_to_formats_map[self.current_device] if self.current_format not in allowable_formats: error_dialog( self, "", _("The {0} device does not support the {1} format.").format( self.current_device, self.current_format ), show=True, ) self.new_device.setCurrentIndex(0) return self.set_fields()