diff --git a/modules/webjournal/etc/AtlantisTimes.css b/modules/webjournal/etc/AtlantisTimes.css
index 152b74300..c0caba305 100644
--- a/modules/webjournal/etc/AtlantisTimes.css
+++ b/modules/webjournal/etc/AtlantisTimes.css
@@ -1,328 +1,332 @@
 @charset "UTF-8";
 #container {
 	padding: 0pt;
 	width: 800px;
 	margin-right: auto;
 	margin-left: auto;
 	background-color: #FFFFFF;
 	margin-top: 0px;
 	margin-bottom: 0px;
 	border-top-style: none;
 	border-right-style: none;
 	border-bottom-style: none;
 	border-left-style: none;
 	border-top-width: 0px;
 	border-right-width: 0px;
 	border-bottom-width: 0px;
 	border-left-width: 0px;
 	min-height: 800px;
 }
 #headerBox {
 	background-image: url(journal_header.png);
 	background-repeat: no-repeat;
 	height: 69px;
 	background-position: left top;
 	padding-top: 10px;
 	padding-right: 20px;
 	padding-left: 20px;
 	padding-bottom: 0px;
 	text-align: center;
 }
 #footerBox {
 	background-image: url(journal_footer.png);
 	background-repeat: no-repeat;
 	height: 70px;
 	background-position: left top;
 	padding-top: 10px;
 	padding-right: 20px;
 	padding-left: 20px;
 	padding-bottom: 0px;
 	text-align: center;
 }
 #imprint {
 	visibility: hidden;
 	position: absolute;
 }
 
 h1.journalTitle {
 	font-size: 3.4em;
 	color: #000000;
 	margin: 0px;
 	padding: 0px;
 	text-transform: uppercase;
 	font-weight: lighter;
 }
 #navigationMenu {
 	border-top-width: 1px;
 	border-bottom-width: 1px;
 	border-top-style: solid;
 	border-bottom-style: solid;
 	border-top-color: #666666;
 	border-bottom-color: #666666;
 	padding: 4px;
 	text-align: center;
 	margin-top: 5px;
 	margin-bottom: 10px;
 }
 #navigationMenu a:link, #navigationMenu a:visited {
 	color: #333333;
 	text-transform: uppercase;
 	font-weight: lighter;
 	font-size: large;
 	letter-spacing: 0.2em;
 	margin-right: 10px;
 	margin-left: 10px;
 	padding: 4px;
 	margin-top: 5px;
 	margin-bottom: 5px;
 }
 h2.rightColumnHeader {
 	font-size: large;
 	color: #333333;
 	text-transform: uppercase;
 	font-weight: lighter;
 	border-bottom-width: 1px;
 	border-bottom-style: dotted;
 	border-bottom-color: #999999;
 }
 #rightColumn {
 	width: 200px;
 	border-left-width: 1px;
 	border-left-style: solid;
 	border-left-color: #666666;
 	font-size: small;
 }
 #rightColumn  ul {
 	padding-left: 0px;
 	margin-left: 3px;
 	list-style-position: inside;
 }
 #searchField {
 	width: 120px;
 }
 #webjournal .header {
 	font-size: small;
 	font-weight: lighter;
 	font-style: italic;
 	color: #333333;
 }
 #webjournal .footer {
 	font-size: x-small;
 	color: #333333;
 	text-align: center;
 }
 /* Images in detailed articles */
 .imageScale, .imageScale img {
         width:280px;
 }
 /* First article image on index page.
 We cannot reuse the phl, ph and phr classes to draw the border, or the
 rendering of the index page on the HTML alert will fail*/
 .featuredImageScale, .featuredImageScale img {
         width:300px; /*Also check bfe_webjournal_MainArticleOverview, parameter 'image_px_width' */
         border:1px solid #999999;
         margin-bottom:6px;
         margin-right:12px;
         margin-top:0.2em;
         padding:2px;
 }
 /* Other articles images on index page.
 We cannot reuse the phl, ph and phr classes to draw the border, or the
 rendering of the index page on the HTML alert will fail */
 .featuredImageScaleSmall, .featuredImageScaleSmall img {
         width:200px; /*Also check bfe_webjournal_MainArticleOverview, parameter 'small_image_px_width' */
         border:1px solid #999999;
         margin-bottom:6px;
         margin-right:12px;
         margin-top:0.2em;
         padding:2px;
 }
 
 #webjournal {
 background-color: #FFFFFF;
 padding: 0px;
 font-family: Georgia, "Times New Roman", Times, serif;
 }
 #webjournal a:link {
 color: #000;
 text-decoration: none;
 }
 #webjournal a:visited{
 color: #3C2D3A;
 text-decoration: none;
 }
 #webjournal a:hover {
 color: #000;
 text-decoration: underline;
 }
 .contentBox {
 	background-image: url(journal_content.png);
 	background-repeat: repeat-y;
 	background-position: left top;
 	padding-top: 0px;
 	padding-right: 20px;
 	padding-bottom: 0px;
 	padding-left: 20px;
 }
 #footerBox2 {
 	background-image: url(journal_footer2.png);
 	background-repeat: no-repeat;
 	height: 70px;
 	background-position: left top;
 	padding-top: 10px;
 	padding-right: 20px;
 	padding-left: 20px;
 	padding-bottom: 0px;
 	text-align: center;
 }
 .articleTitle {
 	font-weight: lighter;
 	margin-bottom: 5px;
 	margin-top: 10px;
 	text-align: left;
 }
 h2 {
         font-size: xx-large
 }
 h3 {
         font-size: x-large
 }
 div.new, h3.new, h2.new {
         background:transparent url(journal_new.png) no-repeat scroll left top;
         padding-left:25px;
 }
 .articleBody {
 	font-size: medium;
 	font-weight: lighter;
 	text-align: justify;
 }
 .articleHeader {
         clear:both;
         font-size:100%;
         font-weight:600;
         margin-bottom:4px;
         margin-top:0pt;
         display: block;
 }
 .subNavigationMenuItem {
 	font-size: small;
 	font-weight: lighter;
 	color: #333333;
 	border-bottom-width: 1px;
 	border-bottom-style: dotted;
 	border-bottom-color: #999999;
 	margin-top: 5px;
 	padding-bottom: 2px;
 }
 #articles {
 	padding-right: 8px;
 	padding-left: 8px;
 }
 .readMore {
 	font-size: small;
 	color: #333333;
 	text-decoration: none;
 }
 .selectedNavigationPage {
 	background-color: #CCCCCC;
 }
 a.selectedNavigationPage:hover {
 	text-decoration:none;
 }
 
 /* Centered container for image + caption */
 .phwithcaption {
         width:280px;
         margin:auto;
         border:1px solid #999;
         background-color:#FFF;
         clear:both;
         font-size:80%;
         color:#555;
         padding:2px;
         text-align:center;
 }
 /* Left-aligned container for image + caption */
 .phlwithcaption {
         background-color:#FFFFFF;
         border:1px solid #999999;
         clear:left;
         color:#555555;
         float:left;
         font-size:80%;
         margin-right:24px;
         max-width:280px;
         padding:2px;
 }
 /* Right-aligned container for image + caption */
 .phrwithcaption {
         background-color:#FFFFFF;
         border:1px solid #999999;
         color:#555555;
         float:right;
         font-size:80%;
         margin-left:24px;
         margin-top:24px;
         max-width:280px;
         padding:2px;
         display:block;
 }
 /* Centered container for image without caption */
 .ph {
         background-color:#FFFFFF;
         border:1px solid #999999;
         margin-bottom:3px;
         margin-top:6px;
         padding:2px;
 }
 /* Left-aligned container for image without caption */
 .phl {
        background-color:#FFFFFF;
        border:1px solid #999999;
        clear:left;
        float:left;
        margin-bottom:6px;
        margin-right:12px;
        margin-top:0.2em;
        padding:2px;
 }
 /* Right-aligned container for image without caption */
 .phr {
         background-color:#FFFFFF;
         border:1px solid #999999;
         clear:right;
         float:right;
         margin-bottom:6px;
         margin-left:12px;
         margin-top:0.2em;
         padding:2px;
 }
 .caption {
         color:#555555;
         font-size:70%;
 }
 ul.whatsNew {
         line-height:1.2em;
         list-style-position:inside;
         list-style-type:none;
         font-weight:700;
 }
 ul.whatsNew li {
         margin-bottom: 15px
 }
 ul.whatsNewItem {
         list-style-image:none;
         list-style-position:inside;
         list-style-type:circle;
         font-weight:normal;
 }
 ul.whatsNewItem li {
         margin-bottom: 0px
 }
 a.rssLink{
         font-size:small;
 }
 a.rssLink img{
         border:none;
         padding-right:4px;
+}
+.htmlalertheader {
+        text-align:center;
+        background-color: #fff;
 }
\ No newline at end of file
diff --git a/modules/webjournal/lib/webjournal_templates.py b/modules/webjournal/lib/webjournal_templates.py
index 39260a71d..d8a4a9770 100644
--- a/modules/webjournal/lib/webjournal_templates.py
+++ b/modules/webjournal/lib/webjournal_templates.py
@@ -1,692 +1,712 @@
 # -*- coding: utf-8 -*-
 ## This file is part of CDS Invenio.
 ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN.
 ##
 ## CDS Invenio 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 2 of the
 ## License, or (at your option) any later version.
 ##
 ## CDS Invenio 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 CDS Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 """
 WebJournal templates - Defines the look of various parts of the
 WebJournal modules. Most customizations will however be done through
 BibFormat format templates files.
 """
 
 import os
 from invenio.config import \
      CFG_SITE_SUPPORT_EMAIL, \
      CFG_ETCDIR, \
      CFG_SITE_URL, \
      CFG_SITE_LANG
 from invenio.messages import gettext_set_language
 from invenio.webpage import page
 from invenio.webjournal_utils import \
      get_number_of_articles_for_issue, \
      get_release_datetime, \
      get_announcement_datetime, \
      get_issue_number_display
 
 class Template:
     """Templating class, refer to bibformat.py for examples of call"""
 
     def tmpl_webjournal_missing_info_box(self, ln, title, msg_title, msg):
         """
         returns a box indicating that the given journal was not found on the
         server, leaving the opportunity to select an existing journal from a list.
         """
         _ = gettext_set_language(ln)
         box_title = msg_title
         box_text = msg
         box_list_title = _("Available Journals")
         # todo: move to DB call
         find_journals = lambda path: [entry for entry in os.listdir(str(path)) \
                                       if os.path.isdir(str(path)+str(entry))]
         try:
             all_journals = find_journals('%s/webjournal/' % CFG_ETCDIR)
         except:
             all_journals = []
 
         mail_msg = _("Contact %(x_url_open)sthe administrator%(x_url_close)s") % \
                    {'x_url_open' :
                     '<a href="mailto:%s">' % CFG_SITE_SUPPORT_EMAIL,
                     'x_url_close' : '</a>'}
         box = '''
         <div style="text-align: center;">
             <fieldset style="width:400px; margin-left: auto; margin-right:auto">
                 <legend style="color:#a70509;background-color:#fff;">
                     <i>%s</i>
                 </legend>
                 <p style="text-align:center;">%s</p>
                 <h2 style="color:#0D2B88;">%s</h2>
                 <ul class="webjournalBoxList">
                     %s
                 </ul>
                 <br/>
                 <div style="text-align:right;">
                 %s
                 </div>
             </fieldset>
         </div>
                 ''' % (box_title,
                        box_text,
                        box_list_title,
                        "".join(['<li><a href="%s/journal/?name=%s">%s</a></li>'
                                 % (CFG_SITE_URL,
                                    journal,
                                    journal) for journal in all_journals]),
                        mail_msg)
         return page(title=title, body=box)
 
     def tmpl_webjournal_error_box(self, ln, title, title_msg, msg):
         """
         returns an error box for webjournal errors.
         """
         _ = gettext_set_language(ln)
         title = _(title)
         title_msg = _(title_msg)
         msg = _(msg)
         mail_msg = _("Contact %(x_url_open)sthe administrator%(x_url_close)s") % \
                    {'x_url_open' :
                     '<a href="mailto:%s">' % CFG_SITE_SUPPORT_EMAIL,
                     'x_url_close' : '</a>'}
         box = '''
         <div style="text-align: center;">
             <fieldset style="width:400px; margin-left: auto; margin-right: auto;">
                 <legend style="color:#a70509;background-color:#fff;">
                     <i>%s</i>
                 </legend>
                 <p style="text-align:center;">%s</p>
                 <br/>
                 <div style="text-align:right;">
                     %s
                 </div>
             </fieldset>
         </div>
                 ''' % (title_msg, msg, mail_msg)
         return page(title=title, body=box)
 
     def tmpl_admin_regenerate_success(self, ln, journal_name, issue):
         """
         Success message if a user applied the "regenerate" link. Links back to
         the regenerated journal.
         """
         _ = gettext_set_language(ln)
 
         out = '''
         The issue number %(issue)s for the %(journal_name)s journal has been successfully
         regenerated. <br/>
         Look at your changes: >> <a href="%(CFG_SITE_URL)s/journal/%(journal_name)s/%(issue_year)s/%(issue_number)s"> %(journal_name)s </a> <br/> or go back to this journal <a href="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/administrate?journal_name=%(journal_name)s">administration interface</a>.
         ''' % {'issue': issue,
                'journal_name': journal_name,
                'CFG_SITE_URL': CFG_SITE_URL,
                'issue_year': issue.split('/')[1],
                'issue_number': issue.split('/')[0]}
 
         return out
 
     def tmpl_admin_regenerate_error(self, ln, journal_name, issue):
         """
         Failure message for a regeneration try.
         """
         _ = gettext_set_language(ln)
         return page(
             title=_("Regeneration Error"),
             body = _("The issue could not be correctly regenerated. "
                      "Please contact your administrator."))
 
     def tmpl_admin_feature_record(self, journal_name,
                                   featured_records=[],
                                   ln=CFG_SITE_LANG,
                                   msg=None):
         """
         Display an interface form to feature a specific record from CDS Invenio.
         """
         _ = gettext_set_language(ln)
         out = ''
         out += '''<table class="admin_wvar">
         <tr><th colspan="5" class="adminheaderleft" cellspacing="0">%(menu)s</th></tr>
         <tr>
         <td>0.&nbsp;<small><a href="administrate?journal_name=%(journal_name)s">Administrate</a></small>&nbsp;</td>
         <td>1.&nbsp;<small>Feature a Record</small>&nbsp;</td>
         <td>2.&nbsp;<small><a href="configure?action=edit&amp;journal_name=%(journal_name)s">Edit Configuration</a></small>&nbsp;</td>
         <td>3.&nbsp;<small><a href="%(CFG_SITE_URL)s/journal/%(journal_name)s">Go to the Journal</a></small>&nbsp;</td>
         </tr>
         </table><br/>''' % {'journal_name': journal_name,
                             'menu': _("Menu"),
                             'CFG_SITE_URL': CFG_SITE_URL}
         if msg is not None:
             out += msg
         out += '<br/><br/>'
         out += '''<table class="admin_wvar" cellspacing="0" width="400px">
                       <tr>
                           <th colspan="3" class="adminheader">Featured records</th>
                       </tr>'''
         color = "fff"
         for (recid, img_url) in featured_records:
             out += '''<tr style="background-color:#%(color)s">
                <td class="admintd"><img src="%(img_url)s" alt="" height="40px"/></td>
                <td class="admintdleft"><a href="%(CFG_SITE_URL)s/record/%(recid)s">Record %(recid)s</a></td>
                <td class="admintdright"><a href="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/feature_record?journal_name=%(journal_name)s&amp;action=askremove&amp;recid=%(recid)s">remove</a></td>
             </tr>''' % {'color': color,
                         'journal_name': journal_name,
                         'recid': recid,
                         'img_url': img_url,
                         'CFG_SITE_URL': CFG_SITE_URL}
             if color == 'fff':
                 color = 'EBF7FF'
             else:
                 color = 'fff'
         if len(featured_records) == 0:
             out += '<tr><td colspan="3" class="admintd"><em>No record featured for the moment. Add one using the form below.</em></td></tr>'
         out += '</table>'
         out += '''
         <br/><br/><br/>
         <form action="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/feature_record" method="post">
         <input type="hidden" name="action" value="add" />
         <input type="hidden" name="journal_name" value="%(journal_name)s"/>
         <table class="admin_wvar" cellspacing="0">
             <tr>
                 <th colspan="2" class="adminheaderleft">Add a new featured record:</th>
             </tr>
             <tr>
                 <td class="admintdright"><label for="recordid"><span style="white-space: nowrap;">Featured Record ID</span></label>:&nbsp;</td>
                 <td><input tabindex="1" type="text" name="recid" value="" id="recordid"/></td>
             </tr>
             <tr>
                 <td class="admintdright"><label for="image_url"><span style="white-space: nowrap;">Icon URL</span></label>:&nbsp;</td>
                 <td><input tabindex="2" type="text" name="img_url" value="" id="image_url" size="60"/><em><br/><small>Image displayed along the featured record</small></em></td>
             </tr>
             <tr>
             <td colspan="2" align="right"><input tabindex="3" class="adminbutton" type="submit" value="Add"/></td>
             </tr>
         </table>
         </form>
         ''' % {'CFG_SITE_URL': CFG_SITE_URL,
                'journal_name': journal_name}
         return out
 
     def tmpl_admin_alert_plain_text(self, journal_name, ln, issue):
         """
         Default plain text message for email alert of journal updates.
         This will be used to pre-fill the content of the mail alert, that
         can be modified by the admin.
 
         Customize this function to return different default texts
         based on journal name and language,
         """
         current_publication = get_issue_number_display(issue, journal_name, ln)
         plain_text = u'''Dear Subscriber,
 
     The latest issue of %(journal_name)s, no. %(current_publication)s, has been released.
     You can access it at the following URL:
     %(CFG_SITE_URL)s/journal/%(journal_name)s/
 
     Best Wishes,
     %(journal_name)s team
 
     ----
 Cher Abonné,
 
     Le nouveau numéro de %(journal_name)s, no. %(current_publication)s, vient de paraître.
     Vous pouvez y accéder à cette adresse :
     %(CFG_SITE_URL)s/journal/%(journal_name)s/?ln=fr
 
     Bonne lecture,
     L'équipe de %(journal_name)s
     ''' % {'journal_name': journal_name,
            'current_publication': current_publication,
            'CFG_SITE_URL': CFG_SITE_URL}
         return plain_text
     # '
 
+    def tmpl_admin_alert_header_html(self, journal_name, ln, issue):
+        """
+        Returns HTML header to be inserted into the HTML alert
+
+        @param journal_name: the journal name
+        @param ln: the current language
+        @param issue: the issue for wich the alert is sent
+        """
+        _ = gettext_set_language(ln)
+        journal_url = '%(CFG_SITE_URL)s/journal/%(journal_name)s/%(year)s/%(number)s' % \
+                      {'CFG_SITE_URL': CFG_SITE_URL,
+                       'journal_name': journal_name,
+                       'year': issue.split('/')[1],
+                       'number': issue.split('/')[0]}
+        journal_link = '<a href="%(journal_url)s">%(journal_url)s</a>' % \
+                       {'journal_url': journal_url}
+        return '<p class="htmlalertheader">' + \
+               _('If you cannot read this email please go to %(x_journal_link)s') % {'x_journal_link': journal_link} + \
+               '</p>'
+
     def tmpl_admin_alert_subject(self, journal_name, ln, issue):
         """
         Default subject for email alert of journal updates.
 
         Customize this function to return different default texts
         based on journal name and language,
         """
         return "%s %s released" % (journal_name, \
                                    get_issue_number_display(issue,
                                                             journal_name,
                                                             ln))
 
     def tmpl_admin_alert_interface(self, ln, journal_name, default_subject,
                                    default_msg, default_recipients, alert_ln):
         """
         Alert email interface.
         """
         _ = gettext_set_language(ln)
         interface = '''
         <table>
         <tr>
         <td valign="top">
         <form action="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/alert" name="alert" method="post">
             <input type="hidden" name="journal_name" value="%(journal_name)s"/>
             <p>Recipients:</p>
             <input type="text" name="recipients" value="%(default_recipients)s" size="60" />
             <p>Subject:</p>
             <input type="text" name="subject" value="%(subject)s" size="60" />
             <p>Plain Text Message:</p>
             <textarea name="plainText" wrap="soft" rows="25" cols="80">%(plain_text)s</textarea>
             <p> <input type="checkbox" name="htmlMail" id="htmlMail" value="html" checked="checked" />
                <label for="htmlMail">Send journal front-page <small>(<em>HTML newsletter</em>)</small></label>
             </p>
             <br/>
             <input class="formbutton" type="submit" value="Send Alert" name="sent"/>
         </form>
         </td><td valign="top">
         <p>HTML newsletter preview:</p>
         <iframe id="htmlMailPreview" src="%(CFG_SITE_URL)s/journal/%(journal_name)s?ln=%(alert_ln)s" height="600" width="600"></iframe>
         </tr>
         </table>
         ''' % {'CFG_SITE_URL': CFG_SITE_URL,
                'journal_name': journal_name,
                'subject': default_subject,
                'plain_text': default_msg,
                'default_recipients': default_recipients,
                'alert_ln': alert_ln}
 
         return interface
 
     def tmpl_admin_alert_was_already_sent(self, ln, journal_name,
                                           subject, plain_text, recipients,
                                           html_mail, issue):
         """
         """
         _ = gettext_set_language(ln)
         out = '''
         <form action="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/alert" name="alert" method="post">
             <input type="hidden" name="journal_name" value="%(journal_name)s"/>
             <input type="hidden" name="recipients" value="%(recipients)s" />
             <input type="hidden" name="subject" value="%(subject)s" />
             <input type="hidden" name="plainText" value="%(plain_text)s" />
             <input type="hidden" name="htmlMail" value="%(html_mail)s" />
             <input type="hidden" name="force" value="True" />
             <p><em>WARNING! </em>The email alert for the issue %(issue)s has already been
-            sent. Are you absolutely sure you want to it send it again?</p>
+            sent. Are you absolutely sure you want to send it again?</p>
             <p>Maybe you forgot to release an update issue? If so, please do this
             first <a href="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/issue_control?journal_name=%(journal_name)s&amp;issue=%(issue)s">here</a>.</p>
             <p>Proceed with caution, or your subscribers will receive the alert a second time.</p>
             <br/>
             <input class="formbutton" type="submit" value="I really want this!" name="sent"/>
         </form>
                 ''' % {'CFG_SITE_URL': CFG_SITE_URL,
                        'journal_name': journal_name,
                        'recipients': recipients,
                        'subject': subject,
                        'plain_text': plain_text,
                        'html_mail': html_mail,
                        'issue': issue}
         return out
 
     def tmpl_admin_alert_unreleased_issue(self, ln, journal_name):
         """
         Tried to announce an unreleased issue
         """
         _ = gettext_set_language(ln)
         out = '''<p style="color:#f00">An alert cannot be send for this issue!</p>
 
         You tried to send an alert for an issue that has not yet been released.
         Release it first and retry.<br/>
 
         Go back to the <a href="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/administrate?journal_name=%(journal_name)s">administration interface</a>.
         ''' % {'CFG_SITE_URL': CFG_SITE_URL,
                'journal_name': journal_name}
         return out
 
     def tmpl_admin_alert_success_msg(self, ln, journal_name):
         """
         Success messge for the alert system.
         """
         _ = gettext_set_language(ln)
         out = '''<p style="color:#0f0">Alert sent successfully!</p>
         Return to your journal here: >> \
                  <a href="%(CFG_SITE_URL)s/journal/%(journal_name)s">%(journal_name)s</a> <br/>
                  or go back to the <a href="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/administrate?journal_name=%(journal_name)s">administration interface</a>''' % {'CFG_SITE_URL': CFG_SITE_URL,
                                       'journal_name': journal_name}
         return out
 
     def tmpl_admin_control_issue(self, ln, journal_name,
                                  active_issues):
         """
         Display the interface allowing to set the current issue.
         """
         _ = gettext_set_language(ln)
         out = '''
         <p>This interface gives you the possibility to create your
            current webjournal publication. Every checked issue number
            will be in the current publication. Once you have made your
            selection you can publish the new issue by clicking the %(publish)s
            button at the end.
         </p>
             <form action="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/issue_control" name="publish">
                 <input type="hidden" name="journal_name" value="%(journal_name)s"/>
                 Issue Numbers to publish:
                 <ul>
                 %(issues_list)s
                 </ul>
                 <br/>
 
                 <p>Add a higher issue number by clicking "%(add)s"</p>
                 <input class="formbutton" type="submit" value="%(add)s" name="action"/>
                 <p>.. or add a custom issue number by typing it here and pressing "%(refresh)s"</p>
                 <input type="text" value="ww/YYYY" name="issue"/>
                 <input class="formbutton" type="submit" value="%(refresh)s" name="action"/>
                 <br/>
                 <br/>
                 <p>If all issues you want to publish are correctly checked, proceed \
                 by clicking "%(publish)s".</p>
                 <input class="formbutton" type="submit" value="%(publish)s" name="action"/>
             </form>
             ''' % {'CFG_SITE_URL': CFG_SITE_URL,
                    'journal_name': journal_name,
                    'issues_list': "".join(['<li><input type="checkbox" name="issue" value="%s" CHECKED>&nbsp;%s</input></li>'
                             % (issue, issue) for issue in active_issues]),
                    'add' : _("Add"),
                    'publish' : _("Publish"),
                    'refresh' : _("Refresh")
                    }
 
         return out
 
     def tmpl_admin_control_issue_success_msg(self, ln,
                                              active_issues, journal_name):
         """
         An issue was successfully published
         """
         _ = gettext_set_language(ln)
         issue_string = "".join([" - %s" % issue for issue in active_issues])
         title = '<h2>Issue(s) %s created successfully!</h2>' % issue_string
         body = '''<p>Now you can:</p>
                  <p>Return to your journal here: >>
                  <a href="%s/journal/%s"> %s </a>
                  </p>
                  <p>Make additional publications here: >>
                  <a href="%s/admin/webjournal/webjournaladmin.py/administrate?journal_name=%s">Publishing Interface</a>
                 </p>
                 <p>Send an alert email here: >>
                 <a href="%s/admin/webjournal/webjournaladmin.py/alert?journal_name=%s"> Send an alert</a>
                 </p>''' % (CFG_SITE_URL, journal_name,
                          journal_name, CFG_SITE_URL,
                          journal_name, CFG_SITE_URL, journal_name)
         return title + body
 
     def tmpl_admin_update_issue(self, ln, journal_name, next_issue,
                                 current_issue):
         """
         A form that lets a user make an update to an issue number.
         """
         _ = gettext_set_language(ln)
         current_articles = get_number_of_articles_for_issue(current_issue,
                                                             journal_name,
                                                             ln)
         next_articles = get_number_of_articles_for_issue(next_issue,
                                                          journal_name,
                                                          ln)
 
         html = '''
         <p>The Issue that was released on week %(current_issue)s has pending updates scheduled. The
         next update for this issue is %(next_issue)s.</p>
         <p><em>Note: If you want to make a new release, please click through all the
         pending updates first.</em></p>
         <p>Do you want to release the update from issue: <br/>
         &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>%(current_issue)s</em> (%(current_articles)s) <br/>
         to issue: <br/>
         &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>%(next_issue)s</em> (%(next_articles)s) <br/>
         now?</p>
         <form action="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/issue_control" name="publish">
             <input type="hidden" name="journal_name" value="%(journal_name)s"/>
             <input type="hidden" name="issue" value="%(next_issue)s"/>
             <input class="formbutton" type="submit" value="%(update)s" name="action"/>
         </form>
         ''' % {'current_issue': current_issue,
                'next_issue' : next_issue,
                'current_articles': ",".join(["%s : %s" % (item[0], item[1]) \
                                              for item in current_articles.iteritems()]),
                'next_articles': ",".join(["%s : %s" % (item[0], item[1]) \
                                           for item in next_articles.iteritems()]),
                'CFG_SITE_URL' : CFG_SITE_URL,
                'journal_name': journal_name,
                'update': _("Update")}
         return html
 
     def tmpl_admin_updated_issue_msg(self, ln, update_issue, journal_name):
         """
         Prints a success message for the Update release of a journal.
         """
         _ = gettext_set_language(ln)
         title = '<h2>Journal update %s published successfully!</h2>' % update_issue
         body = '''<p>Now you can:</p>
                  <p>Return to your journal here: >>
                  <a href="%s/journal/%s"> %s </a>
                  </p>
                  <p>Go back to the publishing interface: >>
                  <a href="%s/admin/webjournal/webjournaladmin.py/administrate?journal_name=%s">Issue Interface</a>
                  </p>
                  <p>Send an alert email here: >>
                  <a href="%s/journal/alert?name=%s"> Send an alert</a>
                  </p>''' % (CFG_SITE_URL, journal_name, journal_name,
                           CFG_SITE_URL, journal_name, CFG_SITE_URL, journal_name)
         return title + body
 
     def tmpl_admin_administrate(self, journal_name, current_issue,
                                 current_publication, issue_list,
                                 next_issue_number, ln=CFG_SITE_LANG,
                                 as_editor=True):
         """
         Returns an administration interface that shows the current publication and
         supports links to all important actions.
 
         @param as_editor: True if can make changes to the configuration. Else read-only mode.
         """
         _ = gettext_set_language(ln)
         out = ''
 
         if as_editor:
             admin_menu = '''<table class="admin_wvar">
             <tr><th colspan="5" class="adminheaderleft" cellspacing="0">%(menu)s</th></tr>
             <tr>
             <td>0.&nbsp;<small>Administrate</small>&nbsp;</td>
             <td>1.&nbsp;<small><a href="feature_record?journal_name=%(journal_name)s">Feature a Record</a></small>&nbsp;</td>
             <td>2.&nbsp;<small><a href="configure?action=edit&amp;journal_name=%(journal_name)s">Edit Configuration</a></small>&nbsp;</td>
             <td>3.&nbsp;<small><a href="%(CFG_SITE_URL)s/journal/%(journal_name)s">Go to the Journal</a></small>&nbsp;</td>
             </tr>
             </table><br/>'''
         else:
             admin_menu = '''<table class="admin_wvar">
             <tr><th colspan="5" class="adminheaderleft" cellspacing="0">%(menu)s</th></tr>
             <tr>
             <td>0.&nbsp;<small>Administrate</small>&nbsp;</td>
             <td>1.&nbsp;<small><a href="%(CFG_SITE_URL)s/journal/%(journal_name)s">Go to the Journal</a></small>&nbsp;</td>
             </tr>
             </table><br/>'''
 
         out += admin_menu % {'journal_name': journal_name,
                              'menu': _("Menu"),
                              'CFG_SITE_URL': CFG_SITE_URL}
 
         # format the issues
         issue_boxes = []
         issue_list.append(next_issue_number)
         for issue in issue_list:
             articles = get_number_of_articles_for_issue(issue,
                                                         journal_name,
                                                         ln)
             released_on = get_release_datetime(issue, journal_name, ln)
             announced_on = get_announcement_datetime(issue, journal_name, ln)
             issue_box = '''
                 <tr style="%s">
                     <td class="admintdright" style="vertical-align: middle;"></td>
                     <td class="admintdleft" style="white-space: nowrap; vertical-align: middle;">
                         <p>Issue: %s</p>
                         <p>Publication: %s</p>
                     </td>
                     <td class="admintdright" style="vertical-align: middle;">
                         %s
                     </td>
                     <td class="admintdright" style="vertical-align: middle;">
                         <p>%s</p>
                         <p>%s</p>
                     </td>
                     <td class="admintdright" style="vertical-align: middle;">
                         <p><a href="%s/admin/webjournal/webjournaladmin.py/regenerate?journal_name=%s&amp;issue=%s&amp;ln=%s">&gt;regenerate</a></p>
                     </td>
                 <tr>
             ''' % ((issue==current_issue) and "background:#00FF00;" or "background:#F1F1F1;",
 
                     issue, (issue==next_issue_number) and "?" or current_publication,
 
                     "\n".join(['<p>%s : %s <a href="%s/journal/%s/%s/%s/%s">&gt;view</a></p>' %
                                (item[0], item[1],
                                 CFG_SITE_URL, journal_name,
                                 issue.split('/')[1], issue.split('/')[0], item[0]) \
                                for item in articles.iteritems()]),
 
                     (not released_on) and
                     ('<em>not released</em>' + (as_editor and '<br/><a href="%s/admin/webjournal/webjournaladmin.py/issue_control?journal_name=%s">&gt;release now</a>' % (CFG_SITE_URL, journal_name) or '')) or
                     'released on: %s' % released_on.strftime("%d.%m.%Y"),
 
                     (not announced_on)
                     and ('<em>not announced</em>' + (as_editor and '<br/><a href="%s/admin/webjournal/webjournaladmin.py/alert?journal_name=%s&issue=%s">&gt;announce now</a>' % (CFG_SITE_URL, journal_name, issue) or '')) or
                     'announced on: %s <br/><a href="%s/admin/webjournal/webjournaladmin.py/alert?journal_name=%s&issue=%s">&gt;re-announce</a>' % (announced_on.strftime("%d.%m.%Y"), CFG_SITE_URL, journal_name, issue),
 
                     CFG_SITE_URL, journal_name, issue, ln
                 )
             issue_boxes.append(issue_box)
         out += '''
                  <table class="admin_wvar" width="80%%" cellspacing="0">
                     <tbody>
                         <tr>
                             <th class="adminheaderleft"></th>
                             <th class="adminheaderleft">Issue / Publication</th>
                             <th class="adminheader">Articles</th>
                             <th class="adminheaderleft">Release / Announcement</th>
                             <th class="adminheaderleft">Cache Status</th>
                         <tr>
                         %s
                     </tbody>
                  </table>
                  ''' % ("\n".join([issue_box for issue_box in issue_boxes]))
 
         return out
 
     def tmpl_admin_index(self, ln, journals, msg=None):
         """
         Returns the admin index page content.
 
         Lists the journals, and offers options to edit them, delete them
         or add new journal
 
         params:
                  ln  - ln
            journals  - list of tuples (journal_info dict, as_editor)
                 msg  - message to be displayed
         """
         out = ""
         if msg is not None:
             out += msg
         out += '''
         <p>Choose the journal you want to administrate.</p>
         <table class="admin_wvar" cellspacing="0">
         <tr>
             <th class="adminheader">Journals</th>
             <th colspan="2" class="adminheader">&nbsp;</th>
         </tr>
         '''
         color = "fff"
         for journal_info, as_editor in journals:
             row = '''<tr style="background-color:#%(color)s">
                <td class="admintdleft"><a href="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/administrate?journal_name=%(journal_name)s">%(journal_name)s</a></td>
                <td class="admintdright"><a href="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/administrate?journal_name=%(journal_name)s">edit</a></td>'''
             if as_editor:
                 row += '<td class="admintdright"><a href="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/index?journal_name=%(journal_name)s&action=askDelete">delete</a></td>'
             row += '</tr>'
             out += row % {'color': color,
                           'journal_name': journal_info['journal_name'],
                           'journal_id': journal_info['journal_id'],
                           'CFG_SITE_URL': CFG_SITE_URL}
             if color == 'fff':
                 color = 'EBF7FF'
             else:
                 color = 'fff'
         out += '''<tr style="background-color:#%(color)s">
             <td class="admintdleft" colspan="3" style="padding: 5px 10px;"><a href="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/configure?action=add">Add new journal</a></td>
         </tr>''' % {'color': color,
                     'CFG_SITE_URL': CFG_SITE_URL}
         out += '</table>'
         return out
 
     def tmpl_admin_configure_journal(self, ln, journal_name='', xml_config=None,
                                      action='edit', msg=None):
         """
         Display a page to change the settings of a journal. Also used to
         add a new journal.
         """
         out = ''
         _ = gettext_set_language(ln)
         journal_name_readonly = 'readonly="readonly" disabled="disabled"'
         journal_name_note = ''
         submit_button_label = _('Apply')
         if action == 'add':
             journal_name = ''
             journal_name_readonly = ''
             journal_name_note = 'Used in URLs. Choose it short and meaningful. This cannot be changed later'
             submit_button_label = _('Add')
         elif action in ['edit', 'editDone']:
             # Display navigation menu
             out += '''<table class="admin_wvar">
         <tr><th colspan="5" class="adminheaderleft" cellspacing="0">%(menu)s</th></tr>
         <tr>
         <td>0.&nbsp;<small><a href="administrate?journal_name=%(journal_name)s">Administrate</a></small>&nbsp;</td>
         <td>1.&nbsp;<small><a href="feature_record?journal_name=%(journal_name)s">Feature a Record</a></small>&nbsp;</td>
         <td>2.&nbsp;<small>Edit Configuration</small>&nbsp;</td>
         <td>3.&nbsp;<small><a href="%(CFG_SITE_URL)s/journal/%(journal_name)s">Go to the Journal</a></small>&nbsp;</td>
         </tr>
         </table><br/>''' % {'journal_name': journal_name,
                             'menu': _("Menu"),
                             'CFG_SITE_URL': CFG_SITE_URL}
         if msg is not None:
             out += msg
             out += '<br/><br/>'
 
         out += '''
           <form action="configure" method="post">
           <input type="hidden" name="ln" value="%(ln)s" />
           <input type="hidden" name="action" value="addDone" />
           <table class="admin_wvar" cellspacing="0" style="width:90%%">
           <tr>
           <th colspan="2" class="adminheaderleft">
           Journal settings</th>
           </tr>
           <tr>
           <td class="admintdright" width="100px"><label for="journal_name">Name</label>:&nbsp;</td>
           <td><input tabindex="0" name="journal_name" type="text" id="journal_name" maxlength="50" size="15" value="%(journal_name)s" %(readonly)s %(journal_name_readonly)s /><small>%(journal_name_note)s</small></td>
           </tr>
           <tr>
           <td class="admintdright"><label for="xml_config">Config</label>:&nbsp;</td>
           <td><textarea wrap="soft" rows="25" style="width:100%%" tabindex="3" name="xml_config" id="xml_config" size="25" %(readonly)s>%(xml_config)s</textarea></td>
           </tr>
           <td colspan="2" align="right"><input type="submit"  class="adminbutton" value="%(submit_button_label)s"></td>
           </tr>
           </table>
           </form>
           ''' % {'journal_name': journal_name,
                  'ln': ln,
                  'readonly': '',
                  'disabled': '',
                  'xml_config': xml_config.encode('utf-8'),
                  'journal_name_note': journal_name_note,
                  'submit_button_label': submit_button_label,
                  'journal_name_readonly': journal_name_readonly}
 
         return out
diff --git a/modules/webjournal/lib/webjournaladminlib.py b/modules/webjournal/lib/webjournaladminlib.py
index 1709b07bd..ec49a5bf5 100644
--- a/modules/webjournal/lib/webjournaladminlib.py
+++ b/modules/webjournal/lib/webjournaladminlib.py
@@ -1,886 +1,903 @@
 ## This file is part of CDS Invenio.
 ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN.
 ##
 ## CDS Invenio 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 2 of the
 ## License, or (at your option) any later version.
 ##
 ## CDS Invenio 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 CDS Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 # pylint: disable-msg=C0301
 """CDS Invenio WebJournal Administration Interface."""
 
 __revision__ = "$Id$"
 
 import sys
 import cPickle
 import re
 import os
 from urllib2 import urlopen
 
 if sys.hexversion < 0x2040000:
     # pylint: disable-msg=W0622
     from sets import Set as set
     # pylint: enable-msg=W0622
 
 from invenio.errorlib import register_exception
 from invenio.config import \
      CFG_SITE_URL, \
      CFG_SITE_LANG, \
      CFG_SITE_NAME, \
      CFG_ETCDIR, \
      CFG_CACHEDIR, \
      CFG_TMPDIR, \
      CFG_SITE_SUPPORT_EMAIL
 from invenio.messages import gettext_set_language
 from invenio.mailutils import send_email
 from invenio.access_control_engine import acc_authorize_action
 from invenio.webjournal_config import \
      InvenioWebJournalJournalIdNotFoundDBError, \
      InvenioWebJournalReleaseUpdateError, \
      InvenioWebJournalNoJournalOnServerError
 from invenio.webjournal_utils import \
      get_journals_ids_and_names, \
      guess_journal_name, \
      get_current_issue, \
      get_issue_number_display, \
      get_featured_records, \
      add_featured_record, \
      remove_featured_record, \
      clear_cache_for_issue, \
      get_next_journal_issues, \
      get_release_datetime, \
      get_journal_id, \
      compare_issues, \
      get_journal_info_path, \
      get_journal_css_url, \
      get_journal_alert_sender_email, \
      get_journal_alert_recipient_email, \
      get_journal_draft_keyword_to_remove, \
      get_journal_categories, \
      get_journal_articles, \
      get_grouped_issues, \
      get_journal_issue_grouping, \
      get_journal_languages
 from invenio.dbquery import run_sql
 from invenio.bibrecord import \
      create_record, \
      print_rec
 from invenio.bibformat import format_record
 from invenio.bibtask import task_low_level_submission
 from invenio.webjournal_config import \
      InvenioWebJournalNoJournalOnServerError
 import invenio.template
 wjt = invenio.template.load('webjournal')
 
 def getnavtrail(previous = ''):
     """Get the navtrail"""
 
     navtrail = """<a class="navtrail" href="%s/help/admin">Admin Area</a> """ % (CFG_SITE_URL,)
     navtrail = navtrail + previous
     return navtrail
 
 def perform_index(ln=CFG_SITE_LANG, journal_name=None, action=None, uid=None):
     """
     Index page
 
     Lists the journals, and offers options to edit them, delete them
     or add new journal.
 
     Parameters:
         journal_name  -  the journal affected by action, if any
               action  -  one of ['', 'askDelete', _('Delete'), _('Cancel')]
                   ln  -  language
                  uid  -  user id
     """
     _ = gettext_set_language(ln)
 
     msg = None
     if action == 'askDelete' and journal_name is not None:
         msg = '''<fieldset style="display:inline;margin-left:auto;margin-right:auto;">
         <legend>Delete Journal Configuration</legend><span style="color:#f00">Are you sure you want to delete the configuration of %(journal_name)s?
         <form action="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py">
         <input type="hidden" name="journal_name" value="%(journal_name)s" />
         <input class="formbutton" type="submit" name="action" value="%(delete)s" />
         <input class="formbutton" type="submit" name="action" value="%(cancel)s" />
         </form></span></fieldset>''' % {'CFG_SITE_URL': CFG_SITE_URL,
                                         'journal_name': journal_name,
                                         'delete': _("Delete"),
                                         'cancel': _("Cancel")}
 
     if action == _("Delete") and journal_name is not None:
         # User confirmed and clicked on "Delete" button
         remove_journal(journal_name)
 
     journals = get_journals_ids_and_names()
     # Only keep journal that user can view or edit
     journals = [(journal_info, acc_authorize_action(uid,
                                                     'cfgwebjournal',
                                                     name=journal_info['journal_name'],
                                                     with_editor_rights='yes')[0] == 0) \
                  for journal_info in journals \
                  if acc_authorize_action(uid,
                                          'cfgwebjournal',
                                          name=journal_info['journal_name'])[0] == 0]
     return wjt.tmpl_admin_index(ln=ln,
                                 journals=journals,
                                 msg=msg)
 
 def perform_administrate(ln=CFG_SITE_LANG, journal_name=None,
                          as_editor=True):
     """
     Administration of a journal
 
     Show the current and next issues/publications, and display links
     to more specific administrative pages.
 
     Parameters:
         journal_name  -  the journal to be administrated
                   ln  -  language
         with_editor_rights  -  True if can edit configuration. Read-only mode otherwise
     """
     if journal_name is None:
         try:
             journal_name = guess_journal_name(ln)
         except InvenioWebJournalNoJournalOnServerError, e:
             return e.user_box()
 
     if not can_read_xml_config(journal_name):
         return '<span style="color:#f00">Configuration could not be read. Please check that %s/webjournal/%s/%s-config.xml exists and can be read by the server.</span><br/>' % (CFG_ETCDIR, journal_name, journal_name)
 
     current_issue = get_current_issue(ln, journal_name)
     current_publication = get_issue_number_display(current_issue,
                                                    journal_name,
                                                    ln)
     issue_list = get_grouped_issues(journal_name, current_issue)
     next_issue_number = get_next_journal_issues(issue_list[-1], journal_name, 1)
 
     return wjt.tmpl_admin_administrate(journal_name,
                                        current_issue,
                                        current_publication,
                                        issue_list,
                                        next_issue_number[0],
                                        ln,
                                        as_editor=as_editor)
 
 def perform_feature_record(journal_name,
                            recid,
                            img_url='',
                            action='',
                            ln=CFG_SITE_LANG):
     """
     Interface to feature a record
 
     Used to list, add and remove featured records of the journal.
 
     Parameters:
         journal_name  -  the journal for which the article is featured
                recid  -  the record affected by 'action'
              img_url  -  the URL to image displayed with given record
                          (only when action == 'add')
               action  -  One of ['', 'add', 'askremove', _('Remove'), _('Cancel')]
                   ln  -  language
     """
     _ = gettext_set_language(ln)
 
     if action == 'add':
         result = add_featured_record(journal_name, recid, img_url)
         if result == 0:
             msg ='''<span style="color:#0f0">Successfully featured
             <a href="%(CFG_SITE_URL)s/record/%(recid)s">record %(recid)s</a>.
         Go to the <a href="%(CFG_SITE_URL)s/journal/%(name)s">%(name)s journal</a> to
         see the result.</span>''' % {'CFG_SITE_URL': CFG_SITE_URL,
                                   'name': journal_name,
                                   'recid': recid}
         elif result == 1:
             msg = '''<span style="color:#f00"><a href="%(CFG_SITE_URL)s/record/%(recid)s">record %(recid)s</a> is already featured. Choose another one or remove it first.</span>''' % \
                   {'CFG_SITE_URL': CFG_SITE_URL,
                    'recid': recid}
         else:
             msg = '''<span style="color:#f00">Record could not be featured. Check file permission.</span>'''
 
         featured_records = get_featured_records(journal_name)
         return wjt.tmpl_admin_feature_record(ln=ln,
                                              journal_name=journal_name,
                                              featured_records=featured_records,
                                              msg=msg)
     elif action == 'askremove':
         msg = '''<fieldset style="display:inline;margin-left:auto;margin-right:auto;">
         <legend>Remove featured record</legend><span style="color:#f00">Are you sure you want to remove <a href="%(CFG_SITE_URL)s/record/%(recid)s">record %(recid)s</a> from the list of featured record?
         <form action="%(CFG_SITE_URL)s/admin/webjournal/webjournaladmin.py/feature_record">
         <input type="hidden" name="journal_name" value="%(name)s" />
         <input type="hidden" name="recid" value="%(recid)s" />
         <input class="formbutton" type="submit" name="action" value="%(remove)s" />
         <input class="formbutton" type="submit" name="action" value="%(cancel)s" />
         </form></span></fieldset>''' % \
             {'CFG_SITE_URL': CFG_SITE_URL,
              'name': journal_name,
              'recid': recid,
              'cancel': _("Cancel"),
              'remove': _("Remove")}
         featured_records = get_featured_records(journal_name)
         return wjt.tmpl_admin_feature_record(ln=ln,
                                              journal_name=journal_name,
                                              featured_records=featured_records,
                                              msg=msg)
     elif action == _("Remove"):
         result = remove_featured_record(journal_name, recid)
         msg = '''<span style="color:#f00"><a href="%(CFG_SITE_URL)s/record/%(recid)s">Record %(recid)s</a>
         has been removed.</span>''' % \
             {'CFG_SITE_URL': CFG_SITE_URL,
              'recid': recid}
         featured_records = get_featured_records(journal_name)
         return wjt.tmpl_admin_feature_record(ln=ln,
                                              journal_name=journal_name,
                                              featured_records=featured_records,
                                              msg=msg)
     else:
         msg = '''Here you can choose which records from the %s should
         be featured on the journal webpage.''' % CFG_SITE_NAME
         featured_records = get_featured_records(journal_name)
         return wjt.tmpl_admin_feature_record(ln=ln,
                                              journal_name=journal_name,
                                              featured_records=featured_records,
                                              msg=msg)
 def perform_regenerate_issue(issue,
                              journal_name,
                              ln=CFG_SITE_LANG):
     """
     Clears the cache for the given issue.
 
     Parameters:
         journal_name  -  the journal for which the cache should be
                          deleted
                issue  -  the issue for which the cache should be deleted
                   ln  -  language
     """
     success = clear_cache_for_issue(journal_name,
                                     issue)
     if success:
         return wjt.tmpl_admin_regenerate_success(ln,
                                                  journal_name,
                                                  issue)
     else:
         return wjt.tmpl_admin_regenerate_error(ln,
                                                journal_name,
                                                issue)
 
 def perform_request_issue_control(journal_name, issues,
                                   action, ln=CFG_SITE_LANG):
     """
     Central logic for issue control.
 
     Regenerates the flat files 'current_issue' and 'issue_group' of
     the journal that control which issue is currently active for the
     journal.
 
     Parameters:
         journal_name  -  the journal affected by 'action'
               issues  -  list of issues affected by 'action' TODO: check
               action  -  One of ['cfg', _('Add'), _('Refresh'),
                          _('Publish'), _('Update')]
                   ln  -  language
     """
     _ = gettext_set_language(ln)
 
     out = ''
     if action == "cfg" or action == _("Refresh") or action == _("Add"):
         # find out if we are in update or release
         current_issue = get_current_issue(ln, journal_name)
         grouped_issues = get_grouped_issues(journal_name, current_issue)
         if current_issue != grouped_issues[-1]:
             # The current issue has "pending updates", i.e. is grouped
             # with unreleased issues. Propose to update these issues
             next_issue = grouped_issues[grouped_issues.index(current_issue) + 1]
             out = wjt.tmpl_admin_update_issue(ln,
                                               journal_name,
                                               next_issue,
                                               current_issue)
         else:
             # Propose a release
             next_issues = get_next_journal_issues(current_issue,
                                                   journal_name,
                                                   n=get_journal_issue_grouping(journal_name))
             if action == _("Refresh"):
                 next_issues += issues
                 next_issues = list(set(next_issues))# avoid double entries
             elif action == _("Add"):
                 next_issues += issues
                 next_issues = list(set(next_issues))# avoid double entries
                 next_issues.sort(compare_issues)
                 highest_issue_so_far = next_issues[-1]
                 one_more_issue = get_next_journal_issues(highest_issue_so_far,
                                                          journal_name,
                                                          1)
                 next_issues += one_more_issue
                 next_issues = list(set(next_issues)) # avoid double entries
             else:
                 # get the next issue numbers to publish
                 next_issues = get_next_journal_issues(current_issue,
                                                       journal_name,
                                                       n=get_journal_issue_grouping(journal_name))
             next_issues.sort(compare_issues)
             out = wjt.tmpl_admin_control_issue(ln,
                                                journal_name,
                                                next_issues)
     elif action == _("Publish"):
         # Publish the given issues (mark them as current issues)
         publish_issues = issues
         publish_issues = list(set(publish_issues)) # avoid double entries
         publish_issues.sort(compare_issues)
         if len(publish_issues) == 0:
             # User did not select an issue
             current_issue = get_current_issue(ln, journal_name)
             next_issues = get_next_journal_issues(current_issue,
                                                   journal_name,
                                                   n=get_journal_issue_grouping(journal_name))
             out = '<p style="color:#f00;text-align:center">' + \
                   _('Please select an issue') + '</p>'
             out += wjt.tmpl_admin_control_issue(ln,
                                                 journal_name,
                                                 next_issues)
             return out
         try:
             release_journal_issue(publish_issues, journal_name, ln)
         except InvenioWebJournalJournalIdNotFoundDBError, e:
             register_exception(req=None)
             return e.user_box()
         out = wjt.tmpl_admin_control_issue_success_msg(ln,
                                                        publish_issues,
                                                        journal_name)
 
     elif action == _("Update"):
         try:
             try:
                 update_issue = issues[0]
             except:
                 raise InvenioWebJournalReleaseUpdateError(ln, journal_name)
         except InvenioWebJournalReleaseUpdateError, e:
             register_exception(req=None)
             return e.user_box()
         try:
             release_journal_update(update_issue, journal_name, ln)
         except InvenioWebJournalJournalIdNotFoundDBError, e:
             register_exception(req=None)
             return e.user_box()
         out = wjt.tmpl_admin_updated_issue_msg(ln,
                                                update_issue,
                                                journal_name)
 
     return out
 
 def perform_request_alert(journal_name, issue,
                           sent, plain_text, subject, recipients,
                           html_mail, force, ln=CFG_SITE_LANG):
     """
     All the logic for alert emails.
 
     Display a form to edit email/recipients and options to send the
     email.  Sent in HTML/PlainText or only PlainText if wished so.
     Also prevent mistake of sending the alert more than one for a
     particular issue.
 
     Parameters:
         journal_name  -  the journal for which the alert is sent
                issue  -  the issue for which the alert is sent
                 sent  -  Display interface to edit email if "False"
                          (string). Else send the email.
           plain_text  -  the text of the mail
              subject  -  the subject of the mail
           recipients  -  the recipients of the mail (string with
                          comma-separated emails)
            html_mail  -  if 'html', also send email as HTML (copying
                          from the current issue on the web)
                force  -  if different than "False", the email is sent
                          even if it has already been sent.
                   ln  -  language
     """
     # FIXME: more flexible options to choose the language of the alert
     languages = get_journal_languages(journal_name)
     if languages:
         alert_ln = languages[0]
     else:
         alert_ln = CFG_SITE_LANG
 
     if not get_release_datetime(issue, journal_name, ln):
         # Trying to send an alert for an unreleased issue
         return wjt.tmpl_admin_alert_unreleased_issue(ln,
                                                      journal_name)
     if sent == "False":
         # Retrieve default message, subject and recipients, and
         # display email editor
         subject = wjt.tmpl_admin_alert_subject(journal_name,
                                                alert_ln,
                                                issue)
         plain_text = wjt.tmpl_admin_alert_plain_text(journal_name,
                                                      alert_ln,
                                                      issue)
         plain_text = plain_text.encode('utf-8')
         recipients = get_journal_alert_recipient_email(journal_name)
         return wjt.tmpl_admin_alert_interface(ln,
                                               journal_name,
                                               subject,
                                               plain_text,
                                               recipients,
                                               alert_ln)
     else:
         # User asked to send the mail
         if was_alert_sent_for_issue(issue,
                                     journal_name,
                                     ln) != False and force == "False":
             # Mmh, email already sent before for this issue. Ask
             # confirmation
             return wjt.tmpl_admin_alert_was_already_sent(ln,
                                                          journal_name,
                                                          subject,
                                                          plain_text,
                                                          recipients,
                                                          html_mail,
                                                          issue)
         html_string = None
         if html_mail == "html":
             # Also send as HTML: retrieve from current issue
             html_file = urlopen('%s/journal/%s?ln=%s'
                                 % (CFG_SITE_URL, journal_name, alert_ln))
             html_string = html_file.read()
             html_file.close()
             html_string = put_css_in_file(html_string, journal_name)
+            html_string = insert_journal_link(html_string, journal_name, issue, ln)
 
         sender_email = get_journal_alert_sender_email(journal_name)
         send_email(sender_email, recipients, subject, plain_text,
                    html_string, header='', footer='', html_header='',
                    html_footer='', charset='utf-8')
 
         update_DB_for_alert(issue, journal_name, ln)
         return wjt.tmpl_admin_alert_success_msg(ln,
                                                 journal_name)
 
 def perform_request_configure(journal_name, xml_config, action, ln=CFG_SITE_LANG):
     """
     Add a new journal or configure the settings of an existing journal.
 
     Parameters:
         journal_name  -  the journal to configure, or name of the new journal
           xml_config  -  the xml configuration of the journal (string)
               action  -  One of ['edit', 'editDone', 'add', 'addDone']
                   ln  -  language
     """
 
     msg = None
     if action == 'edit':
         # Read existing config
         if journal_name is not None:
             if not can_read_xml_config(journal_name):
                 return '<span style="color:#f00">Configuration could not be read. Please check that %s/webjournal/%s/%s-config.xml exists and can be read by the server.</span><br/>' % (CFG_ETCDIR, journal_name, journal_name)
             config_path = '%s/webjournal/%s/%s-config.xml' % (CFG_ETCDIR, journal_name, journal_name)
             xml_config = file(config_path).read()
         else:
             # cannot edit unknown journal...
             return '<span style="color:#f00">You must specify a journal name</span>'
     if action in ['editDone', 'addDone']:
         # Save config
         if action == 'addDone':
             res = add_journal(journal_name, xml_config)
             if res == -1:
                 msg = '<span style="color:#f00">A journal with that name already exists. Please choose another name.</span>'
                 action = 'add'
             elif res == -2:
                 msg = '<span style="color:#f00">Configuration could not be written (no permission). Please manually copy your config to %s/webjournal/%s/%s-config.xml</span><br/>' % (CFG_ETCDIR, journal_name, journal_name)
                 action = 'edit'
             elif res == -4:
                 msg = '<span style="color:#f00">Cache file could not be written (no permission). Please manually create directory %s/webjournal/%s/ and make it writable for your Apache user</span><br/>' % (CFG_CACHEDIR, journal_name)
                 action = 'edit'
             elif res > 0:
                 msg = '<span style="color:#0f0">Journal successfully added.</span>'
                 action = 'edit'
             else:
                 msg = '<span style="color:#f00">An error occurred. The journal could not be added</span>'
                 action = 'edit'
     if action == 'add':
         # Display a sample config.
         xml_config = '''<?xml version="1.0" encoding="UTF-8"?>
 <webjournal name="AtlantisTimes">
     <view>
         <niceName>Atlantis Times</niceName>
         <niceURL>%(CFG_SITE_URL)s</niceURL>
         <css>
             <screen>/img/AtlantisTimes.css</screen>
             <print>/img/AtlantisTimes.css</print>
         </css>
         <format_template>
             <index>AtlantisTimes_Index.bft</index>
             <detailed>AtlantisTimes_Detailed.bft</detailed>
             <search>AtlantisTimes_Search.bft</search>
             <popup>AtlantisTimes_Popup.bft</popup>
             <contact>AtlantisTimes_Contact.bft</contact>
         </format_template>
     </view>
 
     <model>
         <record>
             <rule>News, 980__a:ATLANTISTIMESNEWS or 980__a:ATLANTISTIMESNEWSDRAFT</rule>
             <rule>Science, 980__a:ATLANTISTIMESSCIENCE or 980__a:ATLANTISTIMESSCIENCEDRAFT</rule>
             <rule>Arts, 980__a:ATLANTISTIMESARTS or 980__a:ATLANTISTIMESARTSDRAFT</rule>
         </record>
     </model>
 
     <controller>
         <issue_grouping>2</issue_grouping>
 	<issues_per_year>52</issues_per_year>
 	<hide_unreleased_issues>all</hide_unreleased_issues>
         <marc_tags>
             <issue_number>773__n</issue_number>
 	    <order_number>773__c</order_number>
         </marc_tags>
 	<alert_sender>%(CFG_SITE_SUPPORT_EMAIL)s</alert_sender>
 	<alert_recipients>recipients@atlantis.atl</alert_recipients>
 	<languages>en,fr</languages>
 	<submission>
             <doctype>DEMOJRN</doctype>
             <report_number_field>DEMOJRN_RN</report_number_field>
 	</submission>
         <first_issue>02/2009</first_issue>
         <draft_keyword>DRAFT</draft_keyword>
     </controller>
 </webjournal>''' % {'CFG_SITE_URL': CFG_SITE_URL,
                     'CFG_SITE_SUPPORT_EMAIL': CFG_SITE_SUPPORT_EMAIL}
 
     out = wjt.tmpl_admin_configure_journal(ln=ln,
                                            journal_name=journal_name,
                                            xml_config=xml_config,
                                            action=action,
                                            msg=msg)
 
     return out
 
 ######################## ADDING/REMOVING JOURNALS ###############################
 
 def add_journal(journal_name, xml_config):
     """
     Add a new journal to the DB. Also create the configuration file
 
     Parameters:
          journal_name  -  the name (used in URLs) of the new journal
            xml_config  -  the xml configuration of the journal (string)
     Returns:
          the id of the journal if successfully added
          -1 if could not be added because journal name already exists
          -2 if config could not be saved
          -3 if could not be added for other reasons
          -4 if database cache could not be added
     """
     try:
         get_journal_id(journal_name)
     except InvenioWebJournalJournalIdNotFoundDBError:
         # Perfect, journal does not exist
         res = run_sql("INSERT INTO jrnJOURNAL (name) VALUES(%s)", (journal_name,))
         # Also save xml_config
         config_dir = '%s/webjournal/%s/' % (CFG_ETCDIR, journal_name)
         try:
             if not os.path.exists(config_dir):
                 os.makedirs(config_dir)
             xml_config_file = file(config_dir + journal_name + '-config.xml', 'w')
             xml_config_file.write(xml_config)
             xml_config_file.close()
         except Exception:
             res = -2
         # And save some info in file in case database is down
         journal_info_path = get_journal_info_path(journal_name)
         journal_info_dir = os.path.dirname(journal_info_path)
         if not os.path.exists(journal_info_dir):
             try:
                 os.makedirs(journal_info_dir)
             except Exception:
                 if res <= 0:
                     res = -4
         journal_info_file = open(journal_info_path, 'w')
 
         cPickle.dump({'journal_id': res,
                       'journal_name': journal_name,
                       'current_issue':'01/2000'}, journal_info_file)
         return res
     return -1
 
 def remove_journal(journal_name):
     """
     Remove a journal from the DB.  Does not completely remove
     everything, in case it was an error from the editor..
 
     Parameters:
          journal_name  -  the journal to remove
 
     Returns:
          the id of the journal if successfully removed or
          -1 if could not be removed because journal name does not exist or
          -2 if could not be removed for other reasons
     """
     run_sql("DELETE FROM jrnJOURNAL WHERE name=%s", (journal_name,))
 
 ######################## TIME / ISSUE FUNCTIONS ###############################
 
 
 def release_journal_issue(publish_issues, journal_name, ln=CFG_SITE_LANG):
     """
     Releases a new issue.
 
     This sets the current issue in the database to 'publish_issues' for
     given 'journal_name'
 
     Parameters:
          journal_name  -  the journal for which we release a new issue
        publish_issues  -  the list of issues that will be considered as
                           current (there can be several)
                    ln  -  language
     """
     journal_id = get_journal_id(journal_name, ln)
     if len(publish_issues) > 1:
         publish_issues.sort(compare_issues)
         low_bound = publish_issues[0]
         high_bound = publish_issues[-1]
         issue_display = '%s-%s/%s' % (low_bound.split("/")[0],
                                       high_bound.split("/")[0],
                                       high_bound.split("/")[1])
         # remember convention: if we are going over a new year, take the higher
     else:
         issue_display = publish_issues[0]
     # produce the DB lines
     for publish_issue in publish_issues:
         move_drafts_articles_to_ready(journal_name, publish_issue)
         run_sql("INSERT INTO jrnISSUE (id_jrnJOURNAL, issue_number, issue_display) \
                 VALUES(%s, %s, %s)", (journal_id,
                                       publish_issue,
                                       issue_display))
     # set first issue to published
     release_journal_update(publish_issues[0], journal_name, ln)
 
     # update information in file (in case DB is down)
     journal_info_path = get_journal_info_path(journal_name)
     journal_info_file = open(journal_info_path, 'w')
     cPickle.dump({'journal_id': journal_id,
                   'journal_name': journal_name,
                   'current_issue': get_current_issue(ln, journal_name)},
                  journal_info_file)
 
 def delete_journal_issue(issue, journal_name, ln=CFG_SITE_LANG):
     """
     Deletes an issue from the DB.
     (Not currently used)
     """
     journal_id = get_journal_id(journal_name, ln)
     run_sql("DELETE FROM jrnISSUE WHERE issue_number=%s \
             AND id_jrnJOURNAL=%s",(issue, journal_id))
 
     # update information in file (in case DB is down)
     journal_info_path = get_journal_info_path(journal_name)
     journal_info_file = open(journal_info_path, 'w')
     cPickle.dump({'journal_id': journal_id,
                   'journal_name': journal_name,
                   'current_issue': get_current_issue(ln, journal_name)},
                  journal_info_file)
 
 def was_alert_sent_for_issue(issue, journal_name, ln):
     """
     Returns False if alert has not already been sent for given journal and
     issue, else returns time of last alert, as time tuple
 
     Parameters:
          journal_name  -  the journal for which we want to check last alert
                 issue  -  the issue for which we want to check last alert
                    ln  -  language
     Returns:
          time tuple or False. Eg: (2008, 4, 25, 7, 58, 37, 4, 116, -1)
     """
     journal_id = get_journal_id(journal_name, ln)
     date_announced = run_sql("SELECT date_announced FROM jrnISSUE \
                                 WHERE issue_number=%s \
                                 AND id_jrnJOURNAL=%s", (issue, journal_id))[0][0]
     if date_announced == None:
         return False
     else:
         return date_announced.timetuple()
 
 def update_DB_for_alert(issue, journal_name, ln):
     """
     Update the 'last sent alert' timestamp for the given journal and
     issue.
 
     Parameters:
          journal_name  -  the journal for which we want to update the time
                           of last alert
                 issue  -  the issue for which we want to update the time
                           of last alert
                    ln  -  language
     """
     journal_id = get_journal_id(journal_name, ln)
     run_sql("UPDATE jrnISSUE set date_announced=NOW() \
                 WHERE issue_number=%s \
                 AND id_jrnJOURNAL=%s", (issue,
                                         journal_id))
 
 def release_journal_update(update_issue, journal_name, ln=CFG_SITE_LANG):
     """
     Releases an update to a journal.
     """
     move_drafts_articles_to_ready(journal_name, update_issue)
     journal_id = get_journal_id(journal_name, ln)
     run_sql("UPDATE jrnISSUE set date_released=NOW() \
                 WHERE issue_number=%s \
                 AND id_jrnJOURNAL=%s", (update_issue,
                                         journal_id))
 
 def move_drafts_articles_to_ready(journal_name, issue):
     """
     Move draft articles to their final "collection".
 
     To do so we rely on the convention that an admin-chosen keyword
     must be removed from the metadata
     """
     protected_datafields = ['100', '245', '246', '520', '590', '700']
     keyword_to_remove = get_journal_draft_keyword_to_remove(journal_name)
 
     categories = get_journal_categories(journal_name, issue)
     for category in categories:
         articles = get_journal_articles(journal_name, issue, category)
         for order, recids in articles.iteritems():
             for recid in recids:
                 record_xml = format_record(recid, of='xm')
                 if not record_xml:
                     continue
                 new_record_xml_path = os.path.join(CFG_TMPDIR,
                                                    'webjournal_publish_' + \
                                                    str(recid) + '.xml')
                 if os.path.exists(new_record_xml_path):
                     # Do not modify twice
                     continue
                 record_struc = create_record(record_xml)
                 record = record_struc[0]
                 new_record = update_draft_record_metadata(record,
                                                           protected_datafields,
                                                           keyword_to_remove)
                 new_record_xml = print_rec(new_record)
                 if new_record_xml.find(keyword_to_remove) >= 0:
                     new_record_xml = new_record_xml.replace(keyword_to_remove, '')
                     # Write to file
                     new_record_xml_file = file(new_record_xml_path, 'w')
                     new_record_xml_file.write(new_record_xml)
                     new_record_xml_file.close()
                     # Submit
                     task_low_level_submission('bibupload',
                                               'WebJournal',
                                               '-c', new_record_xml_path)
 
 def update_draft_record_metadata(record, protected_datafields, keyword_to_remove):
     """
     Returns a new record with fields that should be modified in order
     for this draft record to be considered as 'ready': keep only
     controlfield 001 and non-protected fields that contains the
     'keyword_to_remove'
 
     Parameters:
                   record - a single recored (as BibRecord structure)
 
     protected_datafields - *list* tags that should not be part of the
                            returned record
 
        keyword_to_remove - *str* keyword that should be considered
                            when checking if a field should be part of
                            the returned record.
     """
     new_record = {}
     for tag, field in record.iteritems():
         if tag in protected_datafields:
             continue
         elif not keyword_to_remove in str(field) and \
                  not tag == '001':
             continue
         else:
             # Keep
             new_record[tag] = field
 
     return new_record
 
 ######################## XML CONFIG ###############################
 
 def can_read_xml_config(journal_name):
     """
     Check that configuration xml for given journal name is exists and
     can be read.
     """
     config_path = '%s/webjournal/%s/%s-config.xml' % \
                   (CFG_ETCDIR, journal_name, journal_name)
     try:
         file(config_path).read()
     except IOError:
         return False
 
     return True
 
 ######################## EMAIL HELPER FUNCTIONS ###############################
 
+def insert_journal_link(html_string, journal_name, issue, ln):
+    """
+    Insert a warning regarding HTML formatting inside mail client and
+    link to journal page just after the body of the page.
+
+    @param html_string: the HTML newsletter
+    @param journal_name: the journal name
+    @param issue: journal issue for which the alert is sent (in the form number/year)
+    @param ln: language
+    """
+    def replace_body(match_obj):
+        "Replace body with itself + header message"
+        header = wjt.tmpl_admin_alert_header_html(journal_name, ln, issue)
+        return match_obj.group() + header
+    return re.sub('<body.*?>', replace_body, html_string, 1)
+
 def put_css_in_file(html_message, journal_name):
     """
     Retrieve the CSS of the journal and insert/inline it in the <head>
     section of the given html_message. (Used for HTML alert emails)
 
     Parameters:
           journal_name  -  the journal name
           html_message  -  the html message (string) in which the CSS
                            should be inserted
     Returns:
           the HTML message with its CSS inlined
     """
     css_path = get_journal_css_url(journal_name)
     if not css_path:
         return
     css_file = urlopen(css_path)
     css = css_file.read()
     css = make_full_paths_in_css(css, journal_name)
     html_parted = html_message.split("</head>")
     if len(html_parted) > 1:
         html = '%s<style type="text/css">%s</style></head>%s' % (html_parted[0],
                                                         css,
                                                         html_parted[1])
     else:
         html_parted = html_message.split("<html>")
         if len(html_parted) > 1:
             html = '%s<html><head><style type="text/css">%s</style></head>%s' % (html_parted[0],
                                                                                  css,
                                                                                  html_parted[1])
         else:
             return
     return html
 
 def make_full_paths_in_css(css, journal_name):
     """
     Update the URLs in a CSS from relative to absolute URLs, so that the
     URLs are accessible from anywhere (Used for HTML alert emails)
 
     Parameters:
           journal_name  -  the journal name
                    css  -  a cascading stylesheet (string)
     Returns:
           (str) the given css with relative paths converted to absolute paths
     """
     url_pattern = re.compile('''url\(["']?\s*(?P<url>\S*)\s*["']?\)''',
                              re.DOTALL)
     url_iter = url_pattern.finditer(css)
     rel_to_full_path = {}
     for url in url_iter:
         url_string = url.group("url")
         url_string = url_string.replace('"', "")
         url_string = url_string.replace("'", "")
         if url_string[:6] != "http://":
             rel_to_full_path[url_string] = '"%s/img/webjournal_%s/%s"' % \
             (CFG_SITE_URL,
             journal_name,
             url_string)
     for url in rel_to_full_path.keys():
         css = css.replace(url, rel_to_full_path[url])
     return css