diff --git a/config/invenio.conf b/config/invenio.conf
index 1d4b9c85b..66e7eeee4 100644
--- a/config/invenio.conf
+++ b/config/invenio.conf
@@ -1,963 +1,974 @@
## 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.
###################################################
## About 'invenio.conf' and 'invenio-local.conf' ##
###################################################
## The 'invenio.conf' file contains the vanilla default configuration
## parameters of a CDS Invenio installation, as coming from the
## distribution. The file should be self-explanatory. Once installed
## in its usual location (usually /opt/cds-invenio/etc), you could in
## principle go ahead and change the values according to your local
## needs.
##
## However, you can also create a file named 'invenio-local.conf' in
## the same directory where 'invenio.conf' lives and put there only
## the localizations you need to have different from the default ones.
## For example:
##
## $ cat /opt/cds-invenio/etc/invenio-local.conf
## [Invenio]
## CFG_SITE_URL = http://your.site.com
## CFG_SITE_SECURE_URL = https://your.site.com
## CFG_SITE_ADMIN_EMAIL = john.doe@your.site.com
## CFG_SITE_SUPPORT_EMAIL = john.doe@your.site.com
##
## The Invenio system will then read both the default invenio.conf
## file and your customized invenio-local.conf file and it will
## override any default options with the ones you have set in your
## local file. This cascading of configuration parameters will ease
## you future upgrades.
[Invenio]
###################################
## Part 1: Essential parameters ##
###################################
## This part defines essential CDS Invenio internal parameters that
## everybody should override, like the name of the server or the email
## address of the local CDS Invenio administrator.
## CFG_DATABASE_* - specify which MySQL server to use, the name of the
## database to use, and the database access credentials.
CFG_DATABASE_HOST = localhost
CFG_DATABASE_PORT = 3306
CFG_DATABASE_NAME = cdsinvenio
CFG_DATABASE_USER = cdsinvenio
CFG_DATABASE_PASS = my123p$ss
## CFG_SITE_URL - specify URL under which your installation will be
## visible. For example, use "http://your.site.com". Do not leave
## trailing slash.
CFG_SITE_URL = http://localhost
## CFG_SITE_SECURE_URL - specify secure URL under which your
## installation secure pages such as login or registration will be
## visible. For example, use "https://your.site.com". Do not leave
## trailing slash. If you don't plan on using HTTPS, then you may
## leave this empty.
CFG_SITE_SECURE_URL = https://localhost
## CFG_SITE_NAME -- the visible name of your CDS Invenio installation.
CFG_SITE_NAME = Atlantis Institute of Fictive Science
## CFG_SITE_NAME_INTL -- the international versions of CFG_SITE_NAME
## in various languages. (See also CFG_SITE_LANGS below.)
CFG_SITE_NAME_INTL_en = Atlantis Institute of Fictive Science
CFG_SITE_NAME_INTL_fr = Atlantis Institut des Sciences Fictives
CFG_SITE_NAME_INTL_de = Atlantis Institut der fiktiven Wissenschaft
CFG_SITE_NAME_INTL_es = Atlantis Instituto de la Ciencia Fictive
CFG_SITE_NAME_INTL_ca = Institut Atlantis de Ciència Fictícia
CFG_SITE_NAME_INTL_pt = Instituto Atlantis de Ciência Fictícia
CFG_SITE_NAME_INTL_it = Atlantis Istituto di Scienza Fittizia
CFG_SITE_NAME_INTL_ru = Атлантис Институт фиктивных Наук
CFG_SITE_NAME_INTL_sk = Atlantis Inštitút Fiktívnych Vied
CFG_SITE_NAME_INTL_cs = Atlantis Institut Fiktivních Věd
CFG_SITE_NAME_INTL_no = Atlantis Institutt for Fiktiv Vitenskap
CFG_SITE_NAME_INTL_sv = Atlantis Institut för Fiktiv Vetenskap
CFG_SITE_NAME_INTL_el = Ινστιτούτο Φανταστικών Επιστημών Ατλαντίδος
CFG_SITE_NAME_INTL_uk = Інститут вигаданих наук в Атлантісі
CFG_SITE_NAME_INTL_ja = Fictive 科学のAtlantis の協会
CFG_SITE_NAME_INTL_pl = Instytut Fikcyjnej Nauki Atlantis
CFG_SITE_NAME_INTL_bg = Институт за фиктивни науки Атлантис
CFG_SITE_NAME_INTL_hr = Institut Fiktivnih Znanosti Atlantis
CFG_SITE_NAME_INTL_zh_CN = 阿特兰提斯虚拟科学学院
CFG_SITE_NAME_INTL_zh_TW = 阿特蘭提斯虛擬科學學院
CFG_SITE_NAME_INTL_hu = Kitalált Tudományok Atlantiszi Intézete
CFG_SITE_NAME_INTL_af = Atlantis Instituut van Fiktiewe Wetenskap
CFG_SITE_NAME_INTL_gl = Instituto Atlantis de Ciencia Fictive
## CFG_SITE_LANG -- the default language of the interface:
CFG_SITE_LANG = en
## CFG_SITE_LANGS -- list of all languages the user interface should
## be available in, separated by commas. The order specified below
## will be respected on the interface pages. A good default would be
## to use the alphabetical order. Currently supported languages
## include Afrikaans, Bulgarian, Catalan, Czech, German, Greek,
## English, Spanish, French, Croatian, Hungarian, Galician, Italian,
## Japanese, Norwegian, Polish, Portuguese, Russian, Slovak, Swedish,
## Ukrainian, Chinese (China), Chinese (Taiwan), so that the current
## eventual maximum you can currently select is
## "af,bg,ca,cs,de,el,en,es,fr,hr,gl,it,hu,ja,no,pl,pt,ru,sk,sv,uk,zh_CN,zh_TW".
CFG_SITE_LANGS = af,bg,ca,cs,de,el,en,es,fr,hr,gl,it,hu,ja,no,pl,pt,ru,sk,sv,uk,zh_CN,zh_TW
## CFG_SITE_SUPPORT_EMAIL -- the email address of the support team for
## this installation:
CFG_SITE_SUPPORT_EMAIL = cds.support@cern.ch
## CFG_SITE_ADMIN_EMAIL -- the email address of the 'superuser' for
## this installation. Enter your email address below and login with
## this address when using CDS Invenio administration modules. You
## will then be automatically recognized as superuser of the system.
CFG_SITE_ADMIN_EMAIL = cds.support@cern.ch
## CFG_SITE_EMERGENCY_PHONE_NUMBERS -- list of mobile phone numbers to
## which an sms should be sent in case of emergency (e.g. bibsched queue
## has been stopped because of an error).
## Note that in order to use this function, if CFG_CERN_SITE is set to 0,
## the function send_sms in errorlib should be reimplemented.
CFG_SITE_EMERGENCY_PHONE_NUMBERS =
## CFG_CERN_SITE -- do we want to enable CERN-specific code?
## Put "1" for "yes" and "0" for "no".
CFG_CERN_SITE = 0
## CFG_INSPIRE_SITE -- do we want to enable INSPIRE-specific code?
## Put "1" for "yes" and "0" for "no".
CFG_INSPIRE_SITE = 0
## CFG_ADS_SITE -- do we want to enable ADS-specific code?
## Put "1" for "yes" and "0" for "no".
CFG_ADS_SITE = 0
## CFG_DEVEL_SITE -- is this a development site? If it is, you might
## prefer that it doesn't do certain things. For example, you might
## not want WebSubmit to send certain emails or trigger certain
## processes on a development site.
## Put "1" for "yes" (this is a development site) or "0" for "no"
## (this isn't a development site.)
CFG_DEVEL_SITE = 0
################################
## Part 2: Web page style ##
################################
## The variables affecting the page style. The most important one is
## the 'template skin' you would like to use and the obfuscation mode
## for your email addresses. Please refer to the WebStyle Admin Guide
## for more explanation. The other variables are listed here mostly
## for backwards compatibility purposes only.
## CFG_WEBSTYLE_TEMPLATE_SKIN -- what template skin do you want to
## use?
CFG_WEBSTYLE_TEMPLATE_SKIN = default
## CFG_WEBSTYLE_EMAIL_ADDRESSES_OBFUSCATION_MODE. How do we "protect"
## email addresses from undesired automated email harvesters? This
## setting will not affect 'support' and 'admin' emails.
## NOTE: there is no ultimate solution to protect against email
## harvesting. All have drawbacks and can more or less be
## circumvented. Choose you preferred mode ([t] means "transparent"
## for the user):
## -1: hide all emails.
## [t] 0 : no protection, email returned as is.
## foo@example.com => foo@example.com
## 1 : basic email munging: replaces @ by [at] and . by [dot]
## foo@example.com => foo [at] example [dot] com
## [t] 2 : transparent name mangling: characters are replaced by
## equivalent HTML entities.
## foo@example.com => foo@example.com
## [t] 3 : javascript insertion. Requires Javascript enabled on client
## side.
## 4 : replaces @ and . characters by gif equivalents.
## foo@example.com => fooexamplecom
CFG_WEBSTYLE_EMAIL_ADDRESSES_OBFUSCATION_MODE = 2
## CFG_WEBSTYLE_INSPECT_TEMPLATES -- Do we want to debug all template
## functions so that they would return HTML results wrapped in
## comments indicating which part of HTML page was created by which
## template function? Useful only for debugging Pythonic HTML
## template. See WebStyle Admin Guide for more information.
CFG_WEBSTYLE_INSPECT_TEMPLATES = 0
## (deprecated) CFG_WEBSTYLE_CDSPAGEBOXLEFTTOP -- eventual global HTML
## left top box:
CFG_WEBSTYLE_CDSPAGEBOXLEFTTOP =
## (deprecated) CFG_WEBSTYLE_CDSPAGEBOXLEFTBOTTOM -- eventual global
## HTML left bottom box:
CFG_WEBSTYLE_CDSPAGEBOXLEFTBOTTOM =
## (deprecated) CFG_WEBSTYLE_CDSPAGEBOXRIGHTTOP -- eventual global
## HTML right top box:
CFG_WEBSTYLE_CDSPAGEBOXRIGHTTOP =
## (deprecated) CFG_WEBSTYLE_CDSPAGEBOXRIGHTBOTTOM -- eventual global
## HTML right bottom box:
CFG_WEBSTYLE_CDSPAGEBOXRIGHTBOTTOM =
+## 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
+## inspecting. This is useful to detect and correct errors. The
+## variable represents a comma-separated list of HTTP statuses that
+## should alert admin. Wildcards are possible. If the status is
+## followed by an "r", it means that a referer is required to exist
+## (useful to distinguish broken known links from URL typos when 404
+## errors are raised).
+CFG_WEBSTYLE_HTTP_STATUS_ALERT_LIST = 404r,400,5*,41*
+
##################################
## Part 3: WebSearch parameters ##
##################################
## This section contains some configuration parameters for WebSearch
## module. Please note that WebSearch is mostly configured on
## run-time via its WebSearch Admin web interface. The parameters
## below are the ones that you do not probably want to modify very
## often during the runtime. (Note that you may modify them
## afterwards too, though.)
## CFG_WEBSEARCH_SEARCH_CACHE_SIZE -- how many queries we want to
## cache in memory per one Apache httpd process? This cache is used
## mainly for "next/previous page" functionality, but it caches also
## "popular" user queries if more than one user happen to search for
## the same thing. Note that large numbers may lead to great memory
## consumption. We recommend a value not greater than 100.
CFG_WEBSEARCH_SEARCH_CACHE_SIZE = 100
## CFG_WEBSEARCH_FIELDS_CONVERT -- if you migrate from an older
## system, you may want to map field codes of your old system (such as
## 'ti') to CDS Invenio/MySQL ("title"). Use Python dictionary syntax
## for the translation table, e.g. {'wau':'author', 'wti':'title'}.
## Usually you don't want to do that, and you would use empty dict {}.
CFG_WEBSEARCH_FIELDS_CONVERT = {}
## CFG_WEBSEARCH_LIGHTSEARCH_PATTERN_BOX_WIDTH -- width of the
## search pattern window in the light search interface, in
## characters. CFG_WEBSEARCH_LIGHTSEARCH_PATTERN_BOX_WIDTH = 60
CFG_WEBSEARCH_LIGHTSEARCH_PATTERN_BOX_WIDTH = 60
## CFG_WEBSEARCH_SIMPLESEARCH_PATTERN_BOX_WIDTH -- width of the search
## pattern window in the simple search interface, in characters.
CFG_WEBSEARCH_SIMPLESEARCH_PATTERN_BOX_WIDTH = 40
## CFG_WEBSEARCH_ADVANCEDSEARCH_PATTERN_BOX_WIDTH -- width of the
## search pattern window in the advanced search interface, in
## characters.
CFG_WEBSEARCH_ADVANCEDSEARCH_PATTERN_BOX_WIDTH = 30
## CFG_WEBSEARCH_NB_RECORDS_TO_SORT -- how many records do we still
## want to sort? For higher numbers we print only a warning and won't
## perform any sorting other than default 'latest records first', as
## sorting would be very time consuming then. We recommend a value of
## not more than a couple of thousands.
CFG_WEBSEARCH_NB_RECORDS_TO_SORT = 1000
## CFG_WEBSEARCH_CALL_BIBFORMAT -- if a record is being displayed but
## it was not preformatted in the "HTML brief" format, do we want to
## call BibFormatting on the fly? Put "1" for "yes" and "0" for "no".
## Note that "1" will display the record exactly as if it were fully
## preformatted, but it may be slow due to on-the-fly processing; "0"
## will display a default format very fast, but it may not have all
## the fields as in the fully preformatted HTML brief format. Note
## also that this option is active only for old (PHP) formats; the new
## (Python) formats are called on the fly by default anyway, since
## they are much faster. When usure, please set "0" here.
CFG_WEBSEARCH_CALL_BIBFORMAT = 0
## CFG_WEBSEARCH_USE_ALEPH_SYSNOS -- do we want to make old SYSNOs
## visible rather than MySQL's record IDs? You may use this if you
## migrate from a different e-doc system, and you store your old
## system numbers into 970__a. Put "1" for "yes" and "0" for
## "no". Usually you don't want to do that, though.
CFG_WEBSEARCH_USE_ALEPH_SYSNOS = 0
## CFG_WEBSEARCH_I18N_LATEST_ADDITIONS -- Put "1" if you want the
## "Latest Additions" in the web collection pages to show
## internationalized records. Useful only if your brief BibFormat
## templates contains internationalized strings. Otherwise put "0" in
## order not to slow down the creation of latest additions by WebColl.
CFG_WEBSEARCH_I18N_LATEST_ADDITIONS = 0
## CFG_WEBSEARCH_INSTANT_BROWSE -- the number of records to display
## under 'Latest Additions' in the web collection pages.
CFG_WEBSEARCH_INSTANT_BROWSE = 10
## CFG_WEBSEARCH_INSTANT_BROWSE_RSS -- the number of records to
## display in the RSS feed.
CFG_WEBSEARCH_INSTANT_BROWSE_RSS = 25
## CFG_WEBSEARCH_RSS_TTL -- number of minutes that indicates how long
## a feed cache is valid.
CFG_WEBSEARCH_RSS_TTL = 360
## CFG_WEBSEARCH_RSS_MAX_CACHED_REQUESTS -- maximum number of request kept
## in cache. If the cache is filled, following request are not cached.
CFG_WEBSEARCH_RSS_MAX_CACHED_REQUESTS = 1000
## CFG_WEBSEARCH_AUTHOR_ET_AL_THRESHOLD -- up to how many author names
## to print explicitely; for more print "et al". Note that this is
## used in default formatting that is seldomly used, as usually
## BibFormat defines all the format. The value below is only used
## when BibFormat fails, for example.
CFG_WEBSEARCH_AUTHOR_ET_AL_THRESHOLD = 3
## CFG_WEBSEARCH_NARROW_SEARCH_SHOW_GRANDSONS -- whether to show or
## not collection grandsons in Narrow Search boxes (sons are shown by
## default, grandsons are configurable here). Use 0 for no and 1 for
## yes.
CFG_WEBSEARCH_NARROW_SEARCH_SHOW_GRANDSONS = 1
## CFG_WEBSEARCH_CREATE_SIMILARLY_NAMED_AUTHORS_LINK_BOX -- shall we
## create help links for Ellis, Nick or Ellis, Nicholas and friends
## when Ellis, N was searched for? Useful if you have one author
## stored in the database under several name formats, namely surname
## comma firstname and surname comma initial cataloging policy. Use 0
## for no and 1 for yes.
CFG_WEBSEARCH_CREATE_SIMILARLY_NAMED_AUTHORS_LINK_BOX = 1
## CFG_WEBSEARCH_USE_JSMATH_FOR_FORMATS -- jsMath is a JavaScript
## library that renders (La)TeX mathematical formulas in the client
## browser. This parameter must contain a comma-separated list of
## output formats for which to apply the jsMath rendering, for example
## "hb,hd". If the list is empty, jsMath is disabled.
CFG_WEBSEARCH_USE_JSMATH_FOR_FORMATS =
## CFG_WEBSEARCH_EXTERNAL_COLLECTION_SEARCH_TIMEOUT -- when searching
## external collections (e.g. SPIRES, CiteSeer, etc), how many seconds
## do we wait for reply before abandonning?
CFG_WEBSEARCH_EXTERNAL_COLLECTION_SEARCH_TIMEOUT = 5
## CFG_WEBSEARCH_EXTERNAL_COLLECTION_SEARCH_MAXRESULTS -- how many
## results do we fetch?
CFG_WEBSEARCH_EXTERNAL_COLLECTION_SEARCH_MAXRESULTS = 10
## CFG_WEBSEARCH_SPLIT_BY_COLLECTION -- do we want to split the search
## results by collection or not? Use 0 for not, 1 for yes.
CFG_WEBSEARCH_SPLIT_BY_COLLECTION = 1
## CFG_WEBSEARCH_MAX_RECORDS_IN_GROUPS -- in order to limit denial of
## service attacks the total number of records per group displayed as a
## result of a search query will be limited to this number. Only the superuser
## queries will not be affected by this limit.
CFG_WEBSEARCH_MAX_RECORDS_IN_GROUPS = 200
## CFG_WEBSEARCH_PERMITTED_RESTRICTED_COLLECTIONS_LEVEL -- logged in users
## might have rights to access some restricted collections. This variable
## tweaks the kind of support the system will automatically provide to the
## user with respect to searching into these restricted collections.
## Set this to 0 in order to have the user to explicitly activate restricted
## collections in order to search into them. Set this to 1 in order to
## propose to the user the list of restricted collections to which he/she has
## rights (note: this is not yet implemented). Set this to 2 in order to
## silently add all the restricted collections to which the user has rights to
## to any query.
## Note: the system will discover which restricted collections a user has
## rights to, at login time. The time complexity of this procedure is
## proportional to the number of restricted collections. E.g. for a system
## with ~50 restricted collections, you might expect ~1s of delay in the
## login time, when this variable is set to a value higher than 0.
CFG_WEBSEARCH_PERMITTED_RESTRICTED_COLLECTIONS_LEVEL = 0
## CFG_WEBSEARCH_SHOW_COMMENT_COUNT -- do we want to show the 'N comments'
## links on the search engine pages? (useful only when you have allowed
## commenting)
CFG_WEBSEARCH_SHOW_COMMENT_COUNT = 1
## CFG_WEBSEARCH_SHOW_REVIEW_COUNT -- do we want to show the 'N reviews'
## links on the search engine pages? (useful only when you have allowed
## reviewing)
CFG_WEBSEARCH_SHOW_REVIEW_COUNT = 1
#######################################
## Part 4: BibHarvest OAI parameters ##
#######################################
## This part defines parameters for the CDS Invenio OAI gateway.
## Useful if you are running CDS Invenio as OAI data provider.
## CFG_OAI_ID_FIELD -- OAI identifier MARC field:
CFG_OAI_ID_FIELD = 909COo
## CFG_OAI_SET_FIELD -- OAI set MARC field:
CFG_OAI_SET_FIELD = 909COp
## CFG_OAI_DELETED_POLICY -- OAI deletedrecordspolicy
## (no/transient/persistent).
CFG_OAI_DELETED_POLICY = no
## CFG_OAI_ID_PREFIX -- OAI identifier prefix:
CFG_OAI_ID_PREFIX = atlantis.cern.ch
## CFG_OAI_SAMPLE_IDENTIFIER -- OAI sample identifier:
CFG_OAI_SAMPLE_IDENTIFIER = oai:atlantis.cern.ch:CERN-TH-4036
## CFG_OAI_IDENTIFY_DESCRIPTION -- description for the OAI Identify verb:
CFG_OAI_IDENTIFY_DESCRIPTION = oaiatlantis.cern.ch:oai:atlantis.cern.ch:CERN-TH-4036http://atlantis.cern.ch/Free and unlimited use by anybody with obligation to refer to original recordFull content, i.e. preprints may not be harvested by robotsSubmission restricted. Submitted documents are subject of approval by OAI repository admins.
## CFG_OAI_LOAD -- OAI number of records in a response:
CFG_OAI_LOAD = 1000
## CFG_OAI_EXPIRE -- OAI resumptionToken expiration time:
CFG_OAI_EXPIRE = 90000
## CFG_OAI_SLEEP -- service unavailable between two consecutive
## requests for CFG_OAI_SLEEP seconds:
CFG_OAI_SLEEP = 10
##################################
## Part 5: WebSubmit parameters ##
##################################
## This section contains some configuration parameters for WebSubmit
## module. Please note that WebSubmit is mostly configured on
## run-time via its WebSubmit Admin web interface. The parameters
## below are the ones that you do not probably want to modify during
## the runtime.
## CFG_WEBSUBMIT_FILESYSTEM_BIBDOC_GROUP_LIMIT -- the fulltext
## documents are stored under "/opt/cds-invenio/var/data/files/gX/Y"
## directories where X is 0,1,... and Y stands for bibdoc ID. Thusly
## documents Y are grouped into directories X and this variable
## indicates the maximum number of documents Y stored in each
## directory X. This limit is imposed solely for filesystem
## performance reasons in order not to have too many subdirectories in
## a given directory.
CFG_WEBSUBMIT_FILESYSTEM_BIBDOC_GROUP_LIMIT = 5000
## CFG_WEBSUBMIT_ADDITIONAL_KNOWN_FILE_EXTENSIONS -- a comma-separated
## list of document extensions not listed in Python standard mimetype
## library that should be recognized by Invenio.
CFG_WEBSUBMIT_ADDITIONAL_KNOWN_FILE_EXTENSIONS = hpg,link,lis,llb,mat,mpp,msg,docx,docm,xlsx,xlsm,xlsb,pptx,pptm,ppsx,ppsm
#################################
## Part 6: BibIndex parameters ##
#################################
## This section contains some configuration parameters for BibIndex
## module. Please note that BibIndex is mostly configured on run-time
## via its BibIndex Admin web interface. The parameters below are the
## ones that you do not probably want to modify very often during the
## runtime.
## CFG_BIBINDEX_FULLTEXT_INDEX_LOCAL_FILES_ONLY -- when fulltext indexing, do
## you want to index locally stored files only, or also external URLs?
## Use "0" to say "no" and "1" to say "yes".
CFG_BIBINDEX_FULLTEXT_INDEX_LOCAL_FILES_ONLY = 0
## CFG_BIBINDEX_REMOVE_STOPWORDS -- when indexing, do we want to remove
## stopwords? Use "0" to say "no" and "1" to say "yes".
CFG_BIBINDEX_REMOVE_STOPWORDS = 0
## CFG_BIBINDEX_CHARS_ALPHANUMERIC_SEPARATORS -- characters considered as
## alphanumeric separators of word-blocks inside words. You probably
## don't want to change this.
CFG_BIBINDEX_CHARS_ALPHANUMERIC_SEPARATORS = \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
## CFG_BIBINDEX_CHARS_PUNCTUATION -- characters considered as punctuation
## between word-blocks inside words. You probably don't want to
## change this.
CFG_BIBINDEX_CHARS_PUNCTUATION = \.\,\:\;\?\!\"
## CFG_BIBINDEX_REMOVE_HTML_MARKUP -- should we attempt to remove HTML markup
## before indexing? Use 1 if you have HTML markup inside metadata
## (e.g. in abstracts), use 0 otherwise.
CFG_BIBINDEX_REMOVE_HTML_MARKUP = 0
## CFG_BIBINDEX_REMOVE_LATEX_MARKUP -- should we attempt to remove LATEX markup
## before indexing? Use 1 if you have LATEX markup inside metadata
## (e.g. in abstracts), use 0 otherwise.
CFG_BIBINDEX_REMOVE_LATEX_MARKUP = 0
## CFG_BIBINDEX_MIN_WORD_LENGTH -- minimum word length allowed to be added to
## index. The terms smaller then this amount will be discarded.
## Useful to keep the database clean, however you can safely leave
## this value on 0 for up to 1,000,000 documents.
CFG_BIBINDEX_MIN_WORD_LENGTH = 0
## CFG_BIBINDEX_URLOPENER_USERNAME and CFG_BIBINDEX_URLOPENER_PASSWORD --
## access credentials to access restricted URLs, interesting only if
## you are fulltext-indexing files located on a remote server that is
## only available via username/password. But it's probably better to
## handle this case via IP or some convention; the current scheme is
## mostly there for demo only.
CFG_BIBINDEX_URLOPENER_USERNAME = mysuperuser
CFG_BIBINDEX_URLOPENER_PASSWORD = mysuperpass
## CFG_INTBITSET_ENABLE_SANITY_CHECKS --
## Enable sanity checks for integers passed to the intbitset data
## structures. It is good to enable this during debugging
## and to disable this value for speed improvements.
CFG_INTBITSET_ENABLE_SANITY_CHECKS = False
#######################################
## Part 7: Access control parameters ##
#######################################
## This section contains some configuration parameters for the access
## control system. Please note that WebAccess is mostly configured on
## run-time via its WebAccess Admin web interface. The parameters
## below are the ones that you do not probably want to modify very
## often during the runtime. (If you do want to modify them during
## runtime, for example te deny access temporarily because of backups,
## you can edit access_control_config.py directly, no need to get back
## here and no need to redo the make process.)
## CFG_ACCESS_CONTROL_LEVEL_SITE -- defines how open this site is.
## Use 0 for normal operation of the site, 1 for read-only site (all
## write operations temporarily closed), 2 for site fully closed,
## 3 for also disabling any database connection.
## Useful for site maintenance.
CFG_ACCESS_CONTROL_LEVEL_SITE = 0
## CFG_ACCESS_CONTROL_LEVEL_GUESTS -- guest users access policy. Use
## 0 to allow guest users, 1 not to allow them (all users must login).
CFG_ACCESS_CONTROL_LEVEL_GUESTS = 0
## CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS -- account registration and
## activation policy. When 0, users can register and accounts are
## automatically activated. When 1, users can register but admin must
## activate the accounts. When 2, users cannot register nor update
## their email address, only admin can register accounts. When 3,
## users cannot register nor update email address nor password, only
## admin can register accounts. When 4, the same as 3 applies, nor
## user cannot change his login method.
CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS = 0
## CFG_ACCESS_CONTROL_LIMIT_REGISTRATION_TO_DOMAIN -- limit account
## registration to certain email addresses? If wanted, give domain
## name below, e.g. "cern.ch". If not wanted, leave it empty.
CFG_ACCESS_CONTROL_LIMIT_REGISTRATION_TO_DOMAIN =
## CFG_ACCESS_CONTROL_NOTIFY_ADMIN_ABOUT_NEW_ACCOUNTS -- send a
## notification email to the administrator when a new account is
## created? Use 0 for no, 1 for yes.
CFG_ACCESS_CONTROL_NOTIFY_ADMIN_ABOUT_NEW_ACCOUNTS = 0
## CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT -- send a
## notification email to the user when a new account is created in order to
## to verify the validity of the provided email address? Use
## 0 for no, 1 for yes.
CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT = 1
## CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_ACTIVATION -- send a
## notification email to the user when a new account is activated?
## Use 0 for no, 1 for yes.
CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_ACTIVATION = 0
## CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_DELETION -- send a
## notification email to the user when a new account is deleted or
## account demand rejected? Use 0 for no, 1 for yes.
CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_DELETION = 0
## CFG_APACHE_PASSWORD_FILE -- the file where Apache user credentials
## are stored. Must be an absolute pathname. If the value does not
## start by a slash, it is considered to be the filename of a file
## located under prefix/var/tmp directory. This is useful for the
## demo site testing purposes. For the production site, if you plan
## to restrict access to some collections based on the Apache user
## authentication mechanism, you should put here an absolute path to
## your Apache password file.
CFG_APACHE_PASSWORD_FILE = demo-site-apache-user-passwords
## CFG_APACHE_GROUP_FILE -- the file where Apache user groups are
## defined. See the documentation of the preceding config variable.
CFG_APACHE_GROUP_FILE = demo-site-apache-user-groups
###################################
## Part 8: WebSession parameters ##
###################################
## This section contains some configuration parameters for tweaking
## session handling.
## CFG_WEBSESSION_EXPIRY_LIMIT_DEFAULT -- number of days after which a session
## and the corresponding cookie is considered expired.
CFG_WEBSESSION_EXPIRY_LIMIT_DEFAULT = 2
## CFG_WEBSESSION_EXPIRY_LIMIT_REMEMBER -- number of days after which a session
## and the corresponding cookie is considered expired, when the user has
## requested to permanently stay logged in.
CFG_WEBSESSION_EXPIRY_LIMIT_REMEMBER = 365
## CFG_WEBSESSION_RESET_PASSWORD_EXPIRE_IN_DAYS -- when user requested
## a password reset, for how many days is the URL valid?
CFG_WEBSESSION_RESET_PASSWORD_EXPIRE_IN_DAYS = 3
## CFG_WEBSESSION_ADDRESS_ACTIVATION_EXPIRE_IN_DAYS -- when an account
## activation email was sent, for how many days is the URL valid?
CFG_WEBSESSION_ADDRESS_ACTIVATION_EXPIRE_IN_DAYS = 3
## CFG_WEBSESSION_NOT_CONFIRMED_EMAIL_ADDRESS_EXPIRE_IN_DAYS -- when
## user won't confirm his email address and not complete
## registeration, after how many days will it expire?
CFG_WEBSESSION_NOT_CONFIRMED_EMAIL_ADDRESS_EXPIRE_IN_DAYS = 10
## CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS -- when set to 1, the session
## system allocates the same uid=0 to all guests users regardless of where they
## come from. 0 allocate a unique uid to each guest.
CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS = 0
################################
## Part 9: BibRank parameters ##
################################
## This section contains some configuration parameters for the ranking
## system.
## CFG_BIBRANK_SHOW_READING_STATS -- do we want to show reading
## similarity stats? ('People who viewed this page also viewed')
CFG_BIBRANK_SHOW_READING_STATS = 1
## CFG_BIBRANK_SHOW_DOWNLOAD_STATS -- do we want to show the download
## similarity stats? ('People who downloaded this document also
## downloaded')
CFG_BIBRANK_SHOW_DOWNLOAD_STATS = 1
## CFG_BIBRANK_SHOW_DOWNLOAD_GRAPHS -- do we want to show download
## history graph?
CFG_BIBRANK_SHOW_DOWNLOAD_GRAPHS = 1
## CFG_BIBRANK_SHOW_DOWNLOAD_GRAPHS_CLIENT_IP_DISTRIBUTION -- do we
## want to show a graph representing the distribution of client IPs
## downloading given document?
CFG_BIBRANK_SHOW_DOWNLOAD_GRAPHS_CLIENT_IP_DISTRIBUTION = 0
## CFG_BIBRANK_SHOW_CITATION_LINKS -- do we want to show the 'Cited
## by' links? (useful only when you have citations in the metadata)
CFG_BIBRANK_SHOW_CITATION_LINKS = 1
## CFG_BIBRANK_SHOW_CITATION_STATS -- de we want to show citation
## stats? ('Cited by M recors', 'Co-cited with N records')
CFG_BIBRANK_SHOW_CITATION_STATS = 1
## CFG_BIBRANK_SHOW_CITATION_GRAPHS -- do we want to show citation
## history graph?
CFG_BIBRANK_SHOW_CITATION_GRAPHS = 1
####################################
## Part 10: WebComment parameters ##
####################################
## This section contains some configuration parameters for the
## commenting and reviewing facilities.
## CFG_WEBCOMMENT_ALLOW_COMMENTS -- do we want to allow users write
## public comments on records?
CFG_WEBCOMMENT_ALLOW_COMMENTS = 1
## CFG_WEBCOMMENT_ALLOW_REVIEWS -- do we want to allow users write
## public reviews of records?
CFG_WEBCOMMENT_ALLOW_REVIEWS = 1
## CFG_WEBCOMMENT_ALLOW_SHORT_REVIEWS -- do we want to allow short
## reviews, that is just the attribution of stars without submitting
## detailed review text?
CFG_WEBCOMMENT_ALLOW_SHORT_REVIEWS = 0
## CFG_WEBCOMMENT_NB_REPORTS_BEFORE_SEND_EMAIL_TO_ADMIN -- if users
## report a comment to be abusive, how many they have to be before the
## site admin is alerted?
CFG_WEBCOMMENT_NB_REPORTS_BEFORE_SEND_EMAIL_TO_ADMIN = 5
## CFG_WEBCOMMENT_NB_COMMENTS_IN_DETAILED_VIEW -- how many comments do
## we display in the detailed record page upon welcome?
CFG_WEBCOMMENT_NB_COMMENTS_IN_DETAILED_VIEW = 1
## CFG_WEBCOMMENT_NB_REVIEWS_IN_DETAILED_VIEW -- how many reviews do
## we display in the detailed record page upon welcome?
CFG_WEBCOMMENT_NB_REVIEWS_IN_DETAILED_VIEW = 1
## CFG_WEBCOMMENT_ADMIN_NOTIFICATION_LEVEL -- do we notify the site
## admin after every comment?
CFG_WEBCOMMENT_ADMIN_NOTIFICATION_LEVEL = 1
## CFG_WEBCOMMENT_TIMELIMIT_PROCESSING_COMMENTS_IN_SECONDS -- how many
## elapsed seconds do we consider enough when checking for possible
## multiple comment submissions by a user?
CFG_WEBCOMMENT_TIMELIMIT_PROCESSING_COMMENTS_IN_SECONDS = 20
## CFG_WEBCOMMENT_TIMELIMIT_PROCESSING_REVIEWS_IN_SECONDS -- how many
## elapsed seconds do we consider enough when checking for possible
## multiple review submissions by a user?
CFG_WEBCOMMENT_TIMELIMIT_PROCESSING_REVIEWS_IN_SECONDS = 20
## CFG_WEBCOMMENT_USE_RICH_EDITOR -- enable the WYSIWYG
## Javascript-based editor when user edits comments?
CFG_WEBCOMMENT_USE_RICH_TEXT_EDITOR = False
##################################
## Part 11: BibSched parameters ##
##################################
## This section contains some configuration parameters for the
## bibliographic task scheduler.
## CFG_BIBSCHED_REFRESHTIME -- how often do we want to refresh
## bibsched monitor? (in seconds)
CFG_BIBSCHED_REFRESHTIME = 5
## CFG_BIBSCHED_LOG_PAGER -- what pager to use to view bibsched task
## logs?
CFG_BIBSCHED_LOG_PAGER = /bin/more
## CFG_BIBSCHED_GC_TASKS_OLDER_THAN -- after how many days to perform the
## gargbage collector of BibSched queue (i.e. removing/moving task to archive).
CFG_BIBSCHED_GC_TASKS_OLDER_THAN = 30
## CFG_BIBSCHED_GC_TASKS_TO_REMOVE -- list of BibTask that can be safely
## removed from the BibSched queue once they are DONE.
CFG_BIBSCHED_GC_TASKS_TO_REMOVE = bibindex,bibreformat,webcoll,bibrank,inveniogc
## CFG_BIBSCHED_GC_TASKS_TO_ARCHIVE -- list of BibTasks that should be safely
## archived out of the BibSched queue once they are DONE.
CFG_BIBSCHED_GC_TASKS_TO_ARCHIVE = bibupload,oaiarchive
## CFG_BIBSCHED_MAX_NUMBER_CONCURRENT_TASKS -- maximum number of BibTasks
## that can run concurrently.
## NOTE: concurrent tasks are still considered as an experimental
## feature. Please keep this value set to 1 on production environments.
CFG_BIBSCHED_MAX_NUMBER_CONCURRENT_TASKS = 1
## CFG_BIBSCHED_PROCESS_USER -- bibsched and bibtask processes must
## usually run under the same identity as the Apache web server
## process in order to share proper file read/write privileges. If
## you want to force some other bibsched/bibtask user, e.g. because
## you are using a local `invenio' user that belongs to your
## `www-data' Apache user group and so shares writing rights with your
## Apache web server process in this way, then please set its username
## identity here. Otherwise we shall check whether your
## bibsched/bibtask processes are run under the same identity as your
## Apache web server process (in which case you can leave the default
## empty value here).
CFG_BIBSCHED_PROCESS_USER =
###################################
## Part 12: WebBasket parameters ##
###################################
## CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS -- a safety limit for
## a maximum number of displayed baskets
CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS = 20
## CFG_WEBBASKET_USE_RICH_TEXT_EDITOR -- enable the WYSIWYG
## Javascript-based editor when user edits comments in WebBasket?
CFG_WEBBASKET_USE_RICH_TEXT_EDITOR = False
##################################
## Part 13: WebAlert parameters ##
##################################
## This section contains some configuration parameters for the
## automatic email notification alert system.
## CFG_WEBALERT_ALERT_ENGINE_EMAIL -- the email address from which the
## alert emails will appear to be sent:
CFG_WEBALERT_ALERT_ENGINE_EMAIL = cds.alert@cdsdev.cern.ch
## CFG_WEBALERT_MAX_NUM_OF_RECORDS_IN_ALERT_EMAIL -- how many records
## at most do we send in an outgoing alert email?
CFG_WEBALERT_MAX_NUM_OF_RECORDS_IN_ALERT_EMAIL = 20
## CFG_WEBALERT_MAX_NUM_OF_CHARS_PER_LINE_IN_ALERT_EMAIL -- number of
## chars per line in an outgoing alert email?
CFG_WEBALERT_MAX_NUM_OF_CHARS_PER_LINE_IN_ALERT_EMAIL = 72
## CFG_WEBALERT_SEND_EMAIL_NUMBER_OF_TRIES -- when sending alert
## emails fails, how many times we retry?
CFG_WEBALERT_SEND_EMAIL_NUMBER_OF_TRIES = 3
## CFG_WEBALERT_SEND_EMAIL_SLEEPTIME_BETWEEN_TRIES -- when sending
## alert emails fails, what is the sleeptime between tries? (in
## seconds)
CFG_WEBALERT_SEND_EMAIL_SLEEPTIME_BETWEEN_TRIES = 300
####################################
## Part 14: WebMessage parameters ##
####################################
## CFG_WEBMESSAGE_MAX_SIZE_OF_MESSAGE -- how large web messages do we
## allow?
CFG_WEBMESSAGE_MAX_SIZE_OF_MESSAGE = 20000
## CFG_WEBMESSAGE_MAX_NB_OF_MESSAGES -- how many messages for a
## regular user do we allow in its inbox?
CFG_WEBMESSAGE_MAX_NB_OF_MESSAGES = 30
## CFG_WEBMESSAGE_DAYS_BEFORE_DELETE_ORPHANS -- how many days before
## we delete orphaned messages?
CFG_WEBMESSAGE_DAYS_BEFORE_DELETE_ORPHANS = 60
##################################
## Part 15: MiscUtil parameters ##
##################################
## CFG_MISCUTIL_SQL_MAX_CACHED_QUERIES -- maximum number of cached SQL
## queries possible. After reaching this number the cache is pruned
## by deleting half of the older queries.
CFG_MISCUTIL_SQL_MAX_CACHED_QUERIES = 10000
## CFG_MISCUTIL_SQL_USE_SQLALCHEMY -- whether to use SQLAlchemy.pool
## in the DB engine of CDS Invenio. It is okay to enable this flag
## even if you have not installed SQLAlchemy. Note that Invenio will
## loose some perfomance if this option is enabled.
CFG_MISCUTIL_SQL_USE_SQLALCHEMY = False
## CFG_MISCUTIL_SQL_RUN_SQL_MANY_LIMIT -- how many queries can we run
## inside run_sql_many() in one SQL statement? The limit value
## depends on MySQL's max_allowed_packet configuration.
CFG_MISCUTIL_SQL_RUN_SQL_MANY_LIMIT = 10000
## CFG_MISCUTIL_SMTP_HOST -- which server to use as outgoing mail server to
## send outgoing emails generated by the system, for example concerning
## submissions or email notification alerts.
CFG_MISCUTIL_SMTP_HOST = localhost
## CFG_MISCUTIL_SMTP_PORT -- which port to use on the outgoing mail server
## defined in the previous step.
CFG_MISCUTIL_SMTP_PORT = 25
#################################
## Part 16: BibEdit parameters ##
#################################
## CFG_BIBEDIT_TIMEOUT -- when a user edits a record, this record is
## locked to prevent other users to edit it at the same time.
## How many seconds of inactivity before the locked record again will be free
## for other people to edit?
CFG_BIBEDIT_TIMEOUT = 3600
## CFG_BIBEDIT_LOCKLEVEL -- when a user tries to edit a record which there
## is a pending bibupload task for in the queue, this shouldn't be permitted.
## The lock level determines how thouroughly the queue should be investigated
## to determine if this is the case.
## Level 0 - always permits editing, doesn't look at the queue
## (unsafe, use only if you know what you are doing)
## Level 1 - permits editing if there are no queued bibedit tasks for this record
## (safe with respect to bibedit, but not for other bibupload maintenance jobs)
## Level 2 - permits editing if there are no queued bibupload tasks of any sort
## (safe, but may lock more than necessary if many cataloguers around)
## Level 3 - permits editing if no queued bibupload task concerns given record
## (safe, most precise locking, but slow,
## checks for 001/EXTERNAL_SYSNO_TAG/EXTERNAL_OAIID_TAG)
## The recommended level is 3 (default) or 2 (if you use maintenance jobs often).
CFG_BIBEDIT_LOCKLEVEL = 3
## CFG_BIBEDIT_PROTECTED_FIELDS -- a comma-separated list of fields that BibEdit
## will not allow to be added, edited or deleted. Wildcards are not supported,
## but conceptually a wildcard is added at the end of every field specification.
## Examples:
## 500A - protect all MARC fields with tag 500 and first indicator A
## 5 - protect all MARC fields in the 500-series.
## 909C_a - protect subfield a in tag 909 with first indicator C and empty
## second indicator
## Note that 001 is protected by default, but if protection of other
## identifiers or automated fields is a requirement, they should be added to
## this list.
CFG_BIBEDIT_PROTECTED_FIELDS =
###################################
## Part 17: BibUpload parameters ##
###################################
## CFG_BIBUPLOAD_REFERENCE_TAG -- where do we store references?
CFG_BIBUPLOAD_REFERENCE_TAG = 999
## CFG_BIBUPLOAD_EXTERNAL_SYSNO_TAG -- where do we store external
## system numbers? Useful for matching when our records come from an
## external digital library system.
CFG_BIBUPLOAD_EXTERNAL_SYSNO_TAG = 970__a
## CFG_BIBUPLOAD_EXTERNAL_OAIID_TAG -- where do we store OAI ID tags
## of harvested records? Useful for matching when we harvest stuff
## via OAI that we do not want to reexport via Invenio OAI; so records
## may have only the source OAI ID stored in this tag (kind of like
## external system number too).
CFG_BIBUPLOAD_EXTERNAL_OAIID_TAG = 035__a
## CFG_BIBUPLOAD_EXTERNAL_OAIID_PROVENANCE_TAG -- where do we store OAI SRC
## tags of harvested records? Useful for matching when we harvest stuff
## via OAI that we do not want to reexport via Invenio OAI; so records
## may have only the source OAI SRC stored in this tag (kind of like
## external system number too). Note that the field should be the same of
## CFG_BIBUPLOAD_EXTERNAL_OAIID_TAG.
CFG_BIBUPLOAD_EXTERNAL_OAIID_PROVENANCE_TAG = 035__9
## CFG_BIBUPLOAD_STRONG_TAGS -- a comma-separated list of tags that
## are strong enough to resist the replace mode. Useful for tags that
## might be created from an external non-metadata-like source,
## e.g. the information about the number of copies left.
CFG_BIBUPLOAD_STRONG_TAGS = 964
## CFG_BIBUPLOAD_CONTROLLED_PROVENANCE_TAGS -- a comma-separated list
## of tags that contain provenance information that should be checked
## in the bibupload correct mode via matching provenance codes. (Only
## field instances of the same provenance information would be acted
## upon.) Please specify the whole tag info up to subfield codes.
CFG_BIBUPLOAD_CONTROLLED_PROVENANCE_TAGS = 6531_9
## CFG_BIBUPLOAD_FFT_ALLOWED_LOCAL_PATHS -- a comma-separated list of system
## paths from which it is allowed to take fulltextes that will be uploaded via
## FFT (CFG_TMPDIR is included by default).
CFG_BIBUPLOAD_FFT_ALLOWED_LOCAL_PATHS = /tmp,/home
## CFG_BIBUPLOAD_SERIALIZE_RECORD_STRUCTURE -- do we want to serialize
## internal representation of records (Pythonic record structure) into
## the database? This can improve internal processing speed of some
## operations at the price of somewhat bigger disk space usage.
## If you change this value after some records have already been added
## to your installation, you may want to run:
## $ /opt/cds-invenio/bin/inveniocfg --reset-recstruct-cache
## in order to either erase the cache thus freeing database space,
## or to fill the cache for all records that have not been cached yet.
CFG_BIBUPLOAD_SERIALIZE_RECORD_STRUCTURE = 1
####################################
## Part 18: BibCatalog parameters ##
####################################
## EXPERIMENTAL: Please do not use.
CFG_BIBCATALOG_SYSTEM =
CFG_BIBCATALOG_SYSTEM_RT_CLI = /usr/bin/rt
CFG_BIBCATALOG_SYSTEM_RT_URL = http://localhost/rt3
CFG_BIBCATALOG_QUEUES = General
##########################
## THAT's ALL, FOLKS! ##
##########################
diff --git a/modules/miscutil/lib/inveniocfg.py b/modules/miscutil/lib/inveniocfg.py
index e124e2742..4b50d561c 100644
--- a/modules/miscutil/lib/inveniocfg.py
+++ b/modules/miscutil/lib/inveniocfg.py
@@ -1,1092 +1,1093 @@
# -*- 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.
"""
Invenio configuration and administration CLI tool.
Usage: inveniocfg [options]
General options:
-h, --help print this help
-V, --version print version number
Options to finish your installation:
--create-apache-conf create Apache configuration files
--create-tables create DB tables for Invenio
--load-webstat-conf load the WebStat configuration
--drop-tables drop DB tables of Invenio
Options to set up and test a demo site:
--create-demo-site create demo site
--load-demo-records load demo records
--remove-demo-records remove demo records, keeping demo site
--drop-demo-site drop demo site configurations too
--run-unit-tests run unit test suite (needs deme site)
--run-regression-tests run regression test suite (needs demo site)
--run-web-tests run web tests in a browser (needs demo site, Firefox, Selenium IDE)
Options to update config files in situ:
--update-all perform all the update options
--update-config-py update config.py file from invenio.conf file
--update-dbquery-py update dbquery.py with DB credentials from invenio.conf
--update-dbexec update dbexec with DB credentials from invenio.conf
--update-bibconvert-tpl update bibconvert templates with CFG_SITE_URL from invenio.conf
--update-web-tests update web test cases with CFG_SITE_URL from invenio.conf
Options to update DB tables:
--reset-all perform all the reset options
--reset-sitename reset tables to take account of new CFG_SITE_NAME*
--reset-siteadminemail reset tables to take account of new CFG_SITE_ADMIN_EMAIL
--reset-fieldnames reset tables to take account of new I18N names from PO files
--reset-recstruct-cache reset record structure cache according to CFG_BIBUPLOAD_SERIALIZE_RECORD_STRUCTURE
Options to help the work:
--list print names and values of all options from conf files
--get get value of a given option from conf files
--conf-dir path to directory where invenio*.conf files are [optional]
--detect-system-details print system details such as Apache/Python/MySQL versions
"""
__revision__ = "$Id$"
from ConfigParser import ConfigParser
import os
import re
import shutil
import socket
import sys
import zlib
import marshal
def print_usage():
"""Print help."""
print __doc__
def print_version():
"""Print version information."""
print __revision__
def convert_conf_option(option_name, option_value):
"""
Convert conf option into Python config.py line, converting
values to ints or strings as appropriate.
"""
## 1) convert option name to uppercase:
option_name = option_name.upper()
## 2) convert option value to int or string:
if option_name in ['CFG_BIBUPLOAD_REFERENCE_TAG',
'CFG_BIBUPLOAD_EXTERNAL_SYSNO_TAG',
'CFG_BIBUPLOAD_EXTERNAL_OAIID_TAG',
'CFG_BIBUPLOAD_EXTERNAL_OAIID_PROVENANCE_TAG',
'CFG_BIBUPLOAD_STRONG_TAGS',
'CFG_SITE_EMERGENCY_PHONE_NUMBERS']:
# some options are supposed be string even when they look like
# numeric
option_value = '"' + option_value + '"'
else:
try:
option_value = int(option_value)
except ValueError:
option_value = '"' + option_value + '"'
## 3a) special cases: regexps
if option_name in ['CFG_BIBINDEX_CHARS_ALPHANUMERIC_SEPARATORS',
'CFG_BIBINDEX_CHARS_PUNCTUATION']:
option_value = 'r"[' + option_value[1:-1] + ']"'
## 3b) special cases: True, False, None
if option_value in ['"True"', '"False"', '"None"']:
option_value = option_value[1:-1]
## 3c) special cases: dicts
if option_name in ['CFG_WEBSEARCH_FIELDS_CONVERT', ]:
option_value = option_value[1:-1]
## 3d) special cases: comma-separated lists
if option_name in ['CFG_SITE_LANGS',
'CFG_WEBSUBMIT_ADDITIONAL_KNOWN_FILE_EXTENSIONS',
'CFG_WEBSEARCH_USE_JSMATH_FOR_FORMATS',
'CFG_BIBUPLOAD_STRONG_TAGS',
'CFG_BIBSCHED_GC_TASKS_TO_REMOVE',
'CFG_BIBSCHED_GC_TASKS_TO_ARCHIVE',
'CFG_BIBUPLOAD_FFT_ALLOWED_LOCAL_PATHS',
'CFG_BIBUPLOAD_CONTROLLED_PROVENANCE_TAGS',
'CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES',
- 'CFG_SITE_EMERGENCY_PHONE_NUMBERS']:
+ 'CFG_SITE_EMERGENCY_PHONE_NUMBERS',
+ 'CFG_WEBSTYLE_HTTP_STATUS_ALERT_LIST']:
out = "["
for elem in option_value[1:-1].split(","):
if elem:
if option_name in ['CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES']:
# 3d1) integer values
out += "%i, " % int(elem)
else:
# 3d2) string values
out += "'%s', " % elem
out += "]"
option_value = out
## 3e) special cases: multiline
if option_name == 'CFG_OAI_IDENTIFY_DESCRIPTION':
# make triple quotes
option_value = '""' + option_value + '""'
## 3f) ignore some options:
if option_name.startswith('CFG_SITE_NAME_INTL'):
# treated elsewhere
return
## 4) finally, return output line:
return '%s = %s' % (option_name, option_value)
def cli_cmd_update_config_py(conf):
"""
Update new config.py from conf options, keeping previous
config.py in a backup copy.
"""
print ">>> Going to update config.py..."
## location where config.py is:
configpyfile = conf.get("Invenio", "CFG_PYLIBDIR") + \
os.sep + 'invenio' + os.sep + 'config.py'
## backup current config.py file:
if os.path.exists(configpyfile):
shutil.copy(configpyfile, configpyfile + '.OLD')
## here we go:
fdesc = open(configpyfile, 'w')
## generate preamble:
fdesc.write("# -*- coding: utf-8 -*-\n")
fdesc.write("# DO NOT EDIT THIS FILE! IT WAS AUTOMATICALLY GENERATED\n")
fdesc.write("# FROM INVENIO.CONF BY EXECUTING:\n")
fdesc.write("# " + " ".join(sys.argv) + "\n")
## special treatment for CFG_SITE_NAME_INTL options:
fdesc.write("CFG_SITE_NAME_INTL = {}\n")
for lang in conf.get("Invenio", "CFG_SITE_LANGS").split(","):
fdesc.write("CFG_SITE_NAME_INTL['%s'] = \"%s\"\n" % (lang, conf.get("Invenio",
"CFG_SITE_NAME_INTL_" + lang)))
## special treatment for CFG_SITE_SECURE_URL that may be empty, in
## which case it should be put equal to CFG_SITE_URL:
if not conf.get("Invenio", "CFG_SITE_SECURE_URL"):
conf.set("Invenio", "CFG_SITE_SECURE_URL",
conf.get("Invenio", "CFG_SITE_URL"))
## process all the options normally:
sections = conf.sections()
sections.sort()
for section in sections:
options = conf.options(section)
options.sort()
for option in options:
if not option.startswith('CFG_DATABASE_'):
# put all options except for db credentials into config.py
line_out = convert_conf_option(option, conf.get(section, option))
if line_out:
fdesc.write(line_out + "\n")
## FIXME: special treatment for experimental variables
## CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES and CFG_WEBSEARCH_DEFAULT_SEARCH_INTERFACE
## (not offering them in invenio.conf since they will be refactored)
fdesc.write("CFG_WEBSEARCH_DEFAULT_SEARCH_INTERFACE = 0\n")
fdesc.write("CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES = [0, 1,]\n")
## generate postamble:
fdesc.write("")
fdesc.write("# END OF GENERATED FILE")
## we are done:
fdesc.close()
print "You may want to restart Apache now."
print ">>> config.py updated successfully."
def cli_cmd_update_dbquery_py(conf):
"""
Update lib/dbquery.py file with DB parameters read from conf file.
Note: this edits dbquery.py in situ, taking a backup first.
Use only when you know what you are doing.
"""
print ">>> Going to update dbquery.py..."
## location where dbquery.py is:
dbquerypyfile = conf.get("Invenio", "CFG_PYLIBDIR") + \
os.sep + 'invenio' + os.sep + 'dbquery.py'
## backup current dbquery.py file:
if os.path.exists(dbquerypyfile):
shutil.copy(dbquerypyfile, dbquerypyfile + '.OLD')
## replace db parameters:
out = ''
for line in open(dbquerypyfile, 'r').readlines():
match = re.search(r'^CFG_DATABASE_(HOST|PORT|NAME|USER|PASS)(\s*=\s*)\'.*\'$', line)
if match:
dbparam = 'CFG_DATABASE_' + match.group(1)
out += "%s%s'%s'\n" % (dbparam, match.group(2),
conf.get('Invenio', dbparam))
else:
out += line
fdesc = open(dbquerypyfile, 'w')
fdesc.write(out)
fdesc.close()
print "You may want to restart Apache now."
print ">>> dbquery.py updated successfully."
def cli_cmd_update_dbexec(conf):
"""
Update bin/dbexec file with DB parameters read from conf file.
Note: this edits dbexec in situ, taking a backup first.
Use only when you know what you are doing.
"""
print ">>> Going to update dbexec..."
## location where dbexec is:
dbexecfile = conf.get("Invenio", "CFG_BINDIR") + \
os.sep + 'dbexec'
## backup current dbexec file:
if os.path.exists(dbexecfile):
shutil.copy(dbexecfile, dbexecfile + '.OLD')
## replace db parameters via sed:
out = ''
for line in open(dbexecfile, 'r').readlines():
match = re.search(r'^CFG_DATABASE_(HOST|PORT|NAME|USER|PASS)(\s*=\s*)\'.*\'$', line)
if match:
dbparam = 'CFG_DATABASE_' + match.group(1)
out += "%s%s'%s'\n" % (dbparam, match.group(2),
conf.get("Invenio", dbparam))
else:
out += line
fdesc = open(dbexecfile, 'w')
fdesc.write(out)
fdesc.close()
print ">>> dbexec updated successfully."
def cli_cmd_update_bibconvert_tpl(conf):
"""
Update bibconvert/config/*.tpl files looking for 856
http://.../record/ lines, replacing URL with CFG_SITE_URL taken
from conf file. Note: this edits tpl files in situ, taking a
backup first. Use only when you know what you are doing.
"""
print ">>> Going to update bibconvert templates..."
## location where bibconvert/config/*.tpl are:
tpldir = conf.get("Invenio", 'CFG_ETCDIR') + \
os.sep + 'bibconvert' + os.sep + 'config'
## find all *.tpl files:
for tplfilename in os.listdir(tpldir):
if tplfilename.endswith(".tpl"):
## change tpl file:
tplfile = tpldir + os.sep + tplfilename
shutil.copy(tplfile, tplfile + '.OLD')
out = ''
for line in open(tplfile, 'r').readlines():
match = re.search(r'^(.*)http://.*?/record/(.*)$', line)
if match:
out += "%s%s/record/%s\n" % (match.group(1),
conf.get("Invenio", 'CFG_SITE_URL'),
match.group(2))
else:
out += line
fdesc = open(tplfile, 'w')
fdesc.write(out)
fdesc.close()
print ">>> bibconvert templates updated successfully."
def cli_cmd_update_web_tests(conf):
"""
Update web test cases lib/webtest/test_*.html looking for
http://.+?[] strings and replacing them with CFG_SITE_URL
taken from conf file. Note: this edits test files in situ, taking
a backup first. Use only when you know what you are doing.
"""
print ">>> Going to update web tests..."
## location where test_*.html files are:
testdir = conf.get("Invenio", 'CFG_PREFIX') + os.sep + \
'lib' + os.sep + 'webtest' + os.sep + 'invenio'
## find all test_*.html files:
for testfilename in os.listdir(testdir):
if testfilename.startswith("test_") and \
testfilename.endswith(".html"):
## change test file:
testfile = testdir + os.sep + testfilename
shutil.copy(testfile, testfile + '.OLD')
out = ''
for line in open(testfile, 'r').readlines():
match = re.search(r'^(.*
)http://.+?([].*)$', line)
if match:
out += "%s%s%s\n" % (match.group(1),
conf.get("Invenio", 'CFG_SITE_URL'),
match.group(2))
else:
match = re.search(r'^(.*
)/opt/cds-invenio(.*)$', line)
if match:
out += "%s%s%s\n" % (match.group(1),
conf.get("Invenio", 'CFG_PREFIX'),
match.group(2))
else:
out += line
fdesc = open(testfile, 'w')
fdesc.write(out)
fdesc.close()
print ">>> web tests updated successfully."
def cli_cmd_reset_sitename(conf):
"""
Reset collection-related tables with new CFG_SITE_NAME and
CFG_SITE_NAME_INTL* read from conf files.
"""
print ">>> Going to reset CFG_SITE_NAME and CFG_SITE_NAME_INTL..."
from invenio.dbquery import run_sql, IntegrityError
# reset CFG_SITE_NAME:
sitename = conf.get("Invenio", "CFG_SITE_NAME")
try:
run_sql("""INSERT INTO collection (id, name, dbquery, reclist) VALUES
(1,%s,NULL,NULL)""", (sitename,))
except IntegrityError:
run_sql("""UPDATE collection SET name=%s WHERE id=1""", (sitename,))
# reset CFG_SITE_NAME_INTL:
for lang in conf.get("Invenio", "CFG_SITE_LANGS").split(","):
sitename_lang = conf.get("Invenio", "CFG_SITE_NAME_INTL_" + lang)
try:
run_sql("""INSERT INTO collectionname (id_collection, ln, type, value) VALUES
(%s,%s,%s,%s)""", (1, lang, 'ln', sitename_lang))
except IntegrityError:
run_sql("""UPDATE collectionname SET value=%s
WHERE ln=%s AND id_collection=1 AND type='ln'""",
(sitename_lang, lang))
print "You may want to restart Apache now."
print ">>> CFG_SITE_NAME and CFG_SITE_NAME_INTL* reset successfully."
def cli_cmd_reset_recstruct_cache(conf):
"""If CFG_BIBUPLOAD_SERIALIZE_RECORD_STRUCTURE is changed, this function
will adapt the database to either store or not store the recstruct
format."""
from invenio.intbitset import intbitset
from invenio.dbquery import run_sql
from invenio.search_engine import get_record
from invenio.bibsched import server_pid, pidfile
enable_recstruct_cache = conf.get("Invenio", "CFG_BIBUPLOAD_SERIALIZE_RECORD_STRUCTURE")
enable_recstruct_cache = enable_recstruct_cache in ('True', '1')
pid = server_pid(ping_the_process=False)
if pid:
print >> sys.stderr, "ERROR: bibsched seems to run with pid %d, according to %s." % (pid, pidfile)
print >> sys.stderr, " Please stop bibsched before running this procedure."
sys.exit(1)
if enable_recstruct_cache:
print ">>> Searching records which need recstruct cache resetting; this may take a while..."
all_recids = intbitset(run_sql("SELECT id FROM bibrec"))
good_recids = intbitset(run_sql("SELECT bibrec.id FROM bibrec JOIN bibfmt ON bibrec.id = bibfmt.id_bibrec WHERE format='recstruct' AND modification_date < last_updated"))
recids = all_recids - good_recids
print ">>> Generating recstruct cache..."
tot = len(recids)
count = 0
for recid in recids:
value = zlib.compress(marshal.dumps(get_record(recid)))
run_sql("INSERT INTO bibfmt(id_bibrec, format, last_updated, value) VALUES(%s, 'recstruct', NOW(), %s)", (recid, value))
count += 1
if count % 1000 == 0:
print " ... done records %s/%s" % (count, tot)
if count % 1000 != 0:
print " ... done records %s/%s" % (count, tot)
print ">>> recstruct cache generated successfully."
else:
print ">>> Cleaning recstruct cache..."
run_sql("DELETE FROM bibfmt WHERE format='recstruct'")
def cli_cmd_reset_siteadminemail(conf):
"""
Reset user-related tables with new CFG_SITE_ADMIN_EMAIL read from conf files.
"""
print ">>> Going to reset CFG_SITE_ADMIN_EMAIL..."
from invenio.dbquery import run_sql
siteadminemail = conf.get("Invenio", "CFG_SITE_ADMIN_EMAIL")
run_sql("DELETE FROM user WHERE id=1")
run_sql("""INSERT INTO user (id, email, password, note, nickname) VALUES
(1, %s, AES_ENCRYPT(email, ''), 1, 'admin')""",
(siteadminemail,))
print "You may want to restart Apache now."
print ">>> CFG_SITE_ADMIN_EMAIL reset successfully."
def cli_cmd_reset_fieldnames(conf):
"""
Reset I18N field names such as author, title, etc and other I18N
ranking method names such as word similarity. Their translations
are taken from the PO files.
"""
print ">>> Going to reset I18N field names..."
from invenio.messages import gettext_set_language, language_list_long
from invenio.dbquery import run_sql, IntegrityError
## get field id and name list:
field_id_name_list = run_sql("SELECT id, name FROM field")
## get rankmethod id and name list:
rankmethod_id_name_list = run_sql("SELECT id, name FROM rnkMETHOD")
## update names for every language:
for lang, dummy in language_list_long():
_ = gettext_set_language(lang)
## this list is put here in order for PO system to pick names
## suitable for translation
field_name_names = {"any field": _("any field"),
"title": _("title"),
"author": _("author"),
"abstract": _("abstract"),
"keyword": _("keyword"),
"report number": _("report number"),
"subject": _("subject"),
"reference": _("reference"),
"fulltext": _("fulltext"),
"collection": _("collection"),
"division": _("division"),
"year": _("year"),
"journal": _("journal"),
"experiment": _("experiment"),
"record ID": _("record ID")}
## update I18N names for every language:
for (field_id, field_name) in field_id_name_list:
if field_name_names.has_key(field_name):
try:
run_sql("""INSERT INTO fieldname (id_field,ln,type,value) VALUES
(%s,%s,%s,%s)""", (field_id, lang, 'ln',
field_name_names[field_name]))
except IntegrityError:
run_sql("""UPDATE fieldname SET value=%s
WHERE id_field=%s AND ln=%s AND type=%s""",
(field_name_names[field_name], field_id, lang, 'ln',))
## ditto for rank methods:
rankmethod_name_names = {"wrd": _("word similarity"),
"demo_jif": _("journal impact factor"),
"citation": _("times cited"),}
for (rankmethod_id, rankmethod_name) in rankmethod_id_name_list:
try:
run_sql("""INSERT INTO rnkMETHODNAME (id_rnkMETHOD,ln,type,value) VALUES
(%s,%s,%s,%s)""", (rankmethod_id, lang, 'ln',
rankmethod_name_names[rankmethod_name]))
except IntegrityError:
run_sql("""UPDATE rnkMETHODNAME SET value=%s
WHERE id_rnkMETHOD=%s AND ln=%s AND type=%s""",
(rankmethod_name_names[rankmethod_name], rankmethod_id, lang, 'ln',))
print ">>> I18N field names reset successfully."
def test_db_connection():
"""
Test DB connection, and if fails, advise user how to set it up.
Useful to be called during table creation.
"""
print "Testing DB connection...",
from invenio.textutils import wrap_text_in_a_box
from invenio.dbquery import run_sql, Error
## first, test connection to the DB server:
try:
run_sql("SHOW TABLES")
except Error, err:
from invenio.dbquery import CFG_DATABASE_HOST, CFG_DATABASE_PORT, \
CFG_DATABASE_NAME, CFG_DATABASE_USER, CFG_DATABASE_PASS
print wrap_text_in_a_box("""\
DATABASE CONNECTIVITY ERROR %(errno)d: %(errmsg)s.\n
Perhaps you need to set up database and connection rights?
If yes, then please login as MySQL admin user and run the
following commands now:
$ mysql -h %(dbhost)s -P %(dbport)s -u root -p mysql
mysql> CREATE DATABASE %(dbname)s DEFAULT CHARACTER SET utf8;
mysql> GRANT ALL PRIVILEGES ON %(dbname)s.*
TO %(dbuser)s@%(webhost)s IDENTIFIED BY '%(dbpass)s';
mysql> QUIT
The values printed above were detected from your configuration.
If they are not right, then please edit your invenio.conf file
and rerun 'inveniocfg --update-all' first.
If the problem is of different nature, then please inspect
the above error message and fix the problem before continuing.""" % \
{'errno': err.args[0],
'errmsg': err.args[1],
'dbname': CFG_DATABASE_NAME,
'dbhost': CFG_DATABASE_HOST,
'dbport': CFG_DATABASE_PORT,
'dbuser': CFG_DATABASE_USER,
'dbpass': CFG_DATABASE_PASS,
'webhost': CFG_DATABASE_HOST == 'localhost' and 'localhost' or os.popen('hostname -f', 'r').read().strip(),
})
sys.exit(1)
print "ok"
## second, test insert/select of a Unicode string to detect
## possible Python/MySQL/MySQLdb mis-setup:
print "Testing Python/MySQL/MySQLdb UTF-8 chain...",
try:
beta_in_utf8 = "β" # Greek beta in UTF-8 is 0xCEB2
run_sql("CREATE TEMPORARY TABLE test__invenio__utf8 (x char(1), y varbinary(2)) DEFAULT CHARACTER SET utf8")
run_sql("INSERT INTO test__invenio__utf8 (x, y) VALUES (%s, %s)", (beta_in_utf8, beta_in_utf8))
res = run_sql("SELECT x,y,HEX(x),HEX(y),LENGTH(x),LENGTH(y),CHAR_LENGTH(x),CHAR_LENGTH(y) FROM test__invenio__utf8")
assert res[0] == ('\xce\xb2', '\xce\xb2', 'CEB2', 'CEB2', 2L, 2L, 1L, 2L)
run_sql("DROP TEMPORARY TABLE test__invenio__utf8")
except Exception, err:
print wrap_text_in_a_box("""\
DATABASE RELATED ERROR %s\n
A problem was detected with the UTF-8 treatment in the chain
between the Python application, the MySQLdb connector, and
the MySQL database. You may perhaps have installed older
versions of some prerequisite packages?\n
Please check the INSTALL file and please fix this problem
before continuing.""" % err)
sys.exit(1)
print "ok"
def cli_cmd_create_tables(conf):
"""Create and fill Invenio DB tables. Useful for the installation process."""
print ">>> Going to create and fill tables..."
from invenio.config import CFG_PREFIX
test_db_connection()
for cmd in ["%s/bin/dbexec < %s/lib/sql/invenio/tabcreate.sql" % (CFG_PREFIX, CFG_PREFIX),
"%s/bin/dbexec < %s/lib/sql/invenio/tabfill.sql" % (CFG_PREFIX, CFG_PREFIX)]:
if os.system(cmd):
print "ERROR: failed execution of", cmd
sys.exit(1)
cli_cmd_reset_sitename(conf)
cli_cmd_reset_siteadminemail(conf)
cli_cmd_reset_fieldnames(conf)
for cmd in ["%s/bin/webaccessadmin -u admin -c -a" % CFG_PREFIX]:
if os.system(cmd):
print "ERROR: failed execution of", cmd
sys.exit(1)
print ">>> Tables created and filled successfully."
def cli_cmd_load_webstat_conf(conf):
print ">>> Going to load WebStat config..."
from invenio.config import CFG_PREFIX
cmd = "%s/bin/webstatadmin --load-config" % CFG_PREFIX
if os.system(cmd):
print "ERROR: failed execution of", cmd
sys.exit(1)
print ">>> WebStat config load successfully."
def cli_cmd_drop_tables(conf):
"""Drop Invenio DB tables. Useful for the uninstallation process."""
print ">>> Going to drop tables..."
from invenio.config import CFG_PREFIX
from invenio.textutils import wrap_text_in_a_box, wait_for_user
wait_for_user(wrap_text_in_a_box("""WARNING: You are going to destroy
your database tables!"""))
cmd = "%s/bin/dbexec < %s/lib/sql/invenio/tabdrop.sql" % (CFG_PREFIX, CFG_PREFIX)
if os.system(cmd):
print "ERROR: failed execution of", cmd
sys.exit(1)
print ">>> Tables dropped successfully."
def cli_cmd_create_demo_site(conf):
"""Create demo site. Useful for testing purposes."""
print ">>> Going to create demo site..."
from invenio.config import CFG_PREFIX
from invenio.dbquery import run_sql
run_sql("TRUNCATE schTASK")
run_sql("TRUNCATE session")
run_sql("DELETE FROM user WHERE email=''")
for cmd in ["%s/bin/dbexec < %s/lib/sql/invenio/democfgdata.sql" % \
(CFG_PREFIX, CFG_PREFIX),]:
if os.system(cmd):
print "ERROR: failed execution of", cmd
sys.exit(1)
cli_cmd_reset_fieldnames(conf) # needed for I18N demo ranking method names
for cmd in ["%s/bin/webaccessadmin -u admin -c -r -D" % CFG_PREFIX,
"%s/bin/webcoll -u admin" % CFG_PREFIX,
"%s/bin/webcoll 1" % CFG_PREFIX,]:
if os.system(cmd):
print "ERROR: failed execution of", cmd
sys.exit(1)
print ">>> Demo site created successfully."
def cli_cmd_load_demo_records(conf):
"""Load demo records. Useful for testing purposes."""
from invenio.config import CFG_PREFIX
from invenio.dbquery import run_sql
print ">>> Going to load demo records..."
run_sql("TRUNCATE schTASK")
for cmd in ["%s/bin/bibupload -u admin -i %s/var/tmp/demobibdata.xml" % (CFG_PREFIX, CFG_PREFIX),
"%s/bin/bibupload 1" % CFG_PREFIX,
"%s/bin/bibindex -u admin" % CFG_PREFIX,
"%s/bin/bibindex 2" % CFG_PREFIX,
"%s/bin/bibreformat -u admin -o HB" % CFG_PREFIX,
"%s/bin/bibreformat 3" % CFG_PREFIX,
"%s/bin/webcoll -u admin" % CFG_PREFIX,
"%s/bin/webcoll 4" % CFG_PREFIX,
"%s/bin/bibrank -u admin" % CFG_PREFIX,
"%s/bin/bibrank 5" % CFG_PREFIX,]:
if os.system(cmd):
print "ERROR: failed execution of", cmd
sys.exit(1)
print ">>> Demo records loaded successfully."
def cli_cmd_remove_demo_records(conf):
"""Remove demo records. Useful when you are finished testing."""
print ">>> Going to remove demo records..."
from invenio.config import CFG_PREFIX
from invenio.dbquery import run_sql
from invenio.textutils import wrap_text_in_a_box, wait_for_user
wait_for_user(wrap_text_in_a_box("""WARNING: You are going to destroy
your records and documents!"""))
if os.path.exists(CFG_PREFIX + os.sep + 'var' + os.sep + 'data'):
shutil.rmtree(CFG_PREFIX + os.sep + 'var' + os.sep + 'data')
run_sql("TRUNCATE schTASK")
for cmd in ["%s/bin/dbexec < %s/lib/sql/invenio/tabbibclean.sql" % (CFG_PREFIX, CFG_PREFIX),
"%s/bin/webcoll -u admin" % CFG_PREFIX,
"%s/bin/webcoll 1" % CFG_PREFIX,]:
if os.system(cmd):
print "ERROR: failed execution of", cmd
sys.exit(1)
print ">>> Demo records removed successfully."
def cli_cmd_drop_demo_site(conf):
"""Drop demo site completely. Useful when you are finished testing."""
print ">>> Going to drop demo site..."
from invenio.textutils import wrap_text_in_a_box, wait_for_user
wait_for_user(wrap_text_in_a_box("""WARNING: You are going to destroy
your site and documents!"""))
cli_cmd_drop_tables(conf)
cli_cmd_create_tables(conf)
cli_cmd_remove_demo_records(conf)
print ">>> Demo site dropped successfully."
def cli_cmd_run_unit_tests(conf):
"""Run unit tests, usually on the working demo site."""
from invenio.testutils import build_and_run_unit_test_suite
build_and_run_unit_test_suite()
def cli_cmd_run_regression_tests(conf):
"""Run regression tests, usually on the working demo site."""
from invenio.testutils import build_and_run_regression_test_suite
build_and_run_regression_test_suite()
def cli_cmd_run_web_tests(conf):
"""Run web tests in a browser. Requires Firefox with
Selenium IDE extension."""
from invenio.testutils import build_and_run_web_test_suite
build_and_run_web_test_suite()
def cli_cmd_create_apache_conf(conf):
"""
Create Apache conf files for this site, keeping previous
files in a backup copy.
"""
print ">>> Going to create Apache conf files..."
from invenio.textutils import wrap_text_in_a_box
apache_conf_dir = conf.get("Invenio", 'CFG_ETCDIR') + \
os.sep + 'apache'
## TODO: add here the distribution signatures of those distributions
## that already provide some ports.conf configuration file.
for distribution_signature in ('redhat-release', 'debian_version'):
if os.path.exists(os.path.sep + 'etc' + os.path.sep + distribution_signature):
comment_out_listen_directive = '#'
break
else:
comment_out_listen_directive = ''
if not os.path.exists(apache_conf_dir):
os.mkdir(apache_conf_dir)
apache_vhost_file = apache_conf_dir + os.sep + \
'invenio-apache-vhost.conf'
apache_vhost_ssl_file = apache_conf_dir + os.sep + \
'invenio-apache-vhost-ssl.conf'
apache_vhost_body = """\
AddDefaultCharset UTF-8
ServerSignature Off
ServerTokens Prod
NameVirtualHost *:80
%(comment_out_listen_directive)sListen 80
WSGIRestrictStdout Off
deny from all
deny from all
ServerName %(servername)s
ServerAlias %(serveralias)s
ServerAdmin %(serveradmin)s
DocumentRoot %(webdir)s
Options FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from all
ErrorLog %(logdir)s/apache.err
LogLevel warn
CustomLog %(logdir)s/apache.log combined
DirectoryIndex index.en.html index.html
Alias /img/ %(webdir)s/img/
Alias /js/ %(webdir)s/js/
Alias /export/ %(webdir)s/export/
Alias /jsMath/ %(webdir)s/jsMath/
Alias /fckeditor/ %(webdir)s/fckeditor/
AliasMatch /sitemap-(.*) %(webdir)s/sitemap-$1
Alias /robots.txt %(webdir)s/robots.txt
Alias /favicon.ico %(webdir)s/favicon.ico
WSGIDaemonProcess invenio processes=5 threads=1 display-name=%%{GROUP}
WSGIScriptAlias / %(wsgidir)s/invenio.wsgi
WSGIPassAuthorization On
WSGIProcessGroup invenio
Options FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from all
""" % {'servername': conf.get('Invenio', 'CFG_SITE_URL').replace("http://", ""),
'serveralias': conf.get('Invenio', 'CFG_SITE_URL').replace("http://", "").split('.')[0],
'serveradmin': conf.get('Invenio', 'CFG_SITE_ADMIN_EMAIL'),
'webdir': conf.get('Invenio', 'CFG_WEBDIR'),
'logdir': conf.get('Invenio', 'CFG_LOGDIR'),
'libdir' : conf.get('Invenio', 'CFG_PYLIBDIR'),
'wsgidir' : os.path.join(conf.get('Invenio', 'CFG_PREFIX'), 'var', 'www-wsgi'),
'comment_out_listen_directive' : comment_out_listen_directive
}
apache_vhost_ssl_body = """\
ServerSignature Off
ServerTokens Prod
%(comment_out_listen_directive)sListen 443
NameVirtualHost *:443
#SSLCertificateFile /etc/apache2/ssl/apache.pem
SSLCertificateFile /etc/apache2/ssl/server.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
WSGIRestrictStdout Off
deny from all
deny from all
ServerName %(servername)s
ServerAlias %(serveralias)s
ServerAdmin %(serveradmin)s
SSLEngine on
DocumentRoot %(webdir)s
Options FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from all
ErrorLog %(logdir)s/apache-ssl.err
LogLevel warn
CustomLog %(logdir)s/apache-ssl.log combined
DirectoryIndex index.en.html index.html
Alias /img/ %(webdir)s/img/
Alias /js/ %(webdir)s/js/
Alias /export/ %(webdir)s/export/
Alias /jsMath/ %(webdir)s/jsMath/
Alias /fckeditor/ %(webdir)s/fckeditor/
AliasMatch /sitemap-(.*) %(webdir)s/sitemap-$1
Alias /robots.txt %(webdir)s/robots.txt
Alias /favicon.ico %(webdir)s/favicon.ico
WSGIScriptAlias / %(wsgidir)s/invenio.wsgi
WSGIPassAuthorization On
WSGIProcessGroup invenio
Options FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from all
""" % {'servername': conf.get('Invenio', 'CFG_SITE_SECURE_URL').replace("https://", ""),
'serveralias': conf.get('Invenio', 'CFG_SITE_SECURE_URL').replace("https://", "").split('.')[0],
'serveradmin': conf.get('Invenio', 'CFG_SITE_ADMIN_EMAIL'),
'webdir': conf.get('Invenio', 'CFG_WEBDIR'),
'logdir': conf.get('Invenio', 'CFG_LOGDIR'),
'libdir' : conf.get('Invenio', 'CFG_PYLIBDIR'),
'wsgidir' : os.path.join(conf.get('Invenio', 'CFG_PREFIX'), 'var', 'www-wsgi'),
'comment_out_listen_directive' : comment_out_listen_directive
}
# write HTTP vhost snippet:
if os.path.exists(apache_vhost_file):
shutil.copy(apache_vhost_file,
apache_vhost_file + '.OLD')
fdesc = open(apache_vhost_file, 'w')
fdesc.write(apache_vhost_body)
fdesc.close()
print "Created file", apache_vhost_file
# write HTTPS vhost snippet:
if conf.get('Invenio', 'CFG_SITE_SECURE_URL') != \
conf.get('Invenio', 'CFG_SITE_URL'):
if os.path.exists(apache_vhost_ssl_file):
shutil.copy(apache_vhost_ssl_file,
apache_vhost_ssl_file + '.OLD')
fdesc = open(apache_vhost_ssl_file, 'w')
fdesc.write(apache_vhost_ssl_body)
fdesc.close()
print "Created file", apache_vhost_ssl_file
print wrap_text_in_a_box("""\
Apache virtual host configurations for your site have been
created. You can check created files and put the following
include statements in your httpd.conf:\n
Include %s
Include %s
""" % (apache_vhost_file, apache_vhost_ssl_file))
print ">>> Apache conf files created."
def cli_cmd_get(conf, varname):
"""
Return value of VARNAME read from CONF files. Useful for
third-party programs to access values of conf options such as
CFG_PREFIX. Return None if VARNAME is not found.
"""
# do not pay attention to upper/lower case:
varname = varname.lower()
# do not pay attention to section names yet:
all_options = {}
for section in conf.sections():
for option in conf.options(section):
all_options[option] = conf.get(section, option)
return all_options.get(varname, None)
def cli_cmd_list(conf):
"""
Print a list of all conf options and values from CONF.
"""
sections = conf.sections()
sections.sort()
for section in sections:
options = conf.options(section)
options.sort()
for option in options:
print option.upper(), '=', conf.get(section, option)
def _grep_version_from_executable(path_to_exec, version_regexp):
"""
Try to detect a program version by digging into its binary
PATH_TO_EXEC and looking for VERSION_REGEXP. Return program
version as a string. Return empty string if not succeeded.
"""
from invenio.shellutils import run_shell_command
exec_version = ""
if os.path.exists(path_to_exec):
dummy1, cmd2_out, dummy2 = run_shell_command("strings %s | grep %s",
(path_to_exec, version_regexp))
if cmd2_out:
for cmd2_out_line in cmd2_out.split("\n"):
if len(cmd2_out_line) > len(exec_version):
# the longest the better
exec_version = cmd2_out_line
return exec_version
def detect_apache_version():
"""
Try to detect Apache version by localizing httpd or apache
executables and grepping inside binaries. Return list of all
found Apache versions and paths. (For a given executable, the
returned format is 'apache_version [apache_path]'.) Return empty
list if no success.
"""
from invenio.shellutils import run_shell_command
out = []
dummy1, cmd_out, dummy2 = run_shell_command("locate bin/httpd bin/apache")
for apache in cmd_out.split("\n"):
apache_version = _grep_version_from_executable(apache, '^Apache\/')
if apache_version:
out.append("%s [%s]" % (apache_version, apache))
return out
def cli_cmd_detect_system_details(conf):
"""
Detect and print system details such as Apache/Python/MySQL
versions etc. Useful for debugging problems on various OS.
"""
import MySQLdb
print ">>> Going to detect system details..."
print "* Hostname: " + socket.gethostname()
print "* Invenio version: " + conf.get("Invenio", "CFG_VERSION")
print "* Python version: " + sys.version.replace("\n", " ")
print "* Apache version: " + ";\n ".join(detect_apache_version())
print "* MySQLdb version: " + MySQLdb.__version__
try:
from invenio.dbquery import run_sql
print "* MySQL version:"
for key, val in run_sql("SHOW VARIABLES LIKE 'version%'") + \
run_sql("SHOW VARIABLES LIKE 'charact%'") + \
run_sql("SHOW VARIABLES LIKE 'collat%'"):
if False:
print " - %s: %s" % (key, val)
elif key in ['version',
'character_set_client',
'character_set_connection',
'character_set_database',
'character_set_results',
'character_set_server',
'character_set_system',
'collation_connection',
'collation_database',
'collation_server']:
print " - %s: %s" % (key, val)
except ImportError:
print "* ERROR: cannot import dbquery"
print ">>> System details detected successfully."
def main():
"""Main entry point."""
conf = ConfigParser()
if '--help' in sys.argv or \
'-h' in sys.argv:
print_usage()
elif '--version' in sys.argv or \
'-V' in sys.argv:
print_version()
else:
confdir = None
if '--conf-dir' in sys.argv:
try:
confdir = sys.argv[sys.argv.index('--conf-dir') + 1]
except IndexError:
pass # missing --conf-dir argument value
if not os.path.exists(confdir):
print "ERROR: bad or missing --conf-dir option value."
sys.exit(1)
else:
## try to detect path to conf dir (relative to this bin dir):
confdir = re.sub(r'/bin$', '/etc', sys.path[0])
## read conf files:
for conffile in [confdir + os.sep + 'invenio.conf',
confdir + os.sep + 'invenio-autotools.conf',
confdir + os.sep + 'invenio-local.conf',]:
if os.path.exists(conffile):
conf.read(conffile)
else:
if not conffile.endswith("invenio-local.conf"):
# invenio-local.conf is optional, otherwise stop
print "ERROR: Badly guessed conf file location", conffile
print "(Please use --conf-dir option.)"
sys.exit(1)
## decide what to do:
done = False
for opt_idx in range(0, len(sys.argv)):
opt = sys.argv[opt_idx]
if opt == '--conf-dir':
# already treated before, so skip silently:
pass
elif opt == '--get':
try:
varname = sys.argv[opt_idx + 1]
except IndexError:
print "ERROR: bad or missing --get option value."
sys.exit(1)
if varname.startswith('-'):
print "ERROR: bad or missing --get option value."
sys.exit(1)
varvalue = cli_cmd_get(conf, varname)
if varvalue is not None:
print varvalue
else:
sys.exit(1)
done = True
elif opt == '--list':
cli_cmd_list(conf)
done = True
elif opt == '--detect-system-details':
cli_cmd_detect_system_details(conf)
done = True
elif opt == '--create-tables':
cli_cmd_create_tables(conf)
done = True
elif opt == '--load-webstat-conf':
cli_cmd_load_webstat_conf(conf)
done = True
elif opt == '--drop-tables':
cli_cmd_drop_tables(conf)
done = True
elif opt == '--create-demo-site':
cli_cmd_create_demo_site(conf)
done = True
elif opt == '--load-demo-records':
cli_cmd_load_demo_records(conf)
done = True
elif opt == '--remove-demo-records':
cli_cmd_remove_demo_records(conf)
done = True
elif opt == '--drop-demo-site':
cli_cmd_drop_demo_site(conf)
done = True
elif opt == '--run-unit-tests':
cli_cmd_run_unit_tests(conf)
done = True
elif opt == '--run-regression-tests':
cli_cmd_run_regression_tests(conf)
done = True
elif opt == '--run-web-tests':
cli_cmd_run_web_tests(conf)
done = True
elif opt == '--update-all':
cli_cmd_update_config_py(conf)
cli_cmd_update_dbquery_py(conf)
cli_cmd_update_dbexec(conf)
cli_cmd_update_bibconvert_tpl(conf)
cli_cmd_update_web_tests(conf)
done = True
elif opt == '--update-config-py':
cli_cmd_update_config_py(conf)
done = True
elif opt == '--update-dbquery-py':
cli_cmd_update_dbquery_py(conf)
done = True
elif opt == '--update-dbexec':
cli_cmd_update_dbexec(conf)
done = True
elif opt == '--update-bibconvert-tpl':
cli_cmd_update_bibconvert_tpl(conf)
done = True
elif opt == '--update-web-tests':
cli_cmd_update_web_tests(conf)
done = True
elif opt == '--reset-all':
cli_cmd_reset_sitename(conf)
cli_cmd_reset_siteadminemail(conf)
cli_cmd_reset_fieldnames(conf)
cli_cmd_reset_recstruct_cache(conf)
done = True
elif opt == '--reset-sitename':
cli_cmd_reset_sitename(conf)
done = True
elif opt == '--reset-siteadminemail':
cli_cmd_reset_siteadminemail(conf)
done = True
elif opt == '--reset-fieldnames':
cli_cmd_reset_fieldnames(conf)
done = True
elif opt == '--reset-recstruct-cache':
cli_cmd_reset_recstruct_cache(conf)
done = True
elif opt == '--create-apache-conf':
cli_cmd_create_apache_conf(conf)
done = True
elif opt.startswith("-") and opt != '--yes-i-know':
print "ERROR: unknown option", opt
sys.exit(1)
if not done:
print """ERROR: Please specify a command. Please see '--help'."""
sys.exit(1)
if __name__ == '__main__':
main()
diff --git a/modules/webstyle/lib/webinterface_handler_wsgi.py b/modules/webstyle/lib/webinterface_handler_wsgi.py
index cb13e2d28..b9f3e851f 100644
--- a/modules/webstyle/lib/webinterface_handler_wsgi.py
+++ b/modules/webstyle/lib/webinterface_handler_wsgi.py
@@ -1,463 +1,486 @@
# -*- 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.
"""mod_python->WSGI Framework"""
import sys
import os
+from fnmatch import fnmatch
from cgi import parse_qs
from wsgiref.validate import validator
from wsgiref.util import setup_testing_defaults, FileWrapper, \
guess_scheme
if __name__ != "__main__":
# Chances are that we are inside mod_wsgi.
## You can't write to stdout in mod_wsgi, but some of our
## dependecies do this! (e.g. 4Suite)
sys.stdout = sys.stderr
from invenio.webinterface_layout import invenio_handler
from invenio.webinterface_handler_wsgi_utils import table, FieldStorage, \
HTTP_STATUS_MAP, SERVER_RETURN, OK, DONE, \
HTTP_NOT_FOUND
-from invenio.config import CFG_WEBDIR, CFG_SITE_LANG
+from invenio.config import CFG_WEBDIR, CFG_SITE_LANG, \
+ CFG_WEBSTYLE_HTTP_STATUS_ALERT_LIST
from invenio.errorlib import register_exception
## Static files are usually handled directly by the webserver (e.g. Apache)
## However in case WSGI is required to handle static files too (such
## as when running wsgiref simple server), then this flag can be
## turned on (it is done automatically by wsgi_handler_test).
CFG_WSGI_SERVE_STATIC_FILES = False
class InputProcessed(object):
"""
Auxiliary class used when reading input.
@see: .
"""
def read(self, *args):
raise EOFError('The wsgi.input stream has already been consumed')
readline = readlines = __iter__ = read
class SimulatedModPythonRequest(object):
"""
mod_python like request object.
Minimum and cleaned implementation to make moving out of mod_python
easy.
@see:
"""
def __init__(self, environ, start_response):
self.__environ = environ
self.__start_response = start_response
self.__response_sent_p = False
self.__buffer = ''
self.__low_level_headers = []
self.__headers = table(self.__low_level_headers)
self.__headers.add = self.__headers.add_header
self.__status = "200 OK"
self.__filename = None
self.__disposition_type = None
self.__bytes_sent = 0
self.__allowed_methods = []
self.__cleanups = []
self.headers_out = self.__headers
## See:
self.__write = None
self.__errors = environ['wsgi.errors']
self.__headers_in = table([])
for key, value in environ.iteritems():
if key.startswith('HTTP_'):
self.__headers_in[key[len('HTTP_'):].replace('_', '-')] = value
if environ.get('CONTENT_LENGTH'):
self.__headers_in['content-length'] = environ['CONTENT_LENGTH']
if environ.get('CONTENT_TYPE'):
self.__headers_in['content-type'] = environ['CONTENT_TYPE']
self.get_post_form()
def get_wsgi_environ(self):
return self.__environ
def get_post_form(self):
post_form = self.__environ.get('wsgi.post_form')
input = self.__environ['wsgi.input']
if (post_form is not None
and post_form[0] is input):
return post_form[2]
# This must be done to avoid a bug in cgi.FieldStorage
self.__environ.setdefault('QUERY_STRING', '')
fs = FieldStorage(self, keep_blank_values=1)
new_input = InputProcessed()
post_form = (new_input, input, fs)
self.__environ['wsgi.post_form'] = post_form
self.__environ['wsgi.input'] = new_input
return fs
def get_response_sent_p(self):
return self.__response_sent_p
def get_low_level_headers(self):
return self.__low_level_headers
def get_buffer(self):
return self.__buffer
def write(self, string, flush=1):
if isinstance(string, unicode):
self.__buffer += string.encode('utf8')
else:
self.__buffer += string
if flush:
self.flush()
def flush(self):
self.send_http_header()
if self.__buffer:
self.__bytes_sent += len(self.__buffer)
self.__write(self.__buffer)
self.__buffer = ''
def set_content_type(self, content_type):
self.__headers['content-type'] = content_type
def get_content_type(self):
return self.__headers['content-type']
def send_http_header(self):
if not self.__response_sent_p:
if self.__allowed_methods and self.__status.startswith('405 ') or self.__status.startswith('501 '):
self.__headers['Allow'] = ', '.join(self.__allowed_methods)
## See:
#print self.__low_level_headers
self.__write = self.__start_response(self.__status, self.__low_level_headers)
self.__response_sent_p = True
#print "Response sent: %s" % self.__headers
def get_unparsed_uri(self):
return '?'.join([self.__environ['PATH_INFO'], self.__environ['QUERY_STRING']])
def get_uri(self):
return self.__environ['PATH_INFO']
def get_headers_in(self):
return self.__headers_in
def get_subprocess_env(self):
return self.__environ
def add_common_vars(self):
pass
def get_args(self):
return self.__environ['QUERY_STRING']
def get_remote_ip(self):
return self.__environ.get('REMOTE_ADDR')
def get_remote_host(self):
return self.__environ.get('REMOTE_HOST')
def get_header_only(self):
return self.__environ['REQUEST_METHOD'] == 'HEAD'
def set_status(self, status):
self.__status = '%s %s' % (status, HTTP_STATUS_MAP.get(int(status), 'Explanation not available'))
def get_status(self):
return int(self.__status.split(' ')[0])
def get_wsgi_status(self):
return self.__status
def sendfile(self, path, offset=0, the_len=-1):
try:
self.send_http_header()
file_to_send = open(path)
file_to_send.seek(offset)
file_wrapper = FileWrapper(file_to_send)
count = 0
if the_len < 0:
for chunk in file_wrapper:
count += len(chunk)
self.__bytes_sent += len(chunk)
self.__write(chunk)
else:
for chunk in file_wrapper:
if the_len >= len(chunk):
the_len -= len(chunk)
count += len(chunk)
self.__bytes_sent += len(chunk)
self.__write(chunk)
else:
count += the_len
self.__bytes_sent += the_len
self.__write(chunk[:the_len])
break
except Exception, err:
raise IOError(str(err))
return self.__bytes_sent
def set_content_length(self, content_length):
if content_length is not None:
self.__headers['content-length'] = str(content_length)
else:
del self.__headers['content-length']
def is_https(self):
return int(guess_scheme(self.__environ) == 'https')
def get_method(self):
return self.__environ['REQUEST_METHOD']
def get_hostname(self):
return self.__environ('HTTP_HOST', '')
def set_filename(self, filename):
self.__filename = filename
if self.__disposition_type is None:
self.__disposition_type = 'inline'
self.__headers['content-disposition'] = '%s; filename=%s' % (self.__disposition_type, self.__filename)
def set_encoding(self, encoding):
if encoding:
self.__headers['content-encoding'] = str(encoding)
else:
del self.__headers['content-encoding']
def get_bytes_sent(self):
return self.__bytes_sent
def log_error(self, message):
self.__errors.write(message.strip() + '\n')
def get_content_type_set_p(self):
return bool(self.__headers['content-type'])
def allow_methods(self, methods, reset=0):
if reset:
self.__allowed_methods = []
self.__allowed_methods += [method.upper().strip() for method in methods]
def get_allowed_methods(self):
return self.__allowed_methods
def readline(self, hint=None):
try:
return self.__environ['wsgi.input'].readline(hint)
except TypeError:
## the hint param is not part of wsgi pep, although
## it's great to exploit it in when reading FORM
## with large files, in order to avoid filling up the memory
## Too bad it's not there :-(
return self.__environ['wsgi.input'].readline()
def readlines(self, hint=None):
return self.__environ['wsgi.input'].readlines(hint)
def read(self, hint=None):
return self.__environ['wsgi.input'].read(hint)
def register_cleanup(self, callback, data=None):
self.__cleanups.append((callback, data))
def get_cleanups(self):
return self.__cleanups
content_type = property(get_content_type, set_content_type)
unparsed_uri = property(get_unparsed_uri)
uri = property(get_uri)
headers_in = property(get_headers_in)
subprocess_env = property(get_subprocess_env)
args = property(get_args)
header_only = property(get_header_only)
status = property(get_status, set_status)
method = property(get_method)
hostname = property(get_hostname)
filename = property(fset=set_filename)
encoding = property(fset=set_encoding)
bytes_sent = property(get_bytes_sent)
content_type_set_p = property(get_content_type_set_p)
allowed_methods = property(get_allowed_methods)
response_sent_p = property(get_response_sent_p)
form = property(get_post_form)
remote_ip = property(get_remote_ip)
remote_host = property(get_remote_host)
+def alert_admin_for_server_status_p(status, referer):
+ """
+ Check the configuration variable
+ CFG_WEBSTYLE_HTTP_STATUS_ALERT_LIST to see if the exception should
+ be registered and the admin should be alerted.
+ """
+ status = str(status)
+ for pattern in CFG_WEBSTYLE_HTTP_STATUS_ALERT_LIST:
+ pattern = pattern.lower()
+ must_have_referer = False
+ if pattern.endswith('r'):
+ ## e.g. "404 r"
+ must_have_referer = True
+ pattern = pattern[:-1].strip() ## -> "404"
+ if fnmatch(status, pattern) and (not must_have_referer or referer):
+ return True
+ return False
+
def application(environ, start_response):
"""
Entry point for wsgi.
"""
## Needed for mod_wsgi, see:
setup_testing_defaults(environ)
req = SimulatedModPythonRequest(environ, start_response)
#print 'Starting mod_python simulation'
try:
try:
possible_module, possible_handler = is_mp_legacy_publisher_path(environ['PATH_INFO'])
if possible_module is not None:
mp_legacy_publisher(req, possible_module, possible_handler)
elif CFG_WSGI_SERVE_STATIC_FILES:
possible_static_path = is_static_path(environ['PATH_INFO'])
if possible_static_path is not None:
from invenio.bibdocfile import stream_file
stream_file(req, possible_static_path)
else:
ret = invenio_handler(req)
else:
ret = invenio_handler(req)
req.flush()
except SERVER_RETURN, status:
status = int(str(status))
if status not in (OK, DONE):
req.status = status
req.headers_out['content-type'] = 'text/html'
- register_exception(req=req, alert_admin=True)
+ admin_to_be_alerted = alert_admin_for_server_status_p(status,
+ req.headers_in.get('referer'))
+ if admin_to_be_alerted:
+ register_exception(req=req, alert_admin=True)
start_response(req.get_wsgi_status(), req.get_low_level_headers(), sys.exc_info())
- return generate_error_page(req)
+ return generate_error_page(req, admin_to_be_alerted)
else:
req.flush()
except Exception:
register_exception(req=req, alert_admin=True)
req.headers_out['content-type'] = 'text/html'
start_response(req.get_wsgi_status(), req.get_low_level_headers(), sys.exc_info())
return generate_error_page(req)
finally:
for (callback, data) in req.get_cleanups():
callback(data)
return []
-def generate_error_page(req):
+def generate_error_page(req, admin_was_alerted=True):
"""
Returns an iterable with the error page to be sent to the user browser.
"""
from invenio.webpage import page
from invenio import template
webstyle_templates = template.load('webstyle')
ln = req.form.get('ln', CFG_SITE_LANG)
- return [page(title=req.get_wsgi_status(), body=webstyle_templates.tmpl_error_page(status=req.get_wsgi_status(), ln=ln), language=ln, req=req)]
+ return [page(title=req.get_wsgi_status(), body=webstyle_templates.tmpl_error_page(status=req.get_wsgi_status(), ln=ln, admin_was_alerted=admin_was_alerted), language=ln, req=req)]
def is_static_path(path):
"""
Returns True if path corresponds to an exsting file under CFG_WEBDIR.
@param path: the path.
@type path: string
@return: True if path corresponds to an exsting file under CFG_WEBDIR.
@rtype: bool
"""
path = os.path.abspath(CFG_WEBDIR + path)
if path.startswith(CFG_WEBDIR) and os.path.isfile(path):
return path
return None
def is_mp_legacy_publisher_path(path):
"""
Checks path corresponds to an exsting Python file under CFG_WEBDIR.
@param path: the path.
@type path: string
@return: the path of the module to load and the function to call there.
@rtype: tuple
"""
path = path.split('/')
for index, component in enumerate(path):
if component.endswith('.py'):
possible_module = os.path.abspath(CFG_WEBDIR + os.path.sep + os.path.sep.join(path[:index + 1]))
possible_handler = '/'.join(path[index + 1:]).strip()
if not possible_handler:
possible_handler = 'index'
if os.path.exists(possible_module) and possible_module.startswith(CFG_WEBDIR):
return (possible_module, possible_handler)
else:
return None, None
def mp_legacy_publisher(req, possible_module, possible_handler):
"""
mod_python legacy publisher minimum implementation.
"""
the_module = open(possible_module).read()
module_globals = {}
exec(the_module, module_globals)
if possible_handler in module_globals:
from invenio.webinterface_handler import _check_result
## the req.form must be casted to dict because of Python 2.4 and earlier
## otherwise any object exposing the mapping interface can be
## used with the magic **
try:
return _check_result(req, module_globals[possible_handler](req, **dict(req.form)))
except TypeError, err:
if ("%s() got an unexpected keyword argument" % possible_handler) in str(err):
register_exception(req=req, prefix="Wrong GET parameter set in calling a legacy publisher handler", alert_admin=True)
import inspect
expected_args = inspect.getargspec(module_globals[possible_handler]).args
cleaned_form = {}
for arg in expected_args:
if arg != 'req' and arg in req.form: # Just in case of malicious usage!
cleaned_form[arg] = req.form[arg]
return _check_result(req, module_globals[possible_handler](req, **cleaned_form))
else:
raise
else:
raise SERVER_RETURN, HTTP_NOT_FOUND
def check_wsgiref_testing_feasability():
"""
In order to use wsgiref for running Invenio, CFG_SITE_URL and
CFG_SITE_SECURE_URL must not use HTTPS because SSL is not supported.
"""
from invenio.config import CFG_SITE_URL, CFG_SITE_SECURE_URL
if CFG_SITE_URL.lower().startswith('https'):
print >> sys.stderr, """
ERROR: SSL is not supported by the wsgiref simple server implementation.
Please set CFG_SITE_URL not to start with "https".
Currently CFG_SITE_URL is set to: "%s".""" % CFG_SITE_URL
sys.exit(1)
if CFG_SITE_SECURE_URL.lower().startswith('https'):
print >> sys.stderr, """
ERROR: SSL is not supported by the wsgiref simple server implementation.
Please set CFG_SITE_SECURE_URL not to start with "https".
Currently CFG_SITE_SECURE_URL is set to: "%s".""" % CFG_SITE_SECURE_URL
sys.exit(1)
def wsgi_handler_test(port=80):
"""
Simple WSGI testing environment based on wsgiref.
"""
from wsgiref.simple_server import make_server
global CFG_WSGI_SERVE_STATIC_FILES
CFG_WSGI_SERVE_STATIC_FILES = True
check_wsgiref_testing_feasability()
validator_app = validator(application)
httpd = make_server('', port, application)
print "Serving on port %s..." % port
httpd.serve_forever()
def main():
from optparse import OptionParser
parser = OptionParser()
parser.add_option('-t', '--test', action='store_true',
dest='test', default=False,
help="Run a WSGI test server via wsgiref (not using Apache).")
parser.add_option('-p', '--port', type='int', dest='port', default='80',
help="The port where the WSGI test server will listen. [80]")
(options, args) = parser.parse_args()
if options.test:
wsgi_handler_test(options.port)
else:
parser.print_help()
if __name__ == "__main__":
main()
diff --git a/modules/webstyle/lib/webstyle_templates.py b/modules/webstyle/lib/webstyle_templates.py
index 4b7ad0efa..7c0d0ba36 100644
--- a/modules/webstyle/lib/webstyle_templates.py
+++ b/modules/webstyle/lib/webstyle_templates.py
@@ -1,865 +1,865 @@
## 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.
"""
WebStyle templates. Customize the look of pages of CDS Invenio
"""
__revision__ = \
"$Id$"
import time
import cgi
import traceback
import urllib
import sys
import string
from invenio.config import \
CFG_SITE_LANG, \
CFG_SITE_NAME, \
CFG_SITE_NAME_INTL, \
CFG_SITE_SUPPORT_EMAIL, \
CFG_SITE_SECURE_URL, \
CFG_SITE_URL, \
CFG_VERSION, \
CFG_WEBSTYLE_INSPECT_TEMPLATES
from invenio.messages import gettext_set_language, language_list_long
from invenio.urlutils import make_canonical_urlargd, create_html_link
from invenio.dateutils import convert_datecvs_to_datestruct, \
convert_datestruct_to_dategui
from invenio.bibformat import format_record
from invenio import template
websearch_templates = template.load('websearch')
class Template:
def tmpl_navtrailbox_body(self, ln, title, previous_links,
separator, prolog, epilog):
"""Create navigation trail box body
Parameters:
- 'ln' *string* - The language to display
- 'title' *string* - page title;
- 'previous_links' *string* - the trail content from site title until current page (both ends exlusive)
- 'prolog' *string* - HTML code to prefix the navtrail item with
- 'epilog' *string* - HTML code to suffix the navtrail item with
- 'separator' *string* - HTML code that separates two navtrail items
Output:
- text containing the navtrail
"""
# load the right message language
_ = gettext_set_language(ln)
out = ""
if title != CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME):
out += create_html_link(CFG_SITE_URL, {'ln': ln},
_("Home"), {'class': 'navtrail'})
if previous_links:
if out:
out += separator
out += previous_links
if title:
if out:
out += separator
if title == CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME): # hide site name, print Home instead
out += cgi.escape(_("Home"))
else:
out += cgi.escape(title)
return cgi.escape(prolog) + out + cgi.escape(epilog)
def tmpl_page(self, req=None, ln=CFG_SITE_LANG, description="",
keywords="", userinfobox="", navtrailbox="",
pageheaderadd="", boxlefttop="", boxlefttopadd="",
boxleftbottom="", boxleftbottomadd="",
boxrighttop="", boxrighttopadd="",
boxrightbottom="", boxrightbottomadd="",
titleprologue="", title="", titleepilogue="",
body="", lastupdated=None, pagefooteradd="", uid=0,
secure_page_p=0, navmenuid="", metaheaderadd="",
rssurl=CFG_SITE_URL+"/rss",
show_title_p=True):
"""Creates a complete page
Parameters:
- 'ln' *string* - The language to display
- 'description' *string* - description goes to the metadata in the header of the HTML page
- 'keywords' *string* - keywords goes to the metadata in the header of the HTML page
- 'userinfobox' *string* - the HTML code for the user information box
- 'navtrailbox' *string* - the HTML code for the navigation trail box
- 'pageheaderadd' *string* - additional page header HTML code
- 'boxlefttop' *string* - left-top box HTML code
- 'boxlefttopadd' *string* - additional left-top box HTML code
- 'boxleftbottom' *string* - left-bottom box HTML code
- 'boxleftbottomadd' *string* - additional left-bottom box HTML code
- 'boxrighttop' *string* - right-top box HTML code
- 'boxrighttopadd' *string* - additional right-top box HTML code
- 'boxrightbottom' *string* - right-bottom box HTML code
- 'boxrightbottomadd' *string* - additional right-bottom box HTML code
- 'title' *string* - the title of the page
- 'titleprologue' *string* - what to print before page title
- 'titleepilogue' *string* - what to print after page title
- 'body' *string* - the body of the page
- 'lastupdated' *string* - when the page was last updated
- 'uid' *int* - user ID
- 'pagefooteradd' *string* - additional page footer HTML code
- 'secure_page_p' *int* (0 or 1) - are we to use HTTPS friendly page elements or not?
- 'navmenuid' *string* - the id of the navigation item to highlight for this page
- 'metaheaderadd' *string* - list of further tags to add to the part of the page
- 'rssurl' *string* - the url of the RSS feed for this page
- 'show_title_p' *int* (0 or 1) - do we display the page title in the body of the page?
Output:
- HTML code of the page
"""
# load the right message language
_ = gettext_set_language(ln)
out = self.tmpl_pageheader(req,
ln = ln,
headertitle = title,
description = description,
keywords = keywords,
metaheaderadd = metaheaderadd,
userinfobox = userinfobox,
navtrailbox = navtrailbox,
pageheaderadd = pageheaderadd,
secure_page_p = secure_page_p,
navmenuid=navmenuid,
rssurl=rssurl) + """
' or '',
'titleepilogue' : titleepilogue,
'body' : body,
} + self.tmpl_pagefooter(req, ln = ln,
lastupdated = lastupdated,
pagefooteradd = pagefooteradd)
return out
def tmpl_pageheader(self, req, ln=CFG_SITE_LANG, headertitle="",
description="", keywords="", userinfobox="",
navtrailbox="", pageheaderadd="", uid=0,
secure_page_p=0, navmenuid="admin", metaheaderadd="",
rssurl=CFG_SITE_URL+"/rss"):
"""Creates a page header
Parameters:
- 'ln' *string* - The language to display
- 'headertitle' *string* - the second part of the page HTML title
- 'description' *string* - description goes to the metadata in the header of the HTML page
- 'keywords' *string* - keywords goes to the metadata in the header of the HTML page
- 'userinfobox' *string* - the HTML code for the user information box
- 'navtrailbox' *string* - the HTML code for the navigation trail box
- 'pageheaderadd' *string* - additional page header HTML code
- 'uid' *int* - user ID
- 'secure_page_p' *int* (0 or 1) - are we to use HTTPS friendly page elements or not?
- 'navmenuid' *string* - the id of the navigation item to highlight for this page
- 'metaheaderadd' *string* - list of further tags to add to the part of the page
- 'rssurl' *string* - the url of the RSS feed for this page
Output:
- HTML code of the page headers
"""
# load the right message language
_ = gettext_set_language(ln)
if CFG_WEBSTYLE_INSPECT_TEMPLATES:
inspect_templates_message = """
CFG_WEBSTYLE_INSPECT_TEMPLATES debugging mode is enabled. Please
hover your mouse pointer over any region on the page to see which
template function generated it.
""" % {
'title' : cgi.escape(title).replace('"', '"'),
'time_label': _("Time"),
'client_label': _("Client"),
'send_error_label': \
_("Please send an error report to the administrator."),
'send_label': _("Send error report"),
'sys1' : cgi.escape(str((sys.exc_info()[0] or ''))).replace('"', '"'),
'sys2' : cgi.escape(str((sys.exc_info()[1] or ''))).replace('"', '"'),
'contact' : \
_("Please contact %s quoting the following information:") % \
('' + \
CFG_SITE_SUPPORT_EMAIL + ''),
'host' : cgi.escape(host_s),
'page' : cgi.escape(page_s),
'time' : time.strftime("%d/%b/%Y:%H:%M:%S %z"),
'browser' : cgi.escape(browser_s).replace('"', '"'),
'client' : cgi.escape(client_s).replace('"', '"'),
'error' : cgi.escape(error_s).replace('"', '"'),
'traceback' : cgi.escape(traceback_s).replace('"', '"'),
'sys_error' : cgi.escape(sys_error_s).replace('"', '"'),
'siteurl' : CFG_SITE_URL,
'referer' : page_s!=info_not_available and \
("http://" + host_s + page_s) or \
info_not_available
}
return out
def detailed_record_container_top(self, recid, tabs, ln=CFG_SITE_LANG,
show_similar_rec_p=True,
creationdate=None,
modificationdate=None, show_short_rec_p=True):
"""Prints the box displayed in detailed records pages, with tabs at the top.
Returns content as it is if the number of tabs for this record
is smaller than 2
Parameters:
- recid *int* - the id of the displayed record
- tabs ** - the tabs displayed at the top of the box.
- ln *string* - the language of the page in which the box is displayed
- show_similar_rec_p *bool* print 'similar records' link in the box
- creationdate *string* - the creation date of the displayed record
- modificationdate *string* - the last modification date of the displayed record
- show_short_rec_p *boolean* - prints a very short version of the record as reminder.
"""
# If no tabs, returns nothing
if len(tabs) <= 1:
return ''
# load the right message language
_ = gettext_set_language(ln)
# Build the tabs at the top of the page
out_tabs = ''
if len(tabs) > 1:
first_tab = True
for (label, url, selected, enabled) in tabs:
css_class = []
if selected:
css_class.append('on')
if first_tab:
css_class.append('first')
first_tab = False
if not enabled:
css_class.append('disabled')
css_class = ' class="%s"' % ' '.join(css_class)
if not enabled:
out_tabs += '
''' % out_tabs
# Add the clip icon and the brief record reminder if necessary
record_brief = ''
if show_short_rec_p:
record_brief = format_record(recID=recid, of='hs', ln=ln)
record_brief = '''
%(record_brief)s
''' % {'record_brief': record_brief}
# Print the content
out = """
%(tabs)s
%(record_brief)s
""" % {'tabs':out_tabs,
'record_brief':record_brief}
return out
def detailed_record_container_bottom(self, recid, tabs, ln=CFG_SITE_LANG,
show_similar_rec_p=True,
creationdate=None,
modificationdate=None, show_short_rec_p=True):
"""Prints the box displayed in detailed records pages, with tabs at the top.
Returns content as it is if the number of tabs for this record
is smaller than 2
Parameters:
- recid *int* - the id of the displayed record
- tabs ** - the tabs displayed at the top of the box.
- ln *string* - the language of the page in which the box is displayed
- show_similar_rec_p *bool* print 'similar records' link in the box
- creationdate *string* - the creation date of the displayed record
- modificationdate *string* - the last modification date of the displayed record
- show_short_rec_p *boolean* - prints a very short version of the record as reminder.
"""
# If no tabs, returns nothing
if len(tabs) <= 1:
return ''
# load the right message language
_ = gettext_set_language(ln)
out = """
' % {
'dates': _("Record created %(x_date_creation)s, last modified %(x_date_modification)s") % \
{'x_date_creation': creationdate,
'x_date_modification': modificationdate},
} or ''
}
return out
def detailed_record_mini_panel(self, recid, ln=CFG_SITE_LANG,
format='hd',
files='',
reviews='',
actions=''):
"""Displays the actions dock at the bottom of the detailed record
pages.
Parameters:
- recid *int* - the id of the displayed record
- ln *string* - interface language code
- format *string* - the format used to display the record
- files *string* - the small panel representing the fulltext
- reviews *string* - the small panel representing the reviews
- actions *string* - the small panel representing the possible user's action
"""
# load the right message language
_ = gettext_set_language(ln)
out = """
%(files)s
%(reviews)s
%(actions)s
""" % {
'siteurl': CFG_SITE_URL,
'ln':ln,
'recid':recid,
'files': files,
'reviews':reviews,
'actions': actions,
}
return out
- def tmpl_error_page(self, ln=CFG_SITE_LANG, status=""):
+ def tmpl_error_page(self, ln=CFG_SITE_LANG, status="", admin_was_alerted=True):
"""
Display an error page.
- status *string* - the HTTP status.
"""
_ = gettext_set_language(ln)
out = """
%(message)s
%(alerted)s
%(doubts)s
""" % {
'status' : status,
'message' : _("The server encountered an error while dealing with your request."),
- 'alerted' : _("The system administrators have been alerted."),
+ 'alerted' : admin_was_alerted and _("The system administrators have been alerted.") or '',
'doubts' : _("In case of doubt, please contact %(x_admin_email)s.") % {'x_admin_email' : '%(admin)s' % {'admin' : CFG_SITE_SUPPORT_EMAIL}}
}
return out