diff --git a/INSTALL b/INSTALL index f1ad87d6ea..d016a1df8d 100644 --- a/INSTALL +++ b/INSTALL @@ -83,6 +83,9 @@ Contents natively in UTF-8 mode by setting "default-character-set=utf8" in various parts of your "my.cnf" file, such as in the "[mysql]" part and elsewhere; but this is not really required. + Note also that you may encounter problems when MySQL is run in + "strict mode"; you may want to configure your "my.cnf" in order + to avoid using strict mode (such as `STRICT_ALL_TABLES`). c) Redis server (may be on a remote machine) for user session @@ -313,6 +316,7 @@ Contents $ make install $ make install-mathjax-plugin ## optional $ make install-jquery-plugins ## optional + $ make install-font-awesome ## optional $ make install-ckeditor-plugin ## optional $ make install-pdfa-helper-files ## optional $ make install-mediaelement ## optional @@ -522,6 +526,16 @@ Contents Note that `unzip' is needed when installing jquery plugins. + $ make install-font-awesome ## optional + + This will automatically download and install Font Awesome, + the iconic font and CSS framework. + + Note that in order to include Font Awesome in the HTML head + you have to set the CFG_WEBSTYLE_SUPPORT_FONTAWESOME to True + + Note that `unzip' is needed when installing Font Awesome. + $ make install-ckeditor-plugin ## optional This will automatically download and install in the proper diff --git a/Makefile.am b/Makefile.am index 6f44617c95..d8f4fb1e95 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,6 @@ # This file is part of Invenio. -# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 CERN. +# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012, 2013, 2014, 2015, 2016 CERN. # # Invenio is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -265,6 +266,38 @@ uninstall-jquery-plugins: @echo "** The jquery plugins were successfully uninstalled. **" @echo "***********************************************************" +install-font-awesome: + @echo "***********************************************************" + @echo "** Installing Font Awesome, please wait... **" + @echo "***********************************************************" + rm -rf /tmp/font-awesome + mkdir /tmp/font-awesome + mkdir -p ${prefix}/var/www/static/css + mkdir -p ${prefix}/var/www/static/fonts + (cd /tmp/font-awesome && \ + wget 'https://fortawesome.github.io/Font-Awesome/assets/font-awesome-4.5.0.zip' && \ + unzip -u font-awesome-4.5.0.zip && \ + mv font-awesome-4.5.0/css/font-awesome.min.css ${prefix}/var/www/static/css && \ + mv font-awesome-4.5.0/fonts/* ${prefix}/var/www/static/fonts) + rm -rf /tmp/font-awesome + @echo "***********************************************************" + @echo "** Font Awesome was successfully installed. **" + @echo "** It is disabled by default. To enable it, edit **" + @echo "** CFG_WEBSTYLE_SUPPORT_FONTAWESOME in invenio.conf. **" + @echo "***********************************************************" + +uninstall-font-awesome: + @rm -vf ${prefix}/var/www/static/css/font-awesome.min.css + @rm -vf ${prefix}/var/www/static/fonts/FontAwesome.otf + @rm -vf ${prefix}/var/www/static/fonts/fontawesome-webfont.eot + @rm -vf ${prefix}/var/www/static/fonts/fontawesome-webfont.svg + @rm -vf ${prefix}/var/www/static/fonts/fontawesome-webfont.ttf + @rm -vf ${prefix}/var/www/static/fonts/fontawesome-webfont.woff + @rm -vf ${prefix}/var/www/static/fonts/fontawesome-webfont.woff2 + @echo "***********************************************************" + @echo "** Font Awesome was successfully uninstalled. **" + @echo "***********************************************************" + install-ckeditor-plugin: @echo "***********************************************************" @echo "** Installing CKeditor plugin, please wait... **" diff --git a/THANKS b/THANKS index 1335b512ac..98ebc9d4ca 100644 --- a/THANKS +++ b/THANKS @@ -179,4 +179,8 @@ contributed by Yoav Goldberg , new version by Jason Kirtland from Python cookbook. +Some icons are used from the iconic font and CSS toolkit +Font Awesome by Dave Gandy. + + - end of file - diff --git a/config/invenio.conf b/config/invenio.conf index 408411ba6a..eccb9322f1 100644 --- a/config/invenio.conf +++ b/config/invenio.conf @@ -373,6 +373,10 @@ CFG_WEBSTYLE_CDSPAGEBOXRIGHTTOP = # HTML right bottom box: CFG_WEBSTYLE_CDSPAGEBOXRIGHTBOTTOM = +# CFG_WEBSTYLE_SUPPORT_FONTAWESOME -- enables Font Awesome, the iconic +# font and CSS framework. +CFG_WEBSTYLE_SUPPORT_FONTAWESOME = False + # CFG_WEBSTYLE_HTTP_STATUS_ALERT_LIST -- when certain HTTP status # codes are raised to the WSGI handler, the corresponding exceptions # and error messages can be sent to the system administrator for diff --git a/modules/bibdocfile/lib/bibdocfile.py b/modules/bibdocfile/lib/bibdocfile.py index 12598b36ac..0cada52da5 100644 --- a/modules/bibdocfile/lib/bibdocfile.py +++ b/modules/bibdocfile/lib/bibdocfile.py @@ -59,6 +59,7 @@ import cgi import sys import copy +import tarfile if sys.hexversion < 0x2060000: from md5 import md5 @@ -102,6 +103,7 @@ encode_for_xml from invenio.urlutils import create_url, make_user_agent_string from invenio.textutils import nice_size +from invenio.webuser import collect_user_info from invenio.access_control_engine import acc_authorize_action from invenio.access_control_admin import acc_is_user_in_role, acc_get_role_id from invenio.access_control_firerole import compile_role_definition, acc_firerole_check_user @@ -123,7 +125,7 @@ CFG_BIBCATALOG_SYSTEM from invenio.bibcatalog import BIBCATALOG_SYSTEM from invenio.bibdocfile_config import CFG_BIBDOCFILE_ICON_SUBFORMAT_RE, \ - CFG_BIBDOCFILE_DEFAULT_ICON_SUBFORMAT + CFG_BIBDOCFILE_DEFAULT_ICON_SUBFORMAT, CFG_BIBDOCFILE_STREAM_ARCHIVE_FORMATS from invenio.pluginutils import PluginContainer import invenio.template @@ -797,17 +799,22 @@ def get_xml_8564(self): return out - def get_total_size_latest_version(self): + def get_total_size_latest_version(self, user_info=None, subformat=None): """ Returns the total size used on disk by all the files belonging to this record and corresponding to the latest version. + @param user_info: the user_info dictionary, used to check restrictions + @type: dict + @param subformat: if subformat is specified, it limits files + only to those from that specific subformat + @type subformat: string @return: the total size. @rtype: integer """ size = 0 for (bibdoc, _) in self.bibdocs.values(): - size += bibdoc.get_total_size_latest_version() + size += bibdoc.get_total_size_latest_version(user_info, subformat) return size def get_total_size(self): @@ -1564,6 +1571,36 @@ def get_text(self, extract_text_if_necessary=True): return " ".join(texts) + def stream_archive_of_latest_files(self, req, files_size=''): + """ + Streams the tar archive with all files of a certain file size (that + are not restricted or hidden) to the user. + File size should be a string that can be compared with the output of + BibDocFile.get_subformat() function. + + @param req: Apache Request Object + @type req: Apache Request Object + @param files_size: size of the files (they can be defined in + bibdocfile_config). Empty string means the original size. + @type files_size: string + """ + # Get the internal size from the user-friendly file size name + internal_format = [f[1] for f in CFG_BIBDOCFILE_STREAM_ARCHIVE_FORMATS if f[0] == files_size] + if len(internal_format) < 1: + # Incorrect file size + return + internal_format = internal_format[0] + tarname = str(self.id) + "_" + files_size + '.tar' + + # Select files that user can download (not hidden nor restricted) + user_info = collect_user_info(req) + req.content_type = "application/x-tar" + req.headers_out["Content-Disposition"] = 'attachment; filename="%s"' % tarname + tar = tarfile.open(fileobj=req, mode='w|') + for f in self.list_latest_files(): + if f.get_subformat() == internal_format and f.is_restricted(user_info)[0] == 0 and not f.hidden: + tar.add(f.get_path(), arcname=f.get_full_name(), recursive=False) + tar.close() class BibDoc(object): """ @@ -2801,12 +2838,28 @@ def _build_related_file_list(self): cur_doc = BibDoc.create_instance(docid=docid, human_readable=self.human_readable) self.related_files[doctype].append(cur_doc) - def get_total_size_latest_version(self): + def get_total_size_latest_version(self, user_info=None, subformat=None): """Return the total size used on disk of all the files belonging - to this bibdoc and corresponding to the latest version.""" + to this bibdoc and corresponding to the latest version. Restricted + and hidden files are not counted, unless there is no user_info. + @param user_info: the user_info dictionary, used to check restrictions + @type: dict + @param subformat: if subformat is specified, it limits files + only to those from that specific subformat + @type subformat: string + """ ret = 0 + all_files = False + # If we are calling this function without user_info, then we want to + # see all the files + if not user_info: + all_files = True for bibdocfile in self.list_latest_files(): - ret += bibdocfile.get_size() + # First check for restrictions + if all_files or (bibdocfile.is_restricted(user_info)[0] == 0 and not bibdocfile.hidden): + # Then check if the format is correct + if subformat is None or bibdocfile.get_subformat() == subformat: + ret += bibdocfile.get_size() return ret def get_total_size(self): diff --git a/modules/bibdocfile/lib/bibdocfile_config.py b/modules/bibdocfile/lib/bibdocfile_config.py index 0caa8ddbd2..c07eb606ff 100644 --- a/modules/bibdocfile/lib/bibdocfile_config.py +++ b/modules/bibdocfile/lib/bibdocfile_config.py @@ -69,3 +69,12 @@ # CFG_BIBDOCFILE_DEFAULT_ICON_SUBFORMAT -- this is the default subformat used # when creating new icons. CFG_BIBDOCFILE_DEFAULT_ICON_SUBFORMAT = "icon" + +# CFG_BIBDOCFILE_STREAM_ARCHIVE_FORMATS -- a list (not dictionary, because +# we want to preserve the order) that connects the different format sizes +# (like 'small', 'medium', etc.) with internal format sizes (like 'icon-180', 'icon-640', etc.) +CFG_BIBDOCFILE_STREAM_ARCHIVE_FORMATS = [ + ('small', 'icon-180'), + ('medium', 'icon-640'), + ('large', 'icon-1440'), + ('original', '')] diff --git a/modules/bibdocfile/lib/bibdocfile_webinterface.py b/modules/bibdocfile/lib/bibdocfile_webinterface.py index 1547dd3ddf..198b72fb17 100644 --- a/modules/bibdocfile/lib/bibdocfile_webinterface.py +++ b/modules/bibdocfile/lib/bibdocfile_webinterface.py @@ -83,6 +83,12 @@ def _lookup(self, component, path): def getfile(req, form): args = wash_urlargd(form, bibdocfile_templates.files_default_urlargd) ln = args['ln'] + if filename[:9] == "allfiles-": + files_size = filename[9:] + # stream a tar package to the user + brd = BibRecDocs(self.recid) + brd.stream_archive_of_latest_files(req, files_size) + return _ = gettext_set_language(ln) diff --git a/modules/bibformat/lib/bibreformat.py b/modules/bibformat/lib/bibreformat.py index 1571146adb..9c712dcbd3 100644 --- a/modules/bibformat/lib/bibreformat.py +++ b/modules/bibformat/lib/bibreformat.py @@ -353,7 +353,11 @@ def task_run_core(): if task_has_option("last"): recids += outdated_caches(fmt, last_updated) - if task_has_option('ignore_without'): + if task_has_option('ignore_without') or \ + task_has_option('collection') or \ + task_has_option('field') or \ + task_has_option('pattern') or \ + task_has_option('recids'): without_fmt = intbitset() else: without_fmt = missing_caches(fmt) diff --git a/modules/webaccess/doc/hacking/webaccess-api.webdoc b/modules/webaccess/doc/hacking/webaccess-api.webdoc index f657c7ad42..dbec7eed81 100644 --- a/modules/webaccess/doc/hacking/webaccess-api.webdoc +++ b/modules/webaccess/doc/hacking/webaccess-api.webdoc @@ -23,7 +23,7 @@
 Invenio Access Control Engine can be called from within your Python programs
 via both a regular Python API and CLI.
-In addition the you get an explanation of the program flow.
+In addition to the above features, you also get an explanation of the program flow.
 
 Contents:
  1. Regular API
diff --git a/modules/websearch/lib/search_engine.py b/modules/websearch/lib/search_engine.py
index ab15175be8..eb78a0cc09 100644
--- a/modules/websearch/lib/search_engine.py
+++ b/modules/websearch/lib/search_engine.py
@@ -97,7 +97,8 @@
      InvenioWebSearchReferstoLimitError, \
      InvenioWebSearchCitedbyLimitError, \
      CFG_WEBSEARCH_IDXPAIRS_FIELDS,\
-     CFG_WEBSEARCH_IDXPAIRS_EXACT_SEARCH
+     CFG_WEBSEARCH_IDXPAIRS_EXACT_SEARCH, \
+     CFG_WEBSEARCH_BLACKLISTED_FORMATS
 from invenio.search_engine_utils import (get_fieldvalues,
                                          get_fieldvalues_alephseq_like,
                                          record_exists)
@@ -1711,7 +1712,7 @@ def get_synonym_terms(term, kbr_name, match_type, use_memoise=False):
     return dterms.keys()
 
 
-def wash_output_format(ouput_format):
+def wash_output_format(ouput_format, verbose=False, req=None):
     """Wash output format FORMAT.  Currently only prevents input like
     'of=9' for backwards-compatible format that prints certain fields
     only.  (for this task, 'of=tm' is preferred)"""
@@ -1719,6 +1720,12 @@ def wash_output_format(ouput_format):
         # asked to print MARC tags, but not enough digits,
         # so let's switch back to HTML brief default
         return 'hb'
+    elif format in CFG_WEBSEARCH_BLACKLISTED_FORMATS:
+        if verbose:
+            write_warning("Selected format is not available through perform_request_search", req=req)
+            # Returning an empty list seems dangerous because you wouldn't know
+            # right away that the list is not supposed to be empty.
+        return 'hb'
     else:
         return ouput_format
 
@@ -5714,7 +5721,7 @@ def prs_wash_arguments(req=None, cc=CFG_SITE_NAME, c=None, p="", f="", rg=CFG_WE
     """
 
     # wash output format:
-    of = wash_output_format(of)
+    of = wash_output_format(of, verbose=verbose, req=req)
 
     # wash all arguments requiring special care
     p = wash_pattern(p)
diff --git a/modules/websearch/lib/search_engine_config.py b/modules/websearch/lib/search_engine_config.py
index 17d8daf1da..2bc848a427 100644
--- a/modules/websearch/lib/search_engine_config.py
+++ b/modules/websearch/lib/search_engine_config.py
@@ -50,6 +50,11 @@
 # interfaces (0=simple, 1=advanced, 2=add-to-search):
 CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES = [0,1,2]
 
+# CFG_WEBSEARCH_BLACKLISTED_FORMATS -- list of formats that will be refused
+# by perform_request_search:
+# * recstruct is an internal format thus should not be exposed
+CFG_WEBSEARCH_BLACKLISTED_FORMATS = ["recstruct", "wapaff", "wapdat"]
+
 
 class InvenioWebSearchUnknownCollectionError(Exception):
     """Exception for bad collection."""
diff --git a/modules/websearch/lib/websearch_external_collections_getter_unit_tests.py b/modules/websearch/lib/websearch_external_collections_getter_unit_tests.py
index 8d55a05730..5ac036d9b7 100644
--- a/modules/websearch/lib/websearch_external_collections_getter_unit_tests.py
+++ b/modules/websearch/lib/websearch_external_collections_getter_unit_tests.py
@@ -51,7 +51,7 @@ def test_async_download(self):
         ##   - test 1 bad IP: 1.2.3.4
         ## Return the list of errors.
         checks = [
-            {'url': 'http://invenio-software.org', 'content': 'About Invenio'},
+            {'url': 'http://invenio-software.org', 'content': 'Invenio'},
             {'url': 'http://rjfreijoiregjreoijgoirg.fr'},
             {'url': 'http://1.2.3.4/'}]
 
diff --git a/modules/webstyle/lib/webstyle_templates.py b/modules/webstyle/lib/webstyle_templates.py
index 316620ebaa..329214176b 100644
--- a/modules/webstyle/lib/webstyle_templates.py
+++ b/modules/webstyle/lib/webstyle_templates.py
@@ -1,5 +1,6 @@
 # This file is part of Invenio.
-# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 CERN.
+# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
+# 2014, 2016 CERN.
 #
 # Invenio is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License as
@@ -38,6 +39,7 @@
      CFG_SITE_URL, \
      CFG_VERSION, \
      CFG_WEBSTYLE_INSPECT_TEMPLATES, \
+     CFG_WEBSTYLE_SUPPORT_FONTAWESOME, \
      CFG_WEBSTYLE_TEMPLATE_SKIN, \
      CFG_INSPIRE_SITE, \
      CFG_WEBLINKBACK_TRACKBACK_ENABLED
@@ -374,6 +376,7 @@ def tmpl_pageheader(self, req, ln=CFG_SITE_LANG, headertitle="",
  %(metabase)s
  
  
+ %(font_awesome)s
  
@@ -460,6 +463,10 @@ def tmpl_pageheader(self, req, ln=CFG_SITE_LANG, headertitle="",
           'canonical_and_alternate_urls' : self.tmpl_canonical_and_alternate_urls(uri),
           'cssurl' : CFG_BASE_URL,
           'cssskin' : CFG_WEBSTYLE_TEMPLATE_SKIN != 'default' and '_' + CFG_WEBSTYLE_TEMPLATE_SKIN or '',
+          'font_awesome': (
+            '') if (
+              CFG_WEBSTYLE_SUPPORT_FONTAWESOME) else '',
           'rssurl': rssurl,
           'ln' : ln,
           'ln_iso_639_a' : ln.split('_', 1)[0],
diff --git a/modules/websubmit/lib/functions/Stamp_Uploaded_Files.py b/modules/websubmit/lib/functions/Stamp_Uploaded_Files.py
index e8b5b42147..40c9cee7e6 100644
--- a/modules/websubmit/lib/functions/Stamp_Uploaded_Files.py
+++ b/modules/websubmit/lib/functions/Stamp_Uploaded_Files.py
@@ -302,8 +302,8 @@ def visit_for_stamping(visit_for_stamping_arguments, dirname, filenames):
         'file_stamper_options' members.
        @param dirname: (string) - the path to the directory in which the
         files are to be stamped.
-       @param filenames: (list) - the names of each file in dirname. An
-        attempt will be made to stamp each of these files.
+       @param filenames: (list) - the names of each file and subdirectory in
+        dirname. An attempt will be made to stamp each of the files.
        @Exceptions Raised:
          + InvenioWebSubmitFunctionWarning;
          + InvenioWebSubmitFunctionError;
@@ -345,6 +345,10 @@ def visit_for_stamping(visit_for_stamping_arguments, dirname, filenames):
         path_to_subject_file = "%s/%s" % (dirname, file_to_stamp)
         file_stamper_options['input-file'] = path_to_subject_file
 
+        if not os.path.isfile(path_to_subject_file):
+            # If it's not a file, we can't stamp it. Continue with next file
+            continue
+
         ## Just before attempting to stamp the file, log the dictionary of
         ## options (file_stamper_options) that will be passed to websubmit-
         ## file-stamper: