diff --git a/config/invenio.conf b/config/invenio.conf index 59c8b3cd4..911d8c529 100644 --- a/config/invenio.conf +++ b/config/invenio.conf @@ -1,2160 +1,2168 @@ ## This file is part of Invenio. ## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 CERN. ## ## 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. ## ## 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 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 Invenio installation, as coming out of the ## distribution. The file should be self-explanatory. Once installed ## in its usual location (usually /opt/invenio/etc), you could in ## principle go ahead and change the values according to your local ## needs, but this is not advised. ## ## If you would like to customize some of these parameters, you should ## rather create a file named 'invenio-local.conf' in the same ## directory where 'invenio.conf' lives and you should write there ## only the customizations that you want to be different from the ## vanilla defaults. ## ## Here is a realistic, minimalist, yet production-ready example of ## what you would typically put there: ## ## $ cat /opt/invenio/etc/invenio-local.conf ## [Invenio] ## CFG_SITE_NAME = John Doe's Document Server ## CFG_SITE_NAME_INTL_fr = Serveur des Documents de John Doe ## 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 ## CFG_WEBALERT_ALERT_ENGINE_EMAIL = john.doe@your.site.com ## CFG_WEBCOMMENT_ALERT_ENGINE_EMAIL = john.doe@your.site.com ## CFG_WEBCOMMENT_DEFAULT_MODERATOR = john.doe@your.site.com ## CFG_DATABASE_HOST = localhost ## CFG_DATABASE_NAME = invenio ## CFG_DATABASE_USER = invenio ## CFG_DATABASE_PASS = my123p$ss ## ## You should override at least the parameters mentioned above and the ## parameters mentioned in the `Part 1: Essential parameters' below in ## order to define some very essential runtime parameters such as the ## name of your document server (CFG_SITE_NAME and ## CFG_SITE_NAME_INTL_*), the visible URL of your document server ## (CFG_SITE_URL and CFG_SITE_SECURE_URL), the email address of the ## local Invenio administrator, comment moderator, and alert engine ## (CFG_SITE_SUPPORT_EMAIL, CFG_SITE_ADMIN_EMAIL, etc), and last but ## not least your database credentials (CFG_DATABASE_*). ## ## 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 specified in ## your local file. This cascading of configuration parameters will ## ease your future upgrades. [Invenio] ################################### ## Part 1: Essential parameters ## ################################### ## This part defines essential Invenio internal parameters that ## everybody should override, like the name of the server or the email ## address of the local 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 = invenio CFG_DATABASE_USER = invenio CFG_DATABASE_PASS = my123p$ss ## CFG_DATABASE_SLAVE - if you use DB replication, then specify the DB ## slave address credentials. (Assuming the same access rights to the ## DB slave as to the DB master.) If you don't use DB replication, ## then leave this option blank. CFG_DATABASE_SLAVE = ## 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 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_NAME_INTL_ro = Institutul Atlantis al Ştiinţelor Fictive CFG_SITE_NAME_INTL_rw = Atlantis Ishuri Rikuru Ry'ubuhanga CFG_SITE_NAME_INTL_ka = ატლანტიდის ფიქტიური მეცნიერების ინსტიტუტი CFG_SITE_NAME_INTL_lt = Fiktyvių Mokslų Institutas Atlantis CFG_SITE_NAME_INTL_ar = معهد أطلنطيس للعلوم الافتراضية ## 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, Arabic, Bulgarian, Catalan, Czech, German, Georgian, ## Greek, English, Spanish, French, Croatian, Hungarian, Galician, ## Italian, Japanese, Kinyarwanda, Lithuanian, Norwegian, Polish, ## Portuguese, Romanian, Russian, Slovak, Swedish, Ukrainian, Chinese ## (China), Chinese (Taiwan), so that the eventual maximum you can ## currently select is ## "af,ar,bg,ca,cs,de,el,en,es,fr,hr,gl,ka,it,rw,lt,hu,ja,no,pl,pt,ro,ru,sk,sv,uk,zh_CN,zh_TW". CFG_SITE_LANGS = af,ar,bg,ca,cs,de,el,en,es,fr,hr,gl,ka,it,rw,lt,hu,ja,no,pl,pt,ro,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 = info@invenio-software.org ## 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 Invenio inistration modules. You ## will then be automatically recognized as superuser of the system. CFG_SITE_ADMIN_EMAIL = info@invenio-software.org ## CFG_SITE_EMERGENCY_EMAIL_ADDRESSES -- list of email addresses to ## which an email should be sent in case of emergency (e.g. bibsched ## queue has been stopped because of an error). Configuration ## dictionary allows for different recipients based on weekday and ## time-of-day. Example: ## ## CFG_SITE_EMERGENCY_EMAIL_ADDRESSES = { ## 'Sunday 22:00-06:00': '0041761111111@email2sms.foo.com', ## '06:00-18:00': 'team-in-europe@foo.com,0041762222222@email2sms.foo.com', ## '18:00-06:00': 'team-in-usa@foo.com', ## '*': 'john.doe.phone@foo.com'} ## ## If you want the emergency email notifications to always go to the ## same address, just use the wildcard line in the above example. CFG_SITE_EMERGENCY_EMAIL_ADDRESSES = {} ## CFG_SITE_ADMIN_EMAIL_EXCEPTIONS -- set this to 0 if you do not want ## to receive any captured exception via email to CFG_SITE_ADMIN_EMAIL ## address. Captured exceptions will still be available in ## var/log/invenio.err file. Set this to 1 if you want to receive ## some of the captured exceptions (this depends on the actual place ## where the exception is captured). Set this to 2 if you want to ## receive all captured exceptions. CFG_SITE_ADMIN_EMAIL_EXCEPTIONS = 1 ## CFG_SITE_RECORD -- what is the URI part representing detailed ## record pages? We recomment to leave the default value `record' ## unchanged. CFG_SITE_RECORD = record ## CFG_ERRORLIB_RESET_EXCEPTION_NOTIFICATION_COUNTER_AFTER -- set this to ## the number of seconds after which to reset the exception notification ## counter. A given repetitive exception is notified via email with a ## logarithmic strategy: the first time it is seen it is sent via email, ## then the second time, then the fourth, then the eighth and so forth. ## If the number of seconds elapsed since the last time it was notified ## is greater than CFG_ERRORLIB_RESET_EXCEPTION_NOTIFICATION_COUNTER_AFTER ## then the internal counter is reset in order not to have exception ## notification become more and more rare. CFG_ERRORLIB_RESET_EXCEPTION_NOTIFICATION_COUNTER_AFTER = 14400 ## 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_OPENAIRE_SITE -- do we want to enable OpenAIRE-specific code? ## Put "1" for "yes" and "0" for "no". CFG_OPENAIRE_SITE = 0 ## CFG_DEVEL_SITE -- is this a development site? If it is, you might ## prefer that it does not 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 => foo [at] example [dot] com 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* ## CFG_WEBSTYLE_HTTP_USE_COMPRESSION -- whether to enable deflate ## compression of your HTTP/HTTPS connections. This will affect the Apache ## configuration snippets created by inveniocfg --create-apache-conf and ## the OAI-PMH Identify response. CFG_WEBSTYLE_HTTP_USE_COMPRESSION = 0 ## CFG_WEBSTYLE_REVERSE_PROXY_IPS -- if you are setting a multinode ## environment where an HTTP proxy such as mod_proxy is sitting in ## front of the Invenio web application and is forwarding requests to ## worker nodes, set here the the list of IP addresses of the allowed ## HTTP proxies. This is needed in order to avoid IP address spoofing ## when worker nodes are also available on the public Internet and ## might receive forged HTTP requests. Only HTTP requests coming from ## the specified IP addresses will be considered as forwarded from a ## reverse proxy. E.g. set this to '123.123.123.123'. CFG_WEBSTYLE_REVERSE_PROXY_IPS = ################################## ## 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 = 0 ## 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 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_I18N_COLLECTIONS -- comma-separated list of ## collections that feature an internationalized RSS feed on their ## main seach interface page created by webcoll. Other collections ## will have RSS feed using CFG_SITE_LANG. CFG_WEBSEARCH_RSS_I18N_COLLECTIONS = ## 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_MATHJAX_FOR_FORMATS -- MathJax 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 MathJax rendering, for example ## "hb,hd". If the list is empty, MathJax is disabled. CFG_WEBSEARCH_USE_MATHJAX_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_DEF_RECORDS_IN_GROUPS -- the default number of ## records to display per page in the search results pages. CFG_WEBSEARCH_DEF_RECORDS_IN_GROUPS = 10 ## 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_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 ## CFG_WEBSEARCH_FULLTEXT_SNIPPETS -- how many full-text snippets do ## we want to display for full-text searches? If you want to specify ## different values for different document status types, please add ## more items into this dictionary. (Unless specified, the empty ## value will be used as default.) This is useful if you have ## restricted files of different types with various restrictions on ## what we can show. CFG_WEBSEARCH_FULLTEXT_SNIPPETS = { '': 4, } ## CFG_WEBSEARCH_FULLTEXT_SNIPPETS_CHARS -- what is the maximum size ## of a snippet to display around the pattern found in the full-text? ## If you want to specify different values for different document ## status types, please add more items into this dictionary. (Unless ## specified, the empty value will be used as default.) This is ## useful if you have restricted files of different types with various ## restrictions on what we can show. CFG_WEBSEARCH_FULLTEXT_SNIPPETS_CHARS = { '': 100, } ## CFG_WEBSEARCH_WILDCARD_LIMIT -- some of the queries, wildcard ## queries in particular (ex: cern*, a*), but also regular expressions ## (ex: [a-z]+), may take a long time to respond due to the high ## number of hits. You can limit the number of terms matched by a ## wildcard by setting this variable. A negative value or zero means ## that none of the queries will be limited (which may be wanted by ## also prone to denial-of-service kind of attacks). CFG_WEBSEARCH_WILDCARD_LIMIT = 50000 ## CFG_WEBSEARCH_SYNONYM_KBRS -- defines which knowledge bases are to ## be used for which index in order to provide runtime synonym lookup ## of user-supplied terms, and what massaging function should be used ## upon search pattern before performing the KB lookup. (Can be one ## of `exact', 'leading_to_comma', `leading_to_number'.) CFG_WEBSEARCH_SYNONYM_KBRS = { 'journal': ['SEARCH-SYNONYM-JOURNAL', 'leading_to_number'], } ## CFG_SOLR_URL -- optionally, you may use Solr to serve full-text ## queries and ranking. If so, please specify the URL of your Solr instance. ## Example: http://localhost:8983/solr (default solr port) CFG_SOLR_URL = ## CFG_XAPIAN_ENABLED -- optionally, you may use Xapian to serve full-text ## queries and ranking. If so, please enable it: 1 = enabled CFG_XAPIAN_ENABLED = ## CFG_WEBSEARCH_PREV_NEXT_HIT_LIMIT -- specify the limit when ## the previous/next/back hit links are to be displayed on detailed record pages. ## In order to speeding up list manipulations, if a search returns lots of hits, ## more than this limit, then do not loose time calculating next/previous/back ## hits at all, but display page directly without these. ## Note also that Invenio installations that do not like ## to have the next/previous hit link functionality would be able to set this ## variable to zero and not see anything. CFG_WEBSEARCH_PREV_NEXT_HIT_LIMIT = 1000 ## CFG_WEBSEARCH_PREV_NEXT_HIT_FOR_GUESTS -- Set this to 0 if you want ## to disable the previous/next/back hit link functionality for guests ## users. ## Since the previous/next/back hit link functionality is causing the allocation ## of user session in the database even for guests users, it might be useful to ## be able to disable it e.g. when your site is bombarded by web request ## (a.k.a. Slashdot effect). CFG_WEBSEARCH_PREV_NEXT_HIT_FOR_GUESTS = 1 ## CFG_WEBSEARCH_VIEWRESTRCOLL_POLICY -- when a record belongs to more than one ## restricted collection, if the viewrestcoll policy is set to "ALL" (default) ## then the user must be authorized to all the restricted collections, in ## order to be granted access to the specific record. If the policy is set to ## "ANY", then the user need to be authorized to only one of the collections ## in order to be granted access to the specific record. CFG_WEBSEARCH_VIEWRESTRCOLL_POLICY = ANY ## CFG_WEBSEARCH_SPIRES_SYNTAX -- variable to configure the use of the ## SPIRES query syntax in searches. Values: 0 = SPIRES syntax is ## switched off; 1 = leading 'find' is required; 9 = leading 'find' is ## not required (leading SPIRES operator, space-operator-space, etc ## are also accepted). CFG_WEBSEARCH_SPIRES_SYNTAX = 1 ## CFG_WEBSEARCH_DISPLAY_NEAREST_TERMS -- when user search does not ## return any direct result, what do we want to display? Set to 0 in ## order to display a generic message about search returning no hits. ## Set to 1 in order to display list of nearest terms from the indexes ## that may match user query. Note: this functionality may be slow, ## so you may want to disable it on bigger sites. CFG_WEBSEARCH_DISPLAY_NEAREST_TERMS = 1 ## CFG_WEBSEARCH_DETAILED_META_FORMAT -- the output format to use for ## detailed meta tags containing metadata as configured in the tag ## table. Default output format should be 'hdm', included. This ## format will be included in the header of /record/ pages. For ## efficiency this format should be pre-cached with BibReformat. See ## also CFG_WEBSEARCH_ENABLE_GOOGLESCHOLAR and ## CFG_WEBSEARCH_ENABLE_GOOGLESCHOLAR. CFG_WEBSEARCH_DETAILED_META_FORMAT = hdm ## CFG_WEBSEARCH_ENABLE_GOOGLESCHOLAR -- decides if meta tags for ## Google Scholar shall be included in the detailed record page ## header, when using the standard formatting templates/elements. See ## also CFG_WEBSEARCH_DETAILED_META_FORMAT and ## CFG_WEBSEARCH_ENABLE_OPENGRAPH. When this variable is changed and ## output format defined in CFG_WEBSEARCH_DETAILED_META_FORMAT is ## cached, a bibreformat must be run for the cached records. CFG_WEBSEARCH_ENABLE_GOOGLESCHOLAR = True ## CFG_WEBSEARCH_ENABLE_OPENGRAPH -- decides if meta tags for the Open ## Graph protocol shall be included in the detailed record page ## header, when using the standard formatting templates/elements. See ## also CFG_WEBSEARCH_DETAILED_META_FORMAT and ## CFG_WEBSEARCH_ENABLE_GOOGLESCHOLAR. When this variable is changed ## and output format defined in CFG_WEBSEARCH_DETAILED_META_FORMAT is ## cached, a bibreformat must be run for the cached records. Note that ## enabling Open Graph produces invalid XHTML/HTML5 markup. CFG_WEBSEARCH_ENABLE_OPENGRAPH = False ## CFG_WEBSEARCH_CITESUMMARY_SELFCITES_THRESHOLD -- switches off ## self-citations computation if the number records in the citesummary ## is above the threshold CFG_WEBSEARCH_CITESUMMARY_SELFCITES_THRESHOLD = 2000 ####################################### ## Part 4: BibHarvest OAI parameters ## ####################################### ## This part defines parameters for the Invenio OAI gateway. ## Useful if you are running 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_SET_FIELD -- previous OAI set MARC field: CFG_OAI_PREVIOUS_SET_FIELD = 909COq ## CFG_OAI_DELETED_POLICY -- OAI deletedrecordspolicy ## (no/transient/persistent): CFG_OAI_DELETED_POLICY = persistent ## 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:123 ## CFG_OAI_IDENTIFY_DESCRIPTION -- description for the OAI Identify verb: CFG_OAI_IDENTIFY_DESCRIPTION = http://atlantis.cern.ch/ Free and unlimited use by anybody with obligation to refer to original record Full content, i.e. preprints may not be harvested by robots Submission restricted. Submitted documents are subject of approval by OAI repository admins. ## CFG_OAI_LOAD -- OAI number of records in a response: CFG_OAI_LOAD = 500 ## 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 = 2 ## CFG_OAI_METADATA_FORMATS -- mapping between accepted metadataPrefixes and ## the corresponding output format to use, its schema and its metadataNamespace. CFG_OAI_METADATA_FORMATS = { 'marcxml': ('XOAIMARC', 'http://www.openarchives.org/OAI/1.1/dc.xsd', 'http://purl.org/dc/elements/1.1/'), 'oai_dc': ('XOAIDC', 'http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd', 'http://www.loc.gov/MARC21/slim'), } ## CFG_OAI_FRIENDS -- list of OAI baseURL of friend repositories. See: ## CFG_OAI_FRIENDS = http://cds.cern.ch/oai2d,http://openaire.cern.ch/oai2d,http://export.arxiv.org/oai2 ## The following subfields are a completition to ## CFG_BIBUPLOAD_EXTERNAL_OAIID_TAG. If CFG_OAI_PROVENANCE_BASEURL_SUBFIELD is ## set for a record, then the corresponding field is considered has being ## harvested via OAI-PMH ## CFG_OAI_PROVENANCE_BASEURL_SUBFIELD -- baseURL of the originDescription or a ## record CFG_OAI_PROVENANCE_BASEURL_SUBFIELD = u ## CFG_OAI_PROVENANCE_DATESTAMP_SUBFIELD -- datestamp of the originDescription ## or a record CFG_OAI_PROVENANCE_DATESTAMP_SUBFIELD = d ## CFG_OAI_PROVENANCE_METADATANAMESPACE_SUBFIELD -- metadataNamespace of the ## originDescription or a record CFG_OAI_PROVENANCE_METADATANAMESPACE_SUBFIELD = m ## CFG_OAI_PROVENANCE_ORIGINDESCRIPTION_SUBFIELD -- originDescription of the ## originDescription or a record CFG_OAI_PROVENANCE_ORIGINDESCRIPTION_SUBFIELD = d ## CFG_OAI_PROVENANCE_HARVESTDATE_SUBFIELD -- harvestDate of the ## originDescription or a record CFG_OAI_PROVENANCE_HARVESTDATE_SUBFIELD = h ## CFG_OAI_PROVENANCE_ALTERED_SUBFIELD -- altered flag of the ## originDescription or a record CFG_OAI_PROVENANCE_ALTERED_SUBFIELD = t ## CFG_OAI_FAILED_HARVESTING_STOP_QUEUE -- when harvesting OAI sources ## fails, shall we report an error with the task and stop BibSched ## queue, or simply wait for the next run of the task? A value of 0 ## will stop the task upon errors, 1 will let the queue run if the ## next run of the oaiharvest task can safely recover the failure ## (this means that the queue will stop if the task is not set to run ## periodically) CFG_OAI_FAILED_HARVESTING_STOP_QUEUE = 1 ## CFG_OAI_FAILED_HARVESTING_EMAILS_ADMIN -- when ## CFG_OAI_FAILED_HARVESTING_STOP_QUEUE is set to leave the queue ## running upon errors, shall we send an email to admin to notify ## about the failure? CFG_OAI_FAILED_HARVESTING_EMAILS_ADMIN = True ## NOTE: the following parameters are experimenta ## ----------------------------------------------------------------------------- ## CFG_OAI_RIGHTS_FIELD -- MARC field dedicated to storing Copyright information CFG_OAI_RIGHTS_FIELD = 542__ ## CFG_OAI_RIGHTS_HOLDER_SUBFIELD -- MARC subfield dedicated to storing the ## Copyright holder information CFG_OAI_RIGHTS_HOLDER_SUBFIELD = d ## CFG_OAI_RIGHTS_DATE_SUBFIELD -- MARC subfield dedicated to storing the ## Copyright date information CFG_OAI_RIGHTS_DATE_SUBFIELD = g ## CFG_OAI_RIGHTS_URI_SUBFIELD -- MARC subfield dedicated to storing the URI ## (URL or URN, more detailed statement about copyright status) information CFG_OAI_RIGHTS_URI_SUBFIELD = u ## CFG_OAI_RIGHTS_CONTACT_SUBFIELD -- MARC subfield dedicated to storing the ## Copyright holder contact information CFG_OAI_RIGHTS_CONTACT_SUBFIELD = e ## CFG_OAI_RIGHTS_STATEMENT_SUBFIELD -- MARC subfield dedicated to storing the ## Copyright statement as presented on the resource CFG_OAI_RIGHTS_STATEMENT_SUBFIELD = f ## CFG_OAI_LICENSE_FIELD -- MARC field dedicated to storing terms governing ## use and reproduction (license) CFG_OAI_LICENSE_FIELD = 540__ ## CFG_OAI_LICENSE_TERMS_SUBFIELD -- MARC subfield dedicated to storing the ## Terms governing use and reproduction, e.g. CC License CFG_OAI_LICENSE_TERMS_SUBFIELD = a ## CFG_OAI_LICENSE_PUBLISHER_SUBFIELD -- MARC subfield dedicated to storing the ## person or institution imposing the license (author, publisher) CFG_OAI_LICENSE_PUBLISHER_SUBFIELD = b ## CFG_OAI_LICENSE_URI_SUBFIELD -- MARC subfield dedicated to storing the URI ## URI CFG_OAI_LICENSE_URI_SUBFIELD = u ##------------------------------------------------------------------------------ ################################### ## Part 5: BibDocFile parameters ## ################################### ## This section contains some configuration parameters for BibDocFile ## module. ## CFG_BIBDOCFILE_DOCUMENT_FILE_MANAGER_DOCTYPES -- this is the list of ## doctypes (like 'Main' or 'Additional') and their description that admins ## can choose from when adding new files via the Document File Manager ## admin interface. ## - When no value is provided, admins cannot add new ## file (they can only revise/delete/add format) ## - When a single value is given, it is used as ## default doctype for all new documents ## ## Order is relevant ## Eg: ## [('main', 'Main document'), ('additional', 'Figure, schema. etc')] CFG_BIBDOCFILE_DOCUMENT_FILE_MANAGER_DOCTYPES = [ ('Main', 'Main document'), ('LaTeX', 'LaTeX'), ('Source', 'Source'), ('Additional', 'Additional File'), ('Audio', 'Audio file'), ('Video', 'Video file'), ('Script', 'Script'), ('Data', 'Data'), ('Figure', 'Figure'), ('Schema', 'Schema'), ('Graph', 'Graph'), ('Image', 'Image'), ('Drawing', 'Drawing'), ('Slides', 'Slides')] ## CFG_BIBDOCFILE_DOCUMENT_FILE_MANAGER_RESTRICTIONS -- this is the ## list of restrictions (like 'Restricted' or 'No Restriction') and their ## description that admins can choose from when adding or revising files. ## Restrictions can then be configured at the level of WebAccess. ## - When no value is provided, no restriction is ## applied ## - When a single value is given, it is used as ## default resctriction for all documents. ## - The first value of the list is used as default ## restriction if the user if not given the ## choice of the restriction. Order is relevant ## ## Eg: ## [('', 'No restriction'), ('restr', 'Restricted')] CFG_BIBDOCFILE_DOCUMENT_FILE_MANAGER_RESTRICTIONS = [ ('', 'Public'), ('restricted', 'Restricted')] ## CFG_BIBDOCFILE_DOCUMENT_FILE_MANAGER_MISC -- set here the other ## default flags and attributes to tune the Document File Manager admin ## interface. ## See the docstring of bibdocfile_managedocfiles.create_file_upload_interface ## to have a description of the available parameters and their syntax. ## In general you will rarely need to change this variable. CFG_BIBDOCFILE_DOCUMENT_FILE_MANAGER_MISC = { 'can_revise_doctypes': ['*'], 'can_comment_doctypes': ['*'], 'can_describe_doctypes': ['*'], 'can_delete_doctypes': ['*'], 'can_keep_doctypes': ['*'], 'can_rename_doctypes': ['*'], 'can_add_format_to_doctypes': ['*'], 'can_restrict_doctypes': ['*'], } ## CFG_BIBDOCFILE_FILESYSTEM_BIBDOC_GROUP_LIMIT -- the fulltext ## documents are stored under "/opt/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_BIBDOCFILE_FILESYSTEM_BIBDOC_GROUP_LIMIT = 5000 ## CFG_BIBDOCFILE_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_BIBDOCFILE_ADDITIONAL_KNOWN_FILE_EXTENSIONS = hpg,link,lis,llb,mat,mpp,msg,docx,docm,xlsx,xlsm,xlsb,pptx,pptm,ppsx,ppsm ## CFG_BIBDOCFILE_DESIRED_CONVERSIONS -- a dictionary having as keys ## a format and as values the corresponding list of desired converted ## formats. CFG_BIBDOCFILE_DESIRED_CONVERSIONS = { 'pdf' : ('pdf;pdfa', ), 'ps.gz' : ('pdf;pdfa', ), 'djvu' : ('pdf', ), 'sxw': ('doc', 'odt', 'pdf;pdfa', ), 'docx' : ('doc', 'odt', 'pdf;pdfa', ), 'doc' : ('odt', 'pdf;pdfa', 'docx'), 'rtf' : ('pdf;pdfa', 'odt', ), 'odt' : ('pdf;pdfa', 'doc', ), 'pptx' : ('ppt', 'odp', 'pdf;pdfa', ), 'ppt' : ('odp', 'pdf;pdfa', 'pptx'), 'sxi': ('odp', 'pdf;pdfa', ), 'odp' : ('pdf;pdfa', 'ppt', ), 'xlsx' : ('xls', 'ods', 'csv'), 'xls' : ('ods', 'csv'), 'ods' : ('xls', 'xlsx', 'csv'), 'sxc': ('xls', 'xlsx', 'csv'), 'tiff' : ('pdf;pdfa', ), 'tif' : ('pdf;pdfa', ),} ## CFG_BIBDOCFILE_USE_XSENDFILE -- if your web server supports ## XSendfile header, you may want to enable this feature in order for ## to Invenio tell the web server to stream files for download (after ## proper authorization checks) by web server's means. This helps to ## liberate Invenio worker processes from being busy with sending big ## files to clients. The web server will take care of that. Note: ## this feature is still somewhat experimental. Note: when enabled ## (set to 1), then you have to also regenerate Apache vhost conf ## snippets (inveniocfg --update-config-py --create-apache-conf). CFG_BIBDOCFILE_USE_XSENDFILE = 0 ## CFG_BIBDOCFILE_MD5_CHECK_PROBABILITY -- a number between 0 and ## 1 that indicates probability with which MD5 checksum will be ## verified when streaming bibdocfile-managed files. (0.1 will cause ## the check to be performed once for every 10 downloads) CFG_BIBDOCFILE_MD5_CHECK_PROBABILITY = 0.1 ## CFG_BIBDOCFILE_BEST_FORMATS_TO_EXTRACT_TEXT_FROM -- a comma-separated ## list of document extensions in decrescent order of preference ## to suggest what is considered the best format to extract text from. CFG_BIBDOCFILE_BEST_FORMATS_TO_EXTRACT_TEXT_FROM = ('txt', 'html', 'xml', 'odt', 'doc', 'docx', 'djvu', 'pdf', 'ps', 'ps.gz') ## CFG_BIBDOCFILE_ENABLE_BIBDOCFSINFO_CACHE -- whether to use the ## database table bibdocfsinfo as reference for filesystem ## information. The default is 0. Switch this to 1 ## after you have run bibdocfile --fix-bibdocfsinfo-cache ## or on an empty system. CFG_BIBDOCFILE_ENABLE_BIBDOCFSINFO_CACHE = 0 ## CFG_OPENOFFICE_SERVER_HOST -- the host where an OpenOffice Server is ## listening to. If localhost an OpenOffice server will be started ## automatically if it is not already running. ## Note: if you set this to an empty value this will disable the usage of ## OpenOffice for converting documents. ## If you set this to something different than localhost you'll have to take ## care to have an OpenOffice server running on the corresponding host and ## to install the same OpenOffice release both on the client and on the server ## side. ## In order to launch an OpenOffice server on a remote machine, just start ## the usual 'soffice' executable in this way: ## $> soffice -headless -nologo -nodefault -norestore -nofirststartwizard \ ## .. -accept=socket,host=HOST,port=PORT;urp;StarOffice.ComponentContext CFG_OPENOFFICE_SERVER_HOST = localhost ## CFG_OPENOFFICE_SERVER_PORT -- the port where an OpenOffice Server is ## listening to. CFG_OPENOFFICE_SERVER_PORT = 2002 ## CFG_OPENOFFICE_USER -- the user that will be used to launch the OpenOffice ## client. It is recommended to set this to a user who don't own files, like ## e.g. 'nobody'. You should also authorize your Apache server user to be ## able to become this user, e.g. by adding to your /etc/sudoers the following ## line: ## "apache ALL=(nobody) NOPASSWD: ALL" ## provided that apache is the username corresponding to the Apache user. ## On some machine this might be apache2 or www-data. CFG_OPENOFFICE_USER = nobody ################################# ## 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 = 1 ## 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 ## CFG_BIBINDEX_PERFORM_OCR_ON_DOCNAMES -- regular expression that matches ## docnames for which OCR is desired (set this to .* in order to enable ## OCR in general, set this to empty in order to disable it.) CFG_BIBINDEX_PERFORM_OCR_ON_DOCNAMES = scan-.* ## CFG_BIBINDEX_SPLASH_PAGES -- key-value mapping where the key corresponds ## to a regular expression that matches the URLs of the splash pages of ## a given service and the value is a regular expression of the set of URLs ## referenced via tags in the HTML content of the splash pages that are ## referring to documents that need to be indexed. ## NOTE: for backward compatibility reasons you can set this to a simple ## regular expression that will directly be used as the unique key of the ## map, with corresponding value set to ".*" (in order to match any URL) CFG_BIBINDEX_SPLASH_PAGES = { "http://documents\.cern\.ch/setlink\?.*": ".*", "http://ilcagenda\.linearcollider\.org/subContributionDisplay\.py\?.*|http://ilcagenda\.linearcollider\.org/contributionDisplay\.py\?.*": "http://ilcagenda\.linearcollider\.org/getFile\.py/access\?.*|http://ilcagenda\.linearcollider\.org/materialDisplay\.py\?.*", } ## CFG_BIBINDEX_AUTHOR_WORD_INDEX_EXCLUDE_FIRST_NAMES -- do we want ## the author word index to exclude first names to keep only last ## names? If set to True, then for the author `Bernard, Denis', only ## `Bernard' will be indexed in the word index, not `Denis'. Note ## that if you change this variable, you have to re-index the author ## index via `bibindex -w author -R'. CFG_BIBINDEX_AUTHOR_WORD_INDEX_EXCLUDE_FIRST_NAMES = False ## CFG_BIBINDEX_SYNONYM_KBRS -- defines which knowledge bases are to ## be used for which index in order to provide index-time synonym ## lookup, and what massaging function should be used upon search ## pattern before performing the KB lookup. (Can be one of `exact', ## 'leading_to_comma', `leading_to_number'.) CFG_BIBINDEX_SYNONYM_KBRS = { 'global': ['INDEX-SYNONYM-TITLE', 'exact'], 'title': ['INDEX-SYNONYM-TITLE', 'exact'], } ####################################### ## 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. When 5, then the same as 4 ## applies, plus info about how to get an account is hidden from the ## login page. 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 ## CFG_WEBSESSION_IPADDR_CHECK_SKIP_BITS -- to prevent session cookie ## stealing, Invenio checks that the IP address of a connection is the ## same as that of the connection which created the initial session. ## This variable let you decide how many bits should be skipped during ## this check. Set this to 0 in order to enable full IP address ## checking. Set this to 32 in order to disable IP address checking. ## Intermediate values (say 8) let you have some degree of security so ## that you can trust your local network only while helping to solve ## issues related to outside clients that configured their browser to ## use a web proxy for HTTP connection but not for HTTPS, thus ## potentially having two different IP addresses. In general, if use ## HTTPS in order to serve authenticated content, you can safely set ## CFG_WEBSESSION_IPADDR_CHECK_SKIP_BITS to 32. CFG_WEBSESSION_IPADDR_CHECK_SKIP_BITS = 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? (0=no | 1=classic/gnuplot | 2=flot) 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? (0=no | 1=classic/gnuplot | 2=flot) 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? (0=no | 1=classic/gnuplot | 2=flot) CFG_BIBRANK_SHOW_CITATION_GRAPHS = 1 ## CFG_BIBRANK_SELFCITES_USE_BIBAUTHORID -- use authorids for computing ## self-citations ## falls back to hashing the author string CFG_BIBRANK_SELFCITES_USE_BIBAUTHORID = 0 ## CFG_BIBRANK_SELFCITES_PRECOMPUTE -- use precomputed self-citations ## when displaying itesummary. Precomputing citations allows use to ## speed up things CFG_BIBRANK_SELFCITES_PRECOMPUTE = 0 #################################### ## 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 ## CFG_WEBCOMMENT_ALERT_ENGINE_EMAIL -- the email address from which the ## alert emails will appear to be sent: CFG_WEBCOMMENT_ALERT_ENGINE_EMAIL = info@invenio-software.org ## CFG_WEBCOMMENT_DEFAULT_MODERATOR -- if no rules are ## specified to indicate who is the comment moderator of ## a collection, this person will be used as default CFG_WEBCOMMENT_DEFAULT_MODERATOR = info@invenio-software.org ## CFG_WEBCOMMENT_USE_MATHJAX_IN_COMMENTS -- do we want to allow the use ## of MathJax plugin to render latex input in comments? CFG_WEBCOMMENT_USE_MATHJAX_IN_COMMENTS = 1 ## CFG_WEBCOMMENT_AUTHOR_DELETE_COMMENT_OPTION -- allow comment author to ## delete its own comment? CFG_WEBCOMMENT_AUTHOR_DELETE_COMMENT_OPTION = 1 # CFG_WEBCOMMENT_EMAIL_REPLIES_TO -- which field of the record define # email addresses that should be notified of newly submitted comments, # and for which collection. Use collection names as keys, and list of # tags as values CFG_WEBCOMMENT_EMAIL_REPLIES_TO = { 'Articles': ['506__d', '506__m'], } # CFG_WEBCOMMENT_RESTRICTION_DATAFIELD -- which field of the record # define the restriction (must be linked to WebAccess # 'viewrestrcomment') to apply to newly submitted comments, and for # which collection. Use collection names as keys, and one tag as value CFG_WEBCOMMENT_RESTRICTION_DATAFIELD = { 'Articles': '5061_a', 'Pictures': '5061_a', 'Theses': '5061_a', } # CFG_WEBCOMMENT_ROUND_DATAFIELD -- which field of the record define # the current round of comment for which collection. Use collection # name as key, and one tag as value CFG_WEBCOMMENT_ROUND_DATAFIELD = { 'Articles': '562__c', 'Pictures': '562__c', } # CFG_WEBCOMMENT_MAX_ATTACHMENT_SIZE -- max file size per attached # file, in bytes. Choose 0 if you don't want to limit the size CFG_WEBCOMMENT_MAX_ATTACHMENT_SIZE = 5242880 # CFG_WEBCOMMENT_MAX_ATTACHED_FILES -- maxium number of files that can # be attached per comment. Choose 0 if you don't want to limit the # number of files. File uploads can be restricted with action # "attachcommentfile". CFG_WEBCOMMENT_MAX_ATTACHED_FILES = 5 # CFG_WEBCOMMENT_MAX_COMMENT_THREAD_DEPTH -- how many levels of # indentation discussions can be. This can be used to ensure that # discussions will not go into deep levels of nesting if users don't # understand the difference between "reply to comment" and "add # comment". When the depth is reached, any "reply to comment" is # conceptually converted to a "reply to thread" (i.e. reply to this # parent's comment). Use -1 for no limit, 0 for unthreaded (flat) # discussions. CFG_WEBCOMMENT_MAX_COMMENT_THREAD_DEPTH = 1 ################################## ## 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 = /usr/bin/less ## CFG_BIBSCHED_EDITOR -- what editor to use to edit the marcxml ## code of the locked records CFG_BIBSCHED_EDITOR = /usr/bin/vim ## 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,oairepositoryupdater ## 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 = ## CFG_BIBSCHED_NODE_TASKS -- specific nodes may be configured to ## run only specific tasks; if you want this, then this variable is a ## dictionary of the form {'hostname1': ['task1', 'task2']}. The ## default is that any node can run any task. CFG_BIBSCHED_NODE_TASKS = {} ## CFG_BIBSCHED_MAX_ARCHIVED_ROWS_DISPLAY -- number of tasks displayed ## CFG_BIBSCHED_MAX_ARCHIVED_ROWS_DISPLAY = 500 ################################### ## 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 = info@invenio-software.org ## 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_USE_SQLALCHEMY -- whether to use SQLAlchemy.pool ## in the DB engine of 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 ## CFG_MISCUTIL_SMTP_USER -- which username to use on the outgoing mail server ## defined in CFG_MISCUTIL_SMTP_HOST. If either CFG_MISCUTIL_SMTP_USER or ## CFG_MISCUTIL_SMTP_PASS are empty Invenio won't attempt authentication. CFG_MISCUTIL_SMTP_USER = ## CFG_MISCUTIL_SMTP_PASS -- which password to use on the outgoing mail ## server defined in CFG_MISCUTIL_SMTP_HOST. If either CFG_MISCUTIL_SMTP_USER ## or CFG_MISCUTIL_SMTP_PASS are empty Invenio won't attempt authentication. CFG_MISCUTIL_SMTP_PASS = ## CFG_MISCUTIL_SMTP_TLS -- whether to use a TLS (secure) connection when ## talking to the SMTP server defined in CFG_MISCUTIL_SMTP_HOST. CFG_MISCUTIL_SMTP_TLS = False ## CFG_MISCUTILS_DEFAULT_PROCESS_TIMEOUT -- the default number of seconds after ## which a process launched trough shellutils.run_process_with_timeout will ## be killed. This is useful to catch runaway processes. CFG_MISCUTIL_DEFAULT_PROCESS_TIMEOUT = 300 ## CFG_MATHJAX_HOSTING -- if you plan to use MathJax to display TeX ## formulas on HTML web pages, you can specify whether you wish to use ## 'local' hosting or 'cdn' hosting of MathJax libraries. (If set to ## 'local', you have to run 'make install-mathjax-plugin' as described ## in the INSTALL guide.) If set to 'local', users will use your site ## to download MathJax sources. If set to 'cdn', users will use ## centralized MathJax CDN servers instead. Please note that using ## CDN is suitable only for small institutions or for MathJax ## sponsors; see the MathJax website for more details. (Also, please ## note that if you plan to use MathJax on your site, you have to ## adapt CFG_WEBSEARCH_USE_MATHJAX_FOR_FORMATS and ## CFG_WEBCOMMENT_USE_MATHJAX_IN_COMMENTS configuration variables ## elsewhere in this file.) CFG_MATHJAX_HOSTING = local ################################# ## 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 = ## CFG_BIBEDIT_QUEUE_CHECK_METHOD -- how do we want to check for ## possible queue locking situations to prevent cataloguers from ## editing a record that may be waiting in the queue? Use 'bibrecord' ## for exact checking (always works, but may be slow), use 'regexp' ## for regular expression based checking (very fast, but may be ## inaccurate). When unsure, use 'bibrecord'. CFG_BIBEDIT_QUEUE_CHECK_METHOD = bibrecord ## CFG_BIBEDIT_EXTEND_RECORD_WITH_COLLECTION_TEMPLATE -- a dictionary ## containing which collections will be extended with a given template ## while being displayed in BibEdit UI. CFG_BIBEDIT_EXTEND_RECORD_WITH_COLLECTION_TEMPLATE = { 'Poetry' : 'poem'} ## CFG_BIBEDIT_KB_SUBJECTS - Name of the KB used in the field 65017a ## to automatically convert codes into extended version. e.g ## a - Astrophysics CFG_BIBEDIT_KB_SUBJECTS = Subjects ## CFG_BIBEDIT_KB_INSTITUTIONS - Name of the KB used for institution ## autocomplete. To be applied in fields defined in ## CFG_BIBEDIT_AUTOCOMPLETE_INSTITUTIONS_FIELDS CFG_BIBEDIT_KB_INSTITUTIONS = InstitutionsCollection ## CFG_BIBEDIT_AUTOCOMPLETE_INSTITUTIONS_FIELDS - list of fields to ## be autocompleted with the KB CFG_BIBEDIT_KB_INSTITUTIONS CFG_BIBEDIT_AUTOCOMPLETE_INSTITUTIONS_FIELDS = 100__u,700__u,701__u,502__c ## CFG_BIBEDITMULTI_LIMIT_INSTANT_PROCESSING -- maximum number of records ## that can be modified instantly using the multi-record editor. Above ## this limit, modifications will only be executed in limited hours. CFG_BIBEDITMULTI_LIMIT_INSTANT_PROCESSING = 2000 ## CFG_BIBEDITMULTI_LIMIT_DELAYED_PROCESSING -- maximum number of records ## that can be send for modification without having a superadmin role. ## If the number of records is between CFG_BIBEDITMULTI_LIMIT_INSTANT_PROCESSING ## and this number, the modifications will take place only in limited hours. CFG_BIBEDITMULTI_LIMIT_DELAYED_PROCESSING = 20000 ## CFG_BIBEDITMULTI_LIMIT_DELAYED_PROCESSING_TIME -- Allowed time to ## execute modifications on records, when the number exceeds ## CFG_BIBEDITMULTI_LIMIT_INSTANT_PROCESSING. CFG_BIBEDITMULTI_LIMIT_DELAYED_PROCESSING_TIME = 22:00-05:00 ################################### ## 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_FFT_ALLOWED_EXTERNAL_URLS -- a dictionary containing ## external URLs that can be accessed by Invenio and specific HTTP ## headers that will be used for each URL. The keys of the dictionary ## are regular expressions matching a set of URLs, the values are ## dictionaries of headers as consumed by urllib2.Request. If a ## regular expression matching all URLs is created at the end of the ## list, it means that Invenio will download all URLs. Otherwise ## Invenio will just download authorized URLs. Note: by default, a ## User-Agent built after the current Invenio version, site name, and ## site URL will be used. The values of the header dictionary can ## also contain a call to a python function, in the form of a ## disctionary with two entries: the name of the function to be called ## as a value for the 'fnc' key, and the arguments to this function, ## as a value for the 'args' key (in the form of a dictionary). ## CFG_BIBUPLOAD_FFT_ALLOWED_EXTERNAL_URLS = [ ## ('http://myurl.com/.*', {'User-Agent': 'Me'}), ## ('http://yoururl.com/.*', {'User-Agent': 'You', 'Accept': 'text/plain'}), ## ('http://thisurl.com/.*', {'Cookie': {'fnc':'read_cookie', 'args':{'cookiefile':'/tmp/cookies.txt'}}}) ## ('http://.*', {'User-Agent': 'Invenio'}), ## ] CFG_BIBUPLOAD_FFT_ALLOWED_EXTERNAL_URLS = [ ('http(s)?://.*', {}), ] ## 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/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 ## CFG_BIBUPLOAD_DELETE_FORMATS -- which formats do we want bibupload ## to delete when a record is ingested? Enter comma-separated list of ## formats. For example, 'hb,hd' will delete pre-formatted HTML brief ## and defailed formats from cache, so that search engine will ## generate them on-the-fly. Useful to always present latest data of ## records upon record display, until the periodical bibreformat job ## runs next and updates the cache. CFG_BIBUPLOAD_DELETE_FORMATS = hb ## CFG_BATCHUPLOADER_FILENAME_MATCHING_POLICY -- a comma-separated list ## indicating which fields match the file names of the documents to be ## uploaded. ## The matching will be done in the same order as the list provided. CFG_BATCHUPLOADER_FILENAME_MATCHING_POLICY = reportnumber,recid ## CFG_BATCHUPLOADER_DAEMON_DIR -- Directory where the batchuploader daemon ## will look for the subfolders metadata and document by default. ## If path is relative, CFG_PREFIX will be joined as a prefix CFG_BATCHUPLOADER_DAEMON_DIR = var/batchupload ## CFG_BATCHUPLOADER_WEB_ROBOT_AGENTS -- Regular expression to specify the ## agents permitted when calling batch uploader web interface ## cds.cern.ch/batchuploader/robotupload ## if using a curl, eg: curl xxx -A invenio CFG_BATCHUPLOADER_WEB_ROBOT_AGENTS = invenio_webupload|Invenio-.* ## CFG_BATCHUPLOADER_WEB_ROBOT_RIGHTS -- Access list specifying for each ## IP address, which collections are allowed using batch uploader robot ## interface. CFG_BATCHUPLOADER_WEB_ROBOT_RIGHTS = { '127.0.0.1': ['*'], # useful for testing '127.0.1.1': ['*'], # useful for testing '10.0.0.1': ['BOOK', 'REPORT'], # Example 1 '10.0.0.2': ['POETRY', 'PREPRINT'], # Example 2 } #################################### ## Part 18: BibCatalog parameters ## #################################### ## CFG_BIBCATALOG_SYSTEM -- set desired catalog system. For example, RT. CFG_BIBCATALOG_SYSTEM = ## RT CONFIGURATION ## CFG_BIBCATALOG_SYSTEM_RT_CLI -- path to the RT CLI client CFG_BIBCATALOG_SYSTEM_RT_CLI = /usr/bin/rt ## CFG_BIBCATALOG_SYSTEM_RT_URL -- Base URL of the remote RT system CFG_BIBCATALOG_SYSTEM_RT_URL = http://localhost/rt3 ## CFG_BIBCATALOG_SYSTEM_RT_DEFAULT_USER -- Set the username for a default RT account ## on remote system, with limited privileges, in order to only create and modify own tickets. CFG_BIBCATALOG_SYSTEM_RT_DEFAULT_USER = ## CFG_BIBCATALOG_SYSTEM_RT_DEFAULT_PWD -- Set the password for the default RT account ## on remote system. CFG_BIBCATALOG_SYSTEM_RT_DEFAULT_PWD = #################################### ## Part 19: BibFormat parameters ## #################################### ## CFG_BIBFORMAT_HIDDEN_TAGS -- comma-separated list of MARC tags that ## are not shown to users not having cataloging authorizations. CFG_BIBFORMAT_HIDDEN_TAGS = 595 ## CFG_BIBFORMAT_HIDDEN_FILE_FORMATS -- comma-separated list of file formats ## that are not shown explicitly to user not having cataloging authorizations. ## e.g. pdf;pdfa,xml CFG_BIBFORMAT_HIDDEN_FILE_FORMATS = ## CFG_BIBFORMAT_ADDTHIS_ID -- if you want to use the AddThis service from ## , set this value to the pubid parameter as ## provided by the service (e.g. ra-4ff80aae118f4dad), and add a call to ## formatting element in your formats, for example ## Default_HTML_detailed.bft. CFG_BIBFORMAT_ADDTHIS_ID = ## CFG_BIBFORMAT_DISABLE_I18N_FOR_CACHED_FORMATS -- For each output ## format BibReformat currently creates a cache for only one language ## (CFG_SITE_LANG) per record. This means that visitors having set a ## different language than CFG_SITE_LANG will be served an on-the-fly ## output using the language of their choice. You can disable this ## behaviour by specifying below for which output format you would ## like to force the cache to be used whatever language is ## requested. If your format templates do not provide ## internationalization, you can optimize your site by setting for ## eg. hb,hd to always serve the precached output (if it exists) in ## the CFG_SITE_LANG CFG_BIBFORMAT_DISABLE_I18N_FOR_CACHED_FORMATS = #################################### ## Part 20: BibMatch parameters ## #################################### ## CFG_BIBMATCH_LOCAL_SLEEPTIME -- Determines the amount of seconds to sleep ## between search queries on LOCAL system. CFG_BIBMATCH_LOCAL_SLEEPTIME = 0.0 ## CFG_BIBMATCH_REMOTE_SLEEPTIME -- Determines the amount of seconds to sleep ## between search queries on REMOTE systems. CFG_BIBMATCH_REMOTE_SLEEPTIME = 2.0 ## CFG_BIBMATCH_FUZZY_WORDLIMITS -- Determines the amount of words to extract ## from a certain fields value during fuzzy matching mode. Add/change field ## and appropriate number to the dictionary to configure this. CFG_BIBMATCH_FUZZY_WORDLIMITS = { '100__a': 2, '245__a': 4 } ## CFG_BIBMATCH_FUZZY_EMPTY_RESULT_LIMIT -- Determines the amount of empty results ## to accept during fuzzy matching mode. CFG_BIBMATCH_FUZZY_EMPTY_RESULT_LIMIT = 1 ## CFG_BIBMATCH_QUERY_TEMPLATES -- Here you can set the various predefined querystrings ## used to standardize common matching queries. By default the following templates ## are given: ## title - standard title search. Taken from 245__a (default) ## title-author - title and author search (i.e. this is a title AND author a) ## Taken from 245__a and 100__a ## reportnumber - reportnumber search (i.e. reportnumber:REP-NO-123). CFG_BIBMATCH_QUERY_TEMPLATES = { 'title' : '[title]', 'title-author' : '[title] [author]', 'reportnumber' : 'reportnumber:[reportnumber]' } ## CFG_BIBMATCH_MATCH_VALIDATION_RULESETS -- Here you can define the various rulesets for ## validating search results done by BibMatch. Each ruleset contains a certain pattern mapped ## to a tuple defining a "matching-strategy". ## ## The rule-definitions must come in two parts: ## ## * The first part is a string containing a regular expression ## that is matched against the textmarc representation of each record. ## If a match is found, the final rule-set is updated with ## the given "sub rule-set", where identical tag rules are replaced. ## ## * The second item is a list of key->value mappings (dict) that indicates specific ## strategy parameters with corresponding validation rules. ## ## This strategy consists of five items: ## ## * MARC TAGS: ## These MARC tags represents the fields taken from original record and any records from search ## results. When several MARC tags are specified with a given match-strategy, all the fields ## associated with these tags are matched together (i.e. with key "100__a,700__a", all 100__a ## and 700__a fields are matched together. Which is useful when first-author can vary for ## certain records on different systems). ## ## * COMPARISON THRESHOLD: ## a value between 0.0 and 1.0 specifying the threshold for string matches ## to determine if it is a match or not (using normalized string-distance). ## Normally 0.8 (80% match) is considered to be a close match. ## ## * COMPARISON MODE: ## the parse mode decides how the record datafields are compared: ## - 'strict' : all (sub-)fields are compared, and all must match. Order is significant. ## - 'normal' : all (sub-)fields are compared, and all must match. Order is ignored. ## - 'lazy' : all (sub-)fields are compared with each other and at least one must match ## - 'ignored': the tag is ignored in the match. Used to disable previously defined rules. ## ## * MATCHING MODE: ## the comparison mode decides how the fieldvalues are matched: ## - 'title' : uses a method specialized for comparing titles, e.g. looking for subtitles ## - 'author' : uses a special authorname comparison. Will take initials into account. ## - 'identifier' : special matching for identifiers, stripping away punctuation ## - 'date': matches dates by extracting and comparing the year ## - 'normal': normal string comparison. ## Note: Fields are considered matching when all its subfields or values match. ## ## * RESULT MODE: ## the result mode decides how the results from the comparisons are handled further: ## - 'normal' : a failed match will cause the validation to immediately exit as a failure. ## a successful match will cause the validation to continue on other rules (if any) ## - 'final' : a failed match will cause the validation to immediately exit as a failure. ## a successful match will cause validation to immediately exit as a success. ## - 'joker' : a failed match will cause the validation to continue on other rules (if any). ## a successful match will cause validation to immediately exit as a success. ## ## You can add your own rulesets in the dictionary below. The 'default' ruleset is always applied, ## and should therefore NOT be removed, but can be changed. The tag-rules can also be overwritten ## by other rulesets. ## ## WARNING: Beware that the validation quality is only as good as given rules, so matching results ## are never guaranteed to be accurate, as it is very content-specific. CFG_BIBMATCH_MATCH_VALIDATION_RULESETS = [('default', [{ 'tags' : '245__%,242__%', 'threshold' : 0.8, 'compare_mode' : 'lazy', 'match_mode' : 'title', 'result_mode' : 'normal' }, { 'tags' : '037__a,088__a', 'threshold' : 1.0, 'compare_mode' : 'lazy', 'match_mode' : 'identifier', 'result_mode' : 'final' }, { 'tags' : '100__a,700__a', 'threshold' : 0.8, 'compare_mode' : 'normal', 'match_mode' : 'author', 'result_mode' : 'normal' }, { 'tags' : '773__a', 'threshold' : 1.0, 'compare_mode' : 'lazy', 'match_mode' : 'title', 'result_mode' : 'normal' }]), ('980__ \$\$a(THESIS|Thesis)', [{ 'tags' : '100__a', 'threshold' : 0.8, 'compare_mode' : 'strict', 'match_mode' : 'author', 'result_mode' : 'normal' }, { 'tags' : '700__a,701__a', 'threshold' : 1.0, 'compare_mode' : 'lazy', 'match_mode' : 'author', 'result_mode' : 'normal' }, { 'tags' : '100__a,700__a', 'threshold' : 0.8, 'compare_mode' : 'ignored', 'match_mode' : 'author', 'result_mode' : 'normal' }]), ('260__', [{ 'tags' : '260__c', 'threshold' : 0.8, 'compare_mode' : 'lazy', 'match_mode' : 'date', 'result_mode' : 'normal' }]), ('0247_', [{ 'tags' : '0247_a', 'threshold' : 1.0, 'compare_mode' : 'lazy', 'match_mode' : 'identifier', 'result_mode' : 'final' }]), ('020__', [{ 'tags' : '020__a', 'threshold' : 1.0, 'compare_mode' : 'lazy', 'match_mode' : 'identifier', 'result_mode' : 'joker' }]) ] ## CFG_BIBMATCH_FUZZY_MATCH_VALIDATION_LIMIT -- Determines the minimum percentage of the ## amount of rules to be positively matched when comparing two records. Should the number ## of matches be lower than required matches but equal to or above this limit, ## the match will be considered fuzzy. CFG_BIBMATCH_FUZZY_MATCH_VALIDATION_LIMIT = 0.65 ## CFG_BIBMATCH_SEARCH_RESULT_MATCH_LIMIT -- Determines the maximum amount of search results ## a single search can return before acting as a non-match. CFG_BIBMATCH_SEARCH_RESULT_MATCH_LIMIT = 15 ###################################### ## Part 21: BibAuthorID parameters ## ###################################### # CFG_BIBAUTHORID_MAX_PROCESSES is the max number of processes # that may be spawned by the disambiguation algorithm CFG_BIBAUTHORID_MAX_PROCESSES = 12 # CFG_BIBAUTHORID_PERSONID_SQL_MAX_THREADS is the max number of threads # to parallelize sql queries during personID tables updates CFG_BIBAUTHORID_PERSONID_SQL_MAX_THREADS = 12 # CFG_BIBAUTHORID_EXTERNAL_CLAIMED_RECORDS_KEY defines the user info # keys for externally claimed records in an remote-login scenario--e.g. from arXiv.org # e.g. "external_arxivids" for arXiv SSO CFG_BIBAUTHORID_EXTERNAL_CLAIMED_RECORDS_KEY = # CFG_BIBAUTHORID_AID_ENABLED # Globally enable AuthorID Interfaces. # If False: No guest, user or operator will have access to the system. CFG_BIBAUTHORID_ENABLED = True # CFG_BIBAUTHORID_AID_ON_AUTHORPAGES # Enable AuthorID information on the author pages. CFG_BIBAUTHORID_ON_AUTHORPAGES = True # CFG_BIBAUTHORID_AUTHOR_TICKET_ADMIN_EMAIL defines the eMail address # all ticket requests concerning authors will be sent to. CFG_BIBAUTHORID_AUTHOR_TICKET_ADMIN_EMAIL = info@invenio-software.org #CFG_BIBAUTHORID_UI_SKIP_ARXIV_STUB_PAGE defines if the optional arXive stub page is skipped CFG_BIBAUTHORID_UI_SKIP_ARXIV_STUB_PAGE = False ######################################### ## Part 22: BibCirculation parameters ## ######################################### ## CFG_BIBCIRCULATION_ITEM_STATUS_OPTIONAL -- comma-separated list of statuses # Example: missing, order delayed, not published # You can allways add a new status here, but you may want to run some script # to update the database if you remove some statuses. CFG_BIBCIRCULATION_ITEM_STATUS_OPTIONAL = ## Here you can edit the text of the statuses that have specific roles. # You should run a script to update the database if you change them after having # used the module for some time. ## Item statuses # The book is on loan CFG_BIBCIRCULATION_ITEM_STATUS_ON_LOAN = on loan # Available for loan CFG_BIBCIRCULATION_ITEM_STATUS_ON_SHELF = on shelf # The book is being processed by the library (cataloguing, etc.) CFG_BIBCIRCULATION_ITEM_STATUS_IN_PROCESS = in process # The book has been ordered (bought) CFG_BIBCIRCULATION_ITEM_STATUS_ON_ORDER = on order # The order of the book has been cancelled CFG_BIBCIRCULATION_ITEM_STATUS_CANCELLED = cancelled # The order of the book has not arrived yet CFG_BIBCIRCULATION_ITEM_STATUS_NOT_ARRIVED = not arrived # The order of the book has not arrived yet and has been claimed CFG_BIBCIRCULATION_ITEM_STATUS_CLAIMED = claimed ## Loan statuses # This status should not be confussed with CFG_BIBCIRCULATION_ITEM_STATUS_ON_LOAN. # If the item status is CFG_BIBCIRCULATION_ITEM_STATUS_ON_LOAN, then there is # a loan with status CFG_BIBCIRCULATION_LOAN_STATUS_ON_LOAN or # CFG_BIBCIRCULATION_LOAN_STATUS_EXPIRED. # For each copy, there can only be one active loan ('on loan' or 'expired') at # the time, since can be many 'returned' loans for the same copy. CFG_BIBCIRCULATION_LOAN_STATUS_ON_LOAN = on loan # The due date has come and the item has not been returned CFG_BIBCIRCULATION_LOAN_STATUS_EXPIRED = expired # The item has been returned. CFG_BIBCIRCULATION_LOAN_STATUS_RETURNED = returned ## Request statuses # There is at least one copy available, and this is the oldest request. CFG_BIBCIRCULATION_REQUEST_STATUS_PENDING = pending # There are no copies available, or there is another request with more priority. CFG_BIBCIRCULATION_REQUEST_STATUS_WAITING = waiting # The request has become a loan CFG_BIBCIRCULATION_REQUEST_STATUS_DONE = done # The request has been cancelled CFG_BIBCIRCULATION_REQUEST_STATUS_CANCELLED = cancelled # ILL request statuses CFG_BIBCIRCULATION_ILL_STATUS_NEW = new CFG_BIBCIRCULATION_ILL_STATUS_REQUESTED = requested CFG_BIBCIRCULATION_ILL_STATUS_ON_LOAN = on loan CFG_BIBCIRCULATION_ILL_STATUS_RETURNED = returned CFG_BIBCIRCULATION_ILL_STATUS_CANCELLED = cancelled CFG_BIBCIRCULATION_ILL_STATUS_RECEIVED = received # Acquisition statuses CFG_BIBCIRCULATION_ACQ_STATUS_NEW = new CFG_BIBCIRCULATION_ACQ_STATUS_ON_ORDER = on order CFG_BIBCIRCULATION_ACQ_STATUS_PARTIAL_RECEIPT = partial receipt CFG_BIBCIRCULATION_ACQ_STATUS_RECEIVED = received CFG_BIBCIRCULATION_ACQ_STATUS_CANCELLED = cancelled ## Library types # Normal library where you have your books. I can also be a depot. CFG_BIBCIRCULATION_LIBRARY_TYPE_INTERNAL = internal # external libraries for ILL. CFG_BIBCIRCULATION_LIBRARY_TYPE_EXTERNAL = external # The main library is also an internal library. # Since you may have several depots or small sites you can tag one of them as # the main site. CFG_BIBCIRCULATION_LIBRARY_TYPE_MAIN = main # It is also an internal library. The copies in this type of library will NOT # be displayed to borrowers. Use this for depots. CFG_BIBCIRCULATION_LIBRARY_TYPE_HIDDEN = hidden ## Amazon access key. You will need your own key. # Example: 1T6P5M3ZDMW9AWJ212R2 CFG_BIBCIRCULATION_AMAZON_ACCESS_KEY = ###################################### ## Part 22: BibClassify parameters ## ###################################### # CFG_BIBCLASSIFY_WEB_MAXKW -- maximum number of keywords to display # in the Keywords tab web page. CFG_BIBCLASSIFY_WEB_MAXKW = 100 ######################################## ## Part 23: Plotextractor parameters ## ######################################## ## CFG_PLOTEXTRACTOR_SOURCE_BASE_URL -- for acquiring source tarballs for plot ## extraction, where should we look? If nothing is set, we'll just go ## to arXiv, but this can be a filesystem location, too CFG_PLOTEXTRACTOR_SOURCE_BASE_URL = http://arxiv.org/ ## CFG_PLOTEXTRACTOR_SOURCE_TARBALL_FOLDER -- for acquiring source tarballs for plot ## extraction, subfolder where the tarballs sit CFG_PLOTEXTRACTOR_SOURCE_TARBALL_FOLDER = e-print/ ## CFG_PLOTEXTRACTOR_SOURCE_PDF_FOLDER -- for acquiring source tarballs for plot ## extraction, subfolder where the pdf sit CFG_PLOTEXTRACTOR_SOURCE_PDF_FOLDER = pdf/ ## CFG_PLOTEXTRACTOR_DOWNLOAD_TIMEOUT -- a float representing the number of seconds ## to wait between each download of pdf and/or tarball from source URL. CFG_PLOTEXTRACTOR_DOWNLOAD_TIMEOUT = 2.0 ## CFG_PLOTEXTRACTOR_CONTEXT_LIMIT -- when extracting context of plots from ## TeX sources, this is the limitation of characters in each direction to extract ## context from. Default 750. CFG_PLOTEXTRACTOR_CONTEXT_EXTRACT_LIMIT = 750 ## CFG_PLOTEXTRACTOR_DISALLOWED_TEX -- when extracting context of plots from TeX ## sources, this is the list of TeX tags that will trigger 'end of context'. CFG_PLOTEXTRACTOR_DISALLOWED_TEX = begin,end,section,includegraphics,caption,acknowledgements ## CFG_PLOTEXTRACTOR_CONTEXT_WORD_LIMIT -- when extracting context of plots from ## TeX sources, this is the limitation of words in each direction. Default 75. CFG_PLOTEXTRACTOR_CONTEXT_WORD_LIMIT = 75 ## CFG_PLOTEXTRACTOR_CONTEXT_SENTENCE_LIMIT -- when extracting context of plots from ## TeX sources, this is the limitation of sentences in each direction. Default 2. CFG_PLOTEXTRACTOR_CONTEXT_SENTENCE_LIMIT = 2 ###################################### ## Part 24: WebStat parameters ## ###################################### # CFG_WEBSTAT_BIBCIRCULATION_START_YEAR defines the start date of the BibCirculation # statistics. Value should have the format 'yyyy'. If empty, take all existing data. CFG_WEBSTAT_BIBCIRCULATION_START_YEAR = ###################################### ## Part 25: Web API Key parameters ## ###################################### # CFG_WEB_API_KEY_ALLOWED_URL defines the web apps that are going to use the web # API key. It has three values, the name of the web app, the time of life for the # secure url and if a time stamp is needed. #CFG_WEB_API_KEY_ALLOWED_URL = [('search/\?', 3600, True), # ('rss', 0, False)] CFG_WEB_API_KEY_ALLOWED_URL = [] ########################################## -## Part 25: WebAuthorProfile parameters ## +## Part 26: WebAuthorProfile parameters ## ########################################## #CFG_WEBAUTHORPROFILE_CACHE_EXPIRED_DELAY_LIVE consider a cached element expired after days #when loading an authorpage, thus recomputing the content live CFG_WEBAUTHORPROFILE_CACHE_EXPIRED_DELAY_LIVE = 7 #CFG_WEBAUTHORPROFILE_CACHE_EXPIRED_DELAY_BIBSCHED consider a cache element expired after days, #thus recompute it, bibsched daemon CFG_WEBAUTHORPROFILE_CACHE_EXPIRED_DELAY_BIBSCHED = 5 #CFG_WEBAUTHORPROFILE_MAX_COLLAB_LIST: limit collaboration list. #Set to 0 to disable limit. CFG_WEBAUTHORPROFILE_MAX_COLLAB_LIST = 100 #CFG_WEBAUTHORPROFILE_MAX_KEYWORD_LIST: limit keywords list #Set to 0 to disable limit. CFG_WEBAUTHORPROFILE_MAX_KEYWORD_LIST = 100 #CFG_WEBAUTHORPROFILE_MAX_AFF_LIST: limit affiliations list #Set to 0 to disable limit. CFG_WEBAUTHORPROFILE_MAX_AFF_LIST = 100 #CFG_WEBAUTHORPROFILE_MAX_COAUTHOR_LIST: limit coauthors list #Set to 0 to disable limit. CFG_WEBAUTHORPROFILE_MAX_COAUTHOR_LIST = 100 #CFG_WEBAUTHORPROFILE_MAX_HEP_CHOICES: limit HepRecords choices #Set to 0 to disable limit. CFG_WEBAUTHORPROFILE_MAX_HEP_CHOICES = 10 #CFG_WEBAUTHORPROFILE_USE_BIBAUTHORID: use bibauthorid or exactauthor CFG_WEBAUTHORPROFILE_USE_BIBAUTHORID = False #################################### -## Part 25: BibSort parameters ## +## Part 27: BibSort parameters ## #################################### ## CFG_BIBSORT_BUCKETS -- the number of buckets bibsort should use. ## If 0, then no buckets will be used (bibsort will be inactive). ## If different from 0, bibsort will be used for sorting the records. ## The number of buckets should be set with regards to the size ## of the repository; having a larger number of buckets will increase ## the sorting performance for the top results but will decrease ## the performance for sorting the middle results. ## We recommend to to use 1 in case you have less than about ## 1,000,000 records. ## When modifying this variable, re-run rebalancing for all the bibsort ## methods, for having the database in synch. CFG_BIBSORT_BUCKETS = 1 ######################################## -## Part 25: JsTestDriver parameters ## +## Part 28: JsTestDriver parameters ## ######################################## ## CFG_JSTESTDRIVER_PORT -- server port where JS tests will be run. CFG_JSTESTDRIVER_PORT = 9876 ############################ -## Part 26: RefExtract ## +## Part 29: RefExtract ## ############################ ## Refextract can automatically submit tickets (after extracting refereces) ## to CFG_REFEXTRACT_TICKET_QUEUE if it is set CFG_REFEXTRACT_TICKET_QUEUE = None ## Override refextract kbs locations CFG_REFEXTRACT_KBS_OVERRIDE = {} ################################## ## Part 27: CrossRef parameters ## ################################## ## CFG_CROSSREF_USERNAME -- the username used when sending request ## to the Crossref site. CFG_CROSSREF_USERNAME = ## CFG_CROSSREF_PASSWORD -- the password used when sending request ## to the Crossref site. CFG_CROSSREF_PASSWORD = +#################################### +## Part 30: WebLinkback parameters ## +#################################### + +## CFG_WEBLINKBACK_TRACKBACK_ENABLED -- whether to enable trackback support +## 1 to enable, 0 to disable it +CFG_WEBLINKBACK_TRACKBACK_ENABLED = 0 + ########################## ## THAT's ALL, FOLKS! ## ########################## diff --git a/modules/bibsched/lib/tasklets/bst_weblinkback_updater.py b/modules/bibsched/lib/tasklets/bst_weblinkback_updater.py index b5d87b940..ab2a55ca9 100644 --- a/modules/bibsched/lib/tasklets/bst_weblinkback_updater.py +++ b/modules/bibsched/lib/tasklets/bst_weblinkback_updater.py @@ -1,55 +1,62 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2011, 2012, 2013 CERN. ## ## 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. ## ## 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. from invenio.bibtask import write_message +from invenio.weblinkback_config import CFG_WEBLINKBACK_TYPE from invenio.weblinkback import update_linkbacks, \ - delete_linkbacks_on_blacklist + delete_linkbacks_on_blacklist, \ + send_pending_linkbacks_notification def bst_weblinkback_updater(mode): """ Update linkbacks @param mode: 1 delete rejected, broken and pending linkbacks whose URLs is on blacklist 2 update page titles of new linkbacks 3 update page titles of old linkbacks 4 update manually set page titles 5 detect and disable broken linkbacks + 6 send notification email for all pending linkbacks @type mode: int """ mode = int(mode) if mode == 1: write_message("Starting to delete rejected and pending linkbacks URLs on blacklist") delete_linkbacks_on_blacklist() write_message("Completed to delete rejected and pending linkbacks URLs on blacklist") elif mode == 2: write_message("Starting to update the page titles of new linkbacks") update_linkbacks(1) write_message("Completed to update the page titles of new linkbacks") elif mode == 3: write_message("Starting to update the page titles of old linkbacks") update_linkbacks(2) write_message("Completed to update the page titles of old linkbacks") elif mode == 4: write_message("Starting to update manually set page titles") update_linkbacks(3) write_message("Completed to update manually set page titles") elif mode == 5: write_message("Starting to detect and disable broken linkbacks") update_linkbacks(4) write_message("Completed to detect and disable broken linkbacks") + elif mode == 6: + write_message("Starting to send notification email") + send_pending_linkbacks_notification(CFG_WEBLINKBACK_TYPE['TRACKBACK']) + write_message("Completed to send notification email") diff --git a/modules/webhelp/web/admin/howto/howto-run.webdoc b/modules/webhelp/web/admin/howto/howto-run.webdoc index 9c7e4923f..2e10f1a71 100644 --- a/modules/webhelp/web/admin/howto/howto-run.webdoc +++ b/modules/webhelp/web/admin/howto/howto-run.webdoc @@ -1,329 +1,341 @@ ## This file is part of Invenio. -## Copyright (C) 2007, 2008, 2009, 2010, 2011 CERN. +## Copyright (C) 2007, 2008, 2009, 2010, 2011, 2013 CERN. ## ## 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. ## ## 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

Overview

This HOWTO guide intends to give you ideas on how to run your CDS Invenio installation and how to take care of its normal day-to-day operation.

Setting up periodical daemon tasks

Many tasks that manipulate the bibliographic record database can be set to run in a periodical mode. For example, we want to have the indexing engine to scan periodically for newly arrived documents to index them as soon as they enter into the system. It is the role of the BibSched system to take care of the task scheduling and the task execution.

Periodical tasks (such as regular metadata indexing) as well as one-time tasks (such as a batch upload of newly acquired metadata file) are not executed straight away but are stored in the BibSched task queue. BibSched daemon looks periodically in the queue and launches the tasks according to their order or the date of programmed runtime. You can consider BibSched to be a kind of cron daemon for bibliographic tasks.

This means that after having installed Invenio you will want to have the BibSched daemon running permanently. To launch BibSched daemon, do:

  $ bibsched start
 

To setup indexing, ranking, sorting, formatting, and collection cache updating daemons to run periodically with a sleeping period of, say, 5 minutes:

 $ bibindex -f50000 -s5m
 $ bibreformat -oHB -s5m
 $ webcoll -v0 -s5m
 $ bibrank -f50000 -s5m
 $ bibsort -s5m
 

It is imperative to have the above five tasks permanently in your BibSched queue so that newly submitted documents will be processed automatically.

You may also want to set up some periodical housekeeping tasks:

 $ bibrank -f50000 -R -wwrd -s14d -LSunday
 $ bibsort -R -s7d -L 'Sunday 01:00-05:00'
 $ inveniogc -a -s7d -L 'Sunday 01:00-05:00'
 $ dbdump -s20h -L '22:00-06:00' -o/opt2/mysql-backups -n10
 

Please consult the sections below for more details about these housekeeping tasks.

There is also the possibility to setup the batch uploader daemon to run periodically, looking for new documents or metadata files to upload:

 $ batchuploader --documents -s20m
 $ batchuploader --metadata -s20m
 

Additionally you might want to automatically generate sitemap.xml files for your installation. For this just schedule:

 $ bibexport -w sitemap -s1d
 
You will then need to add a line such as:
 Sitemap: /sitemap-index.xml.gz
 
to your robots.txt file.

-

If you are using the WebLinkback module, you should run the following tasklets: +

If you are using the WebLinkback module, you may want to run some of the following tasklets:

+# Delete rejected, broken and pending linkbacks whose URLs is on blacklist
 sudo -u www-data /opt/invenio/bin/bibtasklet \
      -N weblinkbackupdaterdeleteurlsonblacklist \
      -T bst_weblinkback_updater \
      -a "mode=1" \
      -u admin -s1d -L '22:00-05:00'
 
+# Update page titles of new linkbacks
 sudo -u www-data /opt/invenio/bin/bibtasklet \
      -N weblinkbackupdaternewpages \
      -T bst_weblinkback_updater \
      -a "mode=2" \
      -u admin -s1d -L '22:00-05:00'
 
+# Update page titles of old linkbacks
 sudo -u www-data /opt/invenio/bin/bibtasklet \
      -N weblinkbackupdateroldpages \
      -T bst_weblinkback_updater \
      -a "mode=3" \
      -u admin -s7d -L '22:00-05:00'
 
+# Update manually set page titles
 sudo -u www-data /opt/invenio/bin/bibtasklet \
      -N weblinkbackupdatermanuallysettitles \
      -T bst_weblinkback_updater \
      -a "mode=4" \
      -u admin -s7d -L '22:00-05:00'
 
+# Detect and disable broken linkbacks
 sudo -u www-data /opt/invenio/bin/bibtasklet \
      -N weblinkbackupdaterdetectbrokenlinkbacks \
      -T bst_weblinkback_updater \
      -a "mode=5" \
      -u admin -s7d -L 'Sunday 01:00-05:00'
+
+# Send notification email for all pending linkbacks
+sudo -u www-data /opt/invenio/bin/bibtasklet \
+     -N weblinkbacknotifications \
+     -T bst_weblinkback_updater \
+     -a "mode=6" \
+     -u admin -s1d
 

Monitoring periodical daemon tasks

Note that the BibSched automated daemon stops as soon as some of its tasks end with an error. You will be informed by email about this incident. Nevertheless, it is a good idea to inspect the BibSched queue from time to time anyway, say several times per day, to see what is going on. This can be done by running the BibSched command-line monitor:

 $ bibsched
 

The monitor will permit you to stop/start the automated mode, to delete the tasks that were wrongly submitted, to run some of the tasks manually, etc. Note also that the BibSched daemon writes its log and error files about its own operation, as well as on the operation of its tasks, to the /opt/invenio/var/log directory.

Running alert engine

Invenio users may set up an automatic notification email alerts so that they are automatically alerted about documents of their interest by email, either daily, weekly, or monthly. It is the job of the alert engine to do this. The alert engine has to be run every day:

 $ alertengine
 

You may want to set up an external cron job to call alertengine each day, for example:

 $ crontab -l
 # invenio: periodically restart Apache:
 59 23 * * * /usr/sbin/apachectl restart
 # invenio: run alert engine:
 30 14 * * * /usr/bin/sudo -u apache /opt/invenio/bin/alertengine
 

Housekeeping task details

Housekeeping: recalculating ranking weights

When you are adding new records to the system, the word frequency ranking weights for old records aren't recalculated by default in order to speed up the insertion of new records. This may influence a bit the precision of word similarity searches. It is therefore advised to expressely run bibrank in the recalculating mode once in a while during a relatively quiet site operation day, by doing:

 $ bibrank -R -w wrd -s 14d -L Sunday
 
You may want to do this either (i) periodically, say once per month (see the previous section), or (ii) depending on the frequency of new additions to the record database, say when the size grows by 2-3 percent.

Housekeeping: recalculating sorting weights

It is advised to run from time to time the rebalancing of the sorting buckets. In order to speed up the process of insertion of new records, the sorting buckets are not being recalculated, but new records are being added at the end of the corresponding bucket. This might create differences in the size of each bucket which might have a small impact on the speed of sorting.

 $ bibsort -R -s 7d -L 'Sunday 01:00-05:00'
 
The rebalancing might be run weekly or even daily.

Housekeeping: cleaning up the garbage

The tool inveniogc provides a garbage collector for the database, temporary files, and the like.

If you choose to differentiate between guest users (see CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS in invenio.conf), then guest users can create a lot of entries in Invenio tables that are related to their web sessions, their search history, personal baskets, etc. This data has to be garbage-collected periodically. You can run this, say every Sunday between 01:00 and 05:00, via:

 $ inveniogc -s 7d -L 'Sunday 01:00-05:00'
 

Different temporary log and err files are created in /opt/invenio/var/log and /opt/invenio/var/tmp directory that is good to clean up from time to time. The previous command could be used to clean those files, too, via:

 $ inveniogc -s 7d -d -L 'Sunday 01:00-05:00'
 

The inveniogc tool can run other cleaning actions; please refer to its help (inveniogc --help) for more details.

Note that in the above section "Setting up periodical daemon tasks", we have set up inveniogc with argument -a in that example, meaning that it would run all possible cleaning actions. Please modify this if it is not what you want.

Housekeeping: backing up the database

You can launch a bibsched task called dbdump in order to take regular snapshot of your database content into SQL dump files. For example, to back up the database content into /opt2/mysql-backups directory every night, keeping at most 10 latest copies of the backup file, you would launch:

 $ dbdump -s 20h -L '22:00-06:00' -o /opt2/mysql-backups -n 10
 

This will create files named like invenio-dbdump-2009-03-10_22:10:28.sql in this folder.

Note that you may use Invenio-independent MySQL backuping tools like mysqldump, but these might generally lock all tables during backup for consistency, hence it could happen that your site might not be accessible during backuping time due to the user session table being locked as well. The dbdump tool does not lock all tables, therefore the site remains accessible to users while the dump files are being created. Note that the dump files are kept consistent with respect to the data, since dbdump runs via bibsched, hence not allowing any other important bibliographic task to run during the backup.

To load a dump file produced by dbdump into a running Invenio instance later, you can use:

 $ bibsched stop
 $ cat /opt2/mysql-backups/invenio-dbdump-2009-03-10_22\:10\:28.sql | dbexec
 $ bibsched start
 
diff --git a/modules/webjournal/lib/elements/bfe_webjournal_trackback_auto_discovery.py b/modules/webjournal/lib/elements/bfe_webjournal_trackback_auto_discovery.py index 5c1ecf35b..579c328b0 100644 --- a/modules/webjournal/lib/elements/bfe_webjournal_trackback_auto_discovery.py +++ b/modules/webjournal/lib/elements/bfe_webjournal_trackback_auto_discovery.py @@ -1,46 +1,48 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- ## This file is part of Invenio. ## Copyright (C) 2009, 2010, 2011 CERN. ## ## 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. ## ## 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """ WebJournal Element - return trackback auto discovery tag """ import cgi from invenio.webjournal_utils import parse_url_string from invenio.weblinkback_templates import get_trackback_auto_discovery_tag +from invenio.config import CFG_WEBLINKBACK_TRACKBACK_ENABLED def format_element(bfo): """ Return trackback auto discovery tag if recid != -1, will return "" for recid == -1 like index pages """ - # Retrieve context (journal, issue and category) from URI - args = parse_url_string(bfo.user_info['uri']) - recid = args["recid"] - html = "" - if recid != -1: - html = get_trackback_auto_discovery_tag(recid) + if CFG_WEBLINKBACK_TRACKBACK_ENABLED: + # Retrieve context (journal, issue and category) from URI + args = parse_url_string(bfo.user_info['uri']) + recid = args["recid"] + + if recid != -1: + html = get_trackback_auto_discovery_tag(recid) return html def escape_values(bfo): """ Called by BibFormat in order to check if output of this element should be escaped. """ return 0 diff --git a/modules/weblinkback/lib/weblinkback.py b/modules/weblinkback/lib/weblinkback.py index dfa107230..d8b3d6f64 100644 --- a/modules/weblinkback/lib/weblinkback.py +++ b/modules/weblinkback/lib/weblinkback.py @@ -1,313 +1,334 @@ # -*- coding: utf-8 -*- ## This file is part of Invenio. ## Copyright (C) 2011 CERN. ## ## 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. ## ## 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """WebLinkback - Handling Linkbacks""" from invenio.config import CFG_SITE_URL, \ CFG_SITE_RECORD, \ - CFG_SITE_ADMIN_EMAIL + CFG_SITE_ADMIN_EMAIL, \ + CFG_SITE_LANG from invenio.weblinkback_config import CFG_WEBLINKBACK_TYPE, \ CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, \ CFG_WEBLINKBACK_STATUS, \ CFG_WEBLINKBACK_ORDER_BY_INSERTION_TIME, \ CFG_WEBLINKBACK_LIST_TYPE, \ CFG_WEBLINKBACK_TRACKBACK_SUBSCRIPTION_ERROR_MESSAGE, \ CFG_WEBLINKBACK_PAGE_TITLE_STATUS, \ - CFG_WEBLINKBACK_BROKEN_COUNT + CFG_WEBLINKBACK_BROKEN_COUNT, \ + CFG_WEBLINKBACK_LATEST_FACTOR from invenio.weblinkback_dblayer import create_linkback, \ get_url_list, \ get_all_linkbacks, \ get_approved_latest_added_linkbacks, \ approve_linkback, \ get_urls_and_titles, \ update_url_title, \ set_url_broken, \ increment_broken_count, \ remove_linkback from invenio.search_engine import check_user_can_view_record, \ guess_primary_collection_of_a_record from invenio.access_control_engine import acc_authorize_action, \ acc_get_authorized_emails from invenio.webuser import collect_user_info from invenio.mailutils import send_email -from invenio.bibformat import format_record from invenio.urlutils import get_title_of_page def check_user_can_view_linkbacks(user_info, recid): """ Check if the user is authorized to view linkbacks for a given recid. Returns the same type as acc_authorize_action """ # check user cannot view the record itself (auth_code, auth_msg) = check_user_can_view_record(user_info, recid) if auth_code: return (auth_code, auth_msg) # check if user can view the linkbacks record_primary_collection = guess_primary_collection_of_a_record(recid) return acc_authorize_action(user_info, 'viewlinkbacks', authorized_if_no_roles=True, collection=record_primary_collection) -def generate_redirect_url(recid, ln, action = None): +def generate_redirect_url(recid, ln=CFG_SITE_LANG, action = None): """ Get redirect URL for an action @param action: the action, must be defined in weblinkback_webinterface.py @return "CFG_SITE_URL/CFG_SITE_RECORD/recid/linkbacks/action?ln=%s" if action != None, otherwise CFG_SITE_URL/CFG_SITE_RECORD/recid/linkbacks?ln=%s """ result = "%s/%s/%s/linkbacks" % (CFG_SITE_URL, CFG_SITE_RECORD, recid) if action != None: return result + "/%s?ln=%s" % (action, ln) else: return result + "?ln=%s" % ln def split_in_days(linkbacks): """ Split linkbacks in days @param linkbacks: a list of this format: [(linkback_id, origin_url, recid, additional_properties, type, status, insert_time)] in ascending or descending order by insert_time @return a list of lists of linkbacks """ result = [] same_day_list = [] previous_date = None current_date = None for i in range(len(linkbacks)): current_linkback = linkbacks[i] previous_date = None if i > 0: previous_date = current_date else: previous_date = current_linkback[6] current_date = current_linkback[6] # same day --> same group if (current_date.year == previous_date.year and current_date.month == previous_date.month and current_date.day == previous_date.day): same_day_list.append(current_linkback) else: result.append(same_day_list) same_day_list = [] same_day_list.append(current_linkback) # add last group if non-empty if same_day_list: result.append(same_day_list) return result def create_trackback(recid, url, title, excerpt, blog_name, blog_id, source, user_info): """ Create a trackback @param recid """ # copy optional arguments argument_copy = {} if title != CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME: argument_copy['title'] = title if excerpt != CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME: argument_copy['excerpt'] = excerpt if blog_name != CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME: argument_copy['blog_name'] = blog_name if blog_id != CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME: argument_copy['id'] = blog_id if source != CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME: argument_copy['source'] = source additional_properties = "" if len(argument_copy) > 0: additional_properties = argument_copy return create_linkback(url, recid, additional_properties, CFG_WEBLINKBACK_TYPE['TRACKBACK'], user_info) -def send_request_notification_to_all_linkback_moderators(recid, origin_url, linkback_type, ln): +def send_pending_linkbacks_notification(linkback_type): """ - Send notification emails to all linkback moderators for linkback request - @param recid - @param origin_url: URL of the requestor + Send notification emails to all linkback moderators for all pending linkbacks @param linkback_type: of CFG_WEBLINKBACK_LIST_TYPE """ - content = """There is a new %(linkback_type)s request for %(recordURL)s from %(origin_url)s which you should approve or reject. - """ % {'linkback_type': linkback_type, - 'recordURL': generate_redirect_url(recid, ln), - 'origin_url': origin_url} + pending_linkbacks = get_all_linkbacks(linkback_type=CFG_WEBLINKBACK_TYPE['TRACKBACK'], status=CFG_WEBLINKBACK_STATUS['PENDING']) + + if pending_linkbacks: + content = """There are %(count)s new %(linkback_type)s requests which you should approve or reject: + """ % {'count': len(pending_linkbacks), + 'linkback_type': linkback_type} - html_content = """There is a new %(linkback_type)s request for %(record)s (
%(recordURL)s) from %(title)s (%(origin_url)s) which you should approve or reject. - """ % {'linkback_type': linkback_type, - 'record': format_record(recID=recid, of='hs', ln=ln), - 'recordURL': generate_redirect_url(recid, ln), - 'origin_url': origin_url, - 'title': origin_url} + for pending_linkback in pending_linkbacks: + content += """ + For %(recordURL)s from %(origin_url)s. + """ % {'recordURL': generate_redirect_url(pending_linkback[2]), + 'origin_url': pending_linkback[1]} - for email in acc_get_authorized_emails('moderatelinkbacks', collection = guess_primary_collection_of_a_record(recid)): - send_email(CFG_SITE_ADMIN_EMAIL, email, 'New ' + linkback_type + ' request', content, html_content) + for email in acc_get_authorized_emails('moderatelinkbacks'): + send_email(CFG_SITE_ADMIN_EMAIL, email, 'Pending ' + linkback_type + ' requests', content) def infix_exists_for_url_in_list(url, list_type): """ Check if an infix of a url exists in a list @param url @param list_type, of CFG_WEBLINKBACK_LIST_TYPE @return True, False """ urls = get_url_list(list_type) for current_url in urls: if current_url in url: return True return False +def get_latest_linkbacks_to_accessible_records(rg, linkbacks, user_info): + result = [] + for linkback in linkbacks: + (auth_code, auth_msg) = check_user_can_view_record(user_info, linkback[2]) # pylint: disable=W0612 + if not auth_code: + result.append(linkback) + if len(result) == rg: + break + return result + + def perform_request_display_record_linbacks(req, recid, show_admin, weblinkback_templates, ln): # pylint: disable=W0613 """ Display linkbacks of a record @param recid @param argd @param show_admin: True, False --> show admin parts to approve/reject linkbacks pending requests @param weblinkback_templates: template object reference """ out = weblinkback_templates.tmpl_linkbacks_general(recid=recid, ln=ln) if show_admin: pending_linkbacks = get_all_linkbacks(recid, CFG_WEBLINKBACK_STATUS['PENDING'], CFG_WEBLINKBACK_ORDER_BY_INSERTION_TIME['DESC']) out += weblinkback_templates.tmpl_linkbacks_admin(pending_linkbacks=pending_linkbacks, recid=recid, ln=ln) approved_linkbacks = get_all_linkbacks(recid, CFG_WEBLINKBACK_STATUS['APPROVED'], CFG_WEBLINKBACK_ORDER_BY_INSERTION_TIME['DESC']) out += weblinkback_templates.tmpl_linkbacks(approved_linkbacks=approved_linkbacks, ln=ln) return out -def perform_request_display_approved_latest_added_linkbacks(rg, ln, weblinkback_templates): +def perform_request_display_approved_latest_added_linkbacks_to_accessible_records(rg, ln, user_info, weblinkback_templates): """ - Display approved latest added linbacks + Display approved latest added linbacks to accessible records @param rg: count of linkbacks to display @param weblinkback_templates: template object reference """ - latest_linkbacks = get_approved_latest_added_linkbacks(rg) + latest_linkbacks = get_approved_latest_added_linkbacks(rg * CFG_WEBLINKBACK_LATEST_FACTOR) + latest_linkbacks = get_latest_linkbacks_to_accessible_records(rg, latest_linkbacks, user_info) latest_linkbacks_in_days = split_in_days(latest_linkbacks) out = weblinkback_templates.tmpl_get_latest_linkbacks_top(rg, ln) out += '
' out += weblinkback_templates.tmpl_get_latest_linkbacks(latest_linkbacks_in_days, ln) return out def perform_sendtrackback(req, recid, url, title, excerpt, blog_name, blog_id, source, ln): """ Send trackback @param recid: recid """ # assume unsuccessful request status = 400 xml_response = '' xml_error_response = """1 %s """ blacklist_match = infix_exists_for_url_in_list(url, CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST']) whitelist_match = infix_exists_for_url_in_list(url, CFG_WEBLINKBACK_LIST_TYPE['WHITELIST']) # faulty request, url argument not set if url in (CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, None, ''): xml_response += xml_error_response % CFG_WEBLINKBACK_TRACKBACK_SUBSCRIPTION_ERROR_MESSAGE['BAD_ARGUMENT'] # request refused: whitelist match has precedence over blacklist match elif blacklist_match and not whitelist_match: xml_response += xml_error_response % CFG_WEBLINKBACK_TRACKBACK_SUBSCRIPTION_ERROR_MESSAGE['BLACKLIST'] # request accepted: will be either approved automatically or pending else: status = 200 linkback_id = create_trackback(recid, url, title, excerpt, blog_name, blog_id, source, collect_user_info(req)) # approve request automatically from url in whitelist if whitelist_match: approve_linkback(linkback_id, collect_user_info(req)) - # send request notification email to moderators - else: - send_request_notification_to_all_linkback_moderators(recid, url, CFG_WEBLINKBACK_TYPE['TRACKBACK'], ln) xml_response += '' # send response req.set_content_type("text/xml; charset=utf-8") req.set_status(status) req.send_http_header() req.write(xml_response) +def perform_sendtrackback_disabled(req): + status = 404 + xml_response = """ + 1 + Trackback facility disabled + """ + req.set_content_type("text/xml; charset=utf-8") + req.set_status(status) + req.send_http_header() + req.write(xml_response) + + def update_linkbacks(mode): """ Update titles of pages that link to the instance @param mode: 1 update page titles of new linkbacks 2 update page titles of old linkbacks 3 update manually set page titles 4 detect and disable broken linkbacks """ if mode in (1, 2, 3): if mode == 1: urls_and_titles = get_urls_and_titles(CFG_WEBLINKBACK_PAGE_TITLE_STATUS['NEW']) elif mode == 2: urls_and_titles = get_urls_and_titles(CFG_WEBLINKBACK_PAGE_TITLE_STATUS['OLD']) elif mode == 3: urls_and_titles = get_urls_and_titles(CFG_WEBLINKBACK_PAGE_TITLE_STATUS['MANUALLY_SET']) for (url, title, manual_set, broken_count) in urls_and_titles: # pylint: disable=W0612 new_title = get_title_of_page(url) # Only accept valid titles if new_title != None: update_url_title(url, new_title) elif mode == 4: urls_and_titles = get_urls_and_titles() for (url, title, manual_set, broken_count) in urls_and_titles: # pylint: disable=W0612 new_title = get_title_of_page(url) # Broken one detected if new_title == None: increment_broken_count(url) if broken_count + 1 == CFG_WEBLINKBACK_BROKEN_COUNT: set_url_broken(url) def delete_linkbacks_on_blacklist(): """ Delete all rejected, broken and pending linkbacks whose URL on in the blacklist """ linkbacks = list(get_all_linkbacks(status=CFG_WEBLINKBACK_STATUS['PENDING'])) linkbacks.extend(list(get_all_linkbacks(status=CFG_WEBLINKBACK_STATUS['REJECTED']))) linkbacks.extend(list(get_all_linkbacks(status=CFG_WEBLINKBACK_STATUS['BROKEN']))) for linkback in linkbacks: if infix_exists_for_url_in_list(linkback[1], CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST']): remove_linkback(linkback[0]) diff --git a/modules/weblinkback/lib/weblinkback_config.py b/modules/weblinkback/lib/weblinkback_config.py index 452dba92e..287af1c53 100644 --- a/modules/weblinkback/lib/weblinkback_config.py +++ b/modules/weblinkback/lib/weblinkback_config.py @@ -1,62 +1,64 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2011 CERN. ## ## 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. ## ## 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """WebLinkback - Configuration Parameters""" CFG_WEBLINKBACK_STATUS = {'APPROVED': 'approved', 'PENDING': 'pending', 'REJECTED': 'rejected', 'INSERTED': 'inserted', 'BROKEN': 'broken'} CFG_WEBLINKBACK_TYPE = {'TRACKBACK': 'trackback', 'REFBACK': 'refback', 'PINGBACK': 'pingback'} CFG_WEBLINKBACK_LIST_TYPE = {'WHITELIST': 'whitelist', 'BLACKLIST': 'blacklist'} CFG_WEBLINKBACK_ORDER_BY_INSERTION_TIME = {'ASC': 'ASC', 'DESC': 'DESC'} CFG_WEBLINKBACK_ADMIN_MODERATION_ACTION = {'REJECT': 'reject', 'APPROVE': 'approve', 'INSERT': 'insert', 'DELETE': 'delete'} CFG_WEBLINKBACK_ACTION_RETURN_CODE = {'OK': 0, 'INVALID_ACTION': 1, 'DUPLICATE': 2, 'BAD_INPUT': 3} CFG_WEBLINKBACK_PAGE_TITLE_STATUS = {'NEW': 'n', 'OLD': 'o', 'MANUALLY_SET': 'm'} CFG_WEBLINKBACK_LATEST_COUNT_VALUES = (10, 20, 50, 100, 200) CFG_WEBLINKBACK_LATEST_COUNT_DEFAULT = 10 CFG_WEBLINKBACK_BROKEN_COUNT = 5 CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME = 'default' CFG_WEBLINKBACK_TRACKBACK_SUBSCRIPTION_ERROR_MESSAGE= {'BAD_ARGUMENT': 'Refused: URL argument not set', 'BLACKLIST': 'Refused: URL in blacklist'} CFG_WEBLINKBACK_DEFAULT_USER = 0 + +CFG_WEBLINKBACK_LATEST_FACTOR = 3 diff --git a/modules/weblinkback/lib/weblinkback_dblayer.py b/modules/weblinkback/lib/weblinkback_dblayer.py index beca277e3..d73211587 100644 --- a/modules/weblinkback/lib/weblinkback_dblayer.py +++ b/modules/weblinkback/lib/weblinkback_dblayer.py @@ -1,414 +1,419 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2011, 2012 CERN. ## ## 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. ## ## 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """WebLinkback - Database Layer""" from invenio.dbquery import run_sql from invenio.weblinkback_config import CFG_WEBLINKBACK_STATUS, \ CFG_WEBLINKBACK_ORDER_BY_INSERTION_TIME, \ CFG_WEBLINKBACK_DEFAULT_USER, \ CFG_WEBLINKBACK_PAGE_TITLE_STATUS +from invenio.textutils import xml_entities_to_utf8 -def get_all_linkbacks(recid=None, status=None, order=CFG_WEBLINKBACK_ORDER_BY_INSERTION_TIME["ASC"]): +def get_all_linkbacks(recid=None, status=None, order=CFG_WEBLINKBACK_ORDER_BY_INSERTION_TIME["ASC"], linkback_type=None): """ Get all linkbacks @param recid: of one record, of all if None @param status: with a certain status, of all if None @param order: order by insertion time either "ASC" or "DESC" + @param linkback_type: of a certain type, of all if None @return [(linkback_id, origin_url, recid, additional_properties, linkback_type, linkback_status, insert_time)] in order by id """ header_sql = """SELECT id, origin_url, id_bibrec, additional_properties, type, status, insert_time FROM lnkENTRY""" - middle_sql = "" + conditions = [] order_sql = "ORDER by id %s" % order - params = () + params = [] - if not recid: - middle_sql = " WHERE status=%s " - params = (status, ) - if not status: - middle_sql = " WHERE id_bibrec=%s " - params = (recid, ) - if recid and status: - middle_sql = " WHERE id_bibrec=%s AND status=%s " - params = (recid, status, ) + def add_condition(column, value): + if value: + if not conditions: + conditions.append('WHERE %s=%%s' % column) + else: + conditions.append('AND %s=%%s' % column) + params.append(value) - return run_sql(header_sql + middle_sql + order_sql, params) + add_condition('id_bibrec', recid) + add_condition('status', status) + add_condition('type', linkback_type) + + return run_sql(header_sql + ' ' + ' '.join(conditions) + ' ' + order_sql, tuple(params)) def approve_linkback(linkbackid, user_info): """ Approve linkback @param linkbackid: linkback id @param user_info: user info """ update_linkback_status(linkbackid, CFG_WEBLINKBACK_STATUS['APPROVED'], user_info) def reject_linkback(linkbackid, user_info): """ Reject linkback @param linkbackid: linkback id @param user_info: user info """ update_linkback_status(linkbackid, CFG_WEBLINKBACK_STATUS['REJECTED'], user_info) def update_linkback_status(linkbackid, new_status, user_info = None): """ Update status of a linkback @param linkbackid: linkback id @param new_status: new status @param user_info: user info """ if user_info == None: user_info = {} user_info['uid'] = CFG_WEBLINKBACK_DEFAULT_USER run_sql("""UPDATE lnkENTRY SET status=%s WHERE id=%s """, (new_status, linkbackid)) logid = run_sql("""INSERT INTO lnkLOG (id_user, action, log_time) VALUES (%s, %s, NOW()); SELECT LAST_INSERT_ID(); """, (user_info['uid'], new_status)) run_sql("""INSERT INTO lnkENTRYLOG (id_lnkENTRY , id_lnkLOG) VALUES (%s, %s); """, (linkbackid, logid)) def create_linkback(origin_url, recid, additional_properties, linkback_type, user_info): """ Create linkback @param origin_url: origin URL, @param recid: recid @param additional_properties: additional properties @param linkback_type: linkback type @param user_info: user info @return id of the created linkback """ linkbackid = run_sql("""INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES (%s, %s, %s, %s, %s, NOW()); SELECT LAST_INSERT_ID(); """, (origin_url, recid, str(additional_properties), linkback_type, CFG_WEBLINKBACK_STATUS['PENDING'])) logid = run_sql("""INSERT INTO lnkLOG (id_user, action, log_time) VALUES (%s, %s, NOW()); SELECT LAST_INSERT_ID(); """, (user_info['uid'], CFG_WEBLINKBACK_STATUS['INSERTED'])) run_sql("""INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s); """, (linkbackid, logid)) # add url title entry if necessary if len(run_sql("""SELECT url FROM lnkENTRYURLTITLE WHERE url=%s """, (origin_url, ))) == 0: manual_set_title = 0 title = "" if additional_properties != "" and 'title' in additional_properties.keys(): manual_set_title = 1 title = additional_properties['title'] run_sql("""INSERT INTO lnkENTRYURLTITLE (url, title, manual_set) VALUES (%s, %s, %s) """, (origin_url, title, manual_set_title)) return linkbackid def get_approved_latest_added_linkbacks(count): """ Get approved latest added linkbacks @param count: count of the linkbacks @return [(linkback_id, origin_url, recid, additional_properties, type, status, insert_time)] in descending order by insert_time """ return run_sql("""SELECT id, origin_url, id_bibrec, additional_properties, type, status, insert_time FROM lnkENTRY WHERE status=%s ORDER BY insert_time DESC LIMIT %s """, (CFG_WEBLINKBACK_STATUS['APPROVED'], count)) def get_url_list(list_type): """ @param list_type: of CFG_WEBLINKBACK_LIST_TYPE @return (url0, ..., urln) in ascending order by url """ result = run_sql("""SELECT url FROM lnkADMINURL WHERE list=%s ORDER by url ASC """, (list_type, )) return tuple(url[0] for (url) in result) def get_urls(): """ Get all URLs and the corresponding listType @return ((url, CFG_WEBLINKBACK_LIST_TYPE), ..., (url, CFG_WEBLINKBACK_LIST_TYPE)) in ascending order by url """ return run_sql("""SELECT url, list FROM lnkADMINURL ORDER by url ASC """) def url_exists(url, list_type=None): """ Check if url exists @param url @param list_type: specific list of CFG_WEBLINKBACK_LIST_TYPE, all if None @return True or False """ header_sql = """SELECT url FROM lnkADMINURL WHERE url=%s """ optional_sql = " AND list=%s" result = None if list_type: result = run_sql(header_sql + optional_sql, (url, list_type)) else: result = run_sql(header_sql, (url, )) if result != (): return True else: return False def add_url_to_list(url, list_type, user_info): """ Add a URL to a list @param url: unique URL string for all lists @param list_type: of CFG_WEBLINKBACK_LIST_TYPE @param user_info: user info @return id of the created url """ urlid = run_sql("""INSERT INTO lnkADMINURL (url, list) VALUES (%s, %s); SELECT LAST_INSERT_ID(); """, (url, list_type)) logid = run_sql("""INSERT INTO lnkLOG (id_user, action, log_time) VALUES (%s, %s, NOW()); SELECT LAST_INSERT_ID(); """, (user_info['uid'], CFG_WEBLINKBACK_STATUS['INSERTED'])) run_sql("""INSERT INTO lnkADMINURLLOG (id_lnkADMINURL, id_lnkLOG) VALUES (%s, %s); """, (urlid, logid)) return urlid def remove_url(url): """ Remove a URL from list @param url: unique URL string for all lists """ # get ids urlid = run_sql("""SELECT id FROM lnkADMINURL WHERE url=%s """, (url, ))[0][0] logids = run_sql("""SELECT log.id FROM lnkLOG log JOIN lnkADMINURLLOG url_log ON log.id=url_log.id_lnkLOG WHERE url_log.id_lnkADMINURL=%s """, (urlid, )) # delete url and url log run_sql("""DELETE FROM lnkADMINURL WHERE id=%s; DELETE FROM lnkADMINURLLOG WHERE id_lnkADMINURL=%s """, (urlid, urlid)) # delete log for logid in logids: run_sql("""DELETE FROM lnkLOG WHERE id=%s """, (logid[0], )) def get_urls_and_titles(title_status=None): """ Get URLs and their corresponding title @param old_new: of CFG_WEBLINKBACK_PAGE_TITLE_STATUS or None @return ((url, title, manual_set),...), all rows of the table if None """ top_query = """SELECT url, title, manual_set, broken_count FROM lnkENTRYURLTITLE WHERE """ where_sql = "" if title_status == CFG_WEBLINKBACK_PAGE_TITLE_STATUS['NEW']: where_sql = " title='' AND manual_set=0 AND" elif title_status == CFG_WEBLINKBACK_PAGE_TITLE_STATUS['OLD']: where_sql = " title<>'' AND manual_set=0 AND" elif title_status == CFG_WEBLINKBACK_PAGE_TITLE_STATUS['MANUALLY_SET']: where_sql = " manual_set=1 AND" where_sql += " broken=0" return run_sql(top_query + where_sql) def update_url_title(url, title): """ Update the corresponding title of a URL @param url: URL @param title: new title """ run_sql("""UPDATE lnkENTRYURLTITLE SET title=%s, manual_set=0, broken_count=0, broken=0 WHERE url=%s """, (title, url)) def remove_url_title(url): """ Remove URL title @param url: URL """ run_sql("""DELETE FROM lnkENTRYURLTITLE WHERE url=%s """, (url, )) def set_url_broken(url): """ Set URL broken @param url: URL """ linkbackids = run_sql("""SELECT id FROM lnkENTRY WHERE origin_url=%s """, (url, )) run_sql("""UPDATE lnkENTRYURLTITLE SET title=%s, broken=1 WHERE url=%s """, (CFG_WEBLINKBACK_STATUS['BROKEN'], url)) # update all linkbacks for linkbackid in linkbackids: update_linkback_status(linkbackid[0], CFG_WEBLINKBACK_STATUS['BROKEN']) def get_url_title(url): """ Get URL title or URL if title does not exist (empty string) @param url: URL @return title or URL if titles does not exist (empty string) """ title = run_sql("""SELECT title FROM lnkENTRYURLTITLE WHERE url=%s and title<>"" and broken=0 """, (url, )) + res = url if len(title) != 0: - return title[0][0] - else: - return url + res = title[0][0] + + return xml_entities_to_utf8(res) def increment_broken_count(url): """ Increment broken count a URL @param url: URL """ run_sql("""UPDATE lnkENTRYURLTITLE SET broken_count=broken_count+1 WHERE url=%s """, (url, )) def remove_linkback(linkbackid): """ Remove a linkback database @param linkbackid: unique URL string for all lists """ # get ids logids = run_sql("""SELECT log.id FROM lnkLOG log JOIN lnkENTRYLOG entry_log ON log.id=entry_log.id_lnkLOG WHERE entry_log.id_lnkENTRY=%s """, (linkbackid, )) # delete linkback entry and entry log run_sql("""DELETE FROM lnkENTRY WHERE id=%s; DELETE FROM lnkENTRYLOG WHERE id_lnkENTRY=%s """, (linkbackid, linkbackid)) # delete log for logid in logids: run_sql("""DELETE FROM lnkLOG WHERE id=%s """, (logid[0], )) diff --git a/modules/weblinkback/lib/weblinkback_regression_tests.py b/modules/weblinkback/lib/weblinkback_regression_tests.py index e08bf652f..89c8ea963 100644 --- a/modules/weblinkback/lib/weblinkback_regression_tests.py +++ b/modules/weblinkback/lib/weblinkback_regression_tests.py @@ -1,898 +1,942 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2011, 2012, 2013 CERN. ## ## 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. ## ## 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """WebLinkback - Regression Test Suite""" import unittest from invenio.config import CFG_SITE_URL, \ - CFG_SITE_RECORD + CFG_SITE_RECORD, \ + CFG_WEBLINKBACK_TRACKBACK_ENABLED from invenio.dbquery import CFG_DATABASE_NAME from invenio.testutils import make_test_suite, \ run_test_suite, \ test_web_page_content, \ merge_error_messages from invenio.dbquery import run_sql try: from mock import patch HAS_MOCK = True except ImportError: HAS_MOCK = False from invenio.weblinkback_dblayer import get_all_linkbacks, \ approve_linkback, \ reject_linkback, \ get_approved_latest_added_linkbacks, \ get_url_list, \ add_url_to_list, \ remove_url, \ url_exists, \ get_url_title, \ get_urls_and_titles, \ remove_linkback, \ set_url_broken,\ update_url_title from invenio.weblinkback import create_trackback, \ delete_linkbacks_on_blacklist, \ update_linkbacks from invenio.weblinkback_config import CFG_WEBLINKBACK_STATUS, \ CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, \ CFG_WEBLINKBACK_LIST_TYPE, \ CFG_WEBLINKBACK_TYPE, \ CFG_WEBLINKBACK_PAGE_TITLE_STATUS def get_max_auto_increment_id(table): return run_sql("SELECT Auto_increment FROM information_schema.tables WHERE table_name=%s AND table_schema=%s", (table, CFG_DATABASE_NAME))[0][0] - 1 def remove_test_data(): run_sql("DELETE FROM lnkENTRY") run_sql("DELETE FROM lnkENTRYURLTITLE") run_sql("DELETE FROM lnkENTRYLOG") run_sql("DELETE FROM lnkLOG") run_sql("DELETE FROM lnkADMINURL") run_sql("DELETE FROM lnkADMINURLLOG") class WebLinkbackWebPagesAvailabilityTest(unittest.TestCase): """Test WebLinkback web pages whether they are up or not""" - def test_your_baskets_pages_availability(self): + def test_linkback_pages_availability(self): """weblinkback - availability of /linkbacks pages""" error_messages = [] baseurl = CFG_SITE_URL + '/%s/10/linkbacks/' % CFG_SITE_RECORD _exports = ['', 'display', 'index', 'approve', 'reject'] for url in [baseurl + page for page in _exports]: error_messages.extend(test_web_page_content(url)) baseurl = CFG_SITE_URL + '/linkbacks/' error_messages.extend(test_web_page_content(baseurl)) if error_messages: self.fail(merge_error_messages(error_messages)) def test_weblinkback_admin_interface_availability(self): """weblinkback - availability of WebLinkback Admin interface pages""" baseurl = CFG_SITE_URL + '/admin/weblinkback/weblinkbackadmin.py/' _exports = ['', 'lists', 'linkbacks'] error_messages = [] for url in [baseurl + page for page in _exports]: # first try as guest: error_messages.extend(test_web_page_content(url, username='guest', expected_text='Authorization failure')) # then try as admin: error_messages.extend(test_web_page_content(url, username='admin')) if error_messages: self.fail(merge_error_messages(error_messages)) return class WebLinkbackDatabaseTest(unittest.TestCase): """Test WebLinkback database layer""" def setUp(self): """Insert test data""" self.insert_time = [] self.user_info = {'uid': 0} self.remove_test_data() # recid 41 run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URL1', 41, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['TRACKBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) last_linkback_entryid = run_sql("SELECT LAST_INSERT_ID()")[0][0] self.insert_time.append(run_sql("SELECT NOW()")[0][0]) run_sql("INSERT INTO lnkLOG (id_user, action, log_time) VALUES (NULL, %s, %s)", (CFG_WEBLINKBACK_STATUS['INSERTED'], self.insert_time[0])) last_logid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s)", (last_linkback_entryid, last_logid)) run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URL2', 41, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['TRACKBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) last_linkback_entryid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkLOG (id_user, action, log_time) VALUES (NULL, %s, NOW())", (CFG_WEBLINKBACK_STATUS['INSERTED'], )) last_logid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s)", (last_linkback_entryid, last_logid)) run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URL3', 41, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['TRACKBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) last_linkback_entryid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkLOG (id_user, action, log_time) VALUES (NULL, %s, NOW())", (CFG_WEBLINKBACK_STATUS['INSERTED'], )) last_logid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s)", (last_linkback_entryid, last_logid)) run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URL4', 41, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['TRACKBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) last_linkback_entryid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkLOG (id_user, action, log_time) VALUES (NULL, %s, NOW())", (CFG_WEBLINKBACK_STATUS['INSERTED'], )) last_logid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s)", (last_linkback_entryid, last_logid)) # recid 42 run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URL5', 42, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['TRACKBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) last_linkback_entryid = run_sql("SELECT LAST_INSERT_ID()")[0][0] self.insert_time.append(run_sql("SELECT NOW()")[0][0]) run_sql("INSERT INTO lnkLOG (id_user, action, log_time) VALUES (NULL, %s, %s)", (CFG_WEBLINKBACK_STATUS['INSERTED'], self.insert_time[1])) last_logid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s)", (last_linkback_entryid, last_logid)) run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URL6', 42, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['TRACKBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) last_linkback_entryid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkLOG (id_user, action, log_time) VALUES (NULL, %s, %s)", (CFG_WEBLINKBACK_STATUS['INSERTED'], self.insert_time[1])) last_logid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s)", (last_linkback_entryid, last_logid)) run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URL7', 42, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['TRACKBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) last_linkback_entryid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkLOG (id_user, action, log_time) VALUES (NULL, %s, %s)", (CFG_WEBLINKBACK_STATUS['INSERTED'], self.insert_time[1])) last_logid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s)", (last_linkback_entryid, last_logid)) run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URL8', 42, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['TRACKBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) last_linkback_entryid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkLOG (id_user, action, log_time) VALUES (NULL, %s, %s)", (CFG_WEBLINKBACK_STATUS['INSERTED'], self.insert_time[1])) last_logid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s)", (last_linkback_entryid, last_logid)) run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URL1', 42, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['TRACKBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) last_linkback_entryid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkLOG (id_user, action, log_time) VALUES (NULL, %s, %s)", (CFG_WEBLINKBACK_STATUS['INSERTED'], self.insert_time[1])) last_logid = run_sql("SELECT LAST_INSERT_ID()")[0][0] run_sql("INSERT INTO lnkENTRYLOG (id_lnkENTRY, id_lnkLOG) VALUES (%s, %s)", (last_linkback_entryid, last_logid)) def tearDown(self): """Remove test data""" self.remove_test_data() def remove_test_data(self): """Clean tables""" self._max_id_lnkENTRY = get_max_auto_increment_id('lnkENTRY') self._max_id_lnkADMINURL = get_max_auto_increment_id('lnkADMINURL') self._max_id_lnkLOG = get_max_auto_increment_id('lnkLOG') remove_test_data() def get_all_from_table(self, tableName): return run_sql("SELECT * FROM %s" % tableName) # kwalitee: disable=sql def test_get_all_linkbacks1(self): """weblinkback - get all linkbacks for lnkENTRY and with a certain status""" self.assertEqual(0, len(get_all_linkbacks(recid=5, status=CFG_WEBLINKBACK_STATUS['PENDING']))) self.assertEqual(4, len(get_all_linkbacks(recid=41, status=CFG_WEBLINKBACK_STATUS['PENDING']))) self.assertEqual(0, len(get_all_linkbacks(recid=41, status=CFG_WEBLINKBACK_STATUS['INSERTED']))) self.assertEqual(5, len(get_all_linkbacks(recid=42, status=CFG_WEBLINKBACK_STATUS['PENDING']))) self.assertEqual(0, len(get_all_linkbacks(recid=42, status=CFG_WEBLINKBACK_STATUS['APPROVED']))) url = CFG_SITE_URL + '/%s/41/linkbacks/' % CFG_SITE_RECORD expected_texts = ('Linkbacks to review: 4', 'Linkbacks: 0', 'URL1', 'URL2', 'URL3', 'URL4') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) url = CFG_SITE_URL + '/%s/42/linkbacks/' % CFG_SITE_RECORD expected_texts = ('Linkbacks to review: 5', 'Linkbacks: 0', 'URL5', 'URL6', 'URL7', 'URL8', 'URL1') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) def test_get_all_linkbacks2(self): """weblinkback - get all linkbacks with a certain status""" self.assertEqual(9, len(get_all_linkbacks(status=CFG_WEBLINKBACK_STATUS['PENDING']))) self.assertEqual(0, len(get_all_linkbacks(status=CFG_WEBLINKBACK_STATUS['APPROVED']))) def test_approve_linkback(self): """weblinkback - approve linkback""" linkback = get_all_linkbacks(41)[0] linkbackid = linkback[0] linkback_status = linkback[5] self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_status) approve_linkback(linkbackid, self.user_info) linkback = get_all_linkbacks(recid=41)[0] linkback_status = linkback[5] self.assertEqual(CFG_WEBLINKBACK_STATUS['APPROVED'], linkback_status) url = CFG_SITE_URL + '/%s/41/linkbacks/' % CFG_SITE_RECORD expected_texts = ('Linkbacks to review: 3', 'Linkbacks: 1') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) def test_reject_linkback(self): """weblinkback - reject linkback""" linkback = get_all_linkbacks(recid=42)[1] linkbackid = linkback[0] linkback_status = linkback[5] self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_status) reject_linkback(linkbackid, self.user_info) linkback = get_all_linkbacks(recid=42)[1] linkback_status = linkback[5] self.assertEqual(CFG_WEBLINKBACK_STATUS['REJECTED'], linkback_status) url = CFG_SITE_URL + '/%s/42/linkbacks/' % CFG_SITE_RECORD expected_texts = ('Linkbacks to review: 4', 'Linkbacks: 0') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) def test_create_linkback1(self): """weblinkback - create linkback""" recid = 42 argd = {'url': 'URL', 'title': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, 'excerpt': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, 'blog_name': 'Test Blog', 'id': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, 'source': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, } linkbackid = create_trackback(recid, argd['url'], argd['title'], argd['excerpt'], argd['blog_name'], argd['id'], argd['source'], self.user_info) self.assertEqual(10 + self._max_id_lnkENTRY, linkbackid) linkback = get_all_linkbacks(recid=recid)[5] self.assertEqual(linkbackid, linkback[0]) self.assertEqual(argd['url'], linkback[1]) self.assertEqual(recid, linkback[2]) self.assertEqual(str({'blog_name': argd['blog_name']}), linkback[3]) self.assertEqual(CFG_WEBLINKBACK_TYPE['TRACKBACK'], linkback[4]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback[5]) url = CFG_SITE_URL + '/%s/42/linkbacks/' % CFG_SITE_RECORD expected_texts = ('Linkbacks to review: 6', 'Linkbacks: 0') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) approve_linkback(linkbackid, self.user_info) linkback = get_all_linkbacks(recid=recid)[5] self.assertEqual(linkbackid, linkback[0]) self.assertEqual(argd['url'], linkback[1]) self.assertEqual(recid, linkback[2]) self.assertEqual(str({'blog_name': argd['blog_name']}), linkback[3]) self.assertEqual(CFG_WEBLINKBACK_TYPE['TRACKBACK'], linkback[4]) self.assertEqual(CFG_WEBLINKBACK_STATUS['APPROVED'], linkback[5]) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") self.assertEqual(1, len(url_titles)) self.assertEqual(argd['url'], url_titles[0][1]) self.assertEqual("", url_titles[0][2]) self.assertEqual(0, url_titles[0][3]) self.assertEqual(argd['url'], get_url_title(argd['url'])) self.assertEqual(0, len(get_urls_and_titles(CFG_WEBLINKBACK_PAGE_TITLE_STATUS['OLD']))) self.assertEqual(1, len(get_urls_and_titles(CFG_WEBLINKBACK_PAGE_TITLE_STATUS['NEW']))) self.assertEqual(0, len(get_urls_and_titles(CFG_WEBLINKBACK_PAGE_TITLE_STATUS['MANUALLY_SET']))) url = CFG_SITE_URL + '/%s/42/linkbacks/' % CFG_SITE_RECORD expected_texts = ('Linkbacks to review: 5', 'Linkbacks: 1') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) self.assertEqual(10, len(self.get_all_from_table("lnkENTRY"))) self.assertEqual(11, len(self.get_all_from_table("lnkENTRYLOG"))) remove_linkback(linkbackid) self.assertEqual(9, len(self.get_all_from_table("lnkENTRY"))) self.assertEqual(9, len(self.get_all_from_table("lnkENTRYLOG"))) def test_create_linkback2(self): """weblinkback - create linkback with URL title""" recid = 42 argd = {'url': 'URL', 'title': 'My title', 'excerpt': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, 'blog_name': 'Test Blog', 'id': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, 'source': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, } linkbackid = create_trackback(recid, argd['url'], argd['title'], argd['excerpt'], argd['blog_name'], argd['id'], argd['source'], self.user_info) self.assertEqual(10 + self._max_id_lnkENTRY, linkbackid) linkback = get_all_linkbacks(recid=recid)[5] self.assertEqual(linkbackid, linkback[0]) self.assertEqual(argd['url'], linkback[1]) self.assertEqual(recid, linkback[2]) self.assertEqual(CFG_WEBLINKBACK_TYPE['TRACKBACK'], linkback[4]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback[5]) url = CFG_SITE_URL + '/%s/42/linkbacks/' % CFG_SITE_RECORD expected_texts = ('Linkbacks to review: 6', 'Linkbacks: 0') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) approve_linkback(linkbackid, self.user_info) linkback = get_all_linkbacks(recid=recid)[5] self.assertEqual(linkbackid, linkback[0]) self.assertEqual(argd['url'], linkback[1]) self.assertEqual(recid, linkback[2]) self.assertEqual(CFG_WEBLINKBACK_TYPE['TRACKBACK'], linkback[4]) self.assertEqual(CFG_WEBLINKBACK_STATUS['APPROVED'], linkback[5]) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") self.assertEqual(1, len(url_titles)) self.assertEqual(argd['url'], url_titles[0][1]) self.assertEqual(argd['title'], url_titles[0][2]) self.assertEqual(1, url_titles[0][3]) self.assertEqual(argd['title'], get_url_title(argd['url'])) self.assertEqual(0, len(get_urls_and_titles(CFG_WEBLINKBACK_PAGE_TITLE_STATUS['OLD']))) self.assertEqual(0, len(get_urls_and_titles(CFG_WEBLINKBACK_PAGE_TITLE_STATUS['NEW']))) self.assertEqual(1, len(get_urls_and_titles(CFG_WEBLINKBACK_PAGE_TITLE_STATUS['MANUALLY_SET']))) url = CFG_SITE_URL + '/%s/42/linkbacks/' % CFG_SITE_RECORD expected_texts = ('Linkbacks to review: 5', 'Linkbacks: 1') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) def test_send_trackback(self): """weblinkback - create linkback through /sendtrackback""" url = CFG_SITE_URL + '/%s/42/linkbacks/sendtrackback?url=http://www.google.ch' % CFG_SITE_RECORD self.assertEqual([], test_web_page_content(url, username='admin', expected_text='', unexpected_text='')) url = CFG_SITE_URL + '/%s/42/linkbacks/sendtrackback' % CFG_SITE_RECORD self.assertNotEqual([], test_web_page_content(url, username='admin')) url = CFG_SITE_URL + '/%s/42/linkbacks/sendtrackback?url' % CFG_SITE_RECORD self.assertNotEqual([], test_web_page_content(url, username='admin')) url = CFG_SITE_URL + '/%s/42/linkbacks/sendtrackback?url=' % CFG_SITE_RECORD self.assertNotEqual([], test_web_page_content(url, username='admin')) add_url_to_list('google', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) url = CFG_SITE_URL + '/%s/42/linkbacks/sendtrackback?url=http://www.google.ch' % CFG_SITE_RECORD self.assertNotEqual([], test_web_page_content(url, username='admin')) def test_get_approved_latest_added_linkback(self): """weblinkback - get approved latest added linkbacks""" for linkbackid in (1, 2, 5, 6, 7): approve_linkback(linkbackid + self._max_id_lnkENTRY, self.user_info) reject_linkback(4 + self._max_id_lnkENTRY, self.user_info) self.assertEqual(0, len(get_approved_latest_added_linkbacks(0))) self.assertEqual(1, len(get_approved_latest_added_linkbacks(1))) self.assertEqual(2, len(get_approved_latest_added_linkbacks(2))) self.assertEqual(3, len(get_approved_latest_added_linkbacks(3))) self.assertEqual(4, len(get_approved_latest_added_linkbacks(4))) self.assertEqual(5, len(get_approved_latest_added_linkbacks(5))) approved_linkbacks = get_approved_latest_added_linkbacks(6) self.assertEqual(5, len(approved_linkbacks)) self.assertEqual(1 + self._max_id_lnkENTRY, approved_linkbacks[0][0]) self.assertEqual(2 + self._max_id_lnkENTRY, approved_linkbacks[1][0]) self.assertEqual(5 + self._max_id_lnkENTRY, approved_linkbacks[2][0]) self.assertEqual(6 + self._max_id_lnkENTRY, approved_linkbacks[3][0]) self.assertEqual(7 + self._max_id_lnkENTRY, approved_linkbacks[4][0]) url = CFG_SITE_URL + '/linkbacks/' expected_texts = ('URL1', 'URL2', 'URL5', 'URL6', 'URL7') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) unexpected_texts = ('URL3', 'URL4', 'URL8') for text in unexpected_texts: self.assertEqual([], test_web_page_content(url, username='admin', unexpected_text=text)) def test_url_add(self): """weblinkback - test add URL to list""" add_url_to_list('url1', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) add_url_to_list('url2', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) add_url_to_list('url3', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) admin_url_table = self.get_all_from_table('lnkADMINURL') admin_url_log_table = self.get_all_from_table('lnkADMINURLLOG') log_table = self.get_all_from_table('lnkLOG') self.assertEqual(3, len(admin_url_table)) self.assertEqual(3, len(admin_url_log_table)) self.assertEqual(12, len(log_table)) url = CFG_SITE_URL + '/admin/weblinkback/weblinkbackadmin.py/lists' expected_texts = ('url1', 'url2', 'url3') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) def test_url_remove(self): """weblinkback - test remove URL rom list""" add_url_to_list('url1', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) add_url_to_list('url2', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) remove_url('url2') # creating a different log, might detect a bug in the logging ids approve_linkback(1 + self._max_id_lnkENTRY, self.user_info) add_url_to_list('url3', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) admin_url_table = self.get_all_from_table('lnkADMINURL') admin_url_log_table = self.get_all_from_table('lnkADMINURLLOG') logTable = self.get_all_from_table('lnkLOG') self.assertEqual(2, len(admin_url_table)) self.assertEqual(2, len(admin_url_log_table)) # there are more logs due to the inserted linkbacks in setUp() self.assertEqual(12, len(logTable)) self.assertEqual(1 + self._max_id_lnkADMINURL, admin_url_table[0][0]) # there are more logs due to the inserted linkbacks in setUp() self.assertEqual(1 + self._max_id_lnkADMINURL, admin_url_log_table[0][0]) self.assertEqual(10 + self._max_id_lnkLOG, admin_url_log_table[0][1]) self.assertEqual(3 + self._max_id_lnkADMINURL, admin_url_table[1][0]) # there are more logs due to the inserted linkbacks in setUp() self.assertEqual(3 + self._max_id_lnkADMINURL, admin_url_log_table[1][0]) # 9 linkbacks inserted (9) # 2 urls inserted (11) # 1 url removed (11) (log id 10 removed) # 1 linkback approved (12) # 1 url inserted (13) self.assertEqual(13 + self._max_id_lnkLOG, admin_url_log_table[1][1]) url = CFG_SITE_URL + '/admin/weblinkback/weblinkbackadmin.py/lists' expected_texts = ('url1', 'url3') for text in expected_texts: self.assertEqual([], test_web_page_content(url, username='admin', expected_text=text)) unexpected_texts = ('url2', ) for text in unexpected_texts: self.assertEqual([], test_web_page_content(url, username='admin', unexpected_text=text)) def test_url_lists(self): """weblinkback - test URL lists""" add_url_to_list('url1', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) add_url_to_list('url2', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) add_url_to_list('url3', CFG_WEBLINKBACK_LIST_TYPE['WHITELIST'], self.user_info) self.assertEqual(('url1', 'url2'), get_url_list(CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'])) self.assertEqual(('url3', ), get_url_list(CFG_WEBLINKBACK_LIST_TYPE['WHITELIST'])) remove_url('url2') remove_url('url3') self.assertEqual(('url1', ), get_url_list(CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'])) self.assertEqual(tuple(), get_url_list(CFG_WEBLINKBACK_LIST_TYPE['WHITELIST'])) def test_url_exists(self): """weblinkback - test URL existence""" add_url_to_list('url1', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) add_url_to_list('url2', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) add_url_to_list('url3', CFG_WEBLINKBACK_LIST_TYPE['WHITELIST'], self.user_info) self.assertTrue(url_exists('url1')) self.assertTrue(url_exists('url1', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'])) self.assertFalse(url_exists('url1', CFG_WEBLINKBACK_LIST_TYPE['WHITELIST'])) remove_url('url1') self.assertFalse(url_exists('url1')) self.assertFalse(url_exists('url1', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'])) self.assertFalse(url_exists('url1', CFG_WEBLINKBACK_LIST_TYPE['WHITELIST'])) self.assertTrue(url_exists('url3')) self.assertFalse(url_exists('url3', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'])) self.assertTrue(url_exists('url3', CFG_WEBLINKBACK_LIST_TYPE['WHITELIST'])) def test_set_url_broken(self): """weblinkback - test set URL broken""" add_url_to_list('URL1', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) set_url_broken('URL1') entry_table = self.get_all_from_table('lnkENTRY') self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], entry_table[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], entry_table[8][5]) self.assertEqual(9, len(self.get_all_from_table("lnkENTRY"))) self.assertEqual(11, len(self.get_all_from_table("lnkENTRYLOG"))) def test_delete_linkbacks_on_blacklist(self): """weblinkback - test delete linkbacks on blacklist""" for linkbackid in (1, 2, 3, 4): approve_linkback(linkbackid + self._max_id_lnkENTRY, self.user_info) for linkbackid in (5, 6): reject_linkback(linkbackid + self._max_id_lnkENTRY, self.user_info) add_url_to_list('RL1', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) add_url_to_list('URL5', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) add_url_to_list('RL7', CFG_WEBLINKBACK_LIST_TYPE['BLACKLIST'], self.user_info) set_url_broken('URL1') entry_table = self.get_all_from_table('lnkENTRY') self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], entry_table[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], entry_table[8][5]) self.assertEqual(9, len(self.get_all_from_table("lnkENTRY"))) self.assertEqual(17, len(self.get_all_from_table("lnkENTRYLOG"))) self.assertEqual(20, len(self.get_all_from_table("lnkLOG"))) delete_linkbacks_on_blacklist() self.assertEqual(5, len(self.get_all_from_table("lnkENTRY"))) self.assertEqual(9, len(self.get_all_from_table("lnkENTRYLOG"))) self.assertEqual(12, len(self.get_all_from_table("lnkLOG"))) + def test_url_xml_entity_removal(self): + """weblinkback - URL XML entity removal""" + url = 'This is a test' + run_sql("INSERT INTO lnkENTRYURLTITLE ( url, title) VALUES ('URL1', %s)", (url,)) + self.assertEqual('This is a\xc2\xa0test', get_url_title(url)) + + url = 'This “is”  “”test”"' + run_sql("INSERT INTO lnkENTRYURLTITLE ( url, title) VALUES ('URL2', %s)", (url,)) + self.assertEqual('This \xe2\x80\x9cis\xe2\x80\x9d \xc2\xa0\xe2\x80\x9c\xe2\x80\x9dtest\xe2\x80\x9d"', get_url_title(url)) + + def test_get_pending_trackbacks(self): + """weblinkback - get all pending trackbacks""" + pending_trackbacks = get_all_linkbacks(linkback_type=CFG_WEBLINKBACK_TYPE['TRACKBACK'], status=CFG_WEBLINKBACK_STATUS['PENDING']) + self.assertEqual(9, len(pending_trackbacks)) + for pending_trackback in pending_trackbacks: + approve_linkback(pending_trackback[0], self.user_info) + pending_trackbacks = get_all_linkbacks(linkback_type=CFG_WEBLINKBACK_TYPE['TRACKBACK'], status=CFG_WEBLINKBACK_STATUS['PENDING']) + self.assertEqual(0, len(pending_trackbacks)) + + recid = 42 + argd = {'url': 'URL', + 'title': 'My title', + 'excerpt': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, + 'blog_name': 'Test Blog', + 'id': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, + 'source': CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME, + } + linkbackid1 = create_trackback(recid, argd['url'], argd['title'], argd['excerpt'], argd['blog_name'], argd['id'], argd['source'], self.user_info) + create_trackback(recid, argd['url'], argd['title'], argd['excerpt'], argd['blog_name'], argd['id'], argd['source'], self.user_info) + + pending_trackbacks = get_all_linkbacks(linkback_type=CFG_WEBLINKBACK_TYPE['TRACKBACK'], status=CFG_WEBLINKBACK_STATUS['PENDING']) + self.assertEqual(2, len(pending_trackbacks)) + approve_linkback(linkbackid1, self.user_info) + pending_trackbacks = get_all_linkbacks(linkback_type=CFG_WEBLINKBACK_TYPE['TRACKBACK'], status=CFG_WEBLINKBACK_STATUS['PENDING']) + self.assertEqual(1, len(pending_trackbacks)) + + create_trackback(recid, argd['url'], argd['title'], argd['excerpt'], argd['blog_name'], argd['id'], argd['source'], self.user_info) + run_sql("INSERT INTO lnkENTRY (origin_url, id_bibrec, additional_properties, type, status, insert_time) VALUES ('URLN', 41, NULL, %s, %s, NOW())", (CFG_WEBLINKBACK_TYPE['PINGBACK'], CFG_WEBLINKBACK_STATUS['PENDING'])) + pending_trackbacks = get_all_linkbacks(linkback_type=CFG_WEBLINKBACK_TYPE['TRACKBACK'], status=CFG_WEBLINKBACK_STATUS['PENDING']) + self.assertEqual(2, len(pending_trackbacks)) + def get_title_of_page_mock1(url=""): # pylint: disable=W0613 return "MOCK_TITLE1" def get_title_of_page_mock2(url=""): # pylint: disable=W0613 return "MOCK_TITLE2" def get_title_of_page_mock_broken(url=""): # pylint: disable=W0613 return None class WebLinkbackUpdaterTest(unittest.TestCase): """Test WebLinkback updater""" def setUp(self): """Insert test data""" self.user_info = {'uid': 0} self.remove_test_data() def tearDown(self): """Remove test data""" self.remove_test_data() def remove_test_data(self): """Clean tables""" self._max_id_lnkENTRY = get_max_auto_increment_id('lnkENTRY') remove_test_data() def get_all_from_table(self, tableName): return run_sql("SELECT * FROM %s" % tableName) # kwalitee: disable=sql if HAS_MOCK: def test_update_titles_of_new_linkbacks(self): """weblinkback - test update titles of new linkbacks""" self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.au&title=Google' % CFG_SITE_RECORD, username='admin')) self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.at' % CFG_SITE_RECORD, username='admin')) self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.co.za&title=Google' % CFG_SITE_RECORD, username='admin')) p = patch('invenio.weblinkback.get_title_of_page', get_title_of_page_mock1) p.start() update_linkbacks(1) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") self.assertEqual("Google", url_titles[0][2]) self.assertEqual(get_title_of_page_mock1(), url_titles[1][2]) self.assertEqual("Google", url_titles[2][2]) p.stop() if HAS_MOCK: def test_update_titles_of_old_linkbacks(self): """weblinkback - test update titles of old linkbacks""" self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.au&title=Google' % CFG_SITE_RECORD, username='admin')) self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.at' % CFG_SITE_RECORD, username='admin')) self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.co.za&title=Google' % CFG_SITE_RECORD, username='admin')) update_url_title("http://www.google.au", "Google AU") p = patch('invenio.weblinkback.get_title_of_page', get_title_of_page_mock1) p.start() update_linkbacks(2) url_entries = self.get_all_from_table("lnkENTRYURLTITLE") self.assertEqual(get_title_of_page_mock1(), url_entries[0][2]) self.assertEqual("", url_entries[1][2]) self.assertEqual("Google", url_entries[2][2]) update_linkbacks(1) p.stop() p = patch('invenio.weblinkback.get_title_of_page', get_title_of_page_mock2) p.start() update_linkbacks(2) url_entries = self.get_all_from_table("lnkENTRYURLTITLE") self.assertEqual(get_title_of_page_mock2(), url_entries[0][2]) self.assertEqual(get_title_of_page_mock2(), url_entries[1][2]) self.assertEqual("Google", url_entries[2][2]) p.stop() if HAS_MOCK: def test_update_manually_set_page_titles(self): """weblinkback - test update manually set page titles""" self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.au&title=Google' % CFG_SITE_RECORD, username='admin')) self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.at' % CFG_SITE_RECORD, username='admin')) self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.co.za&title=Google' % CFG_SITE_RECORD, username='admin')) p = patch('invenio.weblinkback.get_title_of_page', get_title_of_page_mock1) p.start() update_linkbacks(3) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") self.assertEqual(get_title_of_page_mock1(), url_titles[0][2]) self.assertEqual("", url_titles[1][2]) self.assertEqual(get_title_of_page_mock1(), url_titles[2][2]) p.stop() if HAS_MOCK: def test_detect_and_disable_broken_linkbacks(self): """weblinkback - test detect and disable broken linkbacks""" self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.au&title=Google' % CFG_SITE_RECORD, username='admin')) self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.at' % CFG_SITE_RECORD, username='admin')) self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.co.za&title=GoogleCOZA' % CFG_SITE_RECORD, username='admin')) self.assertNotEqual([], test_web_page_content(CFG_SITE_URL + '/%s/41/linkbacks/sendtrackback?url=http://www.google.co.za&title=Google' % CFG_SITE_RECORD, username='admin')) run_sql("""INSERT INTO lnkENTRYURLTITLE (url, title, manual_set, broken_count) VALUES (%s, %s, %s, %s) """, ("http://www.google.de", "Google DE", 0, 3)) p = patch('invenio.weblinkback.get_title_of_page', get_title_of_page_mock_broken) p.start() update_linkbacks(4) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual("Google", url_titles[0][2]) self.assertEqual(1, url_titles[0][4]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[0][5]) self.assertEqual("", url_titles[1][2]) self.assertEqual(1, url_titles[1][4]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[1][5]) self.assertEqual("GoogleCOZA", url_titles[2][2]) self.assertEqual(1, url_titles[2][4]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[3][5]) self.assertEqual("Google DE", url_titles[3][2]) self.assertEqual(4, url_titles[3][4]) update_linkbacks(4) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual("Google", url_titles[0][2]) self.assertEqual(2, url_titles[0][4]) self.assertEqual(0, url_titles[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[0][5]) self.assertEqual("", url_titles[1][2]) self.assertEqual(2, url_titles[1][4]) self.assertEqual(0, url_titles[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[1][5]) self.assertEqual("GoogleCOZA", url_titles[2][2]) self.assertEqual(2, url_titles[2][4]) self.assertEqual(0, url_titles[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[3][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[3][2]) self.assertEqual(5, url_titles[3][4]) self.assertEqual(1, url_titles[3][5]) update_linkbacks(4) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual("Google", url_titles[0][2]) self.assertEqual(3, url_titles[0][4]) self.assertEqual(0, url_titles[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[0][5]) self.assertEqual("", url_titles[1][2]) self.assertEqual(3, url_titles[1][4]) self.assertEqual(0, url_titles[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[1][5]) self.assertEqual("GoogleCOZA", url_titles[2][2]) self.assertEqual(3, url_titles[2][4]) self.assertEqual(0, url_titles[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[3][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[3][2]) self.assertEqual(5, url_titles[3][4]) self.assertEqual(1, url_titles[3][5]) p.stop() p = patch('invenio.weblinkback.get_title_of_page', get_title_of_page_mock1) p.start() update_linkbacks(1) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual("Google", url_titles[0][2]) self.assertEqual(3, url_titles[0][4]) self.assertEqual(0, url_titles[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[0][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[1][2]) self.assertEqual(0, url_titles[1][4]) self.assertEqual(0, url_titles[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[1][5]) self.assertEqual("GoogleCOZA", url_titles[2][2]) self.assertEqual(3, url_titles[2][4]) self.assertEqual(0, url_titles[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[3][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[3][2]) self.assertEqual(5, url_titles[3][4]) self.assertEqual(1, url_titles[3][5]) approve_linkback(4 + self._max_id_lnkENTRY, self.user_info) update_linkbacks(3) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual(get_title_of_page_mock1(), url_titles[0][2]) self.assertEqual(0, url_titles[0][4]) self.assertEqual(0, url_titles[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[0][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[1][2]) self.assertEqual(0, url_titles[1][4]) self.assertEqual(0, url_titles[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[1][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[2][2]) self.assertEqual(0, url_titles[2][4]) self.assertEqual(0, url_titles[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['APPROVED'], linkback_entries[3][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[3][2]) self.assertEqual(5, url_titles[3][4]) self.assertEqual(1, url_titles[3][5]) p.stop() p = patch('invenio.weblinkback.get_title_of_page', get_title_of_page_mock_broken) p.start() update_linkbacks(4) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual(get_title_of_page_mock1(), url_titles[0][2]) self.assertEqual(1, url_titles[0][4]) self.assertEqual(0, url_titles[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[0][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[1][2]) self.assertEqual(1, url_titles[1][4]) self.assertEqual(0, url_titles[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[1][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[2][2]) self.assertEqual(1, url_titles[2][4]) self.assertEqual(0, url_titles[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['APPROVED'], linkback_entries[3][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[3][2]) self.assertEqual(5, url_titles[3][4]) self.assertEqual(1, url_titles[3][5]) reject_linkback(1 + self._max_id_lnkENTRY, self.user_info) reject_linkback(3 + self._max_id_lnkENTRY, self.user_info) update_linkbacks(4) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual(get_title_of_page_mock1(), url_titles[0][2]) self.assertEqual(2, url_titles[0][4]) self.assertEqual(0, url_titles[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['REJECTED'], linkback_entries[0][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[1][2]) self.assertEqual(2, url_titles[1][4]) self.assertEqual(0, url_titles[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[1][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[2][2]) self.assertEqual(2, url_titles[2][4]) self.assertEqual(0, url_titles[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['REJECTED'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['APPROVED'], linkback_entries[3][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[3][2]) self.assertEqual(5, url_titles[3][4]) self.assertEqual(1, url_titles[3][5]) update_linkbacks(4) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual(get_title_of_page_mock1(), url_titles[0][2]) self.assertEqual(3, url_titles[0][4]) self.assertEqual(0, url_titles[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['REJECTED'], linkback_entries[0][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[1][2]) self.assertEqual(3, url_titles[1][4]) self.assertEqual(0, url_titles[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[1][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[2][2]) self.assertEqual(3, url_titles[2][4]) self.assertEqual(0, url_titles[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['REJECTED'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['APPROVED'], linkback_entries[3][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[3][2]) self.assertEqual(5, url_titles[3][4]) self.assertEqual(1, url_titles[3][5]) update_linkbacks(4) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual(get_title_of_page_mock1(), url_titles[0][2]) self.assertEqual(4, url_titles[0][4]) self.assertEqual(0, url_titles[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['REJECTED'], linkback_entries[0][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[1][2]) self.assertEqual(4, url_titles[1][4]) self.assertEqual(0, url_titles[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['PENDING'], linkback_entries[1][5]) self.assertEqual(get_title_of_page_mock1(), url_titles[2][2]) self.assertEqual(4, url_titles[2][4]) self.assertEqual(0, url_titles[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['REJECTED'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['APPROVED'], linkback_entries[3][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[3][2]) self.assertEqual(5, url_titles[3][4]) self.assertEqual(1, url_titles[3][5]) update_linkbacks(4) url_titles = self.get_all_from_table("lnkENTRYURLTITLE") linkback_entries = self.get_all_from_table("lnkENTRY") self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[0][2]) self.assertEqual(5, url_titles[0][4]) self.assertEqual(1, url_titles[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], linkback_entries[0][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[1][2]) self.assertEqual(5, url_titles[1][4]) self.assertEqual(1, url_titles[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], linkback_entries[1][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[2][2]) self.assertEqual(5, url_titles[2][4]) self.assertEqual(1, url_titles[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], linkback_entries[2][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], linkback_entries[3][5]) self.assertEqual(CFG_WEBLINKBACK_STATUS['BROKEN'], url_titles[3][2]) self.assertEqual(5, url_titles[3][4]) self.assertEqual(1, url_titles[3][5]) p.stop() - -TEST_SUITE = make_test_suite(WebLinkbackWebPagesAvailabilityTest, - WebLinkbackDatabaseTest, - WebLinkbackUpdaterTest) +if CFG_WEBLINKBACK_TRACKBACK_ENABLED: + TEST_SUITE = make_test_suite(WebLinkbackWebPagesAvailabilityTest, + WebLinkbackDatabaseTest, + WebLinkbackUpdaterTest) +else: + TEST_SUITE = make_test_suite() if __name__ == "__main__": run_test_suite(TEST_SUITE, warn_user=True) diff --git a/modules/weblinkback/lib/weblinkback_templates.py b/modules/weblinkback/lib/weblinkback_templates.py index c2dd31514..9142bd50a 100644 --- a/modules/weblinkback/lib/weblinkback_templates.py +++ b/modules/weblinkback/lib/weblinkback_templates.py @@ -1,284 +1,287 @@ # -*- coding: utf-8 -*- ## Comments and reviews for records. ## This file is part of Invenio. ## Copyright (C) 2011 CERN. ## ## 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. ## ## 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """WebLinkback - Web Templates""" from invenio.weblinkback_dblayer import get_all_linkbacks, \ get_url_title from invenio.weblinkback_config import CFG_WEBLINKBACK_STATUS, \ CFG_WEBLINKBACK_LATEST_COUNT_VALUES, \ CFG_WEBLINKBACK_ACTION_RETURN_CODE from invenio.weblinkback import generate_redirect_url from invenio.messages import gettext_set_language from invenio.dateutils import convert_datetext_to_dategui from invenio.config import CFG_SITE_RECORD, \ CFG_SITE_URL, \ CFG_WEBCOMMENT_USE_MATHJAX_IN_COMMENTS from invenio.htmlutils import get_mathjax_header from invenio.bibformat import format_record import cgi class Template: def tmpl_linkbacks_general(self, recid, ln): """ Display general linkback information """ _ = gettext_set_language(ln) + url = get_trackback_url(recid) out = '

' out += _("Trackback URL: ") - out += get_trackback_url(recid) + out += '%s' % (url, url) out += '

' + out += '
Trackbacks are used in blog systems to refer to external content. Please copy and paste this trackback URL to the appropriate field of your blog post if you want to refer to this record.
' + out += '
' return out def tmpl_linkbacks(self, approved_linkbacks, ln): """ Display the approved linkbacks of a record @param approved_linkbacks: approved linkbacks to display """ _ = gettext_set_language(ln) out = self.tmpl_linkbacks_count(approved_linkbacks, ln) if approved_linkbacks: out += self.tmpl_linkback_tuple(approved_linkbacks, ln) return out def tmpl_linkbacks_admin(self, pending_linkbacks, recid, ln): """ Display the pending linkbacks of a record and admin approve/reject features @param pending_linkbacks: pending linkbacks """ _ = gettext_set_language(ln) out = '' out += self.tmpl_linkbacks_count(pending_linkbacks, ln, _('to review')) out += self.tmpl_linkback_tuple_admin(url_approve_prefix=generate_redirect_url(recid, ln, 'approve'), url_reject_prefix=generate_redirect_url(recid, ln, 'reject'), linkbacks=pending_linkbacks, ln=ln) return out def tmpl_linkbacks_count(self, linkbacks, ln, additional_text = ''): """ Display the count of linkbacks plus an additional text in a grey field @param linkbacks: collection of linkbacks @param additional_text: additional text to be display """ _ = gettext_set_language(ln) middle_text = "" if additional_text != "": middle_text = " " + additional_text return self.tmpl_heading(cgi.escape(_('Linkbacks%s: %s')) % (middle_text, len(linkbacks))) def tmpl_heading(self, text): """ Display a text in a grey field @param text: text """ return '''
%s
''' % text def tmpl_linkback_tuple(self, linkbacks, ln): """ Display a linkback @param linkbacks: collection of linkbacks: [(linkback_id, origin_url, recid, additional_properties, type, status, insert_time)] """ _ = gettext_set_language(ln) out = '' for current_linkback in linkbacks: url = current_linkback[1] out += '''''' % { 'type': current_linkback[4], 'origin_url': cgi.escape(url), 'page_title': cgi.escape(get_url_title(url)), 'submit_date': '(submitted on ' + convert_datetext_to_dategui(str(current_linkback[6])) + ')'} out += '
(%(type)s)  %(page_title)s %(submit_date)s
' return out def tmpl_linkback_tuple_admin(self, url_approve_prefix, url_reject_prefix, linkbacks, ln): """ Display linkbacks with admin approve/reject features @param linkbacks: collection of linkbacks: [(linkback_id, origin_url, recid, additional_properties, type, status, insert_time)] """ _ = gettext_set_language(ln) out = '' for current_linkback in linkbacks: linkbackid = current_linkback[0] url = current_linkback[1] out += '
' out += '
 %s
' % (_('Submitted on') + ' ' + convert_datetext_to_dategui(str(current_linkback[6])) + ':') out += '
' out += '
' out += '''(%(type)s)  %(page_title)s''' % { 'type': current_linkback[4], 'origin_url': cgi.escape(url), 'page_title': cgi.escape(get_url_title(url))} out += '
' out += '
' out += '
' out += '' out += '''%s''' % (url_approve_prefix, linkbackid, _("Approve")) out += ' | ' out += '''%s''' % (url_reject_prefix, linkbackid, _("Reject")) out += '' out += '
' out += '
' return out def tmpl_get_mathjaxheader_jqueryheader(self): mathjaxheader = '' if CFG_WEBCOMMENT_USE_MATHJAX_IN_COMMENTS: mathjaxheader = get_mathjax_header() jqueryheader = ''' ''' % {'CFG_SITE_URL': CFG_SITE_URL} return (mathjaxheader, jqueryheader) def tmpl_get_latest_linkbacks_top(self, current_value, ln): """ Top elements to select the count of approved latest added linkbacks to display @param current_value: current value option will be selected if it exists """ _ = gettext_set_language(ln) result = """
%s linkbacks
""" % _("Refresh") return result def tmpl_get_latest_linkbacks(self, latest_linkbacks, ln): """ Display approved latest added linkbacks to display @param latest_linkbacks: a list of lists of linkbacks """ result = '' for i in range(len(latest_linkbacks)): day_group = latest_linkbacks[i] date = day_group[0][6] date_day_month = convert_datetext_to_dategui(str(date))[:6] result += self.tmpl_heading(date_day_month) for j in range(len(day_group)): current_linkback = day_group[j] link_type = current_linkback[4] url = str(current_linkback[1]) recordid = current_linkback[2] result += '(%s) ' % link_type result += '' result += '%s links to ' % (cgi.escape(url), cgi.escape(get_url_title(url))) result += format_record(recID=recordid, of='hs', ln=ln) result += '' result += '
' result += '
' return result def tmpl_admin_index(self, ln): """ Index page of admin interface """ _ = gettext_set_language(ln) out = '
    ' pending_linkback_count = len(get_all_linkbacks(status=CFG_WEBLINKBACK_STATUS['PENDING'])) stat_pending_text = "" if pending_linkback_count > 0: stat_pending_text = ' (' if pending_linkback_count == 1: stat_pending_text += "%s pending linkback request" % pending_linkback_count elif pending_linkback_count > 1: stat_pending_text += "%s pending linkback requests"% pending_linkback_count stat_pending_text += ')' out += '
  1. %(label)s%(stat)s
  2. ' % \ {'siteURL': CFG_SITE_URL, 'ln': ln, 'status': CFG_WEBLINKBACK_STATUS['PENDING'], 'label': _("Pending Linkbacks"), 'stat': stat_pending_text} out += '
  3. %(label)s
  4. ' % \ {'siteURL': CFG_SITE_URL, 'ln': ln, 'label': _("Recent Linkbacks")} out += '
  5. %(label)s
  6. ' % \ {'siteURL': CFG_SITE_URL, 'ln': ln, 'returnCode': CFG_WEBLINKBACK_ACTION_RETURN_CODE['OK'], 'label': _("Linkback Whitelist/Blacklist Manager")} out += '
' from invenio.bibrankadminlib import addadminbox return addadminbox('%s'% _("Menu"), [out]) def get_trackback_url(recid): return '%s/%s/%s/linkbacks/sendtrackback' % (CFG_SITE_URL, CFG_SITE_RECORD, recid) def get_trackback_auto_discovery_tag(recid): return '' \ % cgi.escape(get_trackback_url(recid), True) diff --git a/modules/weblinkback/lib/weblinkback_webinterface.py b/modules/weblinkback/lib/weblinkback_webinterface.py index 4cc98d73e..bae03f805 100644 --- a/modules/weblinkback/lib/weblinkback_webinterface.py +++ b/modules/weblinkback/lib/weblinkback_webinterface.py @@ -1,255 +1,262 @@ # -*- coding: utf-8 -*- ## Comments and reviews for records. ## This file is part of Invenio. ## Copyright (C) 2011 CERN. ## ## 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. ## ## 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """WebLinkback - Web Interface""" from invenio.messages import gettext_set_language from invenio.webinterface_handler import wash_urlargd, WebInterfaceDirectory from invenio.webuser import getUid, collect_user_info, page_not_authorized from invenio.weblinkback import check_user_can_view_linkbacks, \ perform_sendtrackback, \ perform_request_display_record_linbacks, \ - perform_request_display_approved_latest_added_linkbacks + perform_request_display_approved_latest_added_linkbacks_to_accessible_records, \ + perform_sendtrackback_disabled from invenio.weblinkback_dblayer import approve_linkback, \ reject_linkback from invenio.weblinkback_config import CFG_WEBLINKBACK_LATEST_COUNT_DEFAULT, \ CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME from invenio.urlutils import redirect_to_url, make_canonical_urlargd from invenio.config import CFG_SITE_URL, \ CFG_SITE_SECURE_URL, \ CFG_SITE_LANG, \ - CFG_SITE_RECORD + CFG_SITE_RECORD, \ + CFG_WEBLINKBACK_TRACKBACK_ENABLED from invenio.search_engine import guess_primary_collection_of_a_record, \ create_navtrail_links, \ get_colID from invenio.webpage import pageheaderonly, pagefooteronly from invenio.websearchadminlib import get_detailed_page_tabs from invenio.access_control_engine import acc_authorize_action import invenio.template webstyle_templates = invenio.template.load('webstyle') websearch_templates = invenio.template.load('websearch') weblinkback_templates = invenio.template.load('weblinkback') class WebInterfaceRecordLinkbacksPages(WebInterfaceDirectory): """Define the set of record/number/linkbacks pages.""" _exports = ['', 'display', 'index', 'approve', 'reject', 'sendtrackback'] def __init__(self, recid = -1): self.recid = recid def index(self, req, form): """ Redirect to display function """ return self.display(req, form) def display(self, req, form): """ Display the linkbacks of a record and admin approve/reject features """ argd = wash_urlargd(form, {}) _ = gettext_set_language(argd['ln']) # Check authorization uid = getUid(req) user_info = collect_user_info(req) (auth_code, auth_msg) = check_user_can_view_linkbacks(user_info, self.recid) if auth_code and user_info['email'] == 'guest': # Ask to login target = CFG_SITE_SECURE_URL + '/youraccount/login' + \ make_canonical_urlargd({'ln': argd['ln'], 'referer': CFG_SITE_URL + user_info['uri']}, {}) return redirect_to_url(req, target) elif auth_code: return page_not_authorized(req, referer="../", uid=uid, text=auth_msg, ln=argd['ln']) show_admin = False (auth_code, auth_msg) = acc_authorize_action(req, 'moderatelinkbacks', collection = guess_primary_collection_of_a_record(self.recid)) if not auth_code: show_admin = True body = perform_request_display_record_linbacks(req, self.recid, show_admin, weblinkback_templates=weblinkback_templates, ln=argd['ln']) title = websearch_templates.tmpl_record_page_header_content(req, self.recid, argd['ln'])[0] # navigation, tabs, top and bottom part navtrail = create_navtrail_links(cc=guess_primary_collection_of_a_record(self.recid), ln=argd['ln']) if navtrail: navtrail += ' > ' navtrail += ''% (CFG_SITE_URL, CFG_SITE_RECORD, self.recid, argd['ln']) navtrail += title navtrail += '' navtrail += ' > Linkbacks' mathjaxheader, jqueryheader = weblinkback_templates.tmpl_get_mathjaxheader_jqueryheader() unordered_tabs = get_detailed_page_tabs(get_colID(guess_primary_collection_of_a_record(self.recid)), self.recid, ln=argd['ln']) ordered_tabs_id = [(tab_id, values['order']) for (tab_id, values) in unordered_tabs.iteritems()] ordered_tabs_id.sort(lambda x, y: cmp(x[1], y[1])) link_ln = '' if argd['ln'] != CFG_SITE_LANG: link_ln = '?ln=%s' % argd['ln'] tabs = [(unordered_tabs[tab_id]['label'], \ '%s/%s/%s/%s%s' % (CFG_SITE_URL, CFG_SITE_RECORD, self.recid, tab_id, link_ln), \ tab_id in ['linkbacks'], unordered_tabs[tab_id]['enabled']) \ for (tab_id, values) in ordered_tabs_id if unordered_tabs[tab_id]['visible'] == True] top = webstyle_templates.detailed_record_container_top(self.recid, tabs, argd['ln']) bottom = webstyle_templates.detailed_record_container_bottom(self.recid, tabs, argd['ln']) return pageheaderonly(title=title, navtrail=navtrail, uid=uid, verbose=1, metaheaderadd = mathjaxheader + jqueryheader, req=req, language=argd['ln'], navmenuid='search', navtrail_append_title_p=0) + \ websearch_templates.tmpl_search_pagestart(argd['ln']) + \ top + body + bottom + \ websearch_templates.tmpl_search_pageend(argd['ln']) + \ pagefooteronly(language=argd['ln'], req=req) # Return the same page whether we ask for /CFG_SITE_RECORD/123/linkbacks or /CFG_SITE_RECORD/123/linkbacks/ __call__ = index def approve(self, req, form): """ Approve a linkback """ argd = wash_urlargd(form, {'linkbackid': (int, -1)}) authorization = self.check_authorization_moderatelinkbacks(req, argd) if not authorization: approve_linkback(argd['linkbackid'], collect_user_info(req)) return self.display(req, form) else: return authorization def reject(self, req, form): """ Reject a linkback """ argd = wash_urlargd(form, {'linkbackid': (int, -1)}) authorization = self.check_authorization_moderatelinkbacks(req, argd) if not authorization: reject_linkback(argd['linkbackid'], collect_user_info(req)) return self.display(req, form) else: return authorization def check_authorization_moderatelinkbacks(self, req, argd): """ Check if user has authorization moderate linkbacks @return if yes: nothing, if guest: login redirect, otherwise page_not_authorized """ # Check authorization uid = getUid(req) user_info = collect_user_info(req) (auth_code, auth_msg) = acc_authorize_action(req, 'moderatelinkbacks', collection = guess_primary_collection_of_a_record(self.recid)) if auth_code and user_info['email'] == 'guest': # Ask to login target = CFG_SITE_SECURE_URL + '/youraccount/login' + \ make_canonical_urlargd({'ln': argd['ln'], 'referer': CFG_SITE_URL + user_info['uri']}, {}) return redirect_to_url(req, target) elif auth_code: return page_not_authorized(req, referer="../", uid=uid, text=auth_msg, ln=argd['ln']) def sendtrackback(self, req, form): """ Send a new trackback """ - argd = wash_urlargd(form, {'url': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), - 'title': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), - 'excerpt': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), - 'blog_name': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), - 'id': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), - 'source': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), - }) - - perform_sendtrackback(req, self.recid, argd['url'], argd['title'], argd['excerpt'], argd['blog_name'], argd['id'], argd['source'], argd['ln']) + if CFG_WEBLINKBACK_TRACKBACK_ENABLED: + argd = wash_urlargd(form, {'url': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), + 'title': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), + 'excerpt': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), + 'blog_name': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), + 'id': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), + 'source': (str, CFG_WEBLINKBACK_SUBSCRIPTION_DEFAULT_ARGUMENT_NAME), + }) + + perform_sendtrackback(req, self.recid, argd['url'], argd['title'], argd['excerpt'], argd['blog_name'], argd['id'], argd['source'], argd['ln']) + else: + perform_sendtrackback_disabled(req) class WebInterfaceRecentLinkbacksPages(WebInterfaceDirectory): """Define the set of global /linkbacks pages.""" _exports = ['', 'display', 'index'] def index(self, req, form): """ Redirect to display function """ return self.display(req, form) def display(self, req, form): """ Display approved latest added linkbacks of the invenio instance """ argd = wash_urlargd(form, {'rg': (int, CFG_WEBLINKBACK_LATEST_COUNT_DEFAULT)}) # count must be positive if argd['rg'] < 0: argd['rg'] = -argd['rg'] _ = gettext_set_language(argd['ln']) - body = perform_request_display_approved_latest_added_linkbacks(argd['rg'], argd['ln'], weblinkback_templates=weblinkback_templates) + user_info = collect_user_info(req) + + body = perform_request_display_approved_latest_added_linkbacks_to_accessible_records(argd['rg'], argd['ln'], user_info, weblinkback_templates=weblinkback_templates) navtrail = 'Recent Linkbacks' mathjaxheader, jqueryheader = weblinkback_templates.tmpl_get_mathjaxheader_jqueryheader() return pageheaderonly(title=navtrail, navtrail=navtrail, verbose=1, metaheaderadd = mathjaxheader + jqueryheader, req=req, language=argd['ln'], navmenuid='search', navtrail_append_title_p=0) + \ websearch_templates.tmpl_search_pagestart(argd['ln']) + \ body + \ websearch_templates.tmpl_search_pageend(argd['ln']) + \ pagefooteronly(language=argd['ln'], req=req) # Return the same page whether we ask for /linkbacks or /linkbacks/ __call__ = index diff --git a/modules/webstyle/lib/webstyle_templates.py b/modules/webstyle/lib/webstyle_templates.py index 99a0439d9..30af32a96 100644 --- a/modules/webstyle/lib/webstyle_templates.py +++ b/modules/webstyle/lib/webstyle_templates.py @@ -1,1018 +1,1020 @@ ## This file is part of Invenio. -## Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 CERN. +## Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 CERN. ## ## 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. ## ## 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 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 Invenio """ __revision__ = \ "$Id$" import time import cgi import traceback import urllib import sys import string from invenio.config import \ CFG_SITE_RECORD, \ 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, \ CFG_WEBSTYLE_TEMPLATE_SKIN, \ - CFG_INSPIRE_SITE + CFG_INSPIRE_SITE, \ + CFG_WEBLINKBACK_TRACKBACK_ENABLED from invenio.messages import gettext_set_language, language_list_long, is_language_rtl from invenio.urlutils import make_canonical_urlargd, create_html_link, \ get_canonical_and_alternates_urls 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 exclusive) - '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 Note: returns empty string for Home page. (guessed by title). """ # load the right message language _ = gettext_set_language(ln) out = "" if title == CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME): # return empty string for the Home page return out else: 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="", useractivities_menu="", adminactivities_menu="", 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, body_css_classes=None, show_header=True, show_footer=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, not yet escaped for HTML - 'keywords' *string* - keywords goes to the metadata in the header of the HTML page, not yet escaped for HTML - 'userinfobox' *string* - the HTML code for the user information box - 'useractivities_menu' *string* - the HTML code for the user activities menu - 'adminactivities_menu' *string* - the HTML code for the admin activities menu - '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, not yet escaped for HTML - '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? - 'body_css_classes' *list* - list of classes to add to the body tag - 'show_header' *boolean* - tells whether page header should be displayed or not - 'show_footer' *boolean* - tells whether page footer should be displayed or not Output: - HTML code of the page """ # load the right message language _ = gettext_set_language(ln) out = '' if show_header: out += self.tmpl_pageheader(req, ln = ln, headertitle = title, description = description, keywords = keywords, metaheaderadd = metaheaderadd, userinfobox = userinfobox, useractivities_menu = useractivities_menu, adminactivities_menu = adminactivities_menu, navtrailbox = navtrailbox, pageheaderadd = pageheaderadd, uid=uid, secure_page_p = secure_page_p, navmenuid=navmenuid, rssurl=rssurl, body_css_classes=body_css_classes) out += """
%(boxlefttop)s
%(boxlefttopadd)s
%(boxleftbottomadd)s
%(boxleftbottom)s
%(boxrighttop)s
%(boxrighttopadd)s
%(boxrightbottomadd)s
%(boxrightbottom)s
%(titleprologue)s %(title)s %(titleepilogue)s %(body)s
""" % { 'boxlefttop' : boxlefttop, 'boxlefttopadd' : boxlefttopadd, 'boxleftbottom' : boxleftbottom, 'boxleftbottomadd' : boxleftbottomadd, 'boxrighttop' : boxrighttop, 'boxrighttopadd' : boxrighttopadd, 'boxrightbottom' : boxrightbottom, 'boxrightbottomadd' : boxrightbottomadd, 'titleprologue' : titleprologue, 'title' : (title and show_title_p) and '

' + cgi.escape(title) + '

' or '', 'titleepilogue' : titleepilogue, 'body' : body, } if show_footer: out += 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="", useractivities_menu="", adminactivities_menu="", navtrailbox="", pageheaderadd="", uid=0, secure_page_p=0, navmenuid="admin", metaheaderadd="", rssurl=CFG_SITE_URL+"/rss", body_css_classes=None): - from invenio.weblinkback_templates import get_trackback_auto_discovery_tag - # Embed a link in the header to subscribe trackbacks - # TODO: This hack must be replaced with the introduction of the new web framework - uri = req.unparsed_uri - recordIndexInURI = uri.find('/' + CFG_SITE_RECORD + '/') - headerLinkbackTrackbackLink = '' - # substring found --> offer trackback link in header - if recordIndexInURI != -1: - recid = uri[recordIndexInURI:len(uri)].split('/')[2].split("?")[0] #recid might end with ? for journal records - headerLinkbackTrackbackLink = get_trackback_auto_discovery_tag(recid) - """Creates a page header Parameters: - 'ln' *string* - The language to display - 'headertitle' *string* - the title of the HTML page, not yet escaped for HTML - 'description' *string* - description goes to the metadata in the header of the HTML page, not yet escaped for HTML - 'keywords' *string* - keywords goes to the metadata in the header of the HTML page, not yet escaped for HTML - 'userinfobox' *string* - the HTML code for the user information box - 'useractivities_menu' *string* - the HTML code for the user activities menu - 'adminactivities_menu' *string* - the HTML code for the admin activities menu - '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 - 'body_css_classes' *list* - list of classes to add to the body tag Output: - HTML code of the page headers """ # load the right message language _ = gettext_set_language(ln) if body_css_classes is None: body_css_classes = [] body_css_classes.append(navmenuid) + uri = req.unparsed_uri + headerLinkbackTrackbackLink = '' + if CFG_WEBLINKBACK_TRACKBACK_ENABLED: + from invenio.weblinkback_templates import get_trackback_auto_discovery_tag + # Embed a link in the header to subscribe trackbacks + # TODO: This hack must be replaced with the introduction of the new web framework + recordIndexInURI = uri.find('/' + CFG_SITE_RECORD + '/') + # substring found --> offer trackback link in header + if recordIndexInURI != -1: + recid = uri[recordIndexInURI:len(uri)].split('/')[2].split("?")[0] #recid might end with ? for journal records + headerLinkbackTrackbackLink = get_trackback_auto_discovery_tag(recid) + 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.
''' else: inspect_templates_message = "" sitename = CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME) if headertitle == sitename: pageheadertitle = headertitle else: pageheadertitle = headertitle + ' - ' + sitename out = """\ %(pageheadertitle)s %(canonical_and_alternate_urls)s %(linkbackTrackbackLink)s %(metaheaderadd)s """ % { 'rtl_direction': is_language_rtl(ln) and ' dir="rtl"' or '', 'siteurl' : CFG_SITE_URL, 'sitesecureurl' : CFG_SITE_SECURE_URL, 'canonical_and_alternate_urls' : self.tmpl_canonical_and_alternate_urls(uri), 'cssurl' : secure_page_p and CFG_SITE_SECURE_URL or CFG_SITE_URL, 'cssskin' : CFG_WEBSTYLE_TEMPLATE_SKIN != 'default' and '_' + CFG_WEBSTYLE_TEMPLATE_SKIN or '', 'rssurl': rssurl, 'ln' : ln, 'ln_iso_639_a' : ln.split('_', 1)[0], 'langlink': '?ln=' + ln, 'sitename' : CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME), 'pageheadertitle': cgi.escape(pageheadertitle), 'sitesupportemail' : CFG_SITE_SUPPORT_EMAIL, 'description' : cgi.escape(description, True), 'keywords' : cgi.escape(keywords, True), 'metaheaderadd' : metaheaderadd, 'userinfobox' : userinfobox, 'navtrailbox' : navtrailbox, 'useractivities': useractivities_menu, 'adminactivities': adminactivities_menu and (' %(adminactivities)s' % \ {'personalize_selected': navmenuid.startswith('admin') and "selected" or "", 'adminactivities': adminactivities_menu}) or ' ', 'pageheaderadd' : pageheaderadd, 'body_css_classes' : body_css_classes and ' class="%s"' % ' '.join(body_css_classes) or '', 'search_selected': navmenuid == 'search' and "selected" or "", 'submit_selected': navmenuid == 'submit' and "selected" or "", 'personalize_selected': navmenuid.startswith('your') and "selected" or "", 'help_selected': navmenuid == 'help' and "selected" or "", 'msg_search' : _("Search"), 'msg_submit' : _("Submit"), 'msg_personalize' : _("Personalize"), 'msg_help' : _("Help"), 'unAPIurl' : cgi.escape('%s/unapi' % CFG_SITE_URL), 'linkbackTrackbackLink': headerLinkbackTrackbackLink, 'inspect_templates_message' : inspect_templates_message } return out def tmpl_canonical_and_alternate_urls(self, url): """ Return the snippet of HTML to be put within the HTML HEAD tag in order to declare the canonical and language alternate URLs of a page. """ canonical_url, alternate_urls = get_canonical_and_alternates_urls(url) out = """ \n""" % cgi.escape(canonical_url, True) for ln, alternate_url in alternate_urls.iteritems(): ln = ln.replace('_', '-') ## zh_CN -> zh-CN out += """ \n""" % (ln, cgi.escape(alternate_url, True)) return out def tmpl_pagefooter(self, req=None, ln=CFG_SITE_LANG, lastupdated=None, pagefooteradd=""): """Creates a page footer Parameters: - 'ln' *string* - The language to display - 'lastupdated' *string* - when the page was last updated - 'pagefooteradd' *string* - additional page footer HTML code Output: - HTML code of the page headers """ # load the right message language _ = gettext_set_language(ln) if lastupdated and lastupdated != '$Date$': if lastupdated.startswith("$Date: ") or \ lastupdated.startswith("$Id: "): lastupdated = convert_datestruct_to_dategui(\ convert_datecvs_to_datestruct(lastupdated), ln=ln) msg_lastupdated = _("Last updated") + ": " + lastupdated else: msg_lastupdated = "" out = """ """ % { 'siteurl': CFG_SITE_URL, 'sitesecureurl': CFG_SITE_SECURE_URL, 'ln': ln, 'langlink': '?ln=' + ln, 'sitename': CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME), 'sitesupportemail': CFG_SITE_SUPPORT_EMAIL, 'msg_search': _("Search"), 'msg_submit': _("Submit"), 'msg_personalize': _("Personalize"), 'msg_help': _("Help"), 'msg_poweredby': _("Powered by"), 'msg_maintainedby': _("Maintained by"), 'msg_lastupdated': msg_lastupdated, 'languagebox': self.tmpl_language_selection_box(req, ln), 'version': CFG_VERSION, 'pagefooteradd': pagefooteradd, } return out def tmpl_language_selection_box(self, req, language=CFG_SITE_LANG): """Take URLARGS and LANGUAGE and return textual language selection box for the given page. Parameters: - 'req' - The mod_python request object - 'language' *string* - The selected language """ # load the right message language _ = gettext_set_language(language) # Work on a copy in order not to bork the arguments of the caller argd = {} if req and req.args: argd.update(cgi.parse_qs(req.args)) parts = [] for (lang, lang_namelong) in language_list_long(): if lang == language: parts.append('%s' % lang_namelong) else: # Update the 'ln' argument in the initial request argd['ln'] = lang if req and req.uri: args = urllib.quote(req.uri, '/:?') + make_canonical_urlargd(argd, {}) else: args = "" parts.append(create_html_link(args, {}, lang_namelong, {'class': "langinfo"})) if len(parts) > 1: return _("This site is also available in the following languages:") + \ "
" + '  '.join(parts) else: ## There is only one (or zero?) languages configured, ## so there so need to display language alternatives. return "" def tmpl_error_box(self, ln, title, verbose, req, errors): """Produces an error box. Parameters: - 'title' *string* - The title of the error box - 'ln' *string* - The selected language - 'verbose' *bool* - If lots of information should be displayed - 'req' *object* - the request object - 'errors' list of tuples (error_code, error_message) """ # load the right message language _ = gettext_set_language(ln) info_not_available = _("N/A") if title is None: if errors: title = _("Error") + ': %s' % errors[0][1] else: title = _("Internal Error") browser_s = _("Browser") if req: try: if req.headers_in.has_key('User-Agent'): browser_s += ': ' + req.headers_in['User-Agent'] else: browser_s += ': ' + info_not_available host_s = req.hostname page_s = req.unparsed_uri client_s = req.remote_ip except: # FIXME: bad except browser_s += ': ' + info_not_available host_s = page_s = client_s = info_not_available else: browser_s += ': ' + info_not_available host_s = page_s = client_s = info_not_available error_s = '' sys_error_s = '' traceback_s = '' if verbose >= 1: if sys.exc_info()[0]: sys_error_s = '\n' + _("System Error") + ': %s %s\n' % \ (sys.exc_info()[0], sys.exc_info()[1]) if errors: errs = '' for error_tuple in errors: try: errs += "%s%s : %s\n " % (' '*6, error_tuple[0], error_tuple[1]) except: errs += "%s%s\n" % (' '*6, error_tuple) errs = errs[6:-2] # get rid of trainling ',' error_s = _("Error") + ': %s")' % errs + "\n" else: error_s = _("Error") + ': ' + info_not_available if verbose >= 9: traceback_s = '\n' + _("Traceback") + ': \n%s' % \ string.join(traceback.format_tb(sys.exc_info()[2]), "\n") out = """

%(title)s %(sys1)s %(sys2)s

%(contact)s

 URI: http://%(host)s%(page)s
 %(time_label)s: %(time)s
 %(browser)s
 %(client_label)s: %(client)s
 %(error)s%(sys_error)s%(traceback)s
 
%(send_error_label)s
""" % { '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, citationnum=-1, referencenum=-1, discussionnum=-1): """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: @param recid: int - the id of the displayed record @param tabs: ** - the tabs displayed at the top of the box. @param ln: *string* - the language of the page in which the box is displayed @param show_similar_rec_p: *bool* print 'similar records' link in the box @param creationdate: *string* - the creation date of the displayed record @param modificationdate: *string* - the last modification date of the displayed record @param show_short_rec_p: *boolean* - prints a very short version of the record as reminder. @param citationnum: show (this) number of citations in the citations tab @param referencenum: show (this) number of references in the references tab @param discussionnum: show (this) number of comments/reviews in the discussion tab """ from invenio.search_engine import record_public_p # load the right message language _ = gettext_set_language(ln) # Prepare restriction flag restriction_flag = '' if not record_public_p(recid): restriction_flag = '
%s
' % _("Restricted") # If no tabs, returns nothing (excepted if restricted) if len(tabs) <= 1: return restriction_flag # 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: addnum = "" if (citationnum > -1) and url.count("/citation") == 1: addnum = "(" + str(citationnum) + ")" if (referencenum > -1) and url.count("/references") == 1: addnum = "(" + str(referencenum) + ")" if (discussionnum > -1) and url.count("/comments") == 1: addnum = "(" + str(discussionnum) + ")" 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 += '%(label)s %(addnum)s' % \ {'class':css_class, 'label':label, 'addnum':addnum} else: out_tabs += '%(label)s %(addnum)s ' % \ {'class':css_class, 'url':url, 'label':label, 'addnum':addnum} if out_tabs != '': out_tabs = '''
    %s
 
''' % 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} out = restriction_flag + out 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) similar = "" if show_similar_rec_p and not CFG_INSPIRE_SITE: similar = create_html_link( websearch_templates.build_search_url(p='recid:%d' % \ recid, rm='wrd', ln=ln), {}, _("Similar records"),{'class': "moreinfo"}) out = """
%(dates)s
%(similar)s

""" % {'similar' : similar, 'dates' : creationdate and '
 %(dates)s
' % { '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 attached files - 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="", 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' : 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 def tmpl_warning_message(self, ln, msg): """ Produces a warning message for the specified text Parameters: - 'ln' *string* - The language to display the interface in - 'msg' *string* - The message to display """ # load the right message language _ = gettext_set_language(ln) return """
%s
""" % msg def tmpl_write_warning(self, msg, type='', prologue='', epilogue=''): """ Returns formatted warning message. Parameters: - 'msg' *string* - The message string - 'type' *string* - the warning type - 'prologue' *string* - HTML code to display before the warning - 'epilogue' *string* - HTML code to display after the warning """ out = '\n%s' % (prologue) if type: out += '%s: ' % type out += '%s%s' % (msg, epilogue) return out