From 0e18837cb6a1baa7f2219d2ca8ec409a66508105 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Wed, 5 Jan 2011 23:17:38 +0900 Subject: [PATCH 01/17] fix encoding, reflect change of the site --- resources/recipes/cnetjapan.recipe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/recipes/cnetjapan.recipe b/resources/recipes/cnetjapan.recipe index 1058b90401..b57bce5b97 100644 --- a/resources/recipes/cnetjapan.recipe +++ b/resources/recipes/cnetjapan.recipe @@ -11,7 +11,7 @@ class CNetJapan(BasicNewsRecipe): (u'CNet Blog', u'http://feed.japan.cnet.com/rss/blog/index.rdf') ] language = 'ja' - encoding = 'Shift_JIS' + encoding = 'utf-8' remove_javascript = True preprocess_regexps = [ From 6871651ff1719971c1f52b4fb8ed6c2ae2025c44 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 9 Jan 2011 16:41:54 +0000 Subject: [PATCH 02/17] Fix bug in formatter where parse errors at end of file threw an exception instead of providing the message. --- src/calibre/utils/formatter.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/calibre/utils/formatter.py b/src/calibre/utils/formatter.py index 2e4f843c3d..40760bf91b 100644 --- a/src/calibre/utils/formatter.py +++ b/src/calibre/utils/formatter.py @@ -98,9 +98,10 @@ class _Parser(object): m = 'Formatter: ' + message + _(' near ') if self.lex_pos > 0: m = '{0} {1}'.format(m, self.prog[self.lex_pos-1][1]) - m = '{0} {1}'.format(m, self.prog[self.lex_pos][1]) - if self.lex_pos < len(self.prog): + elif self.lex_pos < len(self.prog): m = '{0} {1}'.format(m, self.prog[self.lex_pos+1][1]) + else: + m = '{0} {1}'.format(m, _('end of program')) raise ValueError(m) def token(self): From 0067f6af4edf0a5645acc6a9a48a1608f60fb5a6 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 9 Jan 2011 16:42:11 +0000 Subject: [PATCH 03/17] Fix bug in formatter where parse errors at end of file threw an exception instead of providing the message. --- src/calibre/gui2/preferences/plugboard.py | 31 +++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/calibre/gui2/preferences/plugboard.py b/src/calibre/gui2/preferences/plugboard.py index 296387106c..e1dc6b03bd 100644 --- a/src/calibre/gui2/preferences/plugboard.py +++ b/src/calibre/gui2/preferences/plugboard.py @@ -5,11 +5,11 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' -from PyQt4 import QtGui -from PyQt4.Qt import Qt +from PyQt4.Qt import Qt, QLineEdit, QComboBox, SIGNAL, QListWidgetItem from calibre.gui2 import error_dialog from calibre.gui2.device import device_name_for_plugboards +from calibre.gui2.dialogs.template_dialog import TemplateDialog from calibre.gui2.preferences import ConfigWidgetBase, test_widget from calibre.gui2.preferences.plugboard_ui import Ui_Form from calibre.customize.ui import metadata_writers, device_plugins @@ -17,6 +17,27 @@ from calibre.library.save_to_disk import plugboard_any_format_value, \ plugboard_any_device_value, plugboard_save_to_disk_value from calibre.utils.formatter import validation_formatter + +class LineEditWithTextBox(QLineEdit): + + ''' + Extend the context menu of a QLineEdit to include more actions. + ''' + + def contextMenuEvent(self, event): + menu = self.createStandardContextMenu() + menu.addSeparator() + + action_open_editor = menu.addAction(_('Open Editor')) + + self.connect(action_open_editor, SIGNAL('triggered()'), self.open_editor) + menu.exec_(event.globalPos()) + + def open_editor(self): + t = TemplateDialog(self, self.text()) + if t.exec_(): + self.setText(t.textbox.toPlainText()) + class ConfigWidget(ConfigWidgetBase, Ui_Form): def genesis(self, gui): @@ -72,10 +93,10 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.source_widgets = [] self.dest_widgets = [] for i in range(0, len(self.dest_fields)-1): - w = QtGui.QLineEdit(self) + w = LineEditWithTextBox(self) self.source_widgets.append(w) self.fields_layout.addWidget(w, 5+i, 0, 1, 1) - w = QtGui.QComboBox(self) + w = QComboBox(self) self.dest_widgets.append(w) self.fields_layout.addWidget(w, 5+i, 1, 1, 1) @@ -297,7 +318,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): for op in self.current_plugboards[f][d]: ops.append('([' + op[0] + '] -> ' + op[1] + ')') txt = '%s:%s = %s\n'%(f, d, ', '.join(ops)) - item = QtGui.QListWidgetItem(txt) + item = QListWidgetItem(txt) item.setData(Qt.UserRole, (f, d)) self.existing_plugboards.addItem(item) self.refilling = False From cdc017bc6349cfb29944e7da4657c2ba42f122fd Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 9 Jan 2011 16:42:28 +0000 Subject: [PATCH 04/17] Fix #8244 Merging two books fails (None custom numeric values throws exception) --- src/calibre/library/custom_columns.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/calibre/library/custom_columns.py b/src/calibre/library/custom_columns.py index d925f7c91d..d905f6d01a 100644 --- a/src/calibre/library/custom_columns.py +++ b/src/calibre/library/custom_columns.py @@ -151,6 +151,8 @@ class CustomColumns(object): return v def adapt_number(x, d): + if x is None: + return None if isinstance(x, (str, unicode, bytes)): if x.lower() == 'none': return None From 1670cd29bae7b41186141f902e0057676d985967 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 9 Jan 2011 10:32:19 -0700 Subject: [PATCH 05/17] Cicero by mad --- resources/recipes/cicero.recipe | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 resources/recipes/cicero.recipe diff --git a/resources/recipes/cicero.recipe b/resources/recipes/cicero.recipe new file mode 100644 index 0000000000..2df6b68000 --- /dev/null +++ b/resources/recipes/cicero.recipe @@ -0,0 +1,35 @@ +from calibre.web.feeds.news import BasicNewsRecipe + +class Cicero(BasicNewsRecipe): + timefmt = ' [%Y-%m-%d]' + title = u'Cicero' + __author__ = 'mad@sharktooth.de' + description = u'Magazin f\xfcr politische Kultur' + oldest_article = 7 + language = 'de' + max_articles_per_feed = 100 + no_stylesheets = True + use_embedded_content = False + publisher = 'Ringier Publishing' + category = 'news, politics, Germany' + encoding = 'iso-8859-1' + publication_type = 'magazine' + masthead_url = 'http://www.cicero.de/img2/cicero_logo_rss.gif' + feeds = [ +(u'Das gesamte Portfolio', u'http://www.cicero.de/rss/rss.php?ress_id='), +#(u'Alle Heft-Inhalte', u'http://www.cicero.de/rss/rss.php?ress_id=heft'), +#(u'Alle Online-Inhalte', u'http://www.cicero.de/rss/rss.php?ress_id=online'), +#(u'Berliner Republik', u'http://www.cicero.de/rss/rss.php?ress_id=4'), +#(u'Weltb\xfchne', u'http://www.cicero.de/rss/rss.php?ress_id=1'), +#(u'Salon', u'http://www.cicero.de/rss/rss.php?ress_id=7'), +#(u'Kapital', u'http://www.cicero.de/rss/rss.php?ress_id=6'), +#(u'Netzst\xfccke', u'http://www.cicero.de/rss/rss.php?ress_id=9'), +#(u'Leinwand', u'http://www.cicero.de/rss/rss.php?ress_id=12'), +#(u'Bibliothek', u'http://www.cicero.de/rss/rss.php?ress_id=15'), +(u'Kolumne - Alle Kolulmnen', u'http://www.cicero.de/rss/rss2.php?ress_id='), +#(u'Kolumne - Schreiber, Berlin', u'http://www.cicero.de/rss/rss2.php?ress_id=35'), +#(u'Kolumne - TV Kritik', u'http://www.cicero.de/rss/rss2.php?ress_id=34') +] + + def print_version(self, url): + return 'http://www.cicero.de/page_print.php?' + url.rpartition('?')[2] From e58ccd8c5e4f4a251c8bf738a621d1a29c6e91da Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 9 Jan 2011 10:55:15 -0700 Subject: [PATCH 06/17] Fix XSS vulnerability in content server. Fixes #7980 (Security vulnerability in Calibre 0.7.34) --- src/calibre/library/server/browse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index 37799c4cbc..3e4687be95 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -756,7 +756,7 @@ class BrowseServer(object): sort = self.browse_sort_book_list(items, list_sort) ids = [x[0] for x in items] html = render_book_list(ids, self.opts.url_prefix, - suffix=_('in search')+': '+query) + suffix=_('in search')+': '+xml(query)) return self.browse_template(sort, category=False, initial_search=query).format( title=_('Matching books'), script='booklist();', main=html) From 6349979ca5a06d4efaf573902508fd5ac437128f Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 9 Jan 2011 18:15:02 +0000 Subject: [PATCH 07/17] Fix regression on empty ismult custom columns --- src/calibre/library/custom_columns.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/library/custom_columns.py b/src/calibre/library/custom_columns.py index d905f6d01a..f94081f046 100644 --- a/src/calibre/library/custom_columns.py +++ b/src/calibre/library/custom_columns.py @@ -197,8 +197,8 @@ class CustomColumns(object): data = self.custom_column_num_map[num] row = self.data._data[idx] if index_is_id else self.data[idx] ans = row[self.FIELD_MAP[data['num']]] - if ans and data['is_multiple'] and data['datatype'] == 'text': - ans = ans.split('|') + if data['is_multiple'] and data['datatype'] == 'text': + ans = ans.split('|') if ans else [] if data['display'].get('sort_alpha', False): ans.sort(cmp=lambda x,y:cmp(x.lower(), y.lower())) return ans From 31c354a164a8816576ce5194a6b0e1b5d64b6728 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 9 Jan 2011 11:15:34 -0700 Subject: [PATCH 08/17] ... --- setup/build_environment.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/setup/build_environment.py b/setup/build_environment.py index 10ab1b0735..bdfddd2205 100644 --- a/setup/build_environment.py +++ b/setup/build_environment.py @@ -117,7 +117,6 @@ if iswindows: poppler_inc_dirs = consolidate('POPPLER_INC_DIR', r'%s\poppler;%s'%(sw_inc_dir, sw_inc_dir)) - popplerqt4_inc_dirs = poppler_inc_dirs + [poppler_inc_dirs[1]+r'\qt4'] poppler_lib_dirs = consolidate('POPPLER_LIB_DIR', sw_lib_dir) popplerqt4_lib_dirs = poppler_lib_dirs poppler_libs = ['poppler'] @@ -131,7 +130,6 @@ elif isosx: fc_lib = '/sw/lib' poppler_inc_dirs = consolidate('POPPLER_INC_DIR', '/sw/build/poppler-0.14.5/poppler:/sw/build/poppler-0.14.5') - popplerqt4_inc_dirs = poppler_inc_dirs + [poppler_inc_dirs[0]+'/qt4'] poppler_lib_dirs = consolidate('POPPLER_LIB_DIR', '/sw/lib') poppler_libs = ['poppler'] @@ -150,9 +148,6 @@ else: # Include directories poppler_inc_dirs = pkgconfig_include_dirs('poppler', 'POPPLER_INC_DIR', '/usr/include/poppler') - popplerqt4_inc_dirs = pkgconfig_include_dirs('poppler-qt4', '', '') - if not popplerqt4_inc_dirs: - popplerqt4_inc_dirs = poppler_inc_dirs + [poppler_inc_dirs[0]+'/qt4'] png_inc_dirs = pkgconfig_include_dirs('libpng', 'PNG_INC_DIR', '/usr/include') magick_inc_dirs = pkgconfig_include_dirs('MagickWand', 'MAGICK_INC', '/usr/include/ImageMagick') @@ -187,13 +182,10 @@ if not poppler_inc_dirs or not os.path.exists( poppler_error = \ ('Poppler not found on your system. Various PDF related', ' functionality will not work. Use the POPPLER_INC_DIR and', - ' POPPLER_LIB_DIR environment variables.') - -popplerqt4_error = None -if not popplerqt4_inc_dirs or not os.path.exists( - os.path.join(popplerqt4_inc_dirs[-1], 'poppler-qt4.h')): - popplerqt4_error = \ - ('Poppler Qt4 bindings not found on your system.') + ' POPPLER_LIB_DIR environment variables. calibre requires ' + ' the poppler XPDF headers. If your distro does not ' + ' include them you will have to re-compile poppler ' + ' by hand with --enable-xpdf-headers') magick_error = None if not magick_inc_dirs or not os.path.exists(os.path.join(magick_inc_dirs[0], From d63bfeff1158fc9f8ef9f7ba78cd7b39f18c9a98 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 9 Jan 2011 11:18:35 -0700 Subject: [PATCH 09/17] ... --- setup/build_environment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/build_environment.py b/setup/build_environment.py index bdfddd2205..f0adaf9584 100644 --- a/setup/build_environment.py +++ b/setup/build_environment.py @@ -192,7 +192,7 @@ if not magick_inc_dirs or not os.path.exists(os.path.join(magick_inc_dirs[0], 'wand')): magick_error = ('ImageMagick not found on your system. ' 'Try setting the environment variables MAGICK_INC ' - 'and MAGICK_LIB to help calibre locate the inclue and libbrary ' + 'and MAGICK_LIB to help calibre locate the include and library ' 'files.') podofo_lib = os.environ.get('PODOFO_LIB_DIR', podofo_lib) From be03e57f2cf8d25b87e888b781ab14cc4ff3b20f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 9 Jan 2011 11:44:43 -0700 Subject: [PATCH 10/17] El Correo by desUBIKado --- resources/recipes/el_correo.recipe | 122 +++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 resources/recipes/el_correo.recipe diff --git a/resources/recipes/el_correo.recipe b/resources/recipes/el_correo.recipe new file mode 100644 index 0000000000..9190560b02 --- /dev/null +++ b/resources/recipes/el_correo.recipe @@ -0,0 +1,122 @@ +#!/usr/bin/env python +__license__ = 'GPL v3' +__copyright__ = '08 Januery 2011, desUBIKado' +__author__ = 'desUBIKado' +__description__ = 'Daily newspaper from Biscay' +__version__ = 'v0.08' +__date__ = '08, Januery 2011' +''' +[url]http://www.elcorreo.com/[/url] +''' + +import time +import re +from calibre.web.feeds.news import BasicNewsRecipe + +class heraldo(BasicNewsRecipe): + __author__ = 'desUBIKado' + description = 'Daily newspaper from Biscay' + title = u'El Correo' + publisher = 'Vocento' + category = 'News, politics, culture, economy, general interest' + oldest_article = 2 + delay = 1 + max_articles_per_feed = 100 + no_stylesheets = True + use_embedded_content = False + language = 'es' + timefmt = '[%a, %d %b, %Y]' + encoding = 'iso-8859-1' + remove_empty_feeds = True + remove_javascript = False + + feeds = [ + (u'Portada', u'http://www.elcorreo.com/vizcaya/portada.xml'), + (u'Local', u'http://www.elcorreo.com/vizcaya/rss/feeds/vizcaya.xml'), + (u'Internacional', u'hhttp://www.elcorreo.com/vizcaya/rss/feeds/internacional.xml'), + (u'Econom\xeda', u'http://www.elcorreo.com/vizcaya/rss/feeds/economia.xml'), + (u'Pol\xedtica', u'http://www.elcorreo.com/vizcaya/rss/feeds/politica.xml'), + (u'Opini\xf3n', u'http://www.elcorreo.com/vizcaya/rss/feeds/opinion.xml'), + (u'Deportes', u'http://www.elcorreo.com/vizcaya/rss/feeds/deportes.xml'), + (u'Sociedad', u'http://www.elcorreo.com/vizcaya/rss/feeds/sociedad.xml'), + (u'Cultura', u'http://www.elcorreo.com/vizcaya/rss/feeds/cultura.xml'), + (u'Televisi\xf3n', u'http://www.elcorreo.com/vizcaya/rss/feeds/television.xml'), + (u'Gente', u'http://www.elcorreo.com/vizcaya/rss/feeds/gente.xml') + ] + + keep_only_tags = [ + dict(name='div', attrs={'class':['grouphead','date','art_head','story-texto','text','colC_articulo','contenido_comentarios']}), + dict(name='div' , attrs={'id':['articulo','story-texto','story-entradilla']}) + ] + + remove_tags = [ + dict(name='div', attrs={'class':['art_barra','detalles-opinion','formdenunciar','modulo calculadoras','nubetags','pie']}), + dict(name='div', attrs={'class':['mod_lomas','bloque_lomas','blm_header','link-app3','link-app4','botones_listado']}), + dict(name='div', attrs={'class':['navegacion_galeria','modulocanalpromocion','separa','separacion','compartir','tags_relacionados']}), + dict(name='div', attrs={'class':['moduloBuscadorDeportes','modulo-gente','moddestacadopeq','OpcArt','articulopiniones']}), + dict(name='div', attrs={'class':['modulo-especial','publiEspecial']}), + dict(name='div', attrs={'id':['articulopina']}), + dict(name='br', attrs={'class':'clear'}), + dict(name='form', attrs={'name':'frm_conversor2'}) + ] + + remove_tags_before = dict(name='div' , attrs={'class':'articulo '}) + remove_tags_after = dict(name='div' , attrs={'class':'comentarios'}) + + def get_cover_url(self): + cover = None + st = time.localtime() + year = str(st.tm_year) + month = "%.2d" % st.tm_mon + day = "%.2d" % st.tm_mday + #[url]http://img.kiosko.net/2011/01/02/es/elcorreo.750.jpg[/url] + #[url]http://info.elcorreo.com/pdf/06012011-viz.pdf[/url] + cover='http://info.elcorreo.com/pdf/'+ day + month + year +'-viz.pdf' + + br = BasicNewsRecipe.get_browser() + try: + br.open(cover) + except: + self.log("\nPortada no disponible") + cover ='http://www.elcorreo.com/vizcaya/noticias/201002/02/Media/logo-elcorreo-nuevo.png' + return cover + + extra_css = ''' + h1, .headline {font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:30px;} + h2, .subhead {font-family:Arial,Helvetica,sans-serif; font-style:italic; font-weight:normal;font-size:18px;} + h3, .overhead {font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:16px;} + h4 {font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:16px;} + h5 {font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:16px;} + h6 {font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:16px;} + .date,.byline, .photo {font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:14px;} + img{margin-bottom: 0.4em} + ''' + + + + preprocess_regexps = [ + + # To present the image of the embedded video + (re.compile(r'var RUTA_IMAGEN', re.DOTALL|re.IGNORECASE), lambda match: ''), + (re.compile(r'var SITIO = "elcorreo";', re.DOTALL|re.IGNORECASE), lambda match: '