<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://wiki.eprints.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Libjlrs</id>
	<title>EPrints Documentation - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.eprints.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Libjlrs"/>
	<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/Special:Contributions/Libjlrs"/>
	<updated>2026-04-23T21:01:26Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.8</generator>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17044</id>
		<title>Transitioning from IRUS to OpenAIRE Usage Counts</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17044"/>
		<updated>2026-04-10T14:16:48Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
# Register your repository in the [https://provide.openaire.eu/home OpenAIRE Provide service]&lt;br /&gt;
# Install EPrintsOpenAIRE https://github.com/eprintsug/EprintsOpenAIRE&amp;lt;br&amp;gt;- A new version (v1.1.0) is being tested as both an [https://github.com/eprintsug/EPrintsOpenAIRE/tree/support_config_option ingredient] and a [https://github.com/eprintsug/EPrintsOpenAIRE/tree/support_config_option-epm Bazaar/EPM package]. &lt;br /&gt;
# Make sure repository is getting harvested in OpenAIRE Provide&lt;br /&gt;
# Install tracker NB we need to consolidate these (which are in approx. chronological order):&lt;br /&gt;
## https://github.com/Rudjer-Boskovic-Institute/EPrints-OAPiwik &lt;br /&gt;
## https://github.com/openaire/EPrints-OAPiwik (forked from the above)&lt;br /&gt;
## https://github.com/alex-ball/EPrints-OAPing&lt;br /&gt;
## https://github.com/eprints/EPrints-OAPiwik ''I think this is where the official release will live?''&lt;br /&gt;
# Check data is being received - OpenAIRE is only updated monthly&lt;br /&gt;
# remove/disable IRUS tracker&lt;br /&gt;
&lt;br /&gt;
== Instructions for sending historic data ==&lt;br /&gt;
See notes in Eprints-OAPiwik?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
# [https://www.openaire.eu/?view=article&amp;amp;id=2343&amp;amp;catid=255 UsageCounts – How to track the usage activity of your repository]&lt;br /&gt;
# [https://usagecounts.openaire.eu/resources#apis OpenAIRE - Provide - APIs and reports (COUNTER v4 compliant!?)]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17043</id>
		<title>Transitioning from IRUS to OpenAIRE Usage Counts</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17043"/>
		<updated>2026-04-10T14:15:54Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
# Register your repository in the [https://provide.openaire.eu/home OpenAIRE Provide service]&lt;br /&gt;
# Install EPrintsOpenAIRE https://github.com/eprintsug/EprintsOpenAIRE&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A new version (v1.1.0) is being tested as both an [https://github.com/eprintsug/EPrintsOpenAIRE/tree/support_config_option ingredient] and a [https://github.com/eprintsug/EPrintsOpenAIRE/tree/support_config_option-epm Bazaar/EPM package]. &lt;br /&gt;
# Make sure repository is getting harvested in OpenAIRE Provide&lt;br /&gt;
# Install tracker NB we need to consolidate these (which are in approx. chronological order):&lt;br /&gt;
## https://github.com/Rudjer-Boskovic-Institute/EPrints-OAPiwik &lt;br /&gt;
## https://github.com/openaire/EPrints-OAPiwik (forked from the above)&lt;br /&gt;
## https://github.com/alex-ball/EPrints-OAPing&lt;br /&gt;
## https://github.com/eprints/EPrints-OAPiwik ''I think this is where the official release will live?''&lt;br /&gt;
# Check data is being received - OpenAIRE is only updated monthly&lt;br /&gt;
# remove/disable IRUS tracker&lt;br /&gt;
&lt;br /&gt;
== Instructions for sending historic data ==&lt;br /&gt;
See notes in Eprints-OAPiwik?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
# [https://www.openaire.eu/?view=article&amp;amp;id=2343&amp;amp;catid=255 UsageCounts – How to track the usage activity of your repository]&lt;br /&gt;
# [https://usagecounts.openaire.eu/resources#apis OpenAIRE - Provide - APIs and reports (COUNTER v4 compliant!?)]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17042</id>
		<title>Transitioning from IRUS to OpenAIRE Usage Counts</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17042"/>
		<updated>2026-04-10T14:14:41Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
# Register your repository in the [https://provide.openaire.eu/home OpenAIRE Provide service]&lt;br /&gt;
# Install EPrintsOpenAIRE https://github.com/eprintsug/EprintsOpenAIRE&lt;br /&gt;
## A new version (v1.1.0) is being tested as both an [https://github.com/eprintsug/EPrintsOpenAIRE/tree/support_config_option ingredient] and a [https://github.com/eprintsug/EPrintsOpenAIRE/tree/support_config_option-epm Bazaar/EPM package]. &lt;br /&gt;
# Make sure repository is getting harvested in OpenAIRE Provide&lt;br /&gt;
# Install tracker NB we need to consolidate these (which are in approx. chronological order):&lt;br /&gt;
## https://github.com/Rudjer-Boskovic-Institute/EPrints-OAPiwik &lt;br /&gt;
## https://github.com/openaire/EPrints-OAPiwik (forked from the above)&lt;br /&gt;
## https://github.com/alex-ball/EPrints-OAPing&lt;br /&gt;
## https://github.com/eprints/EPrints-OAPiwik ''I think this is where the official release will live?''&lt;br /&gt;
# Check data is being received - OpenAIRE is only updated monthly&lt;br /&gt;
# remove/disable IRUS tracker&lt;br /&gt;
&lt;br /&gt;
== Instructions for sending historic data ==&lt;br /&gt;
See notes in Eprints-OAPiwik?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
# [https://www.openaire.eu/?view=article&amp;amp;id=2343&amp;amp;catid=255 UsageCounts – How to track the usage activity of your repository]&lt;br /&gt;
# [https://usagecounts.openaire.eu/resources#apis OpenAIRE - Provide - APIs and reports (COUNTER v4 compliant!?)]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17039</id>
		<title>Transitioning from IRUS to OpenAIRE Usage Counts</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17039"/>
		<updated>2026-03-19T08:34:37Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
# Register in OpenAIRE [link]&lt;br /&gt;
# Install EPrintsOpenAIRE https://github.com/eprintsug/EprintsOpenAIRE&lt;br /&gt;
# Make sure repository is getting harvested https://provide.openaire.eu/&lt;br /&gt;
# Install tracker NB we need to consolidate these (which are in approx. chronological order):&lt;br /&gt;
## https://github.com/Rudjer-Boskovic-Institute/EPrints-OAPiwik &lt;br /&gt;
## https://github.com/openaire/EPrints-OAPiwik (forked from the above)&lt;br /&gt;
## https://github.com/alex-ball/EPrints-OAPing&lt;br /&gt;
## https://github.com/eprints/EPrints-OAPiwik&lt;br /&gt;
# Check data is being received&lt;br /&gt;
# remove/disable IRUS tracker&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
# [https://www.openaire.eu/?view=article&amp;amp;id=2343&amp;amp;catid=255 UsageCounts – How to track the usage activity of your repository]&lt;br /&gt;
# [https://usagecounts.openaire.eu/resources#apis OpenAIRE - Provide - APIs and reports (COUNTER v4 compliant!?)]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17038</id>
		<title>Transitioning from IRUS to OpenAIRE Usage Counts</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17038"/>
		<updated>2026-03-05T16:23:43Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
# Register in OpenAIRE [link]&lt;br /&gt;
# Install EPrintsOpenAIRE https://github.com/eprintsug/EprintsOpenAIRE&lt;br /&gt;
# Make sure repository is getting harvested https://provide.openaire.eu/&lt;br /&gt;
# Install tracker NB we need to consolidate these (which are in approx. chronological order):&lt;br /&gt;
## https://github.com/Rudjer-Boskovic-Institute/EPrints-OAPiwik &lt;br /&gt;
## https://github.com/openaire/EPrints-OAPiwik (forked from the above)&lt;br /&gt;
## https://github.com/alex-ball/EPrints-OAPing&lt;br /&gt;
## https://github.com/eprints/EPrints-OAPiwik&lt;br /&gt;
# Check data is being received&lt;br /&gt;
# remove/disable IRUS tracker&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17037</id>
		<title>Transitioning from IRUS to OpenAIRE Usage Counts</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Transitioning_from_IRUS_to_OpenAIRE_Usage_Counts&amp;diff=17037"/>
		<updated>2026-03-04T12:26:43Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Created page with &amp;quot; # Register in OpenAIRE [link] # Install EPrintsOpenAIRE https://github.com/eprintsug/EprintsOpenAIRE # Make sure repository is getting harvested https://provide.openaire.eu/...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
# Register in OpenAIRE [link]&lt;br /&gt;
# Install EPrintsOpenAIRE https://github.com/eprintsug/EprintsOpenAIRE&lt;br /&gt;
# Make sure repository is getting harvested https://provide.openaire.eu/&lt;br /&gt;
# Install tracker&lt;br /&gt;
# Check data is being received&lt;br /&gt;
# remove/disable IRUS tracker&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Altmetric_badges&amp;diff=16990</id>
		<title>Altmetric badges</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Altmetric_badges&amp;diff=16990"/>
		<updated>2025-11-06T15:03:08Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Altmetric plugin for EPrints is available from the [https://bazaar.eprints.org/1300/ Bazaar] or [https://github.com/eprintsug/altmetric/ GitHub] (see the '3_4' branch for the 'ingredient' version).&lt;br /&gt;
&lt;br /&gt;
== Changes (November 2025) - API key now mandatory ==&lt;br /&gt;
Before v2.0.0 the Altmetric plugin used the Altmetric API to get data. In v2.0.0+ this has been updated to use the API if an API key is defined, and fall back to &lt;br /&gt;
the Altmetric 'embed' script to display the badges.&lt;br /&gt;
&lt;br /&gt;
Please see the README at https://github.com/eprintsug/altmetric/ for full details.&lt;br /&gt;
&lt;br /&gt;
You can also embed the badges without this plugin - see instructions here: [https://badge-docs.altmetric.com/index.html], although the plugin assists in finding relevant identifiers within a record to display.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Altmetric_badges&amp;diff=16985</id>
		<title>Altmetric badges</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Altmetric_badges&amp;diff=16985"/>
		<updated>2025-10-21T14:56:56Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Created page with &amp;quot;The Altmetric plugin for EPrints is available from the [https://bazaar.eprints.org/555/ Bazaar] or [https://github.com/eprintsug/altmetric/ GitHub].  The Altmetric badges can...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Altmetric plugin for EPrints is available from the [https://bazaar.eprints.org/555/ Bazaar] or [https://github.com/eprintsug/altmetric/ GitHub].&lt;br /&gt;
&lt;br /&gt;
The Altmetric badges can also be added to pages by following the instructions here: [https://badge-docs.altmetric.com/index.html]&lt;br /&gt;
&lt;br /&gt;
== Changes (November 2025) - API key now mandatory ==&lt;br /&gt;
The Altmetric plugin uses the Altmetric API to get data. If you are using this to display Altmetric badges, please check to see if you have an API key defined.&lt;br /&gt;
This should be in &amp;lt;code&amp;gt;EPRINTS_ROOT/archives/ARCHIVEID/cfg/cfg.d/z_altmetric.pl&amp;lt;/code&amp;gt;, although may have been defined in another config file.&lt;br /&gt;
&lt;br /&gt;
From: https://github.com/eprintsug/altmetric/blob/main/cfg/cfg.d/z_altmetric.pl#L20-L21&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=perl&amp;gt;&lt;br /&gt;
# Optional API key - see http://api.altmetric.com/index.html#keys&lt;br /&gt;
# $c-&amp;gt;{altmetric}-&amp;gt;{api_key} = &amp;quot;&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An upcoming update to the plugin will start requiring this to be set before rendering a badge on a page.&lt;br /&gt;
&lt;br /&gt;
The future of this integration may be a deprecation of the 'API' route, and support a configurable embedded badge instead.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Shibboleth&amp;diff=16941</id>
		<title>Shibboleth</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Shibboleth&amp;diff=16941"/>
		<updated>2025-08-07T15:33:53Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Using Remote IdP Metatdata */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Manual}}&lt;br /&gt;
'''This page details how to install and integrate Shibboleth with EPrints 3.3.x or 3.4.x on a CentOS 7 operating system.'''  The process should be fairly similar for other comparable Red Hat based Linux distributions such as RHEL 7 and Fedora 21/22.  These instructions should also be generally applicable to later versions of RHEL-based Linux (e.g. Rocky Linux 8, Red Hat Enterprise Linux 9, etc.). However, they may be somewhat different for Debian-based Linux, such as Ubuntu and Debian itself and other Linux distributions.  Typically, this will just be different package names and different commands to manage applications.&lt;br /&gt;
&lt;br /&gt;
Generally, it is a good idea to run EPrints with '''HTTPS''' when using Shibboleth authentication for increased security on the attributes being sent back by the Shibboleth Identity Provider (IdP).  Therefore, it is assumed that EPrints has already been set up to use HTTPS and there already exists an '''ssl/securevhost.conf''' under the archive directory structure.&lt;br /&gt;
&lt;br /&gt;
== Installing Shibboleth ==&lt;br /&gt;
* First, add the Shibboleth repository to your list of YUM repositories (if you need this for a different RHEL-based Linux distribution fill in the form at https://shibboleth.net/downloads/service-provider/latest/RPMS/):&lt;br /&gt;
  root&amp;gt; wget -O /etc/yum.repos.d/shibboleth.repo https://shibboleth.net/cgi-bin/sp_repo.cgi?platform=CentOS_7&lt;br /&gt;
&lt;br /&gt;
* Now you can use Yum to install all package dependencies:&lt;br /&gt;
  root&amp;gt; yum install log4shib opensaml shibboleth unixODBC xerces-c xml-security-c xmltooling &lt;br /&gt;
&lt;br /&gt;
* You may be prompted to accept the importing of the key for the Shibboleth repository, for which you should type '''y''' and press enter.&lt;br /&gt;
&lt;br /&gt;
* Once you have done that, test that '''shibd''' has no issues:&lt;br /&gt;
  root&amp;gt; LD_LIBRARY_PATH=/opt/shibboleth/lib64 shibd -t&lt;br /&gt;
&lt;br /&gt;
* ''shibd -t'' should return a couple of warning, like those listed below.  These are due to it not yet being configured.&lt;br /&gt;
  2015-05-11 10:39:01 WARN Shibboleth.Application : insecure cookieProps setting, set to &amp;quot;https&amp;quot; for SSL/TLS-only usage&lt;br /&gt;
  2015-05-11 10:39:01 WARN Shibboleth.Application : handlerSSL should be enabled for SSL/TLS-enabled web sites&lt;br /&gt;
  2015-05-11 10:39:01 WARN Shibboleth.Application : no MetadataProvider available, configure at least one for standard SSO usage&lt;br /&gt;
  overall configuration is loadable, check console for non-fatal problems&lt;br /&gt;
&lt;br /&gt;
* If there are no other warning or error messages from ''shibd -t'', you can start it properly and check to make sure it is running. You may also want ensure Shibboleth starts at boot using '''systemctl  enable'''&lt;br /&gt;
  root&amp;gt; systemctl start shibd.service&lt;br /&gt;
  root&amp;gt; ps aux | grep shib&lt;br /&gt;
  shibd    29338  0.4  0.7 419784 15024 ?        Ssl  11:16   0:00 /usr/sbin/shibd -p /var/run/shibboleth/shibd.pid -f -w 30&lt;br /&gt;
  root     29345  0.0  0.0 112640   940 pts/2    S+   11:17   0:00 grep --color=auto -i shib&lt;br /&gt;
  root&amp;gt; systemctl enable shibd.service&lt;br /&gt;
&lt;br /&gt;
== Configuring Shibboleth ==&lt;br /&gt;
* Replace '''/etc/shibboleth/shibboleth2.xml''' with the following.  Substitute '''foo.eprints.org''' for the hostname of your EPrints repository, '''https://shib.foo.example.org/idp/shibboleth''' with the entity ID for you Shibboleth IdP and '''foo''' in the pathname of files with the name or your repository (e.g. ''foo/attribute-map.xml'' becomes ''myrepo/attribute-map.xml'').  '''(This configuration is intended for Shibboleth SP version 2.x and is liable to cause deprecation warnings if  you have installed a recent version of Shibboleth from a package repository.  [[Shibboleth/3.x|Here is a default shibboleth2.xml configuration for Shibboleth 3.x]]).'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;SPConfig xmlns=&amp;quot;urn:mace:shibboleth:3.0:native:sp:config&amp;quot;&lt;br /&gt;
    xmlns:conf=&amp;quot;urn:mace:shibboleth:3.0:native:sp:config&amp;quot;&lt;br /&gt;
    clockSkew=&amp;quot;180&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;ApplicationDefaults entityID=&amp;quot;https://foo.eprints.org/shibboleth&amp;quot;&lt;br /&gt;
                         REMOTE_USER=&amp;quot;eppn subject-id pairwise-id persistent-id&amp;quot;&lt;br /&gt;
                         cipherSuites=&amp;quot;DEFAULT:!EXP:!LOW:!aNULL:!eNULL:!DES:!IDEA:!SEED:!RC4:!3DES:!kRSA:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
      &amp;lt;Sessions lifetime=&amp;quot;28800&amp;quot; timeout=&amp;quot;3600&amp;quot; relayState=&amp;quot;ss:mem&amp;quot; &lt;br /&gt;
                checkAddress=&amp;quot;false&amp;quot; handlerSSL=&amp;quot;true&amp;quot; cookieProps=&amp;quot;https&amp;quot;&lt;br /&gt;
                redirectLimit=&amp;quot;exact&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;SSO entityID=&amp;quot;https://shib.foo.example.org/idp/shibboleth&amp;quot;&amp;gt;SAML2&amp;lt;/SSO&amp;gt;&lt;br /&gt;
        &amp;lt;Logout&amp;gt;SAML2 Local&amp;lt;/Logout&amp;gt;&lt;br /&gt;
        &amp;lt;LogoutInitiator type=&amp;quot;Admin&amp;quot; Location=&amp;quot;/Logout/Admin&amp;quot; acl=&amp;quot;127.0.0.1 ::1&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Handler type=&amp;quot;Status&amp;quot; Location=&amp;quot;/Status&amp;quot; acl=&amp;quot;127.0.0.1 ::1&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;Handler type=&amp;quot;Session&amp;quot; Location=&amp;quot;/Session&amp;quot; showAttributeValues=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;Handler type=&amp;quot;DiscoveryFeed&amp;quot; Location=&amp;quot;/DiscoFeed&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/Sessions&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
      &amp;lt;Errors supportContact=&amp;quot;root@localhost&amp;quot; helpLocation=&amp;quot;/about.html&amp;quot; styleSheet=&amp;quot;/shibboleth/main.css&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;MetadataProvider type=&amp;quot;XML&amp;quot; path=&amp;quot;foo/idp-metadata.xml&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;AttributeExtractor type=&amp;quot;XML&amp;quot; validate=&amp;quot;true&amp;quot; reloadChanges=&amp;quot;false&amp;quot; path=&amp;quot;foo/attribute-map.xml&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;AttributeFilter type=&amp;quot;XML&amp;quot; validate=&amp;quot;true&amp;quot; path=&amp;quot;attribute-policy.xml&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;CredentialResolver type=&amp;quot;File&amp;quot; use=&amp;quot;signing&amp;quot; key=&amp;quot;foo/sp-key.pem&amp;quot; certificate=&amp;quot;foo/sp-cert.pem&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;CredentialResolver type=&amp;quot;File&amp;quot; use=&amp;quot;encryption&amp;quot; key=&amp;quot;foo/sp-key.pem&amp;quot; certificate=&amp;quot;foo/sp-cert.pem&amp;quot;/&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;/ApplicationDefaults&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;SecurityPolicyProvider type=&amp;quot;XML&amp;quot; validate=&amp;quot;true&amp;quot; path=&amp;quot;security-policy.xml&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;ProtocolProvider type=&amp;quot;XML&amp;quot; validate=&amp;quot;true&amp;quot; reloadChanges=&amp;quot;false&amp;quot; path=&amp;quot;protocols.xml&amp;quot;/&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
  &amp;lt;/SPConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Create the directory '''/etc/shibboleth/foo''', substituting ''foo'' for your repository name.&lt;br /&gt;
  root&amp;gt; mkdir /etc/shibboleth/foo&lt;br /&gt;
&lt;br /&gt;
* Copy '''attribute-map.xml''' into this new directory.&lt;br /&gt;
  cp /etc/shibboleth/attribute-map.xml /etc/shibboleth/foo/&lt;br /&gt;
&lt;br /&gt;
* Temporarily rename '''sp-cert.pem''' and '''sp-key.pem''' in '''/etc/shibboleth/''' to '''sp-cert.pem.old''' and '''sp-key.pem.old'''.&lt;br /&gt;
  root&amp;gt; cd /etc/shibboleth&lt;br /&gt;
  root&amp;gt; mv sp-cert.pem sp-cert.pem.old&lt;br /&gt;
  root&amp;gt; mv sp-key.pem sp-key.pem.old&lt;br /&gt;
&lt;br /&gt;
* Run '''keygen.sh''' from the '''/etc/shibboleth/''' directory, as follows replacing '''foo.eprints.org''' with your EPrints repository hostname.&lt;br /&gt;
  root&amp;gt; cd /etc/shibboleth&lt;br /&gt;
  root&amp;gt; ./keygen.sh -f -h foo.eprints.org -e https://foo.eprints.org/shibboleth&lt;br /&gt;
&lt;br /&gt;
* Move the new '''sp-cert.pem''' and '''sp-key.pem''' to '''/etc/shibboleth/foo/''' and move the ''.old'' files back in place:&lt;br /&gt;
  root&amp;gt; cd /etc/shibboleth&lt;br /&gt;
  root&amp;gt; mv sp-cert.pem sp-key.pem foo/&lt;br /&gt;
  root&amp;gt; mv sp-cert.pem.old sp-cert.pem&lt;br /&gt;
  root&amp;gt; mv sp-key.pem.old sp-key.pem&lt;br /&gt;
&lt;br /&gt;
* Check that '''sp-cert.pem''' and '''sp-key.pem''' in '''/etc/shibboleth/foo/''' still have the owner and group '''shibd'''.&lt;br /&gt;
  root&amp;gt; ls -l /etc/shibboleth/foo/sp-*&lt;br /&gt;
  -rw-r--r-- 1 shibd shibd 1192 May  6 19:04 /etc/shibboleth/foo/sp-cert.pem&lt;br /&gt;
  -rw------- 1 shibd shibd 1708 May  6 19:04 /etc/shibboleth/foo/sp-key.pem&lt;br /&gt;
&lt;br /&gt;
* Run '''metagen.sh''' from the '''/etc/shibboleth/''' directory, as follows replacing '''foo.eprints.org''' with your EPrints repository hostname.  You will ultimately need to send the output of this to the person managing the Shibboleth IdP server with which you want to register your EPrints repository as a service.&lt;br /&gt;
  root&amp;gt; cd /etc/shibboleth&lt;br /&gt;
  root&amp;gt; ./metagen.sh -ALO -c foo/sp-cert.pem -h foo.eprints.org -e https://foo.eprints.org/shibboleth &amp;gt; foo/sp_metadata.xml&lt;br /&gt;
&lt;br /&gt;
* Modify ''' foo/sp_metadata.xml''' to add in the namepace definitions by separately changing the &amp;lt;code&amp;gt;md:EntityDescriptor&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ds:KeyInfo&amp;lt;/code&amp;gt; lines as follows from:&lt;br /&gt;
 &amp;lt;md:EntityDescriptor entityID=&amp;quot;https://foo.eprints.org/shibboleth&amp;quot;&amp;gt;&lt;br /&gt;
   ...&lt;br /&gt;
     ...&lt;br /&gt;
       &amp;lt;ds:KeyInfo&amp;gt;&lt;br /&gt;
to:&lt;br /&gt;
 &amp;lt;md:EntityDescriptor xmlns:md=&amp;quot;urn:oasis:names:tc:SAML:2.0:metadata&amp;quot; entityID=&amp;quot;https://foo.eprints.org/shibboleth&amp;quot;&amp;gt; &lt;br /&gt;
   ...&lt;br /&gt;
     ...&lt;br /&gt;
       &amp;lt;ds:KeyInfo xmlns:ds=&amp;quot;http://www.w3.org/2000/09/xmldsig#&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use ''wget'' to download the metadata from your Shibboleth IdP (e.g. shib.foo.example.org) to the '''/etc/shibboleth/foo/''' directory.&lt;br /&gt;
  root&amp;gt; wget -O /etc/shibboleth/foo/idp-metadata.xml https://shib.foo.example.org/idp/shibboleth&lt;br /&gt;
&lt;br /&gt;
=== Using Remote IdP Metatdata ===&lt;br /&gt;
&lt;br /&gt;
As IdP Metadata may expire, you may want to use the remote metadata URL rather than a local copy.  This is what you need to do to switch to using remote IdP metadata:&lt;br /&gt;
&lt;br /&gt;
* Edit the '''MetadataProvider''' line to something like the following.  The reloadInterval is best set to 7200 but this can be set less frequently:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;MetadataProvider type=&amp;quot;XML&amp;quot; url=&amp;quot;https://shib.foo.example.org/idp/metadata.xml&amp;quot; backingFilePath=&amp;quot;foo/idp-metadata.xml&amp;quot; reloadInterval=&amp;quot;7200&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Make sure the reloadInterval is appropriate for the IdP metadata you are downloading.  If you have large metadata file,(e.g. from a federated metadata service containing metadata for other IdPs), then it may be better to set this higher than the default.  However, the configuration checker may warn you that your reload interval is too long, so you may have to choose to ignore this, if you want to avoid downloading a large federated metadata file too often.&lt;br /&gt;
&lt;br /&gt;
* Make sure that the directory '''/etc/shibboleth/foo/''' and '''/etc/shibboleth/foo/idp-metadata.xml''' if it already exists) are owned by '''shibd''':&lt;br /&gt;
&lt;br /&gt;
 chown shibd:shibd /etc/shibboleth/foo/&lt;br /&gt;
 chown shibd:shibd /etc/shibboleth/foo/idp-metadata.xml&lt;br /&gt;
&lt;br /&gt;
* To test Shibboleth you will need to make sure your '''LD_LIBRARY_PATH''' is set the same as shibd would have when started using ''systemctl shibd start''.&lt;br /&gt;
 &lt;br /&gt;
 LD_LIBRARY_PATH=/opt/shibboleth/lib64:$LD_LIBRARY_PATH shibd -t&lt;br /&gt;
This should return the message: ''overall configuration is loadable, check console for non-fatal problems''.&lt;br /&gt;
&lt;br /&gt;
* The above message is because it is now advised not to leave the MetadataGenerator enabled unnecessarily.  However, whilst you are setting up Shibboleth, it is useful to have the metadata generator, save you needing to build your own Service Provider metadata file to register with your Identity Provider.  Later on you can comment out the MetadataGenerator line to stop getting this warning message.&lt;br /&gt;
&lt;br /&gt;
* Now you can restart '''shibd''' properly:&lt;br /&gt;
&lt;br /&gt;
 systemctl restart shibd&lt;br /&gt;
&lt;br /&gt;
== Configuring Apache and EPrints ==&lt;br /&gt;
'''N.B. All these actions should be carried out by the ''eprints'' user, except when prepended with ''root&amp;gt;'' which means the command should be run as the ''root'' user.'''&lt;br /&gt;
* Add the following configuration to your archive's '''ssl/securevhost.conf''', after the '''Include /opt/eprints3/cfg/apache_ssl/foo.conf''', substituting '''foo''' for your archive's name where appropriate.  (This assumes you are running Apache 2.4 or greater).  See [[#Apache 2.2 (and lower) Configuration for EPrints Shibboleth Integration |Troubleshooting]] for instructions on the configuration to use for Apache 2.2. or lower.&lt;br /&gt;
&lt;br /&gt;
 Alias /shibboleth /opt/eprints3/archives/foo/shibboleth&lt;br /&gt;
 &amp;lt;Location &amp;quot;/shibboleth&amp;quot;&amp;gt;&lt;br /&gt;
   SetHandler perl-script&lt;br /&gt;
   PerlHandler ModPerl::Registry&lt;br /&gt;
   PerlSendHeader Off&lt;br /&gt;
   Options ExecCGI FollowSymLinks&lt;br /&gt;
 &lt;br /&gt;
   AuthType shibboleth&lt;br /&gt;
   ShibRequestSetting requireSession 1&lt;br /&gt;
   require shib-session&lt;br /&gt;
 &amp;lt;/Location&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;Location /cgi/shibboleth&amp;gt;&lt;br /&gt;
   AuthType shibboleth&lt;br /&gt;
   ShibRequestSetting requireSession 1&lt;br /&gt;
   require shib-session&lt;br /&gt;
 &amp;lt;/Location&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Copy the following code into your archive (e.g. /opt/eprints3/archives/foo/) as '''cgi/shibboleth'''.&lt;br /&gt;
 use EPrints;&lt;br /&gt;
 use strict;&lt;br /&gt;
 my $session = new EPrints::Session;&lt;br /&gt;
 exit( 0 ) unless( defined $session );&lt;br /&gt;
 &lt;br /&gt;
 $session-&amp;gt;send_http_header( &amp;quot;content_type&amp;quot; =&amp;gt; &amp;quot;text/html&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
 print &amp;quot;&amp;amp;lt;html&amp;amp;gt;&amp;amp;lt;head/&amp;amp;gt;&amp;amp;lt;body&amp;amp;gt;&amp;amp;lt;code&amp;amp;gt;\n&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 foreach my $key (sort keys(%ENV)) {&lt;br /&gt;
   print &amp;quot;&amp;amp;lt;p&amp;amp;gt;$key = $ENV{$key}&amp;amp;lt;/p&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 print &amp;quot;&amp;amp;lt;/code&amp;amp;gt;&amp;amp;lt;/body&amp;amp;gt;&amp;amp;lt;/html&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit;&lt;br /&gt;
&lt;br /&gt;
* Now restart Shibboleth and Apache:&lt;br /&gt;
  root&amp;gt; systemctl restart shibd.service&lt;br /&gt;
  root&amp;gt; apachectl restart&lt;br /&gt;
&lt;br /&gt;
* In a web browser go the '''/cgi/shibboleth''' page for your repository, (e.g. ''https://foo.eprints.org/cgi/shibboleth'').  You should be redirected to an error page for your your Shibboleth IdP (e.g. ''https://shib.foo.example.org/idp/profile/SAML2/Redirect/SSO?...'').  &lt;br /&gt;
&lt;br /&gt;
* If instead you are displayed with a list of key values or are forbidden to access the page, you have not configured Apache properly, if so, see [[#Apache_Configuration_Issues|Apache_Configuration_Issues]] under [[#Troubleshooting|Troubleshooting]].  If you see an error message like the one below, you have not set up Shibboleth properly, if so, see [[#Shibboleth_Configuration_Issues|Shibboleth_Configuration_Issues]] under [[#Troubleshooting|Troubleshooting]].&lt;br /&gt;
 opensaml::saml2md::MetadataException&lt;br /&gt;
 The system encountered an error at Wed May 6 15:19:27 2015&lt;br /&gt;
 To report this problem, please contact the site administrator at root@localhost.&lt;br /&gt;
 Please include the following message in any email:&lt;br /&gt;
 opensaml::saml2md::MetadataException at (http://foo.eprints.org/cgi/shibboleth)&lt;br /&gt;
 Unable to locate metadata for identity provider (https://shib.foo.example.org/idp/shibboleth)&lt;br /&gt;
&lt;br /&gt;
* Next, copy the following code into your archive (e.g. ''/opt/eprints3/archives/foo/'') as '''cfg/cfg.d/zz_shibboleth.pl'''.  This is needed to redirect login and logout to use Shibboleth rather than local login.&lt;br /&gt;
 $c-&amp;gt;{get_login_url} = sub {&lt;br /&gt;
   my( $session, $target ) = @_;&lt;br /&gt;
 &lt;br /&gt;
   # preserve CGI params&lt;br /&gt;
   $session-&amp;gt;read_params;&lt;br /&gt;
   $target = $session-&amp;gt;get_url(&lt;br /&gt;
     host =&amp;gt; 1,&lt;br /&gt;
     path =&amp;gt; &amp;quot;auto&amp;quot;,&lt;br /&gt;
     query =&amp;gt; 1,&lt;br /&gt;
   );&lt;br /&gt;
 &lt;br /&gt;
   my $url = URI-&amp;gt;new( $session-&amp;gt;config( &amp;quot;https_url&amp;quot; )  . &amp;quot;/shibboleth/login&amp;quot; );&lt;br /&gt;
   $url-&amp;gt;query_form( target =&amp;gt; &amp;quot;$target&amp;quot; );&lt;br /&gt;
   return &amp;quot;$url&amp;quot;;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 $c-&amp;gt;{on_logout} = sub {&lt;br /&gt;
   my( $session ) = @_;&lt;br /&gt;
   my $query = $session-&amp;gt;query;&lt;br /&gt;
   return unless defined $query;&lt;br /&gt;
 &lt;br /&gt;
   # remove _shibsession_ cookie&lt;br /&gt;
   my( $shibname, $shibvalue );&lt;br /&gt;
   for( $query-&amp;gt;cookie() ) {&lt;br /&gt;
     if( $_ =~ /^_shibsession/ ) {&lt;br /&gt;
       $shibname = $_;&lt;br /&gt;
       $shibvalue = $query-&amp;gt;cookie( $shibname );&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   my $cookie = $query-&amp;gt;cookie(&lt;br /&gt;
     -name    =&amp;gt; $shibname,&lt;br /&gt;
     -path    =&amp;gt; &amp;quot;/&amp;quot;,&lt;br /&gt;
     -value   =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
     -host  =&amp;gt; $session-&amp;gt;config(&amp;quot;cookie_domain&amp;quot;),&lt;br /&gt;
     -expires =&amp;gt; &amp;quot;-1d&amp;quot;,&lt;br /&gt;
   );&lt;br /&gt;
   EPrints::Apache::AnApache::header_out(&lt;br /&gt;
     $session-&amp;gt;{request},&lt;br /&gt;
     &amp;quot;Set-Cookie&amp;quot; =&amp;gt; $cookie &lt;br /&gt;
   );&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 push @{$c-&amp;gt;{rewrite_exceptions}}, &amp;quot;/shibboleth/&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
* Create a folder at the top level of your archive (e.g. ''/opt/eprints3/archives/foo/'') called '''shibboleth''' and copy the main CSS file for Shibboleth into this folder:&lt;br /&gt;
 eprints&amp;gt; mkdir /opt/eprints3/archives/foo/shibboleth/&lt;br /&gt;
 eprints&amp;gt; cp /usr/share/shibboleth/main.css /opt/eprints3/archives/foo/shibboleth/&lt;br /&gt;
&lt;br /&gt;
* Now, copy the following code into your archive (e.g. ''/opt/eprints3/archives/foo/'') as '''shibboleth/login'''.  This is the most basic login script that should work with the minimal attributes any Shibboleth IdP returns and '''only logging in users with existing accounts'''. Look under the [[#Customisation|Customisation]] section for advice on how to modify this script to meet your requirements, such as creation user accounts on-the-fly.&lt;br /&gt;
 use EPrints;&lt;br /&gt;
 use strict;&lt;br /&gt;
 &lt;br /&gt;
 my $session = EPrints::Session-&amp;gt;new();&lt;br /&gt;
 my $url = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if ( defined $url )&lt;br /&gt;
 {&lt;br /&gt;
   my $target_uri = URI-&amp;gt;new( $url );&lt;br /&gt;
   my $repository_uri = URI-&amp;gt;new( $session-&amp;gt;get_repository-&amp;gt;get_conf( 'base_url' ) );&lt;br /&gt;
   if ( !$target_uri-&amp;gt;can( 'host' ) || $target_uri-&amp;gt;host ne $repository_uri-&amp;gt;host )&lt;br /&gt;
   {&lt;br /&gt;
     $url = undef;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 $url = $session-&amp;gt;get_repository-&amp;gt;get_conf( &amp;quot;userhome&amp;quot; ) unless EPrints::Utils::is_set( $url );&lt;br /&gt;
 &lt;br /&gt;
 my $user = &amp;amp;get_user;&lt;br /&gt;
 &lt;br /&gt;
 if( defined $user )&lt;br /&gt;
 {&lt;br /&gt;
   $user-&amp;gt;set_value( &amp;quot;last_login&amp;quot;, EPrints::Time::get_iso_timestamp() );&lt;br /&gt;
   $user-&amp;gt;commit;&lt;br /&gt;
 &lt;br /&gt;
   EPrints::DataObj::LoginTicket-&amp;gt;expire_all( $session );&lt;br /&gt;
   $session-&amp;gt;dataset( &amp;quot;loginticket&amp;quot; )-&amp;gt;create_dataobj({&lt;br /&gt;
     userid =&amp;gt; $user-&amp;gt;id,&lt;br /&gt;
   })-&amp;gt;set_cookies();&lt;br /&gt;
 }&lt;br /&gt;
 else&lt;br /&gt;
 {&lt;br /&gt;
   $url = $session-&amp;gt;get_repository-&amp;gt;get_conf( &amp;quot;base_url&amp;quot; ) . &amp;quot;/account_required.html&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $session-&amp;gt;send_http_header( &amp;quot;content-type&amp;quot; =&amp;gt; &amp;quot;text/html&amp;quot; );&lt;br /&gt;
 print '&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;0;url='.$url.'&amp;quot;/&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;';&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
   &lt;br /&gt;
 sub get_user &lt;br /&gt;
 {&lt;br /&gt;
   my ( $username, $email ) = ( undef, &amp;quot;&amp;quot; );&lt;br /&gt;
   if( $ENV{eppn} )&lt;br /&gt;
   {&lt;br /&gt;
    ( $username ) = split( /@/, $ENV{eppn}, 2);&lt;br /&gt;
    $username = lc( $username );&lt;br /&gt;
    $email = $ENV{eppn};&lt;br /&gt;
   }&lt;br /&gt;
   return unless EPrints::Utils::is_set( $username );&lt;br /&gt;
   my $user = $session-&amp;gt;user_by_username( $username );&lt;br /&gt;
   if( defined $user &amp;amp;&amp;amp; defined $email )&lt;br /&gt;
   {&lt;br /&gt;
     $user-&amp;gt;set_value( &amp;quot;email&amp;quot;, $email );&lt;br /&gt;
     $user-&amp;gt;commit;&lt;br /&gt;
   }&lt;br /&gt;
   return $user;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
* Next, add the following markup to '''cfg/lang/en/static/account_required.xpage''' under your archive (e.g. ''/opt/eprints3/archives/foo/'').  Substituting ''staff and students of the University of Foo'' to describe to which particular group of people logged in access is restricted.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&amp;quot;no&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;!DOCTYPE page SYSTEM &amp;quot;entities.dtd&amp;quot; &amp;gt;&lt;br /&gt;
 &amp;lt;xpage:page xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; xmlns:xpage=&amp;quot;http://eprints.org/ep3/xpage&amp;quot; xmlns:epc=&amp;quot;http://eprints.org/ep3/control&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;xpage:title&amp;gt;Login Failed&amp;lt;/xpage:title&amp;gt;&lt;br /&gt;
 &amp;lt;xpage:body&amp;gt;&lt;br /&gt;
    &amp;amp;lt;p style='text-align: center;'&amp;amp;gt;Please note that only staff and students of the University of Foo may log in to &amp;lt;epc:phrase ref=&amp;quot;archive_name&amp;quot; /&amp;gt;&amp;amp;lt;/p&amp;amp;gt;&lt;br /&gt;
 &amp;lt;/xpage:body&amp;gt;&lt;br /&gt;
 &amp;lt;/xpage:page&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Now, reload Apache.&lt;br /&gt;
  root&amp;gt; apachectl reload&lt;br /&gt;
&lt;br /&gt;
* In a web browser go to the '''/shibboleth/login''' page for your repository, (e.g. ''https://foo.eprints.org/shibboleth/login'').  Like before with ''/cgi/shibboleth'' you should be taken to your Shibboleth IdP's site albeit displaying an error message.&lt;br /&gt;
&lt;br /&gt;
* The Shibboleth IdP shows an error message because EPrints as a Shibboleth Service Provider is not yet registered with it.  To do this you need to send the administrator of the Shibboleth IdP the metadata for your Service Provider.  You will have generated this earlier when you ran &amp;lt;code&amp;gt;metagen.sh&amp;lt;/code&amp;gt;.  Copy off your EPrints server the file that this wrote (e.g. to &amp;lt;tt&amp;gt;/etc/shibboleth/foo/sp_metadata.xml&amp;lt;/tt&amp;gt;) and send it to the Shibboleth IdP administrator.  They should be able to upload this to register EPrints as a Service Provider application.&lt;br /&gt;
&lt;br /&gt;
* Once registered, use a web browser to go to '''/shibboleth/login''' page for your repository, (e.g. ''https://foo.eprints.org/shibboleth/login'') again.  This time you should be prompted for a username and password on the Shibboleth IdP site. Once you have typed this in and clicked to login, you should be returned to EPrints on the '''/cgi/users/home''' page for your repository.  If not, see [[#Login_Issues|Login Issues]] under [[#Troubleshooting|Troubleshooting]] below.&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== Apache Configuration Issues ===&lt;br /&gt;
==== Apache 2.2 (and lower) Configuration for EPrints Shibboleth Integration ====&lt;br /&gt;
* Similarly to the instructions for Apache 2.4 and above, place the slightly different following configuration after the '''Include''' line for ''apache_ssl/foo.conf'', (substituting '''foo''' for your archive's name):&lt;br /&gt;
&lt;br /&gt;
  Alias /shibboleth /opt/eprints3/archives/foo/shibboleth&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/eprints3/archives/foo/shibboleth&amp;quot;&amp;gt;&lt;br /&gt;
    SetHandler perl-script&lt;br /&gt;
    PerlHandler ModPerl::Registry&lt;br /&gt;
    PerlSendHeader Off&lt;br /&gt;
    Options ExecCGI FollowSymLinks&lt;br /&gt;
  &lt;br /&gt;
    AuthType shibboleth&lt;br /&gt;
    ShibRequireSession On&lt;br /&gt;
    require valid-user&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;Location /cgi/shibboleth&amp;gt;&lt;br /&gt;
    AuthType shibboleth&lt;br /&gt;
    ShibRequireSession On&lt;br /&gt;
    require valid-user&lt;br /&gt;
  &amp;lt;/Location&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Shibboleth Configuration Issues ===&lt;br /&gt;
==== With attribute-map.xml ====&lt;br /&gt;
When authenticating using Shibboleth to login to EPrints you may see the following line in '''/var/log/shibboleth.shibd.log'''&lt;br /&gt;
&lt;br /&gt;
  2015-09-09 09:26:43 INFO Shibboleth.AttributeExtractor.XML [2]: skipping unmapped SAML 2.0 Attribute with Name:  urn:mace:dir:attribute-def:department&lt;br /&gt;
&lt;br /&gt;
In some cases this might not be an issue, as EPrints does not necessarily to make use of all the attributes returned by the IdP but without a mapping in attribute-map.xml.  In this case '''urn:mace:dir:attribute-def:department''' is not by default needed by EPrints to create/update a user account.  However, values like '''sn''', '''givenName''' and '''mail''' are but if you have used the attribute-map.xml provided later on the page you should not see a line like above in '''shibd.log'''.  In some cases you may still see an line like this in the log even if you think you have defined the attribute.  The line below demonstrate two known issues:&lt;br /&gt;
&lt;br /&gt;
  2015-09-09 09:26:43 INFO Shibboleth.AttributeExtractor.XML [2]: skipping unmapped SAML 2.0 Attribute with Name:  givenName, Format:urn:oasis:names:tc:SAML:2.0:attrname-format:basic&lt;br /&gt;
&lt;br /&gt;
# The attribute itself has no namespace it is just ''''givenName''' rather than '''urn:mace:dir:attribute-def:givenName'''&lt;br /&gt;
# The attribute has a format that most also be defined in the attribute-map.xml attribute.&lt;br /&gt;
&lt;br /&gt;
Below shows how to both include the format, which is required for the attribute to be successful mapped.  As well as define the name of the attribute without a namespace:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;Attribute name=&amp;quot;givenName&amp;quot; nameFormat=&amp;quot;urn:oasis:names:tc:SAML:2.0:attrname-format:basic&amp;quot; id=&amp;quot;givenName&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A typical Shibboleth IdP would have both a namespaced attribute name and would not apply a format to an attribute that is a simple text string.  Therefore it is worth enquiring with the IdP provider if either of these two happen to be the case.&lt;br /&gt;
&lt;br /&gt;
==== With idp-metadata.xml ====&lt;br /&gt;
If you want to be able extract scoped attributes (e.g. '''eduPersonPrincipalName''' otherwise described as '''eppn''').  Then you will need to ensure that the expected scope of this attribute, (effectively the domain part in eduPersonPrincipalName is the scope or one of the scopes in the idp-metadata.xml you downloaded from the Shibboleth IdP.  For example if the '''eduPersonPrincipalName''' is '''bar@foo.ac.uk'''.  Then the following should be defined in idp-metadata.xml ('''N.B. the namespace abbreviations (md: and shibmd:) may be different for the IdP you are working with'''):&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;md:Extensions&amp;gt;&lt;br /&gt;
    &amp;lt;shibmd:Scope regexp=&amp;quot;false&amp;quot;&amp;gt;foo.ac.uk&amp;lt;/shibmd:Scope&amp;gt;&lt;br /&gt;
  &amp;lt;/md:Extensions&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Login Issues ===&lt;br /&gt;
To be added.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Customisation ==&lt;br /&gt;
&lt;br /&gt;
=== Shibboleth /etc/shibboleth/foo/attribute-map.xml config ===&lt;br /&gt;
This is adapted from the default '''attribute-map.xml''' provided when the Shibboleth SP package is installed to only include the attribute subsequently used by EPrints Shibboleth Perl script that can be found below.  Namely:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Field name&lt;br /&gt;
!Field description			&lt;br /&gt;
!SAML v1.1 attribute URN&lt;br /&gt;
!SAMLv2 attribute URN&lt;br /&gt;
|-&lt;br /&gt;
|eppn			&lt;br /&gt;
|Edu Person Principal Name&lt;br /&gt;
|urn:mace:dir:attribute-def:eduPersonPrincipalName&lt;br /&gt;
|urn:oid:1.3.6.1.4.1.5923.1.1.1.6&lt;br /&gt;
|-&lt;br /&gt;
|sn&lt;br /&gt;
|Surname						&lt;br /&gt;
|urn:mace:dir:attribute-def:sn								&lt;br /&gt;
|urn:oid:2.5.4.4&lt;br /&gt;
|-&lt;br /&gt;
|givenName&lt;br /&gt;
|Given (first) name(s)&lt;br /&gt;
|urn:mace:dir:attribute-def:givenName&lt;br /&gt;
|urn:oid:2.5.4.42&lt;br /&gt;
|-&lt;br /&gt;
|mail&lt;br /&gt;
|Email address	&lt;br /&gt;
|urn:mace:dir:attribute-def:mail&lt;br /&gt;
|urn:oid:0.9.2342.19200300.100.1.3  &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You may wish to refer to the default '''attribute-map.xml''' is you want to use other attributes.&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;Attributes xmlns=&amp;quot;urn:mace:shibboleth:2.0:attribute-map&amp;quot; xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;Attribute name=&amp;quot;urn:mace:dir:attribute-def:eduPersonPrincipalName&amp;quot; id=&amp;quot;eppn&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;AttributeDecoder xsi:type=&amp;quot;ScopedAttributeDecoder&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/Attribute&amp;gt;&lt;br /&gt;
    &amp;lt;Attribute name=&amp;quot;urn:oid:1.3.6.1.4.1.5923.1.1.1.6&amp;quot; id=&amp;quot;eppn&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;AttributeDecoder xsi:type=&amp;quot;ScopedAttributeDecoder&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/Attribute&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;Attribute name=&amp;quot;urn:mace:dir:attribute-def:sn&amp;quot; id=&amp;quot;sn&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;Attribute name=&amp;quot;urn:mace:dir:attribute-def:givenName&amp;quot; id=&amp;quot;givenName&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;Attribute name=&amp;quot;urn:mace:dir:attribute-def:mail&amp;quot; id=&amp;quot;mail&amp;quot;/&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;Attribute name=&amp;quot;urn:oid:2.5.4.4&amp;quot; nameFormat=&amp;quot;urn:oasis:names:tc:SAML:2.0:attrname-format:basic&amp;quot; id=&amp;quot;sn&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;Attribute name=&amp;quot;urn:oid:2.5.4.42&amp;quot; nameFormat=&amp;quot;urn:oasis:names:tc:SAML:2.0:attrname-format:basic&amp;quot; id=&amp;quot;givenName&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;Attribute name=&amp;quot;urn:oid:0.9.2342.19200300.100.1.3&amp;quot; nameFormat=&amp;quot;urn:oasis:names:tc:SAML:2.0:attrname-format:basic&amp;quot; id=&amp;quot;mail&amp;quot;/&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;/Attributes&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== EPrints /shibboleth/login script with user account creation ===&lt;br /&gt;
This is the standard EPrints Shibboleth login script.  It makes a number of assumptions:&lt;br /&gt;
# That accounts should be created if they do not already exist for a particular user.&lt;br /&gt;
# That you wish to create a standard user account (not an editor administrator) account.&lt;br /&gt;
# That the Shibboleth IdP provides all the attributes (eduPersonPrinicpalName (seen as eppn), sn, givenName and mail) required.&lt;br /&gt;
&lt;br /&gt;
 use EPrints;&lt;br /&gt;
 use strict;&lt;br /&gt;
 &lt;br /&gt;
 my $session = EPrints::Session-&amp;gt;new();&lt;br /&gt;
 my $url = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if ( defined $url )&lt;br /&gt;
 {&lt;br /&gt;
   my $target_uri = URI-&amp;gt;new( $url );&lt;br /&gt;
   my $repository_uri = URI-&amp;gt;new( $session-&amp;gt;get_repository-&amp;gt;get_conf( 'base_url' ) );&lt;br /&gt;
   if ( !$target_uri-&amp;gt;can( 'host' ) || $target_uri-&amp;gt;host ne $repository_uri-&amp;gt;host )&lt;br /&gt;
   {&lt;br /&gt;
     $url = undef;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 $url = $session-&amp;gt;get_repository-&amp;gt;get_conf( &amp;quot;userhome&amp;quot; ) unless EPrints::Utils::is_set( $url );&lt;br /&gt;
 &lt;br /&gt;
 my $user = &amp;amp;get_user;&lt;br /&gt;
 &lt;br /&gt;
 if( defined $user )&lt;br /&gt;
 {&lt;br /&gt;
   $user-&amp;gt;set_value( &amp;quot;last_login&amp;quot;, EPrints::Time::get_iso_timestamp() );&lt;br /&gt;
   $user-&amp;gt;commit;&lt;br /&gt;
 &lt;br /&gt;
   EPrints::DataObj::LoginTicket-&amp;gt;expire_all( $session );&lt;br /&gt;
   $session-&amp;gt;dataset( &amp;quot;loginticket&amp;quot; )-&amp;gt;create_dataobj({&lt;br /&gt;
     userid =&amp;gt; $user-&amp;gt;id,&lt;br /&gt;
   })-&amp;gt;set_cookies();&lt;br /&gt;
 }&lt;br /&gt;
 else&lt;br /&gt;
 {&lt;br /&gt;
   $url = $session-&amp;gt;get_repository-&amp;gt;get_conf( &amp;quot;base_url&amp;quot; ) . &amp;quot;/account_required.html&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 $session-&amp;gt;send_http_header( &amp;quot;content-type&amp;quot; =&amp;gt; &amp;quot;text/html&amp;quot; );&lt;br /&gt;
 print '&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;0;url='.$url.'&amp;quot;/&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;';&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 &lt;br /&gt;
 sub get_user&lt;br /&gt;
 {&lt;br /&gt;
   my ($username, $given, $family, $email) = (undef, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   if( $ENV{eppn} )&lt;br /&gt;
   {&lt;br /&gt;
     ( $username ) = split( /@/, $ENV{eppn}, 2);&lt;br /&gt;
     $username = lc( $username );&lt;br /&gt;
   }&lt;br /&gt;
   $email = $ENV{mail} if $ENV{mail};&lt;br /&gt;
   if( $ENV{givenName} )&lt;br /&gt;
   {&lt;br /&gt;
     $given = lc( $ENV{givenName} );&lt;br /&gt;
     $given =~ s/^(.)/uc($1)/e;&lt;br /&gt;
     $given =~ s/([- ].)/uc($1)/e;&lt;br /&gt;
   }&lt;br /&gt;
   if( $ENV{sn} )&lt;br /&gt;
   {&lt;br /&gt;
     $family = lc( $ENV{sn} );&lt;br /&gt;
     $family =~ s/^(.)/uc($1)/e;&lt;br /&gt;
     $family =~ s/([- ].)/uc($1)/e;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   return unless EPrints::Utils::is_set( $username );&lt;br /&gt;
 &lt;br /&gt;
   my $user = $session-&amp;gt;user_by_username( $username ); # relying on this to be case insensitive&lt;br /&gt;
 &lt;br /&gt;
   if( !defined $user )&lt;br /&gt;
   {&lt;br /&gt;
     my $usertype = 'user';&lt;br /&gt;
     $user = EPrints::DataObj::User::create( $session, $usertype );&lt;br /&gt;
     $user-&amp;gt;set_value( &amp;quot;username&amp;quot;, $username );&lt;br /&gt;
   }&lt;br /&gt;
   my $name = {&lt;br /&gt;
     given =&amp;gt; $given,&lt;br /&gt;
     family =&amp;gt; $family,&lt;br /&gt;
   };&lt;br /&gt;
   $user-&amp;gt;set_value( &amp;quot;name&amp;quot;, $name );&lt;br /&gt;
   $user-&amp;gt;set_value( &amp;quot;email&amp;quot;, $email );&lt;br /&gt;
   $user-&amp;gt;commit;&lt;br /&gt;
   return $user;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Further Information ==&lt;br /&gt;
* Older instructions of how to set up EPrints for Shibboleth using UK Access management Federation discovery service is available [[Shibboleth authentication|here]].&lt;br /&gt;
&lt;br /&gt;
* For general information about installing and configuring Shibboleth [http://shibboleth.internet2.edu/ click here].&lt;br /&gt;
&lt;br /&gt;
* [https://docs.openathens.net/display/public/TPA/Sign+in+to+a+generic+application+using+OpenAthens#SignintoagenericapplicationusingOpenAthens-SetupthecustomSAMLresourceinOpenAthens Instructions of connection a Shibboleth Service Provider with OpenAthens]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Authentication]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=EPrints_Control_Format&amp;diff=16940</id>
		<title>EPrints Control Format</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=EPrints_Control_Format&amp;diff=16940"/>
		<updated>2025-08-05T09:23:25Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* epc:list (3.3.17+ and 3.4.2+) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{formats}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= EPrints Control =&lt;br /&gt;
&lt;br /&gt;
== Output Tags ==&lt;br /&gt;
&lt;br /&gt;
=== epc:print ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;epc:print expr='expression' opt='key=value;key2=value2'/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;cite:citation xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&lt;br /&gt;
           xmlns:cite=&amp;quot;http://eprints.org/ep3/citation&amp;quot;&lt;br /&gt;
           xmlns:epc=&amp;quot;http://eprints.org/ep3/control&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;epc:print expr=&amp;quot;$item.citation('default')&amp;quot; /&amp;gt;&lt;br /&gt;
 &amp;lt;/cite:citation&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Outputs the result of the expression in the 'expr' attribute. &lt;br /&gt;
&lt;br /&gt;
Rendering options may be passed in the opt attribute using a key=value form, with semicolons separating multiple options.&lt;br /&gt;
&lt;br /&gt;
Any [[EPScript]] expression can be used. The most simple is just 'eprintid','title','creators' etc. You can also use values from the configuration files by using '$config{base_url}'.&lt;br /&gt;
&lt;br /&gt;
=== Print in attributes using {} ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you may wish to insert a value into an XML attribute. eg. the &amp;quot;href&amp;quot; part of an anchor. Rather than a complicated system, but correct XML, we decide to go for something a bit more readable. Any {} pair in an XML attribute will be treated as a epc:print.&lt;br /&gt;
&lt;br /&gt;
So you can do something like &lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://eprints.badger.edu/cgi/myscript.pl?eprintid={eprintid}&amp;quot;&amp;gt;run myscript on this eprint&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== epc:phrase ===&lt;br /&gt;
&lt;br /&gt;
simple:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;epc:phrase ref='phraseid' /&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with pins:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;epc:phrase ref='phraseid'&amp;gt;&lt;br /&gt;
   &amp;lt;epc:param name='somepin'&amp;gt;Content&amp;lt;/epc:param&amp;gt;&lt;br /&gt;
 &amp;lt;/epc:phrase&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Outputs the content of the phrase refered to by 'ref'. Any necessary parameters may be set using the &amp;lt;epc:param&amp;gt; tag, with the contents inserted into the pin with the name corresponding to the name attribute.&lt;br /&gt;
&lt;br /&gt;
== Conditional Tags ==&lt;br /&gt;
&lt;br /&gt;
=== epc:if ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;epc:if test='expr'&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Outputs any XHTML content and evaluates any EPrints Control structures within the epc:if block if the expression in the test attribute is true.&lt;br /&gt;
&lt;br /&gt;
=== epc:choose, epc:when, epc:otherwise ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;epc:choose&amp;gt;&lt;br /&gt;
   &amp;lt;epc:when test='expr'&amp;gt; &lt;br /&gt;
   ...&lt;br /&gt;
   &amp;lt;/epc:when&amp;gt;&lt;br /&gt;
   &amp;lt;epc:when test='expr2'&amp;gt; &lt;br /&gt;
   ...&lt;br /&gt;
   &amp;lt;/epc:when&amp;gt;&lt;br /&gt;
   &amp;lt;epc:otherwise&amp;gt;&lt;br /&gt;
   ...&lt;br /&gt;
   &amp;lt;/epc:otherwise&amp;gt;&lt;br /&gt;
 &amp;lt;/epc:choose&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
epc:choose allows for the construction of a complex conditional. Each epc:when block's 'test' attribute is evaluated, and the content of the block is returned if the result is true. If no expressions return true, the optional epc:otherwise block is returned. Note that no subsequent epc:when blocks are evaluated once the first block to return true is reached.&lt;br /&gt;
&lt;br /&gt;
=== epc:comment ===&lt;br /&gt;
XML comments are not removed from the output when they are encountered in a citation or other EPScript.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;epc:if test=&amp;quot;blah&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- only print blah if it exists --&amp;gt;&lt;br /&gt;
  &amp;lt;epc:print expr=&amp;quot;blah&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
will result in the comment appearing in the html source:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- only print blah if it exists --&amp;gt;&lt;br /&gt;
This is Blah&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Using an epc:comment block allows you to include comments that aren't rendered in the output:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;epc:if test=&amp;quot;blah&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:comment&amp;gt; only print blah if it exists &amp;lt;/epc:comment&amp;gt;&lt;br /&gt;
  &amp;lt;epc:print expr=&amp;quot;blah&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Multiple values can be iterated over. For example.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:foreach expr=&amp;quot;creators_name&amp;quot; iterator=&amp;quot;name&amp;quot;&amp;gt;&lt;br /&gt;
    ( &amp;lt;epc:print expr=&amp;quot;$name&amp;quot; /&amp;gt; )&lt;br /&gt;
  &amp;lt;/epc:foreach&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== $index (3.2.0+) ===&lt;br /&gt;
&lt;br /&gt;
Within a foreach block you can use $index to find what iteration of the loop is on. The first value is zero.&lt;br /&gt;
&lt;br /&gt;
This can be used with the modulus &amp;quot;%&amp;quot; to add a strip effect, if wanted, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
  &amp;lt;epc:foreach expr=&amp;quot;creators_name&amp;quot; iterator=&amp;quot;name&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;epc:if test=&amp;quot;$index % 2&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;tr class='odd'&amp;gt;&amp;lt;td&amp;gt;&amp;lt;epc:print expr=&amp;quot;$name&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
    &amp;lt;epc:if test=&amp;quot;!($index % 2)&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;tr class='even'&amp;gt;&amp;lt;td&amp;gt;&amp;lt;epc:print expr=&amp;quot;$name&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
  &amp;lt;/epc:foreach&amp;gt;&lt;br /&gt;
  &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== limit (3.2.0+) ===&lt;br /&gt;
&lt;br /&gt;
You can set a limit of how many iterations to process using a &amp;quot;limit&amp;quot; attribute on the epc:foreach element. For example, &lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:foreach expr=&amp;quot;creators_name&amp;quot; iterator=&amp;quot;name&amp;quot; limit=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== epc:debug (3.2.0+) ==&lt;br /&gt;
&lt;br /&gt;
The epc:debug element has identical syntax to epc:print, but the result is sent to the error log -- either the command line, or to the apache error log.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:debug expr='expression' opt='key=value;key2=value2'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== epc:set (3.2.0+) ==&lt;br /&gt;
&lt;br /&gt;
This allows a variable to be set for any print or if elements within the epc:set. This is useful if creating the value has a notable cost which you wish to minimise. &lt;br /&gt;
&lt;br /&gt;
$item.documents() requires some database access, and the results are not cached, so using this speeds things up.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:set name='docs' expr='$item.documents()'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== epc:list (3.3.17+ and 3.4.2+) ==&lt;br /&gt;
Allows multiple variables to be printed out with a common separator, where separator is not added if any variables are not set.  Also allows a prefix and suffix to the list.  E.g.&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;epc:list prefix=&amp;amp;apos;[ &amp;amp;apos; suffix=&amp;amp;apos; ]&amp;amp;apos; join=&amp;amp;quot; | &amp;amp;quot;&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;epc:item&amp;amp;gt;First&amp;amp;lt;/epc:item&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;epc:item&amp;amp;gt; &amp;amp;lt;/epc:item&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;epc:item&amp;amp;gt;Third&amp;amp;lt;/epc:item&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;epc:item&amp;amp;gt;&amp;amp;lt;epc:print expr=&amp;amp;quot;title&amp;amp;quot;/&amp;amp;gt;&amp;amp;lt;/epc:item&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;epc:item&amp;amp;gt;&amp;amp;lt;epc:print expr=&amp;amp;quot;patent_applicant&amp;amp;quot;/&amp;amp;gt;&amp;amp;lt;/epc:item&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;epc:item&amp;amp;gt;Sixth&amp;amp;lt;/epc:item&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;/epc:list&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
Produces:&lt;br /&gt;
 [ First | Third | Test Title | UNSPECIFIED | Sixth ]&lt;br /&gt;
&lt;br /&gt;
If the value inside the &amp;amp;lt;epc:item&amp;amp;gt; is empty or only contains whitespace (spaces, tabs, newlines and carriage returns) it will be ignored.  If a variable is used that is not specified, such as patent_applicant, then this will still be displayed if the default value for an unspecified value is set (e.g. like UNSPECIFIED in the example above).  To avoid this put an if test for the variable and the whole item will be ignored.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Bots&amp;diff=16835</id>
		<title>Bots</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Bots&amp;diff=16835"/>
		<updated>2025-07-23T17:34:16Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Analysing traffic */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;big&amp;gt;'''NOTE: 2025-07-23 THIS PAGE IS CURRENTLY UNDER CONSTRUCTION'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The GLAM (Galleries, Libraries, Archives and Museums) sector have seen increased activity that appears to be automated, but doesn't identify itself as a 'robot' and doesn't follow robots.txt rules. The traffic makes repeated requests to systems (including EPrints repositories) for the same search terms, but with requests coming from a wide spread of IP addresses. Often an IP address will only make a single request, so traditional approaches to block traffic based in the IP address may not be enough.&lt;br /&gt;
&lt;br /&gt;
Other attributes of these requests e.g. the User-Agent are variable and don't help to distinguish when requests are part of the same 'swarm' of requests.&lt;br /&gt;
&lt;br /&gt;
The problematic traffic are requests to the search interface. These are , and this can cause performance issues with the platform. This isn't just an EPrints issue, other platforms experience the same issues.&lt;br /&gt;
&lt;br /&gt;
Below are some approaches that may help to limit the impact of these 'swarms' of bots.&lt;br /&gt;
&lt;br /&gt;
== Analysing traffic ==&lt;br /&gt;
* if system logs are in an analysis platform e.g. splunk&lt;br /&gt;
* TODO (+ Thanks to members of the EP-Tech mailing list for some of the suggestions below. &lt;br /&gt;
&lt;br /&gt;
=== Apache logs ===&lt;br /&gt;
TODO (detail from tech-list)&lt;br /&gt;
&lt;br /&gt;
=== Cachemap ===&lt;br /&gt;
When the internal EPrints search is used, a cache table is created in the database, and the details of the search are stored in the core &amp;lt;code&amp;gt;cachemap&amp;lt;/code&amp;gt; table.&lt;br /&gt;
&lt;br /&gt;
The pattern of 'swarm' activity can result in many identical searches being run. We can see these using the following query:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SET @threshold = 30;&lt;br /&gt;
SELECT COUNT(*) c, searchexp FROM cachemap GROUP BY searchexp HAVING c &amp;gt; @threshold ORDER BY c;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analysis of the web logs using search expressions returned from above may identify some attributes of the 'swarm'.&lt;br /&gt;
&lt;br /&gt;
NB If EPrints is using Xapian to process searches, the majority of searches will ''not'' create a cache table.&lt;br /&gt;
&lt;br /&gt;
== Blocking abusive search traffic ==&lt;br /&gt;
&lt;br /&gt;
=== Firewall ===&lt;br /&gt;
???&lt;br /&gt;
&lt;br /&gt;
=== fail2ban ===&lt;br /&gt;
??? - scanning logs for repeated cache=[x]&lt;br /&gt;
&lt;br /&gt;
=== Apache configuration - mod_security (WAF) ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
# details from DRN 2025-07-23&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Approach: EPrints configuration to block specific searches ===&lt;br /&gt;
The example below creates an EPrints trigger that is active when a request is being processed by EPrints. Any incoming requests that contain the terms in the &amp;lt;code&amp;gt;$bad_search&amp;lt;/code&amp;gt; configuration will not run a search, but will be presented with a '429 - too many requests' page.&lt;br /&gt;
&lt;br /&gt;
NB the core Apache::Const module does not include a constant for a 429 response, so a numeric value is used instead of e.g. &amp;lt;code&amp;gt;OK&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;FORBIDDEN&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
# save in a cfg.d dir somewhere e.g. [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/a_BOT_BLOCK.pl&lt;br /&gt;
use EPrints::Const;&lt;br /&gt;
&lt;br /&gt;
### UPDATE THESE WITH SEARCHES YOU WANT TO BLOCK!&lt;br /&gt;
my $bad_search = join &amp;quot;|&amp;quot;, map quotemeta, qw{&lt;br /&gt;
	IN:Habits|&lt;br /&gt;
	%3AHabits%7C&lt;br /&gt;
	ZEPLIN+COSINE+DRIFT+ADMX+LIGO+Kamiokande+SBND&lt;br /&gt;
};&lt;br /&gt;
$c-&amp;gt;{blocked_search_terms_re} = qr/$bad_search/;&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;add_trigger( EP_TRIGGER_URL_REWRITE, sub {&lt;br /&gt;
	my( %args ) = @_;&lt;br /&gt;
&lt;br /&gt;
	# args passed are: request, lang, args, urlpath, cgipath, uri, secure, return_code&lt;br /&gt;
	my( $repository, $request, $return_code, $uri, $urlpath ) = @args{ qw( repository request return_code uri urlpath ) };&lt;br /&gt;
&lt;br /&gt;
	# Just interested in searches&lt;br /&gt;
	if( $uri =~ /^$urlpath\/cgi\/search/  )&lt;br /&gt;
	{&lt;br /&gt;
		my $r_args = $request-&amp;gt;args();&lt;br /&gt;
&lt;br /&gt;
		if( defined $r_args )&lt;br /&gt;
		{&lt;br /&gt;
			if( $r_args =~ /$c-&amp;gt;{blocked_search_terms_re}/ )&lt;br /&gt;
			{&lt;br /&gt;
				#NB Apache2::COnst doesn't define 429.&lt;br /&gt;
				$request-&amp;gt;custom_response( 429, $c-&amp;gt;{bot_429_page_html} );&lt;br /&gt;
				${$return_code} = 429;&lt;br /&gt;
				return EP_TRIGGER_DONE;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;{bot_429_page_html} = '&amp;lt;!DOCTYPE HTML&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=UTF-8&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
body {&lt;br /&gt;
    font-family: sans-serif;&lt;br /&gt;
    margin: 3em;&lt;br /&gt;
}&lt;br /&gt;
footer {&lt;br /&gt;
    font-size: 80%;&lt;br /&gt;
    margin-top:2em;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;Rate Limited&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;header&amp;gt;&lt;br /&gt;
&amp;lt;h1&amp;gt;429 Too Many Requests&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;/header&amp;gt;&lt;br /&gt;
&amp;lt;section&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;This search has been blocked due to abuse by automated activity.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/section&amp;gt;&lt;br /&gt;
&amp;lt;footer&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;White Rose Libraries&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/footer&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;';&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using 3rd party tools ===&lt;br /&gt;
* Cloudflare&lt;br /&gt;
* Anubis&lt;br /&gt;
&lt;br /&gt;
== Related resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.code4lib.org/Blocking_Bots Code4Lib Blocking Bots] - there is also a useful channel on the Code4Lib slack&lt;br /&gt;
* [https://www.glamelab.org/products/are-ai-bots-knocking-cultural-heritage-offline/ Are AI Bots Knocking Cultural Heritage Offline? GLAM-E Lab report]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Bots&amp;diff=16834</id>
		<title>Bots</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Bots&amp;diff=16834"/>
		<updated>2025-07-23T17:33:05Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Created page with &amp;quot;&amp;lt;big&amp;gt;'''NOTE: 2025-07-23 THIS PAGE IS CURRENTLY UNDER CONSTRUCTION'''&amp;lt;/big&amp;gt;  The GLAM (Galleries, Libraries, Archives and Museums) sector have seen increased activity that app...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;big&amp;gt;'''NOTE: 2025-07-23 THIS PAGE IS CURRENTLY UNDER CONSTRUCTION'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The GLAM (Galleries, Libraries, Archives and Museums) sector have seen increased activity that appears to be automated, but doesn't identify itself as a 'robot' and doesn't follow robots.txt rules. The traffic makes repeated requests to systems (including EPrints repositories) for the same search terms, but with requests coming from a wide spread of IP addresses. Often an IP address will only make a single request, so traditional approaches to block traffic based in the IP address may not be enough.&lt;br /&gt;
&lt;br /&gt;
Other attributes of these requests e.g. the User-Agent are variable and don't help to distinguish when requests are part of the same 'swarm' of requests.&lt;br /&gt;
&lt;br /&gt;
The problematic traffic are requests to the search interface. These are , and this can cause performance issues with the platform. This isn't just an EPrints issue, other platforms experience the same issues.&lt;br /&gt;
&lt;br /&gt;
Below are some approaches that may help to limit the impact of these 'swarms' of bots.&lt;br /&gt;
&lt;br /&gt;
== Analysing traffic ==&lt;br /&gt;
You may be lucky enough to have your system logs available for analysis in a system like Splunk o&lt;br /&gt;
TODO (+ Thanks to members of the EP-Tech mailing list for some of the suggestions below. &lt;br /&gt;
&lt;br /&gt;
=== Apache logs ===&lt;br /&gt;
TODO (detail from tech-list)&lt;br /&gt;
&lt;br /&gt;
=== Cachemap ===&lt;br /&gt;
When the internal EPrints search is used, a cache table is created in the database, and the details of the search are stored in the core &amp;lt;code&amp;gt;cachemap&amp;lt;/code&amp;gt; table.&lt;br /&gt;
&lt;br /&gt;
The pattern of 'swarm' activity can result in many identical searches being run. We can see these using the following query:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SET @threshold = 30;&lt;br /&gt;
SELECT COUNT(*) c, searchexp FROM cachemap GROUP BY searchexp HAVING c &amp;gt; @threshold ORDER BY c;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analysis of the web logs using search expressions returned from above may identify some attributes of the 'swarm'.&lt;br /&gt;
&lt;br /&gt;
NB If EPrints is using Xapian to process searches, the majority of searches will ''not'' create a cache table.&lt;br /&gt;
&lt;br /&gt;
== Blocking abusive search traffic ==&lt;br /&gt;
&lt;br /&gt;
=== Firewall ===&lt;br /&gt;
???&lt;br /&gt;
&lt;br /&gt;
=== fail2ban ===&lt;br /&gt;
??? - scanning logs for repeated cache=[x]&lt;br /&gt;
&lt;br /&gt;
=== Apache configuration - mod_security (WAF) ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
# details from DRN 2025-07-23&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Approach: EPrints configuration to block specific searches ===&lt;br /&gt;
The example below creates an EPrints trigger that is active when a request is being processed by EPrints. Any incoming requests that contain the terms in the &amp;lt;code&amp;gt;$bad_search&amp;lt;/code&amp;gt; configuration will not run a search, but will be presented with a '429 - too many requests' page.&lt;br /&gt;
&lt;br /&gt;
NB the core Apache::Const module does not include a constant for a 429 response, so a numeric value is used instead of e.g. &amp;lt;code&amp;gt;OK&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;FORBIDDEN&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
# save in a cfg.d dir somewhere e.g. [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/a_BOT_BLOCK.pl&lt;br /&gt;
use EPrints::Const;&lt;br /&gt;
&lt;br /&gt;
### UPDATE THESE WITH SEARCHES YOU WANT TO BLOCK!&lt;br /&gt;
my $bad_search = join &amp;quot;|&amp;quot;, map quotemeta, qw{&lt;br /&gt;
	IN:Habits|&lt;br /&gt;
	%3AHabits%7C&lt;br /&gt;
	ZEPLIN+COSINE+DRIFT+ADMX+LIGO+Kamiokande+SBND&lt;br /&gt;
};&lt;br /&gt;
$c-&amp;gt;{blocked_search_terms_re} = qr/$bad_search/;&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;add_trigger( EP_TRIGGER_URL_REWRITE, sub {&lt;br /&gt;
	my( %args ) = @_;&lt;br /&gt;
&lt;br /&gt;
	# args passed are: request, lang, args, urlpath, cgipath, uri, secure, return_code&lt;br /&gt;
	my( $repository, $request, $return_code, $uri, $urlpath ) = @args{ qw( repository request return_code uri urlpath ) };&lt;br /&gt;
&lt;br /&gt;
	# Just interested in searches&lt;br /&gt;
	if( $uri =~ /^$urlpath\/cgi\/search/  )&lt;br /&gt;
	{&lt;br /&gt;
		my $r_args = $request-&amp;gt;args();&lt;br /&gt;
&lt;br /&gt;
		if( defined $r_args )&lt;br /&gt;
		{&lt;br /&gt;
			if( $r_args =~ /$c-&amp;gt;{blocked_search_terms_re}/ )&lt;br /&gt;
			{&lt;br /&gt;
				#NB Apache2::COnst doesn't define 429.&lt;br /&gt;
				$request-&amp;gt;custom_response( 429, $c-&amp;gt;{bot_429_page_html} );&lt;br /&gt;
				${$return_code} = 429;&lt;br /&gt;
				return EP_TRIGGER_DONE;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;{bot_429_page_html} = '&amp;lt;!DOCTYPE HTML&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=UTF-8&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
body {&lt;br /&gt;
    font-family: sans-serif;&lt;br /&gt;
    margin: 3em;&lt;br /&gt;
}&lt;br /&gt;
footer {&lt;br /&gt;
    font-size: 80%;&lt;br /&gt;
    margin-top:2em;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;Rate Limited&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;header&amp;gt;&lt;br /&gt;
&amp;lt;h1&amp;gt;429 Too Many Requests&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;/header&amp;gt;&lt;br /&gt;
&amp;lt;section&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;This search has been blocked due to abuse by automated activity.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/section&amp;gt;&lt;br /&gt;
&amp;lt;footer&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;White Rose Libraries&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/footer&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;';&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using 3rd party tools ===&lt;br /&gt;
* Cloudflare&lt;br /&gt;
* Anubis&lt;br /&gt;
&lt;br /&gt;
== Related resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.code4lib.org/Blocking_Bots Code4Lib Blocking Bots] - there is also a useful channel on the Code4Lib slack&lt;br /&gt;
* [https://www.glamelab.org/products/are-ai-bots-knocking-cultural-heritage-offline/ Are AI Bots Knocking Cultural Heritage Offline? GLAM-E Lab report]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Miscellaneous_Config_Options&amp;diff=16801</id>
		<title>Miscellaneous Config Options</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Miscellaneous_Config_Options&amp;diff=16801"/>
		<updated>2025-06-25T08:55:43Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* E */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Manual]]&lt;br /&gt;
&amp;lt;div style=&amp;quot;border: solid black 1px; text-align: center; background-color: #eee; font-size: 1.5em; font-weight: bold;&amp;quot;&amp;gt;&lt;br /&gt;
[[#A|A]] | [[#B|B]] | [[#C|C]] | [[#D|D]] | [[#E|E]] | [[#F|F]] | [[#G|G]] | [[#H|H]] | [[#I|I]] | [[#J|J]] | [[#K|K]] | [[#L|L]] | [[#M|M]] | [[#N|N]] | [[#O|O]] | [[#P|P]] | [[#Q|Q]] | [[#R|R]] | [[#S|S]] | [[#T|T]] | [[#U|U]] | [[#V|V]] | [[#W|W]] | [[#X|X]] | [[#Y|Y]] | [[#Z|Z]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page describes configuration options that do not appear in any [[Config Options by File|specific configuration files present]] in the main codebase (inc. pub_lib flavour).  &amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;The reason a configuration option does not appear in a default configuration file may be because it is a legacy option that may become deprecated and removed.&amp;lt;/font&amp;gt; Some descriptions below state that a configuration option is legacy but some descriptions may still need updating to explain they are legacy options.&lt;br /&gt;
&lt;br /&gt;
== A ==&lt;br /&gt;
* '''access_logger_func''' - Defines a function that is called every time a documents is downloaded or abstract/summary page is viewed (i.e. an access record is created).  This is used by recent versions of IRStats2, so it can process stats from a file-based access records rather than the database, which is more efficient if the &amp;lt;code&amp;gt;access&amp;lt;/code&amp;gt; database table is large (10 million+ records).&lt;br /&gt;
* '''access_table_logger_disabled''' - Whether access records should still be saved to the database.  (Without a setting database will continue to store access records).&lt;br /&gt;
* '''allow_duplicate_usernames''' - Whether the validation of &amp;lt;code&amp;gt;user&amp;lt;/code&amp;gt; metadata should check for duplicate usernames.  (Without a setting user metadata validation will fail if there are duplicate usernames.  This should only ever be set to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; temporarily, if username changes are required that may briefly lead to duplicates).&lt;br /&gt;
* '''allow_uploaded_doc_js''' - A malevolent user could deliberately upload malicious JavaScript to perform a clickjacking or similar attack against logged in users.  Should uploaded JavaScript only be returned with a Content Security Policy (CSP) to prevent it from being run on the client web browser.  (Without a setting CSP to prevent JavaScript running on the client is enabled).&lt;br /&gt;
* '''&amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;auth_basic&amp;lt;/font&amp;gt;''' - &amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;Legacy configuration for specifying basic rather than cookie-based user authentication.&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== B ==&lt;br /&gt;
* '''browse_views_max_items''' - Global setting for the maximum number of results that can be displayed on a browse view listing page.  Superseded if a particular view has a &amp;lt;code&amp;gt;max_items&amp;lt;/code&amp;gt; attribute set.  (Without a setting this defaults to &amp;lt;code&amp;gt;2000&amp;lt;/code&amp;gt; items).&lt;br /&gt;
&lt;br /&gt;
== C ==&lt;br /&gt;
* '''check_user_password''' - Allows a function to be defined to perform a bespoke check of whether the users password is correct.  Is passed the username and password and should return &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; if the password validation failed and &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; if it was successful.  (Without a setting, standard local authentication of the user's password is used).&lt;br /&gt;
* '''custom_handlers''' - If you have a third-party application that needs to integrate with its own connector (e.g. Pure), then this allow you to [[Custom_handlers|define configuration for this]].&lt;br /&gt;
&lt;br /&gt;
== D ==&lt;br /&gt;
* '''dbdriver''' - Which database driver (type of database, i.e. &amp;lt;code&amp;gt;mysql&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Pg&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Oracle&amp;lt;/code&amp;gt;) to use.  (Without a setting this defaults to &amp;lt;code&amp;gt;mysql&amp;lt;/code&amp;gt;).&lt;br /&gt;
* '''dbschema''' - Which database schema to use.  This is only applicable for &amp;lt;code&amp;gt;Pg&amp;lt;/code&amp;gt; (PostGreSQL) databases.&lt;br /&gt;
* '''default_export_plugin''' - Which export plugin to pre-select on browse view and search results pages.  (Without a setting, whichever export plugin appears first is pre-selected).&lt;br /&gt;
* '''deps''' - Defines dependencies of [[EPrints_Ingredients|ingredients]] on other ingredients.  By default this is not defined as no ingredients packaged in an EPrints standard release have any dependencies.&lt;br /&gt;
* '''disable_basic_auth''' - Ensure authentication cannot accidentally fallback to basic (rather than cookie-based) authentication.  (Without a setting it could fallback but it is very unlikely to do this unless your EPrints repository has been significantly modified).&lt;br /&gt;
* '''disable_make_open_access''' - Remove the option on the Request Copy approval form to immediately make the document open access.  (Without a setting the checkbox for this is present).&lt;br /&gt;
* '''does_user_own_eprint''' - Allows a function to augment what eprint records a user appears to own.  This may be useful if a particular user is acting as a surrogate for another user.  Should be defined in conjunction with &amp;lt;code&amp;gt;get_users_owned_eprints&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== E ==&lt;br /&gt;
* '''email_blacklist''' - Array reference containing a list of email addresses that are not allowed to make requests for copies.  Can be useful if some individual is making excessive requests, although ReCaptcha is probably more useful  (Without being defined there is no restriction on email addresses that can requests copies).&lt;br /&gt;
* '''enable_file_imports''' - Whether local files (for the importer) can be uploaded to the repository an part of an XML (e.g. EP3XML, Atom, etc.) import.  (Without a setting they cannot be uploaded).&lt;br /&gt;
* '''enable_import_fields''' - Specify fields for a data object that can be imported even through their field definition says they can not.&lt;br /&gt;
* '''enable_web_imports''' - Whether web-based files can be uploaded to the repository an part of an XML (e.g. EP3XML, Atom, etc.) import. (Without a setting they cannot be uploaded).&lt;br /&gt;
* '''eprints_access_restrictions_callback''' - Allows a function to be defined to test if the current user has access to read/write (access View/Edit page for) the specified eprint record.  Useful if you want to give access to certain eprint records without changing a user's type.&lt;br /&gt;
* '''eprint_rss_media_doc''' - Allows a function to be defined to build a bespoke XML document fragment to encapsulate RSSv2 export (Without a setting an empty XML document fragment is used).&lt;br /&gt;
* '''&amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;eprint_status_change&amp;lt;/font&amp;gt;''' - Allows a function to be defined that is called when the status (i.e. &amp;lt;code&amp;gt;eprint_status&amp;lt;/code&amp;gt; metadata field) has changed.  &amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;This is a legacy function.  &amp;lt;code&amp;gt;EP_TRIGGER_STATUS_CHANGE&amp;lt;/code&amp;gt; [[Triggers#Dataset Triggers|dataset trigger function]] should be used instead.&amp;lt;/font&amp;gt;&lt;br /&gt;
* '''expiry_for_doc_request''' - How many days an approved request copy link will last before access will be revoked. (Without a setting this is &amp;lt;code&amp;gt;7&amp;lt;/code&amp;gt; days).&lt;br /&gt;
* '''expiry_for_unresponded_doc_request''' - How many days an unapproved request can exists before the request can no longer be approved. Saves really old requests being approved without proper consideration or confusing / annoying the requester months/years after their request.  (Without a setting this is &amp;lt;code&amp;gt;90&amp;lt;/code&amp;gt; days, approx. 3 months).&lt;br /&gt;
* '''export_fieldlists''' - What fields can exported for a data object.  Further restricts field definition settings for &amp;lt;code&amp;gt;export_as_xml&amp;lt;/code&amp;gt;.  This may be useful to block fields with data privacy concerns but it will mean that not even repository admins will not be able to export these fields.  Consider using [[y_export_privacy.pl|export_privacy]] instead.  (Without a setting, what fields can be exported are only defined by their field definitions).&lt;br /&gt;
&lt;br /&gt;
== F ==&lt;br /&gt;
* '''file_local_path_function''' - Allows function to be defined to modify the location where the file represented by the file data object can be found on the local filesystem.  Could be used if a bespoke new type of data object that has associated files need to be added.&lt;br /&gt;
&lt;br /&gt;
== G ==&lt;br /&gt;
* '''generic_filenames''' - New (non-history) files will be added to the documents directory as &amp;lt;code&amp;gt;&amp;amp;lt;fileid&amp;amp;gt;.bin&amp;lt;/code&amp;gt; rather than there actual filename.  This can be useful if users are uploading files with names that use special characters that are not compatible with the filesystem or database encoding.  EPrints will already allow existing files to be manually changed to the &amp;lt;code&amp;gt;&amp;amp;lt;fileid&amp;amp;gt;.bin&amp;lt;/code&amp;gt; to provide a simple fix for existing issues using special characters, which subsequently cannot be downloaded.&lt;br /&gt;
* '''get_current_user''' - Allows a bespoke function to defined to determine who the current user is.  (Without a setting current user is determine from cookie or basic authentication attributes in the request).&lt;br /&gt;
* '''get_custom_view_header''' - Allows a function to be defined that adds custom HTML markup (XML DOM object) to a browse view page.  By default this is after the navigation but before any listings / menus.&lt;br /&gt;
* '''get_custom_view_header_location''' - Allows content for &amp;lt;code&amp;gt;get_custom_view_header&amp;lt;/code&amp;gt; (if defined) to be added either before the navigation (&amp;lt;code&amp;gt;before_nav&amp;lt;/code&amp;gt;) or after the navigation (&amp;lt;code&amp;gt;after_nav&amp;lt;/code&amp;gt;).  (Without a setting it is added after the navigation.  Only added since EPrints 3.4.6).&lt;br /&gt;
* '''get_login_url''' - Allows bespoke function to defined to generate the login URL for the repository archive.  Useful for [[Shibboleth]] or other SAML-based login.  (Without a setting &amp;lt;code&amp;gt;/cgi/users/login&amp;lt;/code&amp;gt; is used).&lt;br /&gt;
* '''get_request_eprint_descriptor''' - Allows a bespoke function to be defined to generate the descriptor for an eprint.  This may be useful if multiple eprints have the same title.  (Without a setting the &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; of the eprint is used as the descriptor).&lt;br /&gt;
* '''[[Miscellaneous Config Options/get_users_owned_eprints|get_users_owned_eprints]]''' - Allows function to be defined that lists the set of eprints a user owns, instead of just those where their &amp;lt;code&amp;gt;userid&amp;lt;/code&amp;gt; is set on the eprint record.  Should be defined in conjunction with &amp;lt;code&amp;gt;does_user_own_eprint&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== H ==&lt;br /&gt;
* '''history_enable''' - Allows revision history to be recorded for [[API:EPrints/DataObj/RichDataObj|rich data objects]] beyond just eprint data objects. Is an hash reference of &amp;lt;code&amp;gt;datasetid&amp;lt;/code&amp;gt; to whether history is enabled. Any defined value means enabled.&lt;br /&gt;
&lt;br /&gt;
== I ==&lt;br /&gt;
* '''ignore_login_ip''' - Whether IP address should be ignored in &amp;lt;code&amp;gt;loginticket&amp;lt;/code&amp;gt; so user can change IP address without being logged out.  (Without a setting up to 3.4.6 the login IP address has not been ignored, from 3.4.6. it will be ignored by default).&lt;br /&gt;
* '''items_filters''' - What filters can be used on the &amp;lt;code&amp;gt;EPrints::Plugin::Screen::Items&amp;lt;/code&amp;gt; (i.e. Manage Deposits) page.  Useful if an additional &amp;lt;code&amp;gt;eprint_status&amp;lt;/code&amp;gt; option has been added.  (Without a setting this uses the four &amp;lt;code&amp;gt;eprint_status&amp;lt;/code&amp;gt; options (&amp;lt;code&amp;gt;inbox, buffer, archive, deletion&amp;lt;/code&amp;gt;).&lt;br /&gt;
* '''items_filters_order''' - What order should filters be displayed on the &amp;lt;code&amp;gt;EPrints::Plugin::Screen::Items&amp;lt;/code&amp;gt; (i.e. Manage Deposits) page. (Without a setting this uses the four &amp;lt;code&amp;gt;eprint_status&amp;lt;/code&amp;gt; options in the following order (&amp;lt;code&amp;gt;inbox, buffer, archive, deletion&amp;lt;/code&amp;gt;).&lt;br /&gt;
* '''import_xml_permitted_tags''' - When importing HTML encoded text through an XML import what HTML tags are allowed.  Useful if there is a particular HTML tag that is commonly used is not included in the hardcoded default list, which is quite restrictive to avoid use of certain HTML tags for malicious purposes.  (By default allowed HTML tags are: &amp;lt;code&amp;gt;b big blockquote br code dd div dl dt em h1 h2 h3 h4 h5 h6 hr i li ol p pre s small span strike strong sub sup table tbody td th tr tt u ul&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== J ==&lt;br /&gt;
&lt;br /&gt;
== K ==&lt;br /&gt;
&lt;br /&gt;
== L ==&lt;br /&gt;
* '''login_required_for_cgi'''&lt;br /&gt;
** '''enable''' -  Whether users need to be logged in to access &amp;lt;code&amp;gt;/cgi/...&amp;lt;/code&amp;gt; pages (&amp;lt;code&amp;gt;/cgi/users/...&amp;lt;/code&amp;gt; pages always required being logged in).  (Without a setting login is not required, set to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; to enable).&lt;br /&gt;
** '''exceptions''' - Array reference of paths that are excluded from needing login.  (Without a setting all CGI scripts require login, if &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;.  This would cause a problem if your &amp;lt;code&amp;gt;login_required_url&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;/cgi/users/login&amp;lt;/code&amp;gt; and therefore at least &amp;lt;code&amp;gt;users/login&amp;lt;/code&amp;gt; should be added).&lt;br /&gt;
* '''login_required_for_eprints'''&lt;br /&gt;
** '''enable''' -  Whether users need to be logged in to access eprint abstract/summary pages. (Without a setting login is not required, set to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; to enable).&lt;br /&gt;
* '''login_required_for_static''' (EPrints 3.4.7+)&lt;br /&gt;
** '''enable''' -  Whether users need to be logged in to access static pages (e.g. the homepage, information and help pages. etc.).  (Without a setting login is not required, set to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; to enable).&lt;br /&gt;
** '''exceptions''' - Array reference of paths that are excluded from needing login.  (Without a setting all static require login, if &amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. All paths requires leading &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;.  So information page would be &amp;lt;code&amp;gt;/information.html&amp;lt;/code&amp;gt; and hompage would be just &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;.  If some static pages are excepted, some of their resources will also need to be, e.g. &amp;lt;code&amp;gt;/favicon.ico&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/images/.*&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;/style/images/.*&amp;lt;/code&amp;gt;).&lt;br /&gt;
* '''login_required_for_views''' &lt;br /&gt;
** '''enable''' - Whether users need to be logged in to access browse view pages. (Without a setting login is not required, set to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; to enable).&lt;br /&gt;
* '''login_required_url''' - URL for page to be redirected to if login is required. This is different to &amp;lt;code&amp;gt;get_login_url&amp;lt;/code&amp;gt; as it is only applicable to pages that are affected by &amp;lt;code&amp;gt;login_required_for_cgi&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;login_required_for_eprints&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;login_required_for_views&amp;lt;/code&amp;gt;.  (Typically, this should be set to ths default login URL &amp;lt;code&amp;gt;/cgi/users/login&amp;lt;/code&amp;gt;.  If this is not set the pages will try redirecting to themselves and get stuck in a loop).&lt;br /&gt;
&lt;br /&gt;
== M ==&lt;br /&gt;
* '''max_history_width''' - The number of characters per line for XML displayed in the history tab before wrapping to a new line.  (Without a setting a maximum of &amp;lt;code&amp;gt;120&amp;lt;/code&amp;gt; characters are displayed before wrapping).&lt;br /&gt;
&lt;br /&gt;
== N ==&lt;br /&gt;
* '''notify_embargo_expiry''' - Allows a bespoke function to be defined to perform actions when an embargo is lifted on a document.  As the name suggests, such actions may be sending out a notification to the eprint owner or a repository administrator.  (Without a setting no additional actions are performed when an embargo is lifted).&lt;br /&gt;
&lt;br /&gt;
== O ==&lt;br /&gt;
* '''oai'''&lt;br /&gt;
** '''v2'''&lt;br /&gt;
*** '''output_plugins''' - Hash reference of additional export plugins that can be used with OAI-PMH.  (Without a setting just those that have an &amp;lt;code&amp;gt;xmlns&amp;lt;/code&amp;gt; set, provide export for the appropriate dataset (typically &amp;lt;code&amp;gt;eprint&amp;lt;/code&amp;gt;) and are at least visible to &amp;lt;code&amp;gt;staff&amp;lt;/code&amp;gt;).&lt;br /&gt;
*** '''sample_identifier''' - An example of an identifier used by OAI-PMH for individual records.  (Without a setting no sample identifier is shown on OAI-PMH pages).&lt;br /&gt;
* '''&amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;on_files_modified&amp;lt;/font&amp;gt;''' - Allows a function to be defined that is called when a &amp;lt;code&amp;gt;FilesModified&amp;lt;/code&amp;gt; indexer task runs.  &amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;This is a legacy function.  &amp;lt;code&amp;gt;EP_TRIGGER_FILES_MODIFIED&amp;lt;/code&amp;gt; [[Triggers|trigger function]] should be used instead.&amp;lt;/font&amp;gt;&lt;br /&gt;
* '''&amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;on_generate_thumbnails&amp;lt;/font&amp;gt;''' - Allows a function to be defined that is called when a &amp;lt;code&amp;gt;FilesModified&amp;lt;/code&amp;gt; indexer task runs which includes generating thumbnails.  This may be useful if a special type of thumbnail file is required but cannot be defined with existing configuration for thumbnail types.  &amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;This is a legacy function.  &amp;lt;code&amp;gt;EP_TRIGGER_THUMBNAIL_TYPES&amp;lt;/code&amp;gt; [[Triggers|trigger function]] instead&amp;lt;/font&amp;gt;.&lt;br /&gt;
* '''on_logout''' - Allows a bespoke function to be defined to carry out certain actions before a user is logged out.  (Without a setting no additional actions are performed).&lt;br /&gt;
* '''order_auto_submit''' - Whether changing the ordering for search results will automatically reload the page.  (Without a setting search results pages will not automatically be reloaded on ordering change).&lt;br /&gt;
&lt;br /&gt;
== P ==&lt;br /&gt;
&lt;br /&gt;
== Q ==&lt;br /&gt;
&lt;br /&gt;
== R ==&lt;br /&gt;
&lt;br /&gt;
* '''recaptcha''' - Configuration for [[Recaptcha field]]s.&lt;br /&gt;
** '''ignore_countries''' - Array reference of ISO-639-1 two character codes for countries who should be automatically rejected. (Without a setting no countries are automatically rejected).&lt;br /&gt;
** '''private_key''' - The secret key generated by registering the hostname of the EPrints repository as a reCATPCHAv2 site.&lt;br /&gt;
** '''public_key''' - The site key generated by registering the hostname of the EPrints repository as a reCATPCHAv2 site.&lt;br /&gt;
** '''timeout''' - The maximum time to wait for a response from ReCAPTCHA.  (Without a setting LWP's default of 180 seconds is used. ReCAPTCHA is usually fairly quick to respond, so there is not really any need to set this).&lt;br /&gt;
* '''recaptcha3''' - Configuration for [[Recaptcha3 field]]s.&lt;br /&gt;
** '''ignore_countries''' - Array reference of ISO-639-1 two character codes for countries who should be automatically rejected. (Without a setting no countries are automatically rejected).&lt;br /&gt;
** '''min_score''' - The minimum score reCAPTCHAv3 needs gives for the request for it to be valid.  (Without a setting Google's default of &amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt; is used).&lt;br /&gt;
** '''private_key''' - The secret key generated by registering the hostname of the EPrints repository as a reCATPCHAv3 site.&lt;br /&gt;
** '''public_key''' - The site key generated by registering the hostname of the EPrints repository as a reCATPCHAv3 site.&lt;br /&gt;
** '''timeout''' - The maximum time to wait for a response from ReCAPTCHA.  (Without a setting LWP's default of 180 seconds is used. ReCAPTCHA is usually fairly quick to respond, so there is not really any need to set this).&lt;br /&gt;
* '''request_copy_cc''' - Array reference of email addresses that should be cc-ed in on all requests submissions that lead to an email being sent.&lt;br /&gt;
* '''&amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;required_formats&amp;lt;/font&amp;gt;''' -  Allows the definition of either an array reference or a function that will generate an array reference of required formats for documents. &amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;This is a legacy option. &amp;lt;code&amp;gt;EP_TRIGGER_VALIDATE_FIELD&amp;lt;/code&amp;gt; [[Triggers|trigger function]] should now be used instead.&amp;lt;/font&amp;gt;&lt;br /&gt;
* '''retain_embargo_dates''' - Whether embargo dates for documents should be retained when the embargo date has been reached.  This may be useful if EPrints integrates with a third-party application that needs to retain embargo dates.  (Without this setting &amp;lt;code&amp;gt;bin/lift_embargos&amp;lt;/code&amp;gt; will remove dates once the embargoes expire.  Otherwise, validation warnings for both the dates being in the past and documents still having embargo dates when they are public will be generated).&lt;br /&gt;
* '''rewrite_exceptions''' - Array reference of paths that should not be served by EPrints's Perl handler and should be served directly by Apache or some other handler.&lt;br /&gt;
* '''robotstxt'''&lt;br /&gt;
** '''crawl_delay''' - Adds crawl delay configuration to robots.txt.&lt;br /&gt;
*** '''default_seconds''' - The default number of seconds all other user agents (bots) should wait between crawl requests.  (without a setting no default crawl delay will be set).&lt;br /&gt;
*** '''seconds''' - The number of seconds for specified (i.e. more aggressive) user agents (bots) should wait between crawl requests.  (Without a setting &amp;lt;code&amp;gt;10&amp;lt;/code&amp;gt; seconds will be used).&lt;br /&gt;
*** '''user_agents''' - Array reference of specific (more aggressive) user agents that require a (greater) crawl delay.  (Without a setting no user agents will have a crawl delay, unless &amp;lt;code&amp;gt;default_seconds&amp;lt;/code&amp;gt; is set).&lt;br /&gt;
&lt;br /&gt;
== S ==&lt;br /&gt;
* '''saved_search_additional_recipients''' - Comma separated list of emails addresses that should additionally be included in saved search emails.  (Without a setting no additional recipients will be added to saved search emails). &lt;br /&gt;
* '''saved_search_citation''' - &amp;lt;code&amp;gt;eprint&amp;lt;/code&amp;gt; citation format to use for items listed in saved search emails.  (Without a set the default eprint citation format will be used).&lt;br /&gt;
* '''signup_style''' - The introductory message to show on the sign up page.  (Without a setting the default introductory message is used.  If set to &amp;lt;code&amp;gt;minimal&amp;lt;/code&amp;gt; then the minimal introductory message is used.  Typically using this setting is only useful if &amp;lt;code&amp;gt;default_user_type&amp;lt;/code&amp;gt; is also set to &amp;lt;code&amp;gt;minuser&amp;lt;/code&amp;gt;).&lt;br /&gt;
* '''skip_validation''' - Allows a bespoke function to be defined to determine if an eprint is allowed to skip validation. This may be useful for imported records that had different validation rules (Without a setting, no eprints are allowed to skip validation).&lt;br /&gt;
* '''STAFF_ONLY_LOCAL_callback''' - Allows a function to be defined to test of current user is a local staff (editor/admin) user to set &amp;lt;code&amp;gt;STAFF_ONLY_LOCAL&amp;lt;/code&amp;gt; for use in workflows.  (Without setting &amp;lt;code&amp;gt;STAFF_ONLY_LOCAL&amp;lt;/code&amp;gt; will be set to &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, i.e. current user is not local staff).&lt;br /&gt;
&lt;br /&gt;
== T ==&lt;br /&gt;
* '''theme''' - Rather than having to define templates, CSS and JavaScript branding just for the archive, use the files under the defined theme subdirectory (e.g. &amp;lt;code&amp;gt;lib/theme/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;archives/ARCHIVE_ID/cfg/theme/&amp;lt;/code&amp;gt; or a theme sub-directory for paths listed in flavour's inc file).  (Without a setting no theme will be used).&lt;br /&gt;
* '''&amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;thumbnail_types&amp;lt;/font&amp;gt;''' - Allows a function to be define to add extra thumbnail types that should be generated for a document.  &amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;This is a legacy option.  &amp;lt;code&amp;gt;EP_TRIGGER_THUMBNAIL_TYPES&amp;lt;/code&amp;gt; [[Triggers|trigger function]] should be used instead.&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== U ==&lt;br /&gt;
* '''ultimate_doc_pos''' - Allows a bespoke function to be defined for determining the &amp;lt;code&amp;gt;pos&amp;lt;/code&amp;gt; value (i.e. the sub-directory where files associated with this document are stored on disk) for the newly created document under an eprint.  (Without a setting this value for the document's &amp;lt;code&amp;gt;pos&amp;lt;/code&amp;gt; field is one greater than the current maximum &amp;lt;code&amp;gt;pos&amp;lt;/code&amp;gt; value of all documents under that eprint).&lt;br /&gt;
* '''&amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;update_submitted_eprint&amp;lt;/font&amp;gt;''' - Allows a bespoke function to be defined to perform actions once an eprint has been  moved to the review buffer.  &amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;This is a legacy option.  The more generic &amp;lt;code&amp;gt;EP_TRIGGER_STATUS_CHANGE&amp;lt;/code&amp;gt; [[Triggers#Dataset Triggers|dataset trigger function]] should be used instead.&amp;lt;/font&amp;gt;&lt;br /&gt;
* '''user_access_restrictions_callback''' - Allows a function to be defined to test if the current user has access to read/write (access View/Edit page) the specified user record.&lt;br /&gt;
* '''&amp;lt;font style=&amp;quot;color: red;&amp;quot;&amp;gt;user_area_template&amp;lt;/font&amp;gt;''' - Page template to use when accessing user area pages.  Superseded in EPrints 3.4.x by automatically using &amp;lt;code&amp;gt;default_internal&amp;lt;/code&amp;gt; template all screen plugins.  (Without a setting either &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; (EPrints 3.3.x) or &amp;lt;code&amp;gt;default_internal&amp;lt;/code&amp;gt; (EPrints 3.4.x) template is used.&lt;br /&gt;
* '''user_cookie_timeout''' - The amount time (using: h, d, w, m, and y) before the user session cookie should expire (e.g. &amp;lt;code&amp;gt;+1h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;+7d&amp;lt;/code&amp;gt;).  (Without a setting no cookie timeout is set).&lt;br /&gt;
* '''user_inactivity_timeout''' - How long to wait in seconds before logging the user out after their last activity.  (Without a setting &amp;lt;code&amp;gt;86400 * 7&amp;lt;/code&amp;gt; seconds, i.e. 7 days is used).&lt;br /&gt;
* '''user_session_timeout''' - How long in seconds the user can stay logged in before they must re-log in. (Without a setting user session never times out.  With a setting &amp;lt;code&amp;gt;user_inactivity_timeout&amp;lt;/code&amp;gt; probably will to be reduced to a considerably shorter period of time to this).&lt;br /&gt;
&lt;br /&gt;
== V ==&lt;br /&gt;
* '''version_extra''' - Extra information to add about the EPrints repository software version, as appears under &amp;lt;code&amp;gt;/cgi/counter&amp;lt;/code&amp;gt;  Useful if the version of the codebase has been augmented.  (Without a setting no extra version is included).&lt;br /&gt;
* '''view_sort_function''' - Redefines the sort function used by &amp;lt;code&amp;gt;EPrints::MetaField-&amp;gt;sort_values&amp;lt;/code&amp;gt;  (Without setting the &amp;lt;code&amp;gt;Unicode::Collate&amp;lt;/code&amp;gt; is used as the collator to compare values when sorting).&lt;br /&gt;
* '''virtualhost''' - When running &amp;lt;code&amp;gt;bin/generate_apacheconf&amp;lt;/code&amp;gt; what to set in the &amp;lt;code&amp;gt;&amp;amp;lt;virtualhost HOSTNAME:PORT&amp;amp;gt;&amp;lt;/code&amp;gt; lines.  (Without a setting, &amp;lt;code&amp;gt;*&amp;lt;/code&amp;gt;, i.e. a wildcard is used).&lt;br /&gt;
&lt;br /&gt;
== W ==&lt;br /&gt;
* '''workflow_datepicker''' - Defines function for rendering a date-picker for date fields in a workflow.  Useful if you want to include some JavaScript to help a user pick a date. (Without a setting, a simple year, month and day set of fields is rendered.)&lt;br /&gt;
&lt;br /&gt;
== X ==&lt;br /&gt;
== Y ==&lt;br /&gt;
== Z ==&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=XPAGE_Format&amp;diff=16800</id>
		<title>XPAGE Format</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=XPAGE_Format&amp;diff=16800"/>
		<updated>2025-06-24T14:17:21Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Add 'template' to list of tags.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{formats}}&lt;br /&gt;
&lt;br /&gt;
'''See [[API:EPrints/Apache/Template#Static_HTML_Pages]] for a list of the pins you can use in an xpage'''&lt;br /&gt;
&lt;br /&gt;
Stored in the [[EPrints_Directory_Structure/eprints3/archives/ARCHIVEID/cfg/lang/en/static|static]] folder, xpage files are portions of HTML that are rendered into static files when generate_static is run. Four tags are in the xpage namespace: &amp;lt;code&amp;gt;xpage:page&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;xpage:title&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;xpage:body&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;xpage:template&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The beginning of index.xpage (which generates the site's index page) is as follows - the three tags are analogous to the html, title, and body tags of an HTML document, except the body is included within the site's template. It is recommended to use xhtml as the default namespace to ease writing. As with templates, [[EPrints Control Format]] tags may be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;iso-8859-1&amp;quot; standalone=&amp;quot;no&amp;quot;  ?&amp;gt;&lt;br /&gt;
 &amp;lt;!DOCTYPE page SYSTEM &amp;quot;entities.dtd&amp;quot; &amp;gt;&lt;br /&gt;
 &amp;lt;xpage:page xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; xmlns:xpage=&amp;quot;http://eprints.org/ep3/xpage&amp;quot; xmlns:epc=&amp;quot;http://eprints.org/ep3/control&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;xpage:title&amp;gt;Welcome to &amp;lt;epc:phrase ref=&amp;quot;archive_name&amp;quot; /&amp;gt;&amp;lt;/xpage:title&amp;gt;&lt;br /&gt;
   &amp;lt;xpage:body&amp;gt;Some example body text.&amp;lt;/xpage:body&amp;gt;&lt;br /&gt;
 &amp;lt;/xpage:page&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
When generate_statics is run, four static files are created for each xpage file. For index.xpage, these would be index.html (the HTML page), index.page (the contents of the xpage:body tag), index.title (the contents of the xpage:title tag), and index.title.textonly (the contents of the xpage:title with HTML tags stripped out). Note that these files are generated by generate_static, and shouldn't be edited by hand.&lt;br /&gt;
&lt;br /&gt;
2013-10-21 NOTE: Some versions of EPrints (3.3.10 and lower?) don't process phrases with pins in them properly from xpages. Whitespace in the phrase tag breaks the processor, resulting in a '[error in script]' message in the page, and something like ' EPScript error: Can't locate object method &amp;quot;tagName&amp;quot; via package &amp;quot;XML::LibXML::Text&amp;quot; at /usr/share/eprints/perl_lib/EPrints/XML/EPC.pm line 204' in the apache error logs.&lt;br /&gt;
This can be fixed by removing the whitespace:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- BROKEN --&amp;gt;&lt;br /&gt;
        &amp;lt;epc:phrase ref=&amp;quot;lib/searchexpression:results_for&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;epc:param name='title'&amp;gt;Test&amp;lt;/epc:param&amp;gt;&lt;br /&gt;
        &amp;lt;/epc:phrase&amp;gt;&lt;br /&gt;
&amp;lt;!-- OK --&amp;gt;&lt;br /&gt;
        &amp;lt;epc:phrase ref=&amp;quot;lib/searchexpression:results_for&amp;quot;&amp;gt;&amp;lt;epc:param name='title'&amp;gt;Test&amp;lt;/epc:param&amp;gt;&amp;lt;/epc:phrase&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
or possibly patching ~/perl_lib/EPrints/XML/EPC.pm with https://github.com/eprints/eprints/commit/10fc4e67fac54dc87c6968ac3be79c4cb121efcf&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=16764</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=16764"/>
		<updated>2025-04-28T13:15:50Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* View list options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Browse Views]]&lt;br /&gt;
{{dirs}}&lt;br /&gt;
{{cfgd}}&lt;br /&gt;
&lt;br /&gt;
'''views.pl''' contains configuration for rendering ''views''.  Conceptually a ''view'' is a browsable list of eprints split into ''menus'' and a ''list''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{| cellpadding=&amp;quot;0&amp;quot; cellspacing=&amp;quot;0&amp;quot; border=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;border-color:black; border-style:solid; border-width:1px 1px 0 1px; margin:0; padding:0; text-align:center; font-size:10px&amp;quot; |Menu1&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; margin:0; padding:0; font-size:10px&amp;quot;| &amp;amp;nbsp; Item1_1 ------&lt;br /&gt;
| style=&amp;quot;font-size:10px&amp;quot;|---&amp;gt;&lt;br /&gt;
| style=&amp;quot;border-color:black; border-style:solid; border-width:1px 1px 0 1px; margin:0; padding:0; text-align:center; font-size:10px&amp;quot;|Menu2&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; font-size:10px&amp;quot;| &amp;amp;nbsp; Item1_2 &lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; margin:0; padding:0; font-size:10px&amp;quot;| &amp;amp;nbsp; Item2_1 ----- &lt;br /&gt;
|style=&amp;quot;font-size:10px&amp;quot;|---&amp;gt;&lt;br /&gt;
|style=&amp;quot;border-color:black; border-style:solid; border-width:1px 1px 0 1px; margin:0; padding:0; text-align:center; font-size:10px&amp;quot;| &amp;amp;nbsp; &amp;amp;nbsp; LIST &amp;amp;nbsp; &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px 1px 1px; margin:0; padding:0; text-align:left; font-size:10px&amp;quot;| &amp;amp;nbsp; ....&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; margin:0; padding:0; font-size:10px&amp;quot;| &amp;amp;nbsp; Item2_2&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px 1px 1px; margin:0; padding:0; text-align:left; font-size:10px&amp;quot;| &amp;amp;nbsp; ....&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px 1px 1px; margin:0; padding:0; text-align:left; font-size:10px&amp;quot;| &amp;amp;nbsp; ....&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
In a ''menu'' values of one (or more) fields are listed, and a link points to the collection of all items with that particular value in that field.&lt;br /&gt;
&lt;br /&gt;
The ''list'' contains the final list of eprints with field values as determined by the menus above it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Options available for the views config ==&lt;br /&gt;
This link is an [http://wiki.eprints.org/w/Adding_new_views 'How to' about views] with examples.&lt;br /&gt;
&lt;br /&gt;
The general form of views definition is&lt;br /&gt;
&lt;br /&gt;
  $c-&amp;gt;{browse_views} = [&lt;br /&gt;
    { &amp;lt;first view definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second view definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last view definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the view definitions determines the order in which these will appear in the &amp;lt;nowiki&amp;gt;http://repoid/view/&amp;lt;/nowiki&amp;gt; page.&lt;br /&gt;
&lt;br /&gt;
Each view definition is a collection of attributes, given as&lt;br /&gt;
&lt;br /&gt;
    attribute1 =&amp;gt; value1,&lt;br /&gt;
    attribute2 =&amp;gt; value2,&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
(again, the ''value'' should end by a comma). The ''value'' can be&lt;br /&gt;
*''integer''&lt;br /&gt;
*''string'' enclosed by quotation marks (&amp;quot;) or by apostrophes (')&lt;br /&gt;
*''array'' which starts by a square bracket [ followed by the elements of the array (separated by commas) and closed by ] or &lt;br /&gt;
*''hash'' which is a list of &amp;quot;attribute =&amp;gt; value&amp;quot; pairs enclosed by curly brackets { and }.&lt;br /&gt;
Thus the browse_views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
Attributes marked by &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt; are ''view'' attributes and are in the view definition; attributes marked by &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt; are ''menu'' attributes and should be used only in [[#Menu options|menu definitions]].&lt;br /&gt;
&lt;br /&gt;
==Basic options==&lt;br /&gt;
&lt;br /&gt;
Options in the first category are ''view'' options.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;4&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| id &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
| (mandatory) String, this is the ID by which you will refer to this view, and also the name of the top directory in &amp;lt;nowiki&amp;gt;http://repoid/view/&amp;lt;/nowiki&amp;gt;. This is the value of the ''browse_link'' attribute in [[eprint_fields.pl]]. Example:&lt;br /&gt;
&lt;br /&gt;
    id =&amp;gt; 'divisions',&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|fields &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt; &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Menu options|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
allow_null &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
new_column_at &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
render_menu &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|These define the default values of the same attributes in all [[#Menu options|menus]]. I.e, if not defined otherwise there, they take this as the default value in this view. &amp;quot;Hideempty&amp;quot; is also used when rendering the [[#View list options|view]] list.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|menus &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|An array of ''[[#Menu options|menu descriptions]]''. Each ''menu'' is a refinement of the previous ones, and last menu points to the [[#View list options|view list(s)]]. In each menu, as minimum, you should give the field(s) which are used to define entries at that level. The menus definition looks like&lt;br /&gt;
  menus =&amp;gt; [&lt;br /&gt;
     { &amp;lt;first menu definition&amp;gt; },&lt;br /&gt;
     { &amp;lt;second level menu&amp;gt; },&lt;br /&gt;
     { &amp;lt;last level&amp;gt; },&lt;br /&gt;
  ],&lt;br /&gt;
You must have at least one menu level.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|template &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Define an alternate template for all pages in this view. The template page should be a proper xml file in the &amp;lt;tt&amp;gt;repoid/cfg/lang/&amp;lt;langid&amp;gt;/templates/&amp;lt;/tt&amp;gt; directory. The best way is to copy the default.xml file and edit it according to taste. &lt;br /&gt;
  template =&amp;gt; 'view_template',&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|nolink &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|When this is set to 1 by adding&lt;br /&gt;
  nolink =&amp;gt; 1,&lt;br /&gt;
then this view won't appear in the outmost &amp;lt;nowiki&amp;gt;http://repoid/view/&amp;lt;/nowiki&amp;gt; browse page.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| max_menu_age&amp;amp;nbsp;&amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
| Defaults to 86400 (one day in seconds). If the menus in this view has been generated more than that many seconds ago, it is regenerated.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| max_items &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Defaults to 2000.  If the items list is larger increase the number enough to accomodate the number of items needed to be displayed.&lt;br /&gt;
  max_items =&amp;gt; 3000,&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
These are the options which determine how the last list page in the menu chain should look like. They must be entered at the outmost ''view'' level. &lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;4&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|order &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|This defines how the items in the view list (at the lowest level) are ordered. The format is 'foo/-bar'. This means that the list will be sorted by 'foo' and then any equal 'foo' values will be reverse sorted by 'bar'. More than 2 fields can be specified. Example:&lt;br /&gt;
  order =&amp;gt; &amp;quot;-date/title&amp;quot;,&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Don't show the &amp;quot;up one level&amp;quot; link in the list page. You ''must'' set this attribute for each menu separately, it is not inherited.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Do not list the empty (undefined) entry in the list. This property inherits to the menus.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|nocount &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|If set, the &amp;quot;Number of items&amp;quot; line at the top of the page is omitted.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|notimestamp &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|If set, the &amp;quot;This list was generated on&amp;quot; line at the bottom of the list is omitted.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|variations &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|An array of strings describing different rendering of the items at the ''list''. For datails see [[#Variations|variations]]. Example:&lt;br /&gt;
    variations =&amp;gt; [ &amp;quot;creators_name;first_letter&amp;quot;, &lt;br /&gt;
        &amp;quot;type&amp;quot;, &amp;quot;DEFAULT&amp;quot;, ],&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|layout &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Possible values are &lt;br /&gt;
*paragraph (default)&lt;br /&gt;
*orderedlist&lt;br /&gt;
*unorderedlist&lt;br /&gt;
Determines how items in the list (or sublist) is rendered. In the first case each item is a paragraph by itself. In the other cases items are rendered as an ordered (unordered) list.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|citation &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|The citation style defined in archives/&amp;lt;REPOID&amp;gt;/cfg/citations/eprint/ which is used to render each item. Example:&lt;br /&gt;
  citation =&amp;gt; 'screen',&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|max_list_age&amp;amp;nbsp;&amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(V)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Defaults to 86400 (one day in seconds). If the lists in this view were generated more than than many seconds ago, it is regenerated.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations, if defined, determine how the final list is rendered. ''Variations'' is an array of strings, for example,&lt;br /&gt;
&lt;br /&gt;
 [ &amp;quot;creators_name;first_letter&amp;quot;,&lt;br /&gt;
   &amp;quot;type&amp;quot;,&lt;br /&gt;
   &amp;quot;DEFAULT&amp;quot;,&lt;br /&gt;
 ]&lt;br /&gt;
&lt;br /&gt;
For each string in the list, a different rendering is produced, and you can switch from one to the other. The variation &amp;quot;DEFAULT&amp;quot; is the default one, it is always a good practice to include it in the list. If no variation is given, &amp;quot;DEFAULT&amp;quot; is used.&lt;br /&gt;
&lt;br /&gt;
A ''variation definition'' consists of a field name, followed by zero, one or more ''options'' after a semicolon. Options are separated by commas. An ''option'' is either a single attribute, or an attribute, an equal sign, and the value of the attribute. For example,&lt;br /&gt;
    &amp;quot;creators_name;truncate=4,hideup&amp;quot;&lt;br /&gt;
sets the attribute value &amp;quot;truncate&amp;quot; to 4, and &amp;quot;hideup&amp;quot; to 1 (or true).&lt;br /&gt;
&lt;br /&gt;
The following options are available. These options are ''part of the string'' defining the variation, and ''should not be entered'' as attributes.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;4&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|reverse&lt;br /&gt;
|Reverses the order in which the groupings are shown.  Default is the ordervalue for that field (usually alphanumeric).  Useful for dates as you may want the highest values first.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|filename&lt;br /&gt;
|Changes the filename of the view variation.  The default is the name of the metadata field used, so if two variations use the same metadata field with different options, this is needed.&lt;br /&gt;
 filename=different_filename&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|first_value&lt;br /&gt;
|If a field is multiple, only use the first value.  Otherwise each item will appear once for each value.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|first_initial&lt;br /&gt;
|If using a name, truncate the given name to the first initial.  This will make items like &amp;quot;Les Carr&amp;quot; and &amp;quot;Leslie Carr&amp;quot; appear together.  Note it will also make &amp;quot;John Smith&amp;quot; and &amp;quot;Jake Smith&amp;quot; appear together too, showing that you really never can win.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|first_letter&lt;br /&gt;
|The same as 'truncate=1'&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|truncate&lt;br /&gt;
|Use the first X characters of a value to group by.  truncate=4 may be useful for dates as it will group by the first four digits (the year) only.&lt;br /&gt;
 truncate=4&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|tags&lt;br /&gt;
|Useful for fields like keywords where values may be separated by commas or semi-colons.  The value is split on these two characters ( , and ; ) and a heading is created for each.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|cloud&lt;br /&gt;
|Creates a tag cloud.  Sets jump to 'plain', cloudmax to 200, cloudmin to 80 and no_separator, then resizes the jump-to links according to frequency of use.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|cloudmax&lt;br /&gt;
|The % size of the largest tag in a tag cloud.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|cloudmin&lt;br /&gt;
|The % size of the smallest tag in a tag cloud.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|jump&lt;br /&gt;
|Possible values are 'plain', 'default', and 'none'. Example:&lt;br /&gt;
  jump=plain&lt;br /&gt;
When set to 'plain' turns off the 'jump to' text before the list of subheading navigation links. When 'none', then the 'jump' part is not rendered.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|no_seperator (sic)&lt;br /&gt;
|Turns of the separator between each subheading navigation link (by default a vertical bar symbol).&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|string&lt;br /&gt;
|Uses values 'as is'.  No ordervalues, no phrases.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup (since 3.1.1) &lt;br /&gt;
|Defaults to &amp;quot;0&amp;quot;. If set to &amp;quot;1&amp;quot; this hides the &amp;quot;up to parent&amp;quot; link (often you want to hide this on .include files)&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|render_fn&lt;br /&gt;
|Name of a function to render this groupings list of items. For an example, see views_render_items_example.pl&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Menu options===&lt;br /&gt;
&lt;br /&gt;
These options can only be used in the '''menu definitions'''.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;4&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|fields  &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Obligatory, an array of field identifiers. Items in all fields are merged together. For example, to define a list of those those who are either authors or editors or both, use the definition&lt;br /&gt;
&lt;br /&gt;
    fields =&amp;gt; [ &amp;quot;creators_id&amp;quot;, &amp;quot;editors_id&amp;quot; ],&lt;br /&gt;
&lt;br /&gt;
Even if there is a single field, you must use square brackets, such as&lt;br /&gt;
&lt;br /&gt;
    fields =&amp;gt; [ &amp;quot;subjects&amp;quot; ],&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;color: #662211; background-color:#ddffdc; border:1px solid black; padding:3px;&amp;quot;&amp;gt;'''Important!''' All fields must have the same type - i.e. you cannot mix titles and authors, say.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also add extra rendering info to the field name, without the &amp;quot;render_&amp;quot; prefix. For example, to make a date have resolution year, you would write&lt;br /&gt;
&lt;br /&gt;
    fields =&amp;gt; [ &amp;quot;date;res=year&amp;quot; ],&lt;br /&gt;
&lt;br /&gt;
or, ordering authors by their ''given'' names rather than by their family names:&lt;br /&gt;
&lt;br /&gt;
    fields =&amp;gt; [ &amp;quot;creators_name;order=gf&amp;quot; ],&lt;br /&gt;
&lt;br /&gt;
You can add &amp;quot;;quiet&amp;quot; to the field name to force non-existing values to appear as empty space rather than the ugly &amp;quot;UNDEFINED&amp;quot; (see the allow_null property below). You can find the available rendering properties of different fields in the [[Metadata]] section.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|allow_null &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt; &lt;br /&gt;
|The ''undefined'' value among the possible values of the fields does not show up in the generated view. To allow the undefined value to appear as well, set&lt;br /&gt;
&lt;br /&gt;
  allow_null =&amp;gt; 1,&lt;br /&gt;
&lt;br /&gt;
Beware: the title of the undefined entries will be the ugly UNDEFINED. You might consider to use the &amp;quot;;quiet&amp;quot; rendering option for field names.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|If a category is empty, don't show it as an entry. Default value: show all entries, even if they contain no entries. Used only in menus, not at the lower level (list).&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
    hideempty =&amp;gt; 1,&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|reverse_order &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|If set, then the ordering of items in this menu is reversed. Example:&lt;br /&gt;
&lt;br /&gt;
    reverse_order =&amp;gt; 1,&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|mode &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Possible values: ''[[#Sections|sections]]'' and ''default'' (default). When defined as ''sections'' then grouping can be defined by the following data:&lt;br /&gt;
* ''grouping_function'' (group by first character if not defined)&lt;br /&gt;
* ''group_sorting_function'' (how to sort members of a group)&lt;br /&gt;
* ''group_range_function''&lt;br /&gt;
* ''open_first_section'' the front page should show the first section&lt;br /&gt;
See [[#Sections|below]].&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|When set to 1, don't show the &amp;quot;move one level up&amp;quot; link at the top of the page.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|render_menu &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|The configuration parameter which renders this menu. This should be a string, and also you should define a routine with the same name. For example if you write&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
then this menu will be rendered by the routine which is defined in [[views_render_menu_example.pl]] as&lt;br /&gt;
  $c-&amp;gt;{render_view_menu_3col_boxes} = sub&lt;br /&gt;
  {&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
See there for hints how to tweak your own routine.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|new_column_at &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Used in menus (not lists) and in default mode. This is an array of integers representing the number of items in a view list before another column is added.  For example:&lt;br /&gt;
&lt;br /&gt;
 [ 11 ]&lt;br /&gt;
&lt;br /&gt;
The menu is rendered as a single column data if there are less than 11 entries, then there would be 2 columns.&lt;br /&gt;
&lt;br /&gt;
 [ 11, 21 ]&lt;br /&gt;
&lt;br /&gt;
This would have one column if there were ten or less values, two columns if there are twenty or less, and three columns for all other cases.&lt;br /&gt;
&lt;br /&gt;
 [ 0, 0 ]&lt;br /&gt;
&lt;br /&gt;
This would always have three columns.&lt;br /&gt;
&lt;br /&gt;
 [ 2, 3 ]&lt;br /&gt;
&lt;br /&gt;
This would have one column for a single data, two columns for two, and three columns for three or more data.&lt;br /&gt;
&lt;br /&gt;
Add one to the number of integers in the array and you get the maximum number of columns. The entries are evenly distributed in the columns.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sections===&lt;br /&gt;
&lt;br /&gt;
When a menu is using &amp;quot;sections&amp;quot;, then items on the menu are grouped together. The exact method is defined by defining values for several options. These options go to the ''menus section'' as well.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;4&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|grouping_function &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|This function determines how grouping is done. The following predefined functions can be used:&lt;br /&gt;
*&amp;quot;EPrints::Update::Views::group_by_a_to_z&amp;quot;&lt;br /&gt;
*&amp;quot;EPrints::Update::Views::group_by_first_character&amp;quot; (default)&lt;br /&gt;
*&amp;quot;EPrints::Update::Views::group_by_2_characters&amp;quot;&lt;br /&gt;
*&amp;quot;EPrints::Update::Views::group_by_3_characters&amp;quot;&lt;br /&gt;
*&amp;quot;EPrints::Update::Views::group_by_4_characters&amp;quot;&lt;br /&gt;
*&amp;quot;EPrints::Update::Views::group_by_5_characters&amp;quot;&lt;br /&gt;
with the usual meaning. If you use 'group_by_a_to_z', all entries not starting with a letter will be discarded.&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|group_sorting_function &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|A custom function which sorts the group identifiers. The only available function&lt;br /&gt;
*&amp;quot;EPrints::Update::Views::default_sort&amp;quot;&lt;br /&gt;
sorts alphabetically.&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|group_range_function &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Splits the groups (as determined by the grouping function) into sections so that a group never splits. Groups are rendered separately, but a section is kept on a single page. Available grouping functions are&lt;br /&gt;
*&amp;quot;Eprints::Update::Views::no_ranges&amp;quot; (default)&lt;br /&gt;
*&amp;quot;EPrints::Update::Views::cluster_ranges_&amp;lt;range&amp;gt;&amp;quot;&lt;br /&gt;
where &amp;lt;range&amp;gt; is one of 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, and 200.&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|open_first_section &amp;lt;sup style=&amp;quot;font-weight:bold; font-size:10px;&amp;quot;&amp;gt;(M)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Phrases==&lt;br /&gt;
&lt;br /&gt;
Views can have their own titles and other phrases. If they do not exist, then a default one is used (usually containing the view's id). For examples, see the views.xml file.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;3&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|viewname_eprint_&amp;lt;viewid&amp;gt;&lt;br /&gt;
|the name of the browse pages&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|viewintro_&amp;lt;viewid&amp;gt;&lt;br /&gt;
|The phrase to replace the text &amp;quot;Please select a value to browse from the list below.&amp;quot; in the top level menu&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|viewintro_&amp;lt;viewid&amp;gt;/&amp;lt;value&amp;gt;&lt;br /&gt;
|Intro phrase on the next level&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|viewtitle_eprint_&amp;lt;viewid&amp;gt;_menu_&amp;lt;level&amp;gt;&lt;br /&gt;
|Title of browse page at level &amp;lt;level&amp;gt;, which is 1, 2, ... In the phrase you can use the pins &amp;quot;value1&amp;quot;, &amp;quot;value2&amp;quot;, etc. where the number can be one less than the present level; the value of the pin is the actual value of the previous levels. See the example below.&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|viewgroup_eprint_&amp;lt;viewid&amp;gt;_&amp;lt;filename&amp;gt;&lt;br /&gt;
|Used as a pin value for the title on the list pages, when [[#Variations|variations]] are used. &amp;lt;Filename&amp;gt; is the filename defined as the option of the variation, or, if it is not defined, then it is the fieldname at the beginning.&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|viewtitle_eprint_&amp;lt;viewid&amp;gt;_list&lt;br /&gt;
|Title of the list pages of the view. You can use the same pins as before (&amp;quot;value1&amp;quot;, &amp;quot;value2&amp;quot;, etc.). If the list was generated by a [[#Variations|variation]] then the &amp;quot;grouping&amp;quot; pin is also available.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The following example shows how to define these values.&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewname_eprint_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprint_divisions_menu_1&amp;quot;&amp;gt;&lt;br /&gt;
    Browse by Division and Year&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprint_divisions_menu_2&amp;quot;&amp;gt;&lt;br /&gt;
    Browse by Year where Division is&lt;br /&gt;
     &amp;lt;epc:pin name=&amp;quot;value1&amp;quot; /&amp;gt; &amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;4&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|heading_level&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
|include&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
|subheadings&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
|nohtml&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
|noindex&lt;br /&gt;
| ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Example=&lt;br /&gt;
==EPrints 3.2 example==&lt;br /&gt;
===cfg/cfg.d/views.pl===&lt;br /&gt;
  { id         =&amp;gt; &amp;quot;target&amp;quot;,  # The 'name' for this view&lt;br /&gt;
    allow_null =&amp;gt; 0,&lt;br /&gt;
    hide_empty =&amp;gt; 1,&lt;br /&gt;
    menus      =&amp;gt; [&lt;br /&gt;
      { fields =&amp;gt; [&amp;quot;broker_reponame&amp;quot;], # The field(s) to use - in this case the 'reponame' sub-element of the 'broker' field&lt;br /&gt;
        new_column_at      =&amp;gt; [0],    # force 2 columns, even if the&lt;br /&gt;
                                      # second is blank&lt;br /&gt;
        mode               =&amp;gt; &amp;quot;sections&amp;quot;,&lt;br /&gt;
        open_first_section =&amp;gt; 1,&lt;br /&gt;
        group_range_function   =&amp;gt; &amp;quot;EPrints::Update::Views::cluster_ranges_30&amp;quot;,&lt;br /&gt;
        group_sorting_function =&amp;gt; &amp;quot;EPrints::Update::Views::default_sort&amp;quot;,&lt;br /&gt;
      },&lt;br /&gt;
    ],&lt;br /&gt;
    order =&amp;gt; &amp;quot;-date/title&amp;quot;,&lt;br /&gt;
    citation =&amp;gt; 'router',    # This defines the file in cfg/citations/eprint/&lt;br /&gt;
    layout   =&amp;gt; 'router',    # This is used in Views.pm to determine how to&lt;br /&gt;
                             # join individual citations together...&lt;br /&gt;
  },&lt;br /&gt;
&lt;br /&gt;
This creates a view, which will be 2-columns wide.&lt;br /&gt;
Two important definitions here are:&lt;br /&gt;
* '''citation''' defines the citation file used to create the block of html for each record to be displayed, and&lt;br /&gt;
* '''layout''' indicates how those blocks are joined together.&lt;br /&gt;
&lt;br /&gt;
====Layout====&lt;br /&gt;
'''Layout''' can be one of:&lt;br /&gt;
* paragraph (the default)&lt;br /&gt;
puts &amp;amp;lt;p&amp;gt; elements round each citation&lt;br /&gt;
&lt;br /&gt;
* orderedlist&lt;br /&gt;
makes an ordered list (1,2,3,4 or whatever the CSS defines)&lt;br /&gt;
&lt;br /&gt;
* unorderedlist&lt;br /&gt;
makes an unordered list&lt;br /&gt;
&lt;br /&gt;
* ''anything else''&lt;br /&gt;
just puts a newline (in the page source) after each citation&lt;br /&gt;
&lt;br /&gt;
====citation====&lt;br /&gt;
In our example, we're using a home-made citation layout&lt;br /&gt;
&lt;br /&gt;
The citation file is in &amp;lt;code&amp;gt;/cfg/citations/eprint/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above view, we have defined the citation format to be '''router''', therefore we need a file called '''router.xml''' in the citations directory.&lt;br /&gt;
&lt;br /&gt;
Remember this format is used for each record, so needs to be complete in it's own right - and if you want records to line up vertically, you need to plan that in advance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;lt;?xml version=&amp;quot;1.0&amp;quot; ?&amp;gt;&lt;br /&gt;
    &amp;amp;lt;!-- &lt;br /&gt;
  	Full citation for an eprint. &lt;br /&gt;
    --&amp;gt;&lt;br /&gt;
    &amp;amp;lt;cite:citation xmlns:xhtml=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; xmlns=&amp;quot;http://eprints.org/ep3/control&amp;quot; xmlns:cite=&amp;quot;http://eprints.org/ep3/citation&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;amp;lt;table class='ep_rt_citation'&amp;gt;;&lt;br /&gt;
    &amp;amp;lt;tr&amp;gt;&amp;amp;lt;td colspan='2'&amp;gt;&lt;br /&gt;
    &amp;amp;lt;choose&amp;gt;&lt;br /&gt;
      &amp;amp;lt;when test=&amp;quot;type = 'book' and is_set( creators )&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;amp;lt;span class='strong'&amp;gt;&amp;amp;lt;print expr=&amp;quot;creators_name&amp;quot;/&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
      &amp;amp;lt;/when&amp;gt;&lt;br /&gt;
      .... more code ....&lt;br /&gt;
    &amp;amp;lt;/choose&amp;gt;&lt;br /&gt;
    &amp;amp;lt;/td&amp;gt;&amp;amp;lt;td style=&amp;quot;width:8em&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;amp;lt;if test=&amp;quot;date&amp;quot;&amp;gt;&amp;amp;lt;span class='right strong'&amp;gt;(&amp;amp;lt;print expr=&amp;quot;date&amp;quot; opts=&amp;quot;res=year&amp;quot;/&amp;gt;)&amp;amp;lt;/span&amp;gt;&amp;amp;lt;/if&amp;gt;&lt;br /&gt;
    &amp;amp;lt;/td&amp;gt;&amp;amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;amp;lt;tr&amp;gt;&amp;amp;lt;td style=&amp;quot;width:50%&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;amp;lt;cite:linkhere&amp;gt;&amp;amp;lt;xhtml:em&amp;gt;&amp;amp;lt;print expr=&amp;quot;title&amp;quot; opts=&amp;quot;magicstop&amp;quot;/&amp;gt;&amp;amp;lt;/xhtml:em&amp;gt;&amp;amp;lt;/cite:linkhere&amp;gt;&lt;br /&gt;
    &amp;amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;amp;lt;choose&amp;gt;&lt;br /&gt;
     .... more code&lt;br /&gt;
    &amp;amp;lt;when test=&amp;quot;type = 'article'&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;amp;lt;td&amp;gt;&lt;br /&gt;
      &amp;amp;lt;if test=&amp;quot;publication&amp;quot;&amp;gt;&amp;amp;lt;print expr=&amp;quot;publication&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;amp;lt;if test=&amp;quot;volume&amp;quot;&amp;gt;, &amp;amp;lt;print expr=&amp;quot;volume&amp;quot;/&amp;gt;&amp;amp;lt;/if&amp;gt;&lt;br /&gt;
        &amp;amp;lt;if test=&amp;quot;number&amp;quot;&amp;gt; (&amp;amp;lt;print expr=&amp;quot;number&amp;quot;/&amp;gt;)&amp;amp;lt;/if&amp;gt;&lt;br /&gt;
        .&amp;amp;lt;/if&amp;gt;&lt;br /&gt;
      &amp;amp;lt;if test=&amp;quot;pagerange&amp;quot;&amp;gt; &amp;amp;lt;print expr=&amp;quot;pagerange&amp;quot;/&amp;gt;.&amp;amp;lt;/if&amp;gt;&lt;br /&gt;
      &amp;amp;lt;/td&amp;gt;&amp;amp;lt;td&amp;gt;&lt;br /&gt;
      &amp;amp;lt;if test=&amp;quot;issn&amp;quot;&amp;gt;&amp;lt;span class='right'&amp;gt; ISSN &amp;lt;print expr=&amp;quot;issn&amp;quot;/&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/if&amp;gt;&lt;br /&gt;
      &amp;amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;amp;lt;/when&amp;gt;&lt;br /&gt;
    .... more code&lt;br /&gt;
  &amp;amp;lt;/choose&amp;gt;&lt;br /&gt;
  &amp;amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;amp;lt;if test=&amp;quot; ! type.one_of( 'patent','thesis' )&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;amp;lt;if test=&amp;quot;ispublished.one_of('unpub', 'submitted', 'inpress')&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;amp;lt;tr&amp;gt;&amp;amp;lt;td colspan='2'&amp;gt;&lt;br /&gt;
     (&amp;amp;lt;print expr=&amp;quot;ispublished&amp;quot;/&amp;gt;)&lt;br /&gt;
    &amp;amp;lt;/td&amp;gt;&amp;amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;amp;lt;/if&amp;gt;&lt;br /&gt;
  &amp;amp;lt;/if&amp;gt;&lt;br /&gt;
  &amp;amp;lt;/table&amp;gt;&lt;br /&gt;
  &amp;amp;lt;/cite:citation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This creates a table for each record, and CSS is used to manage the size &amp;amp; position of the various elements&lt;br /&gt;
&lt;br /&gt;
===cfg/cfg.d/eprint_render.pl===&lt;br /&gt;
When viewing a record, the main abstract view page can also be altered&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;cfg/cfg.d/eprint_render.pl&amp;lt;/code&amp;gt;, towards the bottom of the subroutine &amp;lt;code&amp;gt;$c-&amp;gt;{eprint_render}&amp;lt;/code&amp;gt; is the following line:&lt;br /&gt;
&lt;br /&gt;
   my $page = $eprint-&amp;gt;render_citation( &amp;quot;router_page&amp;quot;, %fragments, flags=&amp;gt;$flags );&lt;br /&gt;
&lt;br /&gt;
Here, '''router_page''' is the name of the citation file for creating the abstract page..... '''router_page.xml''' in this case&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Installing_EPrints_on_Debian/Ubuntu&amp;diff=16749</id>
		<title>Installing EPrints on Debian/Ubuntu</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Installing_EPrints_on_Debian/Ubuntu&amp;diff=16749"/>
		<updated>2025-04-09T19:21:17Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Debian and Ubuntu]]&lt;br /&gt;
[[Category:Installation]]&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Ubuntu 20.04 LTS, 22.04 LTS and Ubuntu 24.04 LTS (non-LTS versions not recommended)&lt;br /&gt;
* Debian 10 (Buster), Debian 11 (Bullseye) or Debian 12 (Bookworm) - These are not as comprehensively tested as Ubuntu LTS versions.&lt;br /&gt;
&lt;br /&gt;
== Installing EPrints from Source ==&lt;br /&gt;
&lt;br /&gt;
=== Dependencies and Pre-configuration ===&lt;br /&gt;
'''The ideal way to install from source is via git using the Core Git repositories [https://github.com/eprints/eprints3.4 EPrints 3.4] or [https://github.com/eprints/eprints EPrints 3.3], and installing from a source tarball is generally discouraged.'''&lt;br /&gt;
&lt;br /&gt;
'''Installing from source via git is now the recommended  way to install EPrints for production repositories, after having proved to be a useful installation method to those seeking to develop the EPrints code, develop a plugin or develop a Bazaar package too.'''&lt;br /&gt;
&lt;br /&gt;
First, as the root user install all the dependencies for EPrints ('''N.B.''' Some dependencies may not be able in certain versions of Debian/Ubuntu.  See [[#Operating System Version Specific Requirements|Operating System Version Specific Requirements]] towards the end of this page):&lt;br /&gt;
&lt;br /&gt;
 apt-get install perl libncurses5 libselinux1 apache2 libapache2-mod-perl2 libxml-libxml-perl \&lt;br /&gt;
   libunicode-string-perl libterm-readkey-perl libmime-lite-perl libmime-types-perl libdigest-sha-perl \&lt;br /&gt;
   libdbd-mysql-perl libxml-parser-perl libxml2-dev libxml-twig-perl libarchive-any-perl libjson-perl \&lt;br /&gt;
   liblwp-protocol-https-perl libtext-unidecode-perl lynx wget ghostscript poppler-utils antiword elinks \&lt;br /&gt;
   texlive-base texlive-binaries psutils imagemagick adduser tar gzip unzip libsearch-xapian-perl \&lt;br /&gt;
   libtex-encode-perl libio-string-perl python3-html2text make libexpat1-dev libxslt1-dev&lt;br /&gt;
&lt;br /&gt;
If you are installing on Ubuntu, install MySQL server and client:&lt;br /&gt;
&lt;br /&gt;
  apt-get install mysql-server mysql-client libmysqlclient-dev&lt;br /&gt;
&lt;br /&gt;
If you are installing on Debian, install MariaDB server and client:&lt;br /&gt;
&lt;br /&gt;
  apt-get install mariadb-server mariadb-client libmariadb-dev&lt;br /&gt;
&lt;br /&gt;
Next, create the eprints user&lt;br /&gt;
&lt;br /&gt;
 useradd eprints&lt;br /&gt;
&lt;br /&gt;
Now add the eprints user to the www-data group and vice-versa&lt;br /&gt;
&lt;br /&gt;
 usermod -a -G eprints www-data&lt;br /&gt;
 usermod -a -G www-data eprints&lt;br /&gt;
&lt;br /&gt;
=== Downloading and Deploying EPrints Source ===&lt;br /&gt;
&lt;br /&gt;
==== EPrints 3.4.x for GitHub ====&lt;br /&gt;
&lt;br /&gt;
 apt install git&lt;br /&gt;
 mkdir /opt/eprints3&lt;br /&gt;
 chown eprints:eprints /opt/eprints3&lt;br /&gt;
 chmod 2775 /opt/eprints3&lt;br /&gt;
 su eprints&lt;br /&gt;
 git clone https://github.com/eprints/eprints3.4.git /opt/eprints3&lt;br /&gt;
 cd /opt/eprints3/&lt;br /&gt;
 git checkout tags/v3.4.6&lt;br /&gt;
&lt;br /&gt;
==== EPrints 3.4.x from files.eprints.org ====&lt;br /&gt;
&lt;br /&gt;
 cd /tmp/&lt;br /&gt;
 wget https://files.eprints.org/3097/5/eprints-3.4.6.tar.gz&lt;br /&gt;
 tar -xzvf eprints-3.4.6.tar.gz&lt;br /&gt;
&lt;br /&gt;
Then put in the source code in place:&lt;br /&gt;
&lt;br /&gt;
 mv eprints-3.4.6 /usr/share/eprints&lt;br /&gt;
 chmod 2775 /usr/share/eprints&lt;br /&gt;
 chown -R eprints:eprints /usr/share/eprints&lt;br /&gt;
&lt;br /&gt;
If you want a publications flavoured repository, then also:&lt;br /&gt;
&lt;br /&gt;
 wget https://files.eprints.org/3097/6/eprints-3.4.6-flavours.tar.gz&lt;br /&gt;
 tar -xzvf eprints-3.4.6-flavours.tar.gz&lt;br /&gt;
 mv eprints-3.4.6/flavours/pub_lib /usr/share/eprints/flavours&lt;br /&gt;
 chmod -R g+w /usr/share/eprints/flavours/pub_lib&lt;br /&gt;
 chown -R eprints:eprints /usr/share/eprints/flavours/pub_lib&lt;br /&gt;
&lt;br /&gt;
== Installing from Debian package ==&lt;br /&gt;
As of EPrints 3.4.5 Debian (.deb) packages will no longer be produced.  Due to the complexity of the installation process there are a number of inherent problems with installing using a Deb package. As new operating systems (e.g. Debian and Ubuntu) are released the available packages have changed.  This often leads to packages upon which that EPrints depends ceasing to be available.  This makes it very difficult or impossible to install the Debian package, as well as requiring retrospective effort to install packages using other sources, (e.g. additional APT repositories or using CPAN).  However, the main concern of installation the Debian package, particularly through EPrints' APT repository, is that it can lead to EPrints being upgraded automatically to a new version.  Upgrading EPrints using a Debian package is likely to lead to EPrints producing errors, as configuration changes are often required as part of the upgrade process.  Automating these changes within the Debian package would be all but impossible due to EPrints' high level of customisability.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
Next, as the eprints user copy &amp;lt;code&amp;gt;EPRINTS_PATH/perl_lib/EPrints/SystemSettings.pm.tmpl&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;EPRINTS_PATH/perl_lib/EPrints/SystemSettings.pm&amp;lt;/code&amp;gt;, if it does not already exist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;EPRINTS_PATH&amp;lt;/code&amp;gt; will be either &amp;lt;code&amp;gt;/opt/eprints3/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/usr/share/eprints3/&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;/usr/share/eprints&amp;lt;/code&amp;gt; depending on which instructions you followed above.&lt;br /&gt;
&lt;br /&gt;
EPrints is now fully installed at &amp;lt;code&amp;gt;EPRINTS_PATH/&amp;lt;/code&amp;gt;. However, you will not yet have a running archive. Follow the [[Getting Started with EPrints 3]] instructions to set this up.&lt;br /&gt;
&lt;br /&gt;
=== Post-configuration ===&lt;br /&gt;
Next, add the file &amp;lt;code&amp;gt;/etc/apache2/sites-available/eprints.conf&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&lt;br /&gt;
 Include EPRINTS_PATH/cfg/apache.conf&lt;br /&gt;
&lt;br /&gt;
To enable this as root run the command:&lt;br /&gt;
&lt;br /&gt;
 root&amp;gt; a2ensite eprints&lt;br /&gt;
&lt;br /&gt;
Also it may be necessary to disable the default site otherwise the default Apache page will still be shown:&lt;br /&gt;
&lt;br /&gt;
 a2dissite 000-default&lt;br /&gt;
&lt;br /&gt;
Finally, restart Apache:&lt;br /&gt;
&lt;br /&gt;
 service apache2 restart&lt;br /&gt;
&lt;br /&gt;
You should now be able to access your vanilla repository at the hostname you specified when running '''epadmin create''' from the [[Getting Started with EPrints 3]] instructions.  You should then login as the admin user you created during this process and turn on the indexer.  This can be done by clicking on the '''Admin''' link under the Logged in menu, then clicking on the '''System Tools''' tab and finally the '''Start Indexer''' button.&lt;br /&gt;
&lt;br /&gt;
== Operating System Version Specific Requirements ==&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu 20.04 LTS ===&lt;br /&gt;
{{:Issues with Installing EPrints on Ubuntu 20.04}}&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu 22.04 LTS ===&lt;br /&gt;
{{:Issues with Installing EPrints on Ubuntu 22.04}}&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu 24.04 LTS ===&lt;br /&gt;
{{:Issues with Installing EPrints on Ubuntu 24.04}}&lt;br /&gt;
&lt;br /&gt;
=== Debian Known Issues ===&lt;br /&gt;
See [[Debian Known Issues]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Installing_EPrints_on_Debian/Ubuntu&amp;diff=16748</id>
		<title>Installing EPrints on Debian/Ubuntu</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Installing_EPrints_on_Debian/Ubuntu&amp;diff=16748"/>
		<updated>2025-04-09T10:54:08Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Post-configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Debian and Ubuntu]]&lt;br /&gt;
[[Category:Installation]]&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Ubuntu 20.04 LTS, 22.04 LTS and Ubuntu 24.04 LTS (non-LTS versions not recommended)&lt;br /&gt;
* Debian 10 (Buster), Debian 11 (Bullseye) or Debian 12 (Bookworm) - These are not as comprehensively tested as Ubuntu LTS versions.&lt;br /&gt;
&lt;br /&gt;
== Installing EPrints from Source ==&lt;br /&gt;
&lt;br /&gt;
=== Dependencies and Pre-configuration ===&lt;br /&gt;
'''The ideal way to install from source is via git using the Core Git repositories [https://github.com/eprints/eprints3.4 EPrints 3.4] or [https://github.com/eprints/eprints EPrints 3.3], and installing from a source tarball is generally discouraged.'''&lt;br /&gt;
&lt;br /&gt;
'''Installing from source via git is now the recommended  way to install EPrints for production repositories, after having proved to be a useful installation method to those seeking to develop the EPrints code, develop a plugin or develop a Bazaar package too.'''&lt;br /&gt;
&lt;br /&gt;
First, as the root user install all the dependencies for EPrints ('''N.B.''' Some dependencies may not be able in certain versions of Debian/Ubuntu.  See [[#Operating System Version Specific Requirements|Operating System Version Specific Requirements]] towards the end of this page):&lt;br /&gt;
&lt;br /&gt;
 apt-get install perl libncurses5 libselinux1 apache2 libapache2-mod-perl2 libxml-libxml-perl \&lt;br /&gt;
   libunicode-string-perl libterm-readkey-perl libmime-lite-perl libmime-types-perl libdigest-sha-perl \&lt;br /&gt;
   libdbd-mysql-perl libxml-parser-perl libxml2-dev libxml-twig-perl libarchive-any-perl libjson-perl \&lt;br /&gt;
   liblwp-protocol-https-perl libtext-unidecode-perl lynx wget ghostscript poppler-utils antiword elinks \&lt;br /&gt;
   texlive-base texlive-binaries psutils imagemagick adduser tar gzip unzip libsearch-xapian-perl \&lt;br /&gt;
   libtex-encode-perl libio-string-perl python3-html2text make libexpat1-dev libxslt1-dev&lt;br /&gt;
&lt;br /&gt;
If you are installing on Ubuntu, install MySQL server and client:&lt;br /&gt;
&lt;br /&gt;
  apt-get install mysql-server mysql-client libmysqlclient-dev&lt;br /&gt;
&lt;br /&gt;
If you are installing on Debian, install MariaDB server and client:&lt;br /&gt;
&lt;br /&gt;
  apt-get install mariadb-server mariadb-client libmariadb-dev&lt;br /&gt;
&lt;br /&gt;
Next, create the eprints user&lt;br /&gt;
&lt;br /&gt;
 useradd eprints&lt;br /&gt;
&lt;br /&gt;
Now add the eprints user to the www-data group and vice-versa&lt;br /&gt;
&lt;br /&gt;
 usermod -a -G eprints www-data&lt;br /&gt;
 usermod -a -G www-data eprints&lt;br /&gt;
&lt;br /&gt;
=== Downloading and Deploying EPrints Source ===&lt;br /&gt;
&lt;br /&gt;
==== EPrints 3.4.x for GitHub ====&lt;br /&gt;
&lt;br /&gt;
 apt install git&lt;br /&gt;
 mkdir /opt/eprints3&lt;br /&gt;
 chown eprints:eprints /opt/eprints3&lt;br /&gt;
 chmod 2775 /opt/eprints3&lt;br /&gt;
 su eprints&lt;br /&gt;
 git clone https://github.com/eprints/eprints3.4.git /opt/eprints3&lt;br /&gt;
 cd /opt/eprints3/&lt;br /&gt;
 git checkout tags/v3.4.6&lt;br /&gt;
&lt;br /&gt;
==== EPrints 3.4.x from files.eprints.org ====&lt;br /&gt;
&lt;br /&gt;
 cd /tmp/&lt;br /&gt;
 wget https://files.eprints.org/3097/5/eprints-3.4.6.tar.gz&lt;br /&gt;
 tar -xzvf eprints-3.4.6.tar.gz&lt;br /&gt;
&lt;br /&gt;
Then put in the source code in place:&lt;br /&gt;
&lt;br /&gt;
 mv eprints-3.4.6 /usr/share/eprints&lt;br /&gt;
 chmod 2775 /usr/share/eprints&lt;br /&gt;
 chown -R eprints:eprints /usr/share/eprints&lt;br /&gt;
&lt;br /&gt;
If you want a publications flavoured repository, then also:&lt;br /&gt;
&lt;br /&gt;
 wget https://files.eprints.org/3097/6/eprints-3.4.6-flavours.tar.gz&lt;br /&gt;
 tar -xzvf eprints-3.4.6-flavours.tar.gz&lt;br /&gt;
 mv eprints-3.4.6/flavours/pub_lib /usr/share/eprints/flavours&lt;br /&gt;
 chmod -R g+w /usr/share/eprints/flavours/pub_lib&lt;br /&gt;
 chown -R eprints:eprints /usr/share/eprints/flavours/pub_lib&lt;br /&gt;
&lt;br /&gt;
== Installing from Debian package ==&lt;br /&gt;
As of EPrints 3.4.5 Debian (.deb) packages will no longer be produced.  Due to the complexity of the installation process there are a number of inherent problems with installing using a Deb package. As new operating systems (e.g. Debian and Ubuntu) are released the available packages have changed.  This often leads to packages upon which that EPrints depends ceasing to be available.  This makes it very difficult or impossible to install the Debian package, as well as requiring retrospective effort to install packages using other sources, (e.g. additional APT repositories or using CPAN).  However, the main concern of installation the Debian package, particularly through EPrints' APT repository, is that it can lead to EPrints being upgraded automatically to a new version.  Upgrading EPrints using a Debian package is likely to lead to EPrints producing errors, as configuration changes are often required as part of the upgrade process.  Automating these changes within the Debian package would be all but impossible due to EPrints' high level of customisability.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
Next, as the eprints user copy &amp;lt;code&amp;gt;EPRINTS_PATH/perl_lib/EPrints/SystemSettings.pm.tmpl&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;EPRINTS_PATH/perl_lib/EPrints/SystemSettings.pm&amp;lt;/code&amp;gt;, if it does not already exist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;EPRINTS_PATH&amp;lt;/code&amp;gt; will be either &amp;lt;code&amp;gt;/usr/share/eprints3/&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;/usr/share/eprints&amp;lt;/code&amp;gt; depending on which instructions you followed above.&lt;br /&gt;
&lt;br /&gt;
EPrints is now fully installed at &amp;lt;code&amp;gt;EPRINTS_PATH/&amp;lt;/code&amp;gt;. However, you will not yet have a running archive. Follow the [[Getting Started with EPrints 3]] instructions to set this up.&lt;br /&gt;
&lt;br /&gt;
=== Post-configuration ===&lt;br /&gt;
Next, add the file &amp;lt;code&amp;gt;/etc/apache2/sites-available/eprints.conf&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&lt;br /&gt;
 Include EPRINTS_PATH/cfg/apache.conf&lt;br /&gt;
&lt;br /&gt;
To enable this as root run the command:&lt;br /&gt;
&lt;br /&gt;
 root&amp;gt; a2ensite eprints&lt;br /&gt;
&lt;br /&gt;
Also it may be necessary to disable the default site otherwise the default Apache page will still be shown:&lt;br /&gt;
&lt;br /&gt;
 a2dissite 000-default&lt;br /&gt;
&lt;br /&gt;
Finally, restart Apache:&lt;br /&gt;
&lt;br /&gt;
 service apache2 restart&lt;br /&gt;
&lt;br /&gt;
You should now be able to access your vanilla repository at the hostname you specified when running '''epadmin create''' from the [[Getting Started with EPrints 3]] instructions.  You should then login as the admin user you created during this process and turn on the indexer.  This can be done by clicking on the '''Admin''' link under the Logged in menu, then clicking on the '''System Tools''' tab and finally the '''Start Indexer''' button.&lt;br /&gt;
&lt;br /&gt;
== Operating System Version Specific Requirements ==&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu 20.04 LTS ===&lt;br /&gt;
{{:Issues with Installing EPrints on Ubuntu 20.04}}&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu 22.04 LTS ===&lt;br /&gt;
{{:Issues with Installing EPrints on Ubuntu 22.04}}&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu 24.04 LTS ===&lt;br /&gt;
{{:Issues with Installing EPrints on Ubuntu 24.04}}&lt;br /&gt;
&lt;br /&gt;
=== Debian Known Issues ===&lt;br /&gt;
See [[Debian Known Issues]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Installing_EPrints_on_Debian/Ubuntu&amp;diff=16747</id>
		<title>Installing EPrints on Debian/Ubuntu</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Installing_EPrints_on_Debian/Ubuntu&amp;diff=16747"/>
		<updated>2025-04-09T10:53:59Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Post-configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Debian and Ubuntu]]&lt;br /&gt;
[[Category:Installation]]&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Ubuntu 20.04 LTS, 22.04 LTS and Ubuntu 24.04 LTS (non-LTS versions not recommended)&lt;br /&gt;
* Debian 10 (Buster), Debian 11 (Bullseye) or Debian 12 (Bookworm) - These are not as comprehensively tested as Ubuntu LTS versions.&lt;br /&gt;
&lt;br /&gt;
== Installing EPrints from Source ==&lt;br /&gt;
&lt;br /&gt;
=== Dependencies and Pre-configuration ===&lt;br /&gt;
'''The ideal way to install from source is via git using the Core Git repositories [https://github.com/eprints/eprints3.4 EPrints 3.4] or [https://github.com/eprints/eprints EPrints 3.3], and installing from a source tarball is generally discouraged.'''&lt;br /&gt;
&lt;br /&gt;
'''Installing from source via git is now the recommended  way to install EPrints for production repositories, after having proved to be a useful installation method to those seeking to develop the EPrints code, develop a plugin or develop a Bazaar package too.'''&lt;br /&gt;
&lt;br /&gt;
First, as the root user install all the dependencies for EPrints ('''N.B.''' Some dependencies may not be able in certain versions of Debian/Ubuntu.  See [[#Operating System Version Specific Requirements|Operating System Version Specific Requirements]] towards the end of this page):&lt;br /&gt;
&lt;br /&gt;
 apt-get install perl libncurses5 libselinux1 apache2 libapache2-mod-perl2 libxml-libxml-perl \&lt;br /&gt;
   libunicode-string-perl libterm-readkey-perl libmime-lite-perl libmime-types-perl libdigest-sha-perl \&lt;br /&gt;
   libdbd-mysql-perl libxml-parser-perl libxml2-dev libxml-twig-perl libarchive-any-perl libjson-perl \&lt;br /&gt;
   liblwp-protocol-https-perl libtext-unidecode-perl lynx wget ghostscript poppler-utils antiword elinks \&lt;br /&gt;
   texlive-base texlive-binaries psutils imagemagick adduser tar gzip unzip libsearch-xapian-perl \&lt;br /&gt;
   libtex-encode-perl libio-string-perl python3-html2text make libexpat1-dev libxslt1-dev&lt;br /&gt;
&lt;br /&gt;
If you are installing on Ubuntu, install MySQL server and client:&lt;br /&gt;
&lt;br /&gt;
  apt-get install mysql-server mysql-client libmysqlclient-dev&lt;br /&gt;
&lt;br /&gt;
If you are installing on Debian, install MariaDB server and client:&lt;br /&gt;
&lt;br /&gt;
  apt-get install mariadb-server mariadb-client libmariadb-dev&lt;br /&gt;
&lt;br /&gt;
Next, create the eprints user&lt;br /&gt;
&lt;br /&gt;
 useradd eprints&lt;br /&gt;
&lt;br /&gt;
Now add the eprints user to the www-data group and vice-versa&lt;br /&gt;
&lt;br /&gt;
 usermod -a -G eprints www-data&lt;br /&gt;
 usermod -a -G www-data eprints&lt;br /&gt;
&lt;br /&gt;
=== Downloading and Deploying EPrints Source ===&lt;br /&gt;
&lt;br /&gt;
==== EPrints 3.4.x for GitHub ====&lt;br /&gt;
&lt;br /&gt;
 apt install git&lt;br /&gt;
 mkdir /opt/eprints3&lt;br /&gt;
 chown eprints:eprints /opt/eprints3&lt;br /&gt;
 chmod 2775 /opt/eprints3&lt;br /&gt;
 su eprints&lt;br /&gt;
 git clone https://github.com/eprints/eprints3.4.git /opt/eprints3&lt;br /&gt;
 cd /opt/eprints3/&lt;br /&gt;
 git checkout tags/v3.4.6&lt;br /&gt;
&lt;br /&gt;
==== EPrints 3.4.x from files.eprints.org ====&lt;br /&gt;
&lt;br /&gt;
 cd /tmp/&lt;br /&gt;
 wget https://files.eprints.org/3097/5/eprints-3.4.6.tar.gz&lt;br /&gt;
 tar -xzvf eprints-3.4.6.tar.gz&lt;br /&gt;
&lt;br /&gt;
Then put in the source code in place:&lt;br /&gt;
&lt;br /&gt;
 mv eprints-3.4.6 /usr/share/eprints&lt;br /&gt;
 chmod 2775 /usr/share/eprints&lt;br /&gt;
 chown -R eprints:eprints /usr/share/eprints&lt;br /&gt;
&lt;br /&gt;
If you want a publications flavoured repository, then also:&lt;br /&gt;
&lt;br /&gt;
 wget https://files.eprints.org/3097/6/eprints-3.4.6-flavours.tar.gz&lt;br /&gt;
 tar -xzvf eprints-3.4.6-flavours.tar.gz&lt;br /&gt;
 mv eprints-3.4.6/flavours/pub_lib /usr/share/eprints/flavours&lt;br /&gt;
 chmod -R g+w /usr/share/eprints/flavours/pub_lib&lt;br /&gt;
 chown -R eprints:eprints /usr/share/eprints/flavours/pub_lib&lt;br /&gt;
&lt;br /&gt;
== Installing from Debian package ==&lt;br /&gt;
As of EPrints 3.4.5 Debian (.deb) packages will no longer be produced.  Due to the complexity of the installation process there are a number of inherent problems with installing using a Deb package. As new operating systems (e.g. Debian and Ubuntu) are released the available packages have changed.  This often leads to packages upon which that EPrints depends ceasing to be available.  This makes it very difficult or impossible to install the Debian package, as well as requiring retrospective effort to install packages using other sources, (e.g. additional APT repositories or using CPAN).  However, the main concern of installation the Debian package, particularly through EPrints' APT repository, is that it can lead to EPrints being upgraded automatically to a new version.  Upgrading EPrints using a Debian package is likely to lead to EPrints producing errors, as configuration changes are often required as part of the upgrade process.  Automating these changes within the Debian package would be all but impossible due to EPrints' high level of customisability.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
Next, as the eprints user copy &amp;lt;code&amp;gt;EPRINTS_PATH/perl_lib/EPrints/SystemSettings.pm.tmpl&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;EPRINTS_PATH/perl_lib/EPrints/SystemSettings.pm&amp;lt;/code&amp;gt;, if it does not already exist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;EPRINTS_PATH&amp;lt;/code&amp;gt; will be either &amp;lt;code&amp;gt;/usr/share/eprints3/&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;/usr/share/eprints&amp;lt;/code&amp;gt; depending on which instructions you followed above.&lt;br /&gt;
&lt;br /&gt;
EPrints is now fully installed at &amp;lt;code&amp;gt;EPRINTS_PATH/&amp;lt;/code&amp;gt;. However, you will not yet have a running archive. Follow the [[Getting Started with EPrints 3]] instructions to set this up.&lt;br /&gt;
&lt;br /&gt;
=== Post-configuration ===&lt;br /&gt;
Next, add the file &amp;lt;code&amp;gt;/etc/apache2/sites-available/eprints.conf&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&lt;br /&gt;
 Include EPRINTS_PATH/cfg/apache.conf&lt;br /&gt;
&lt;br /&gt;
To enable this as root run the command:&lt;br /&gt;
&lt;br /&gt;
root&amp;gt; a2ensite eprints&lt;br /&gt;
&lt;br /&gt;
Also it may be necessary to disable the default site otherwise the default Apache page will still be shown:&lt;br /&gt;
&lt;br /&gt;
 a2dissite 000-default&lt;br /&gt;
&lt;br /&gt;
Finally, restart Apache:&lt;br /&gt;
&lt;br /&gt;
 service apache2 restart&lt;br /&gt;
&lt;br /&gt;
You should now be able to access your vanilla repository at the hostname you specified when running '''epadmin create''' from the [[Getting Started with EPrints 3]] instructions.  You should then login as the admin user you created during this process and turn on the indexer.  This can be done by clicking on the '''Admin''' link under the Logged in menu, then clicking on the '''System Tools''' tab and finally the '''Start Indexer''' button.&lt;br /&gt;
&lt;br /&gt;
== Operating System Version Specific Requirements ==&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu 20.04 LTS ===&lt;br /&gt;
{{:Issues with Installing EPrints on Ubuntu 20.04}}&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu 22.04 LTS ===&lt;br /&gt;
{{:Issues with Installing EPrints on Ubuntu 22.04}}&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu 24.04 LTS ===&lt;br /&gt;
{{:Issues with Installing EPrints on Ubuntu 24.04}}&lt;br /&gt;
&lt;br /&gt;
=== Debian Known Issues ===&lt;br /&gt;
See [[Debian Known Issues]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Export_bar_on_abstract_page&amp;diff=16745</id>
		<title>Export bar on abstract page</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Export_bar_on_abstract_page&amp;diff=16745"/>
		<updated>2025-03-30T22:55:23Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Add a sort to the plugins to provide consistent ordering on item pages.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Abstract Pages]]&lt;br /&gt;
{{Version|since=3.2.0}}&lt;br /&gt;
&lt;br /&gt;
To add an export bar to the abstract page requires editing the eprint_render() method, eprint summary citation style and adding a CGI script to link the abstract page's form to the export URL.&lt;br /&gt;
&lt;br /&gt;
===cgi/export_redirect===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/perl&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
use EPrints;&lt;br /&gt;
&lt;br /&gt;
my $eprints = EPrints-&amp;gt;new;&lt;br /&gt;
my $repo = $eprints-&amp;gt;current_repository;&lt;br /&gt;
exit( 0 ) if !defined $repo;&lt;br /&gt;
&lt;br /&gt;
my $id = $repo-&amp;gt;param( &amp;quot;dataobj&amp;quot; );&lt;br /&gt;
my $format = $repo-&amp;gt;param( &amp;quot;format&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
exit( 0 ) if !EPrints::Utils::is_set( $id );&lt;br /&gt;
exit( 0 ) if !EPrints::Utils::is_set( $format );&lt;br /&gt;
&lt;br /&gt;
my $dataobj = $repo-&amp;gt;dataset( &amp;quot;archive&amp;quot; )-&amp;gt;dataobj( $id );&lt;br /&gt;
if( !defined $dataobj )&lt;br /&gt;
{&lt;br /&gt;
    $repo-&amp;gt;not_found( &amp;quot;eprint $id doesn't exist&amp;quot; );&lt;br /&gt;
    exit( 0 );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
my $plugin = $repo-&amp;gt;plugin( &amp;quot;Export::&amp;quot;.$format );&lt;br /&gt;
if( !defined $plugin )&lt;br /&gt;
{&lt;br /&gt;
    $repo-&amp;gt;not_found( &amp;quot;export format $format doesn't exist&amp;quot; );&lt;br /&gt;
    exit( 0 );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$repo-&amp;gt;redirect( $plugin-&amp;gt;dataobj_export_url( $dataobj ) );&lt;br /&gt;
exit( 0 );&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===archives/[repoid]/cfg/cfg.d/eprint_render.pl===&lt;br /&gt;
&lt;br /&gt;
Somewhere in eprint_render.pl, below &amp;lt;em&amp;gt;my $fragments&amp;lt;/em&amp;gt; add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang='perl'&amp;gt;&lt;br /&gt;
    my $export_bar = $session-&amp;gt;make_element( &amp;quot;div&amp;quot;, class =&amp;gt; &amp;quot;ep_block&amp;quot; );&lt;br /&gt;
    $fragments{export_bar} = $export_bar;&lt;br /&gt;
    {&lt;br /&gt;
        my @plugins = $session-&amp;gt;get_plugins(&lt;br /&gt;
            type =&amp;gt; &amp;quot;Export&amp;quot;,&lt;br /&gt;
            can_accept =&amp;gt; &amp;quot;dataobj/eprint&amp;quot;,&lt;br /&gt;
            is_advertised =&amp;gt; 1,&lt;br /&gt;
            is_visible =&amp;gt; &amp;quot;all&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
        # Added March 2025 - sort the plugins into a consistent order.&lt;br /&gt;
        # You may also want to make a custom order somehow. The 'qs' parameter seems&lt;br /&gt;
        # more focused on machine users than humans.&lt;br /&gt;
        my %names = map { $_ =&amp;gt; $_-&amp;gt;get_name } @plugins;&lt;br /&gt;
        @plugins = sort { $names{$a} cmp $names{$b} } @plugins;&lt;br /&gt;
        # /End Added March 2025&lt;br /&gt;
&lt;br /&gt;
        my $uri = $session-&amp;gt;get_url( path =&amp;gt; &amp;quot;cgi&amp;quot; ) . &amp;quot;/export_redirect&amp;quot;;&lt;br /&gt;
        my $form = $session-&amp;gt;render_form( &amp;quot;GET&amp;quot;, $uri );&lt;br /&gt;
        $export_bar-&amp;gt;appendChild( $form );&lt;br /&gt;
        $form-&amp;gt;appendChild( $session-&amp;gt;render_hidden_field( dataobj =&amp;gt; $eprint-&amp;gt;id ) );&lt;br /&gt;
        my $select = $session-&amp;gt;make_element( &amp;quot;select&amp;quot;, name =&amp;gt; &amp;quot;format&amp;quot; );&lt;br /&gt;
        $form-&amp;gt;appendChild( $select );&lt;br /&gt;
        foreach my $plugin (@plugins)&lt;br /&gt;
        {&lt;br /&gt;
            my $plugin_id = $plugin-&amp;gt;get_id;&lt;br /&gt;
            $plugin_id =~ s/^Export:://;&lt;br /&gt;
            my $option = $session-&amp;gt;make_element( &amp;quot;option&amp;quot;, value =&amp;gt; $plugin_id );&lt;br /&gt;
            $select-&amp;gt;appendChild( $option );&lt;br /&gt;
            $option-&amp;gt;appendChild( $plugin-&amp;gt;render_name );&lt;br /&gt;
        }&lt;br /&gt;
        my $button = $session-&amp;gt;make_element( &amp;quot;input&amp;quot;, type =&amp;gt; &amp;quot;submit&amp;quot;, value =&amp;gt; $session-&amp;gt;phrase( &amp;quot;lib/searchexpression:export_button&amp;quot; ), class =&amp;gt; &amp;quot;ep_form_action_button&amp;quot; );&lt;br /&gt;
        $form-&amp;gt;appendChild( $button );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===archives/[repoid]/cfg/citations/eprint/summary_page.xml===&lt;br /&gt;
&lt;br /&gt;
Where you want the export bar to appear add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang='xml'&amp;gt;&lt;br /&gt;
&amp;lt;epc:print expr=&amp;quot;$export_bar&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Contact&amp;diff=16720</id>
		<title>Contact</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Contact&amp;diff=16720"/>
		<updated>2025-02-14T12:35:20Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* eprints-tech Mailing List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{manual}}&lt;br /&gt;
&lt;br /&gt;
==Bug Report Policy==&lt;br /&gt;
&lt;br /&gt;
We use a [https://github.com/eprints/eprints/ Github] to record bugs and issues for EPrints. You can search there or the eprints-tech mailing list for existing bugs and possible solutions.&lt;br /&gt;
&lt;br /&gt;
If you identify a new bug or &amp;quot;issue&amp;quot; (issues are not bugs, but are things which could be clearer or better) please post a message to the eprints-tech mailing list - include all the information you can: what version of eprints, operating system etc.&lt;br /&gt;
&lt;br /&gt;
If you think the bug has security implications (i.e. it shouldn't be made public) please email [mailto:support@eprints.org support@eprints.org].&lt;br /&gt;
&lt;br /&gt;
== [[eprints-tech Mailing List]] ==&lt;br /&gt;
&lt;br /&gt;
[https://www.eprints.org/eptech/ eprints-tech] is the mailing list for technical queries or feedback. It can also have general queries, but most traffic is of a technical nature.&lt;br /&gt;
&lt;br /&gt;
{{EPrints-tech Subscription}}&lt;br /&gt;
&lt;br /&gt;
For more options to manage your subscription to the eprints-tech list [[eprints-tech Mailing List#Subscription Options|click here]].&lt;br /&gt;
&lt;br /&gt;
{{EPrints-tech Archive}}&lt;br /&gt;
&lt;br /&gt;
== Twitter==&lt;br /&gt;
&lt;br /&gt;
The following twitter accounts and hashtags are currently used:&lt;br /&gt;
&lt;br /&gt;
* [http://twitter.com/EPrints @EPrints] - EPrints twitter account&lt;br /&gt;
* [http://twitter.com/EPrintsServices @EPrintsServices] - EPrints Services twitter account&lt;br /&gt;
* [http://twitter.com/hashtag/EPrints #EPrints] - EPrints Hashtag&lt;br /&gt;
&lt;br /&gt;
== EPrints User Groups ==&lt;br /&gt;
&lt;br /&gt;
For general or language dependent EPrints discussion&lt;br /&gt;
&lt;br /&gt;
* [[German_User_Group|DE]]&lt;br /&gt;
* [https://groups.google.com/forum/#!forum/eprints-uk-user-group UK]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Upgrading_3.3.12%2B_to_3.4&amp;diff=16719</id>
		<title>Upgrading 3.3.12+ to 3.4</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Upgrading_3.3.12%2B_to_3.4&amp;diff=16719"/>
		<updated>2025-02-11T12:59:58Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These instructions help you upgrade EPrints 3.3.16+ (or any newer version of EPrints 3.3) to EPrints 3.4 while keeping all your eprints, documents and local configuration changes.&lt;br /&gt;
&lt;br /&gt;
It assumes your EPrints 3.3.16+ was installed using a tarball (tar.gz) file and installed in &amp;lt;code&amp;gt;/opt/eprints3&amp;lt;/code&amp;gt;. The commands in these instructions assume Centos 7 OS and run as the eprints user, unless it is stated to run as the root user.&lt;br /&gt;
&lt;br /&gt;
=Upgrade from Tarball=&lt;br /&gt;
&lt;br /&gt;
==Pre-upgrade==&lt;br /&gt;
* If you have local modifications to the core files (in /opt/eprints3/perl_lib), you may need to manually migrate your changes.&lt;br /&gt;
* If you use Twitter integration, use CPAN to install LWP::Authen::OAuth as this is no longer in perl_lib.  To do so, as root run:&lt;br /&gt;
 cpan LWP::Authen::OAuth&lt;br /&gt;
* Download each of the Bazaar plugins you have installed as EPM files from your existing repository.&lt;br /&gt;
* Make a backup of your local configurations.&lt;br /&gt;
&lt;br /&gt;
==Process==&lt;br /&gt;
We will move your existing eprints 3.3.16+ installation from &amp;lt;code&amp;gt;/opt/eprints3/&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/opt/eprints3.3&amp;lt;/code&amp;gt;, install eprints 3.4, then migrate your configurations into EPrints 3.4; cf. [https://wiki.eprints.org/w/Category:Installation Category Installation]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''as root'''&lt;br /&gt;
 apachectl stop&lt;br /&gt;
 cd /opt&lt;br /&gt;
 eprints3/bin/epindexer stop&lt;br /&gt;
 mv eprints3 eprints3.3&lt;br /&gt;
&lt;br /&gt;
* Download EPrints 3.4 core and publication flavour tarball and install them from [http://files.eprints.org/ Files.eprints.org] with&lt;br /&gt;
 wget https://files.eprints.org/3097/5/eprints-3.4.6.tar.gz&lt;br /&gt;
 wget https://files.eprints.org/3097/6/eprints-3.4.6-flavours.tar.gz&lt;br /&gt;
'''as root'''&lt;br /&gt;
 cd /root&lt;br /&gt;
 tar xvzf eprints-3.4.6.tar.gz&lt;br /&gt;
 tar xvzf eprints-3.4.6-flavours.tar.gz&lt;br /&gt;
&lt;br /&gt;
* Have a look to &amp;lt;code&amp;gt;/root/eprints-3.4.6/INSTALL&amp;lt;/code&amp;gt; for some local adaption options.&lt;br /&gt;
'''as root'''&lt;br /&gt;
 cd eprints-3.4.6&lt;br /&gt;
 ./configure&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
* Move your current repository from 3.3 to 3.4&lt;br /&gt;
'''as root'''&lt;br /&gt;
 cd /opt&lt;br /&gt;
 mv eprints3.3/archives/ARCHIVENAME eprints3/archives/&lt;br /&gt;
* After moving, make sure all files inside &amp;lt;code&amp;gt;/opt/eprints3&amp;lt;/code&amp;gt; are still owned by eprints user and belongs to eprints group, thus&lt;br /&gt;
'''as root'''&lt;br /&gt;
 chown -R eprints:eprints /opt/eprints3&lt;br /&gt;
&lt;br /&gt;
* Create &amp;lt;code&amp;gt;/opt/eprints3/archives/ARCHIVENAME/cfg/cfg.d/00_flavour.pl&amp;lt;/code&amp;gt; to set the appropriate flavour, typically 'pub', i.e. &lt;br /&gt;
 echo &amp;quot;\$c-&amp;gt;{flavour} = 'pub';&amp;quot; &amp;gt; /opt/eprints3/archives/ARCHIVENAME/cfg/cfg.d/00_flavour.pl&lt;br /&gt;
&lt;br /&gt;
* create a symbolic link to &amp;lt;tt&amp;gt;default.xml&amp;lt;/tt&amp;gt; &lt;br /&gt;
 cd /opt/eprints3/archives/ARCHIVENAME/cfg/templates/ (or /opt/eprints3/archives/ARCHIVENAME/cfg/lang/en/templates/&lt;br /&gt;
 ln -s default.xml default_internal.xml&lt;br /&gt;
&lt;br /&gt;
* Audit each of their local config files against the pub_lib flavours config files:&lt;br /&gt;
#The first &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; below will identify all the files that are the same.  If so, delete the ones in &amp;lt;code&amp;gt;archives/ARCHIVENAME/cfg/cfg.d/&amp;lt;/code&amp;gt;.  You almost certainly should not find any, as the files in &amp;lt;code&amp;gt;flavours/pub_lib/cfg.d&amp;lt;/code&amp;gt; will at very least have updated copyright/licensing boilerplate.&lt;br /&gt;
#The second &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; will find where files exists in both directory are different.  Here they should be compared to see, if the local differences are superficial (e.g. slightly different comments or spacing) and therefore can be removed.  Also the pub_lib flavour version may fix an outstanding bug or perform the required functionality more succinctly.  If this is the only change, then the local archive version can be deleted, otherwise the change should be incorporated in the local version.&lt;br /&gt;
 cd /opt/eprints3/&lt;br /&gt;
 diff -rs archives/ARCHIVENAME/cfg/cfg.d flavours/pub_lib/cfg.d | egrep '^Files .+ and .+ are identical$'&lt;br /&gt;
 diff -rq archives/ARCHIVENAME/cfg/cfg.d flavours/pub_lib/cfg.d | egrep '^Files .+ and .+ differ$'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Compare &amp;lt;code&amp;gt;archives/ARCHIVENAME/cfg/cfg.d/eprint_fields.pl&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;flavours/pub_lib/cfg/cfg.d/eprint_fields_pub.pl&amp;lt;/code&amp;gt;  maybe with the help of [http://diffuse.sourceforge.net/download_de.html ''diffuse''] to overcome this business easier:&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If these are different and fields are present in &amp;lt;code&amp;gt;eprint_fields_pub.pl&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;eprint_fields.pl&amp;lt;/code&amp;gt; or the definitions (e.g. type, options, etc.)  for the same field are different then:&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Copy &amp;lt;code&amp;gt;flavours/pub_lib/cfg.d/eprint_fields_pub.pl&amp;lt;/code&amp;gt; to their archive's &amp;lt;code&amp;gt;cfg/cfg.d/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;li&amp;gt;Modify the fields in their archive's &amp;lt;code&amp;gt;cfg/cfg.d/eprint_fields_pub.pl&amp;lt;/code&amp;gt; where they have different definitions (e.g. type, options, etc.) to those in &amp;lt;code&amp;gt;eprint_fields.pl&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;li&amp;gt;Remove all fields in their archive's &amp;lt;code&amp;gt;cfg/cfg.d/eprint_fields.pl&amp;lt;/code&amp;gt; where they also occur in their archive's &amp;lt;code&amp;gt;cfg/cfg.d/eprint_fields_pub.pl&amp;lt;/code&amp;gt;, no matter if already transferred due to previous item or initially the same.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If there are only additional fields in &amp;lt;code&amp;gt;archives/ARCHIVENAME/cfg/cfg.d/eprint_fields.pl&amp;lt;/code&amp;gt; then just do the last step.&lt;br /&gt;
&amp;lt;li&amp;gt;If the two files are identical then you need to do nothing.  However, this is extremly unlikely.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Finally, the specification is still the same, but mostly split into two distinct files, which obey the known rule ''Local version overrides central one''.&amp;lt;/ul&amp;gt;&lt;br /&gt;
* Synchronise &amp;lt;code&amp;gt;archives/ARCHIVENAME/cfg/cfg.d/epm.pl&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;ingredients/bazaar/cfg.d/epm.pl&amp;lt;/code&amp;gt;, i.e. remove &amp;lt;code&amp;gt;archives/ARCHIVENAME/cfg/cfg.d/epm.pl&amp;lt;/code&amp;gt; in case of ''no'' local modifications.&lt;br /&gt;
&lt;br /&gt;
* Ensure the following bazaar files are disabled by renaming to FILENAME.pl''.disabled''.  Once they have been reinstalled via the Bazaar then they can be moved back into place.  Using &amp;lt;code&amp;gt;epadmin test&amp;lt;/code&amp;gt; is a good way of discovering which files need this doing, but below is a list of common files that should be temporarily moved, if they exist in your archive's &amp;lt;code&amp;gt;cfg/cfg.d/&amp;lt;/code&amp;gt; directory:&lt;br /&gt;
 mv z_orcid_support.pl z_orcid_support.pl.disabled&lt;br /&gt;
 mv zz_hefce_oa_fields.pl zz_hefce_oa_fields.pl.disabled&lt;br /&gt;
 mv zz_rioxx2.pl zz_rioxx2.pl.disabled&lt;br /&gt;
 mv z_meprints.pl z_meprints.pl.disabled &lt;br /&gt;
&lt;br /&gt;
* As the eprints user, run &amp;lt;code&amp;gt;epadmin update&amp;lt;/code&amp;gt; to add any new fields that were not previously present (typically this is embargo_reason for documents and requester_email for request)&lt;br /&gt;
 /opt/eprints3/bin/epadmin update ARCHIVENAME&lt;br /&gt;
&lt;br /&gt;
* Generate new Apache configuration and as root test (fixing any issues) and restart Apache after necessary site-specific adaption are done.&lt;br /&gt;
 /opt/eprints3/bin/generate_apacheconf --system --replace ARCHIVENAME&lt;br /&gt;
'''as root'''&lt;br /&gt;
 apachectl configtest&lt;br /&gt;
 apachectl restart&lt;br /&gt;
&lt;br /&gt;
* Once confirming that EPrints is generally working.  Go to Admin-&amp;gt;Bazaar then install the Bazaar plugins you downloaded from your 3.3 repository before starting the upgrade process.  This can be done by going to the Available tab in the Bazaar and strolling to the Upload section at the bottom.  Unfortunately, you cannot do a bulk upload, so will need to install each plugin in turn. &lt;br /&gt;
&lt;br /&gt;
* Move back the files you renamed to FILENAME''.disabled'' earlier, the epindexer into service and reload Apache&lt;br /&gt;
'''as root'''&lt;br /&gt;
 /opt/eprints3/bin/epindexer start&lt;br /&gt;
 apachectl graceful&lt;br /&gt;
&lt;br /&gt;
* Finally, run &amp;lt;code&amp;gt;generate_static&amp;lt;/code&amp;gt; to make sure all pages are regenerated with any changes to configuration.&lt;br /&gt;
  /opt/eprints3/bin/generate_static ARCHIVEID&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
* EPrints 3.4.4+ now uses LONGTEXT instead of VARCHAR(255) for the &amp;lt;code&amp;gt;requester_user_agent&amp;lt;/code&amp;gt; column. Upgrading from v3.3 '''will not''' automatically update this column definition in the database. Manually altering the column is an option, but may take a long time as the access table can contain millions of rows. See: https://github.com/eprints/eprints3.4/issues/427 &lt;br /&gt;
* 3.4 does not automatically update an archive's &amp;lt;code&amp;gt;html/en/&amp;lt;/code&amp;gt; files. If there are any bugs with broken JavaScript or unexpected CSS, try deleting the archives &amp;lt;code&amp;gt;html/en/javascript/auto.js&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;html/en/style/auto.css&amp;lt;/code&amp;gt;.  Similarly if a static page cannot be changed try deleting it under the archive's &amp;lt;code&amp;gt;html/en/&amp;lt;/code&amp;gt; or running &amp;lt;code&amp;gt;generate_static&amp;lt;/code&amp;gt;.&lt;br /&gt;
* If some Perl modules are giving out error messages like: &lt;br /&gt;
  Can't locate object method &amp;quot;new&amp;quot; via package &amp;quot;EPrints::Plugin::Event::PIRUS&amp;quot; at /opt/eprints3/bin/../perl_lib/EPrints/PluginFactory.pm line 276.&lt;br /&gt;
  Can't locate object method &amp;quot;new&amp;quot; via package &amp;quot;EPrints::Plugin::Screen::EPrint::Box::Tools::SUPER&amp;quot; at /opt/eprints3/site_lib/plugins/EPrints/Plugin/Screen/EPrint/Box/Tools.pm line 12.&lt;br /&gt;
It is because their parent module has not been initialised. This happens when the parent module lives in perl_lib, and the problem module live in elsewhere; e.g. parent module of PIRUS(Event.pm) is in &amp;lt;code&amp;gt;./perl_lib&amp;lt;/code&amp;gt;, while the &amp;lt;code&amp;gt;PIRUS.pm&amp;lt;/code&amp;gt; is in &amp;lt;code&amp;gt;./pub_lib&amp;lt;/code&amp;gt;. &lt;br /&gt;
Just need to &amp;lt;code&amp;gt;use&amp;lt;/code&amp;gt; the parent module before the &amp;lt;code&amp;gt;ISA&amp;lt;/code&amp;gt; line:&lt;br /&gt;
 use EPrints::Plugin::Event;&lt;br /&gt;
&lt;br /&gt;
[[Category:Upgrading]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Cron_Events_and_Simple_email_Reports&amp;diff=16717</id>
		<title>Cron Events and Simple email Reports</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Cron_Events_and_Simple_email_Reports&amp;diff=16717"/>
		<updated>2025-01-29T09:52:14Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:EPrints_Bazaar]]&lt;br /&gt;
'''NOTE''' On EPrints v3.3.14 and lower, day-of-week or day-of-month events may actually run on a daily basis. See: https://github.com/eprints/eprints/issues/313 for details and patches.&lt;br /&gt;
&lt;br /&gt;
In this exercise we are going to create an Event plug-in which will run every day and produce a report of all the EPrints which have been added in the last day.&lt;br /&gt;
&lt;br /&gt;
= Step 1: Create the Event Plug-In = &lt;br /&gt;
&lt;br /&gt;
In the lib/plugins/EPrints/Plugin/Event directory create your main plugin with the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=perl&amp;gt;&lt;br /&gt;
package EPrints::Plugin::Event::EPrintsReportEx;&lt;br /&gt;
&lt;br /&gt;
use EPrints::Plugin::Event;&lt;br /&gt;
&lt;br /&gt;
@ISA = qw( EPrints::Plugin::Event );&lt;br /&gt;
&lt;br /&gt;
sub action_send_email &lt;br /&gt;
{&lt;br /&gt;
    my ( $self ) = @_;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub generate_content&lt;br /&gt;
{&lt;br /&gt;
    my ( $self ) = @_;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Step 2: Create your package =&lt;br /&gt;
&lt;br /&gt;
Create your package and don't forget to enable the Event Plugin according to http://wiki.eprints.org/w/My_First_Bazaar_Package&lt;br /&gt;
&lt;br /&gt;
= Step 3: Search for EPrints Added in the Last Day = &lt;br /&gt;
&lt;br /&gt;
In your event fill the &amp;lt;code&amp;gt;generate_content&amp;lt;/code&amp;gt; routine with the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=perl&amp;gt;&lt;br /&gt;
my $repository = $self-&amp;gt;{repository};&lt;br /&gt;
my $xml = $repository-&amp;gt;xml;&lt;br /&gt;
&lt;br /&gt;
my $content = $xml-&amp;gt;create_document_fragment();&lt;br /&gt;
my $h1 = $xml-&amp;gt;create_element(&amp;quot;h1&amp;quot;);&lt;br /&gt;
$content-&amp;gt;appendChild($h1);&lt;br /&gt;
$h1-&amp;gt;appendChild($repository-&amp;gt;make_text(&amp;quot;EPrints Added in the Last Day&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
my $ds = $repository-&amp;gt;dataset( &amp;quot;eprint&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
my $date = time() - 86400; # 1 day ago&lt;br /&gt;
$date = EPrints::Time::iso_date( $date ) . &amp;quot; 00:00:00&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
my $eprint_section;&lt;br /&gt;
&lt;br /&gt;
$ds-&amp;gt;search(&lt;br /&gt;
    custom_order =&amp;gt; &amp;quot;-datestamp&amp;quot;,&lt;br /&gt;
)-&amp;gt;map(sub {&lt;br /&gt;
    my( undef, undef, $item ) = @_;&lt;br /&gt;
    return if(!defined $item);&lt;br /&gt;
   &lt;br /&gt;
    my $ep_date = $item-&amp;gt;get_value(&amp;quot;datestamp&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
    last if($ep_date lt $date);&lt;br /&gt;
  &lt;br /&gt;
    if( !defined $eprint_section )&lt;br /&gt;
    {&lt;br /&gt;
        $eprint_section = $xml-&amp;gt;create_document_fragment();&lt;br /&gt;
    }&lt;br /&gt;
    $eprint_section-&amp;gt;appendChild( $item-&amp;gt;render_value(&amp;quot;title&amp;quot;) );&lt;br /&gt;
    $eprint_section-&amp;gt;appendChild( $item-&amp;gt;render_citation_link() );&lt;br /&gt;
    $eprint_section-&amp;gt;appendChild( $repository-&amp;gt;make_text(&amp;quot; (&amp;quot;) );&lt;br /&gt;
    $eprint_section-&amp;gt;appendChild( $item-&amp;gt;render_value(&amp;quot;eprint_status&amp;quot;) );&lt;br /&gt;
    $eprint_section-&amp;gt;appendChild( $repository-&amp;gt;make_text(&amp;quot;)&amp;quot;) );&lt;br /&gt;
    $eprint_section-&amp;gt;appendChild( $xml-&amp;gt;create_element(&amp;quot;br&amp;quot;) );&lt;br /&gt;
    $eprint_section-&amp;gt;appendChild( $xml-&amp;gt;create_element(&amp;quot;br&amp;quot;) );&lt;br /&gt;
  &lt;br /&gt;
});&lt;br /&gt;
  &lt;br /&gt;
if( defined $eprint_section ) {&lt;br /&gt;
    $content-&amp;gt;appendChild($eprint_section);&lt;br /&gt;
} else {&lt;br /&gt;
    $content-&amp;gt;appendChild($repository-&amp;gt;make_text(&amp;quot;Nothing has happened!&amp;quot;));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return $content;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Step 4: Email the report to the repository admins=&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;action_send_email&amp;lt;/code&amp;gt; sub routine, add the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=perl&amp;gt;&lt;br /&gt;
my $repository = $self-&amp;gt;{repository};&lt;br /&gt;
&lt;br /&gt;
my $mail_body = $self-&amp;gt;generate_content();&lt;br /&gt;
my $subject = &amp;quot;id/report_email_title&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
my $ds = $repository-&amp;gt;dataset( &amp;quot;user&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
$ds-&amp;gt;search(&lt;br /&gt;
    filters =&amp;gt; [&lt;br /&gt;
        { meta_fields =&amp;gt; [qw( usertype )], value =&amp;gt; &amp;quot;admin&amp;quot; },&lt;br /&gt;
    ],&lt;br /&gt;
)-&amp;gt;map(sub {&lt;br /&gt;
    my( undef, undef, $user ) = @_;&lt;br /&gt;
    $user-&amp;gt;mail( $subject, $mail_body,undef,undef );&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
return 1;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Step 5: Set up the crontab to email you this report =&lt;br /&gt;
&lt;br /&gt;
In order to set up the cron event we need to add some code to an EPMC screen related to this package, follow the instructions @ http://wiki.eprints.org/w/XML_manipulation_of_the_EPrints_Workflow_using_a_Bazaar_Package on creating an EPMC screen with and enable and disable method.&lt;br /&gt;
&lt;br /&gt;
To enable cron we need to add the following to the enable method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=perl&amp;gt;&lt;br /&gt;
EPrints::DataObj::EventQueue-&amp;gt;create_unique( $repository, {&lt;br /&gt;
    pluginid =&amp;gt; &amp;quot;Event&amp;quot;,&lt;br /&gt;
    action =&amp;gt; &amp;quot;cron&amp;quot;,&lt;br /&gt;
    params =&amp;gt; [&lt;br /&gt;
        &amp;quot;0,15,30,45,60 * * * *&amp;quot;,&lt;br /&gt;
        &amp;quot;Event::EPrintsReportEx&amp;quot;,&lt;br /&gt;
        &amp;quot;action_send_email&amp;quot;,&lt;br /&gt;
    ],&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will send you an update email every 15 minutes, note that EPrints uses the standard cron syntax so you can change this as you will. &lt;br /&gt;
&lt;br /&gt;
A guide on using cron can be found @ http://en.wikipedia.org/wiki/Cron&lt;br /&gt;
&lt;br /&gt;
We also need to disable this event again when the package is removed, to do this add the following to the disable method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=perl&amp;gt;&lt;br /&gt;
my $event = EPrints::DataObj::EventQueue-&amp;gt;new_from_hash( $repository, {&lt;br /&gt;
    pluginid =&amp;gt; &amp;quot;Event&amp;quot;,&lt;br /&gt;
    action =&amp;gt; &amp;quot;cron&amp;quot;,&lt;br /&gt;
    params =&amp;gt; [&lt;br /&gt;
        &amp;quot;0,15,30,45,60 * * * *&amp;quot;,&lt;br /&gt;
        &amp;quot;Event::EPrintsReportEx&amp;quot;,&lt;br /&gt;
        &amp;quot;action_send_email&amp;quot;,&lt;br /&gt;
    ],&lt;br /&gt;
});&lt;br /&gt;
$event-&amp;gt;delete if (defined $event);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the 2 events and cron syntax's MUST match.&lt;br /&gt;
&lt;br /&gt;
= Step 6 - Package Test and Wait for Email =&lt;br /&gt;
&lt;br /&gt;
Finish up, package and enable your code. Note that we have not defined any nice phrases here that will be needed to make a proper package.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=API:EPrints/Plugin/Search/Xapian&amp;diff=16716</id>
		<title>API:EPrints/Plugin/Search/Xapian</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=API:EPrints/Plugin/Search/Xapian&amp;diff=16716"/>
		<updated>2025-01-28T12:40:46Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* DESCRIPTION */ Default qs for 'Internal' search is 0, so setting a value of 0.1 as previously suggested doesn't stop if being used. Now suggests a value of -1.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Pod2Wiki=_preamble_ &lt;br /&gt;
This page has been automatically generated from the EPrints 3.2 source. Any wiki changes made between the 'Pod2Wiki=*' and 'Edit below this comment' comments will be lost.&lt;br /&gt;
 --&amp;gt;{{API}}{{Pod2Wiki}}{{API:Source|file=perl_lib/EPrints/Plugin/Search/Xapian.pm|package_name=EPrints::Plugin::Search::Xapian}}[[Category:API|XAPIAN]][[Category:API:EPrints/Plugin/Search|XAPIAN]][[Category:API:EPrints/Plugin/Search/Xapian|XAPIAN]]&amp;lt;div&amp;gt;&amp;lt;!-- Edit below this comment --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=_private_ --&amp;gt;&amp;lt;!-- Pod2Wiki=head_name --&amp;gt;&lt;br /&gt;
==NAME==&lt;br /&gt;
EPrints::Plugin::Search::Xapian&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Edit below this comment --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Pod2Wiki= --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=head_description --&amp;gt;&lt;br /&gt;
==DESCRIPTION==&lt;br /&gt;
&amp;lt;pre&amp;gt;  Xapian is a highly adaptable toolkit which allows developers to easily add&lt;br /&gt;
  advanced indexing and search facilities to their own applications. It supports&lt;br /&gt;
  the Probabilistic Information Retrieval model and also supports a rich set of&lt;br /&gt;
  boolean query operators.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Xapian currently only supports simple searches.&lt;br /&gt;
&lt;br /&gt;
Xapian simple searches are parsed by the Xapian query parser which supports prefixes for search terms:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  title:(eagle buzzard) abstract:&amp;quot;london wetlands&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The field prefixes are taken from the search configuration and constrain the following term (or bracketed terms) to that field only. If no prefix is given the entire Xapian index will be used i.e. it will search any indexed term, not just those from the search configuration fields. For example, the following simple search configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  search_fields =&amp;amp;gt; [&lt;br /&gt;
    {&lt;br /&gt;
      id =&amp;amp;gt; &amp;quot;q&amp;quot;,&lt;br /&gt;
         meta_fields =&amp;amp;gt; [&lt;br /&gt;
           &amp;quot;documents&amp;quot;,&lt;br /&gt;
           &amp;quot;title&amp;quot;,&lt;br /&gt;
           &amp;quot;abstract&amp;quot;,&lt;br /&gt;
           &amp;quot;creators_name&amp;quot;,&lt;br /&gt;
           &amp;quot;date&amp;quot;&lt;br /&gt;
         ]&lt;br /&gt;
    },&lt;br /&gt;
  ],&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Allows the user to specify &amp;quot;documents&amp;quot;, &amp;quot;title&amp;quot;, &amp;quot;abstract&amp;quot;, &amp;quot;creators_name&amp;quot; or &amp;quot;date&amp;quot; as a prefix to a search term. Omitting a prefix will match any field e.g. &amp;quot;publisher&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Terms can be negated by prefixing the term with '-':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  eagle -buzzard&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Phrases can be specified by using quotes, for example  &amp;quot;Southampton University&amp;quot; won't match &amp;lt;em&amp;gt;University of Southampton&amp;lt;/em&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Terms are stemmed by default ('bubbles' becomes 'bubble') except if you use the term in a phrase.&lt;br /&gt;
&lt;br /&gt;
Partial matches are supported by using '*':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  ameri* - americans, americas, amerillo etc.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Xapian search results are returned in a sub-class of [[API:EPrints/List|EPrints::List]] (a wrapper around a Xapian enquire object). Calling [[API:EPrints/List#count|EPrints::List/count]] will return an '''estimate''' of the total matches.&lt;br /&gt;
&lt;br /&gt;
As Xapian has a higher 'qs' score than Internal it will (once enabled) override the default EPrints simple search. You can override this behaviour in '''cfg.d/plugins.pl''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  $c-&amp;amp;gt;{plugins}{'Search::Xapian'}{params}{qs} = -1;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or disable completely (including disabling indexing):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  $c-&amp;amp;gt;{plugins}{'Search::Xapian'}{params}{disable} = 1;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Edit below this comment --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Pod2Wiki= --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=head_usage --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==USAGE==&lt;br /&gt;
Install the [http://search.cpan.org/search?query=xapian&amp;amp;mode=dist Search::Xapian] extension. Note: there are two Perl bindings available for Xapian. The CPAN version is older and based on Perl-XS. xapian-bindings-perl available from xapian.org is based on SWIG and has better coverage of the API. Regardless, for the best feature support/performance it is highly recommended to have the latest stable version of the Xapian library.&lt;br /&gt;
&lt;br /&gt;
Xapian uses a separate (from MySQL) index that is stored in &amp;lt;tt&amp;gt;archives/''[archiveid]''/var/xapian&amp;lt;/tt&amp;gt;. To build the Xapian index you will need to reindex:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  ./bin/epadmin reindex [archiveid] eprint&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Repeat for any other datasets you expect to use Xapian with.)&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;var/xapian/&amp;lt;/tt&amp;gt; directory should contain something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  flintlock  position.baseA  position.DB     postlist.baseB  &lt;br /&gt;
       record.baseA  record.DB       termlist.baseB&lt;br /&gt;
  iamchert   position.baseB  postlist.baseA  postlist.DB     &lt;br /&gt;
       record.baseB  termlist.baseA  termlist.DB&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The indexing process for Xapian is in &amp;lt;tt&amp;gt;lib/cfg.d/search_xapian.pl&amp;lt;/tt&amp;gt;. This can be overridden by dropping the same-named file into your repository &amp;lt;tt&amp;gt;archives/''[archiveid]''/cfg.d/&amp;lt;/tt&amp;gt;. If the Xapian search is not matching what you might expect it to, you probably need to fix the indexing process (and re-index!). Terms indexed by Xapian can also be weighted to e.g. give names a higher weighting than abstract text.&lt;br /&gt;
&lt;br /&gt;
You will need to restart your Apache server to enable the Xapian search plugin and dependencies.&lt;br /&gt;
&lt;br /&gt;
If the Xapian search is working correctly you will have a &amp;quot;by relevance&amp;quot; option available in the ordering of simple search results.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Edit below this comment --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Pod2Wiki= --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=head_lock_files --&amp;gt;&lt;br /&gt;
===Lock Files===&lt;br /&gt;
Xapian maintains a lock file in &amp;lt;tt&amp;gt;archives/''[archiveid]''/var/xapian&amp;lt;/tt&amp;gt;. If you see indexing errors about not being able to lock the database ensure you aren't running multiple copies of the EPrints [http://wiki.eprints.org/w/API:bin/indexer indexer]. If no other processes are running you may need to manually remove the lock file from the &amp;lt;tt&amp;gt;var/xapian&amp;lt;/tt&amp;gt; directory. While only one process may modify the Xapian index at a time, any number of processes may concurrently read.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Edit below this comment --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Pod2Wiki= --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=head_parameters --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PARAMETERS==&lt;br /&gt;
* lang&lt;br /&gt;
: Override the default language used for stemming.&lt;br /&gt;
&lt;br /&gt;
* stopwords&lt;br /&gt;
: An array reference of stop words to use (defaults to English).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Edit below this comment --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Pod2Wiki= --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=head_methods --&amp;gt;&lt;br /&gt;
==METHODS==&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=head_stemmer --&amp;gt;&lt;br /&gt;
===stemmer===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;$stemmer = $plugin-&amp;gt;stemmer()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Returns a {{API:PodLink|file=Search/Xapian/Stem|package_name=Search::Xapian::Stem|section=|text=Search::Xapian::Stem}} for the default language.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Edit below this comment --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Pod2Wiki= --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=head_stopper --&amp;gt;&lt;br /&gt;
===stopper===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;$stopper = $plugin-&amp;gt;stopper()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Returns a {{API:PodLink|file=Search/Xapian/SimpleStopper|package_name=Search::Xapian::SimpleStopper|section=|text=Search::Xapian::SimpleStopper}} for &amp;lt;code&amp;gt;stopwords&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Edit below this comment --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Pod2Wiki= --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=head_copyright --&amp;gt;&lt;br /&gt;
==COPYRIGHT==&lt;br /&gt;
Copyright 2000-2011 University of Southampton.&lt;br /&gt;
&lt;br /&gt;
This file is part of EPrints http://www.eprints.org/.&lt;br /&gt;
&lt;br /&gt;
EPrints is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.&lt;br /&gt;
&lt;br /&gt;
EPrints 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 Lesser General Public License for more details.&lt;br /&gt;
&lt;br /&gt;
You should have received a copy of the GNU Lesser General Public License along with EPrints.  If not, see http://www.gnu.org/licenses/.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Edit below this comment --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Pod2Wiki= --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Pod2Wiki=_postamble_ --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Edit below this comment --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Miscellaneous_Config_Options/get_users_owned_eprints&amp;diff=16614</id>
		<title>Miscellaneous Config Options/get users owned eprints</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Miscellaneous_Config_Options/get_users_owned_eprints&amp;diff=16614"/>
		<updated>2024-07-26T14:33:21Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This example should work with v3.4.6+.&lt;br /&gt;
&lt;br /&gt;
Prior to v3.4.6 defining this method resulted in unexpected behaviour when eprint_status checkboxes were used on the ''Manage deposits'' page.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
 $c-&amp;gt;{get_users_owned_eprints} = sub &lt;br /&gt;
 {&lt;br /&gt;
     my( $session, $user, %opts ) = @_;&lt;br /&gt;
     # for non-editorial accounts, return the normal list&lt;br /&gt;
     if( $user-&amp;gt;get_type ne &amp;quot;editor&amp;quot; )&lt;br /&gt;
     {&lt;br /&gt;
         return $user-&amp;gt;owned_eprints_list_actual( %opts );&lt;br /&gt;
     }&lt;br /&gt;
     # only interested in editor accounts now&lt;br /&gt;
     # allow editors to see their items, and items from a specific userid e.g. 99999&lt;br /&gt;
     my $extra_userid = 99999;&lt;br /&gt;
     my $searchexp = $opts{dataset}-&amp;gt;prepare_search( %opts );&lt;br /&gt;
     $searchexp-&amp;gt;add_field( $opts{dataset}-&amp;gt;field( &amp;quot;userid&amp;quot; ), $user-&amp;gt;id . &amp;quot; $extra_userid&amp;quot;, &amp;quot;IN&amp;quot;, &amp;quot;ANY&amp;quot; );&lt;br /&gt;
     return $searchexp-&amp;gt;perform_search;&lt;br /&gt;
 };&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Adding_multilang_fields&amp;diff=16181</id>
		<title>Adding multilang fields</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Adding_multilang_fields&amp;diff=16181"/>
		<updated>2024-02-08T14:00:54Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Add another note about return value&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Howto]]&lt;br /&gt;
&lt;br /&gt;
EPrints' builtin fields are not multilingual, in the sense that there is only one version of each field -indirectly this means one language support. This page explains how to add multilingual versions of existing fields in EPrints and how they can be integrated with its subsystems.&lt;br /&gt;
&lt;br /&gt;
== Multilang fields and EPrints ==&lt;br /&gt;
EPrints supports the '''multilang''' field type (see [[API:EPrints/MetaField/Multilang]] for more details) which allows a user to insert different content for different languages. There are a few limitations with '''multilang''' fields though:&lt;br /&gt;
&lt;br /&gt;
* When its value is printed it is shown in all languages containing content.&lt;br /&gt;
* If a basic EPrints field's type is replaced to become '''multilang''' (like '''title''' and '''abstract'''), EPrints functionality breaks because it expects a single output.&lt;br /&gt;
&lt;br /&gt;
To address these limitations. this article explains how we can replace a basic field, the '''title''' field as an example, with a multilingual one.&lt;br /&gt;
&lt;br /&gt;
== Warning for already populated repositories ==&lt;br /&gt;
Once you follow this article's procedure, '''existing titles and abstracts''' will not be copied into their multilingual counterparts and '''access to them via the API will be lost'''! The users of this plugin are requested to use EPrints API to copy the values from the old fields to the new ones. A script that copies the '''title''' value of each eprint to '''ml_title''' field's '''en''' and '''el''' languages can be found here:[https://github.com/mamalos/eprints/blob/master/help_scripts/set_ml_title.pl]. Please, use this script at your own risk and don't forget to change its content to reflect the languages of your repository. The same script can be used for copying the '''abstract''' field's values to '''ml_abstract''' '''en''' and '''el''' by replacing title with abstract in this script.&lt;br /&gt;
&lt;br /&gt;
== How to add a custom, multilingual field ==&lt;br /&gt;
Replacing an EPrints basic field, like the '''title''' field, involves a few steps. First, a new field needs to be created that will be able to store information for different languages; this field will be of type '''multilang'''. Next, the basic field's type needs to be replaced with one that is able to use our newly created field as its storage place. This field type will use a function wrapper for storing and retrieving information from the '''multilang''' field, hence the '''title''' field will become a calculated field.&lt;br /&gt;
&lt;br /&gt;
So, in order to add multilingual support for the '''title''' field, the following actions need to take place:&lt;br /&gt;
&lt;br /&gt;
* A ''new field type needs to be created'' that will help our '''title''' field to implement some of EPrints logic. Our field type is called '''virtualwithvalue'''.&lt;br /&gt;
* A ''new '''multilang''' field needs to be created'' that will store our multilingual information. We will call this field '''ml_title'''.&lt;br /&gt;
* '''''ml_title''' field and '''title''' field's functionality need to be introduced to the EPrints system'' via a configuration file located in '''~eprints/archives/&amp;lt;reponame&amp;gt;/cfg/cfg.d/'''.&lt;br /&gt;
* ''EPrints' database needs to be updated'' to include the new field. &lt;br /&gt;
* ''The appropriate phrases need to be added'' for the '''ml_title''' field on each supported language.&lt;br /&gt;
* ''The '''title''' field needs to be replaced'' with '''ml_title''' field in the workflow.&lt;br /&gt;
* '''''ml_title''' field in the workflow will needs a custom lookup script''.&lt;br /&gt;
* ''The '''title''' field needs to be replaced with the '''ml_title''' field in the simple and advanced search scripts''.&lt;br /&gt;
* The ''repository needs to be reloaded''.&lt;br /&gt;
* ''Static files need to be regenerated'' if our repository already contains data.&lt;br /&gt;
The following sections explain each step in detail, and ''title''' and '''ml_title''' are used as our example fields. The code snippets are just for demonstration purposes - and proof of concept. If you want to see the final, working implementation, you should look at the source code of the [[MultiLang_Fields_Bazaar_Package]] plugin.&lt;br /&gt;
&lt;br /&gt;
== Adding a new field type (VirtualWithValue)==&lt;br /&gt;
In order to create a multiple-language field we have to create an appropriate field type. EPrints' '''MetaField''' (see [[API:EPrints/MetaField|MetaField]] article for details) is a perfect candidate for this, and we need to extend it and override its '''get_value''' and '''set_value''' functions for the field to work properly with the rest of EPrints API, as well as its '''get_property_defaults''' function to sort out warnings for default values. The following code could be a rough implementation of such a field:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;package EPrints::MetaField::Virtualwithvalue;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
use EPrints::MetaField;&lt;br /&gt;
&lt;br /&gt;
our @ISA = qw( EPrints::MetaField );&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
sub get_property_defaults&lt;br /&gt;
{&lt;br /&gt;
    my ( $self ) = @_;&lt;br /&gt;
    my %defaults = $self-&amp;gt;SUPER::get_property_defaults;&lt;br /&gt;
    $defaults{get_value} = $EPrints::MetaField::UNDEF;&lt;br /&gt;
    $defaults{set_value} = $EPrints::MetaField::UNDEF;&lt;br /&gt;
&lt;br /&gt;
    return %defaults;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub get_value&lt;br /&gt;
{&lt;br /&gt;
    my( $self, $object ) = @_;&lt;br /&gt;
    if ( defined $self-&amp;gt;get_property(&amp;quot;get_value&amp;quot;) )&lt;br /&gt;
    {&lt;br /&gt;
        return $self-&amp;gt;call_property( &amp;quot;get_value&amp;quot;, $object);&lt;br /&gt;
    }&lt;br /&gt;
    return undef; # This is important. Using just a 'return;' or no return statement may break your repository e.g. when an EPrint revision file tried to be created.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub set_value&lt;br /&gt;
{&lt;br /&gt;
     my( $self, $object, $value ) = @_;&lt;br /&gt;
     if ( defined $self-&amp;gt;get_property(&amp;quot;set_value&amp;quot;) )&lt;br /&gt;
     {&lt;br /&gt;
         return $self-&amp;gt;call_property( &amp;quot;set_value&amp;quot;, $object, $value);&lt;br /&gt;
     }&lt;br /&gt;
     return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We could save this file in '''~eprints/lib/plugins/EPrints/MetaField/Virtualwithvalue.pm'''.&lt;br /&gt;
&lt;br /&gt;
== Introducing ml_title field in EPrints and replacing title field's type==&lt;br /&gt;
To inform EPrints about our new field (that will be of type '''virtualwithvalue'''), we should create a configuration file, eg: '''~eprints/archives/&amp;lt;reponame&amp;gt;/cfg/cfg.d/zz_multilang_field.pl''' with content like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang='perl'&amp;gt;&lt;br /&gt;
#define local fields&lt;br /&gt;
my $local_fields = [&lt;br /&gt;
{&lt;br /&gt;
    name =&amp;gt; 'ml_title',&lt;br /&gt;
    type =&amp;gt; 'multilang',&lt;br /&gt;
    multiple =&amp;gt; 1,&lt;br /&gt;
    fields =&amp;gt; [ { sub_name =&amp;gt; &amp;quot;text&amp;quot;, type =&amp;gt; &amp;quot;longtext&amp;quot;, input_rows =&amp;gt; 3, make_single_value_orderkey =&amp;gt; 'EPrints::Extras::english_title_orderkey' } ],&lt;br /&gt;
    input_add_boxes =&amp;gt; 1,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    name =&amp;gt; 'title',&lt;br /&gt;
    type =&amp;gt; 'virtualwithvalue',&lt;br /&gt;
    virtual =&amp;gt; 1,&lt;br /&gt;
&lt;br /&gt;
    get_value =&amp;gt; sub&lt;br /&gt;
    {&lt;br /&gt;
        my ($eprint) = @_;&lt;br /&gt;
        if ($eprint-&amp;gt;is_set('ml_title'))&lt;br /&gt;
        {&lt;br /&gt;
            my $lang = $eprint-&amp;gt;repository-&amp;gt;get_langid;&lt;br /&gt;
            my $lang_set = 0;&lt;br /&gt;
            my $vals = $eprint-&amp;gt;get_value('ml_title');&lt;br /&gt;
            my $title = '';&lt;br /&gt;
            if (!$lang)&lt;br /&gt;
            {&lt;br /&gt;
                $lang_set = 1;&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                # set the default lang's text as title&lt;br /&gt;
                foreach my $v1 (@{$vals})&lt;br /&gt;
                {&lt;br /&gt;
                    if ($v1-&amp;gt;{lang} eq $lang)&lt;br /&gt;
                    {&lt;br /&gt;
                        $title = $v1-&amp;gt;{text};&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            # if the language is not set or I can't find an abstract in the &lt;br /&gt;
            # user's language, get the first object's text as abstract&lt;br /&gt;
            if ($lang_set or $title eq '')&lt;br /&gt;
            {&lt;br /&gt;
                $title = $vals-&amp;gt;[0]-&amp;gt;{text};&lt;br /&gt;
            }&lt;br /&gt;
            return $title;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        return undef; # This is important. Using just a 'return;' or no return statement may break your repository e.g. when an EPrint revision file tried to be created.&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    set_value =&amp;gt; sub&lt;br /&gt;
    {&lt;br /&gt;
        my ($eprint, $value) = @_;&lt;br /&gt;
        my $lang = 'en';&lt;br /&gt;
        #only use this on imports, NOT if the value is already set&lt;br /&gt;
        if ($eprint-&amp;gt;is_set('ml_title'))&lt;br /&gt;
        {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($value)&lt;br /&gt;
        {&lt;br /&gt;
            $eprint-&amp;gt;set_value('ml_title', [{lang=&amp;gt;$lang, text=&amp;gt;$value}]);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
#create lookup hash of local field names&lt;br /&gt;
my $local_fieldnames = {};&lt;br /&gt;
&lt;br /&gt;
foreach my $f (@{$local_fields})&lt;br /&gt;
{&lt;br /&gt;
    $local_fieldnames-&amp;gt;{$f-&amp;gt;{name}} = 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#merge in existing field configurations&lt;br /&gt;
foreach my $f (@{$c-&amp;gt;{fields}-&amp;gt;{eprint}})&lt;br /&gt;
{&lt;br /&gt;
    if (!$local_fieldnames-&amp;gt;{$f-&amp;gt;{name}})&lt;br /&gt;
    {&lt;br /&gt;
     push @{$local_fields}, $f;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#overwrite original array of configured fields&lt;br /&gt;
$c-&amp;gt;{fields}-&amp;gt;{eprint} = $local_fields;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where we can see that our new '''ml_title''' field is of type '''multilang''' and the '''title''' field's type has become '''virtualwithvalue'''. Moreover, the '''title''' field now implements the two aforementioned functions: '''get_value''' and '''set_value'''. Both these functions -whose names imply their functionality- are used by EPrints API, and their existence, as well as their return values, are critical for EPrints to work properly. The last statements of our example code show how a custom field can be added in the list of EPrints fields.&lt;br /&gt;
&lt;br /&gt;
What has happened in effect is that the '''title''' field has become a calculated field that gets or sets its value via its corresponding '''multilang''' field ('''ml_title'''). So, each new record now has a '''multilang''' field which it can access via the interface provided by the calculated field of type '''virtualwithvalue''', which is no other than EPrints' basic '''title''' field.&lt;br /&gt;
&lt;br /&gt;
The reason we didn't set the '''title''' field to be of type '''multilang''' in the first place is that many EPrints builtin functions expect only a single value from the '''title''' (and '''abstract''') field, and '''multilang''' fields don't support such functionality. Hence, doing so would cause EPrints to throw errors. By using and extending calculated fields (like '''MetaFields'''), we can calculate and produce always a single output for our '''title''' field (using the data stored in '''ml_title''' field) via its '''get_value''' function; its '''set_value''' function is used for populating our '''ml_title''' field's values. Our sample code prints output based on the user's language settings, but the programmer can do whatever they wish when overriding these functions, as long as their code return values that comply with EPrints' API.&lt;br /&gt;
&lt;br /&gt;
== Updating EPrints database to include the ml_title field ==&lt;br /&gt;
EPrints database is updated when the user eprints executes (from his home directory):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./bin/epadmin update reponame&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adding the appropriate phrases ==&lt;br /&gt;
EPrints phrases are not aware of our new field ('''ml_title'''), so we need to update them. In our example we update the phrases for the English and for the Greek languages ('''en''' and '''el''' respectively). We chose to add new files instead of changing the default ones so as to help EPrints upgrades. So, for the English language we can add the file '''~eprints/archives/reponame/cfg/lang/en/phrases/local.xml''' that contains the following information:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title&amp;quot;&amp;gt;Title&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_text&amp;quot;&amp;gt;Text&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_lang&amp;quot;&amp;gt;Language&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldhelp_ml_title&amp;quot;&amp;gt;The title of the item. The title should not end with a full stop, but may end with a question mark. There is no way to make italic text, please enter it normally. If you have a subtitle, it should be preceded with a colon [:]. Use capitals only for the first word and for proper nouns.&lt;br /&gt;
    &amp;lt;br/&amp;gt;Example: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;A brief history of time&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Example: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Life: an unauthorised biography&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Example: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Mathematics for engineers and scientists. 5th edition&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Example: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Ecosystems of the world. Vol. 26. Estuaries of the world&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Greek phrases can be added in file '''~eprints/archives/reponame/cfg/lang/el/phrases/local.xml''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title&amp;quot;&amp;gt;Τίτλος&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_text&amp;quot;&amp;gt;Κείμενο&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_help&amp;quot;&amp;gt;Το help τεξτ&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_lang&amp;quot;&amp;gt;Γλώσσα&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldhelp_ml_title&amp;quot;&amp;gt;Ο τίτλος του τεκμηρίου. Ο τίτλος δεν πρέπει να τελειώνει με τελεία, αλλά μπορεί να τελειώνει με ερωτηματικό. Δεν υπάρχει τρόπος να γράψετε με πλάγια γράμματα, παρακαλώ χρησιμοποιήστε απλό κείμενο. Εάν έχετε έναν υπότιτλο, θα πρέπει να προηγείται η άνω και κάτω τελεία του υπότιτλου [:]. Χρησιμοποιήστε κεφαλαία γράμματα μόνο στην πρώτη λέξη και στα κύρια ονόματα.&lt;br /&gt;
    &amp;lt;br/&amp;gt;Παράδειγμα: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Μια σύντομη ιστορία&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Παράδειγμα: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Καβάφης: η βιογραφία&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Παράδειγμα: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Μαθηματικά για μηχανικούς και επιστήμονες. 5η έκδοση&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Παράδειγμα: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Οικοσυστήματα του πλανήτη. Τόμ. 26. Εκβολές του πλανήτη.&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Replacing the title field with ml_title field in the workflow ==&lt;br /&gt;
In order to use our new '''ml_title''' field in the workflow, we need to replace the existing one ('''title'''). So, the '''title''' needs to be commented out and the new '''multilang''' should be added. This means that '''~eprints/archives/reponame/cfg/workflows/eprint/default.xml''' is edited as follows:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&amp;lt;!--    &lt;br /&gt;
    &amp;lt;component&amp;gt;&amp;lt;field ref=&amp;quot;title&amp;quot; required=&amp;quot;yes&amp;quot; input_lookup_url=&amp;quot;{$config{rel_cgipath}}/users/lookup/title_duplicates&amp;quot; input_lookup_params=&amp;quot;id={eprintid}&amp;amp;amp;dataset=eprint&amp;amp;amp;field=title&amp;quot; /&amp;gt;&amp;lt;/component&amp;gt;&lt;br /&gt;
    &amp;lt;component&amp;gt;&amp;lt;field ref=&amp;quot;abstract&amp;quot;/&amp;gt;&amp;lt;/component&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;component&amp;gt;&amp;lt;field ref=&amp;quot;ml_title&amp;quot; required=&amp;quot;yes&amp;quot; input_lookup_url=&amp;quot;{$config{rel_cgipath}}/users/lookup/ml_title_duplicates&amp;quot; input_lookup_params=&amp;quot;id={eprintid}&amp;amp;amp;dataset=eprint&amp;amp;amp;field=ml_title&amp;quot;/&amp;gt;&amp;lt;/component&amp;gt;&lt;br /&gt;
    &amp;lt;component&amp;gt;&amp;lt;field ref=&amp;quot;ml_abstract&amp;quot;/&amp;gt;&amp;lt;/component&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
As can be seen, the default lookup script is replaced by the plugin's lookup script ('''ml_title_duplicates''') which supports our new '''ml_title''' field.&lt;br /&gt;
&lt;br /&gt;
== Adding a custom lookup script for ml_title autocompletion ==&lt;br /&gt;
We copy the default lookup script to a new one ('''~eprints/cgi/users/lookup/ml_title_duplicates in our example'''):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ cp ~eprints/cgi/users/lookup/title_duplicates ~eprints/cgi/users/lookup/ml_title_duplicates&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
and edit the SQL statement to contain '''ml_title''' instead of '''title''' (line 70 in EPrints 3.3.14):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
my $sql = &amp;quot;SELECT ep.eprintid, ml_title_text FROM eprint AS ep JOIN eprint_ml_title_text AS ml ON ep.eprintid = ml.eprintid WHERE &amp;quot;;&lt;br /&gt;
if ($dataset_name eq &amp;quot;eprint&amp;quot;) {&lt;br /&gt;
    $sql .= &amp;quot; $Q_eprint_status=&amp;quot; .  $db-&amp;gt;quote_value( &amp;quot;archive&amp;quot; ) . &amp;quot; AND &amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
$sql .= &amp;quot;ml.ml_title_text IS NOT NULL&amp;quot; .&lt;br /&gt;
    &amp;quot; AND ml.ml_title_text &amp;quot; .&lt;br /&gt;
    $db-&amp;gt;sql_LIKE() .&lt;br /&gt;
    $db-&amp;gt;quote_value( EPrints::Database::prep_like_value( $q ) . '%' );&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adding search support for the ml_title field ==&lt;br /&gt;
EPrints' search functionality is only aware of the '''title''' field, so its search mechanisms -which directly search EPrints' database- has no knowledge about '''ml_title'''. To address this, we should allow our search scripts to be able to search into '''ml_title''' instead of  '''title''', since '''title''' is now a calculated field and contains no information in EPrints database. To do so, we add two configuration files that add support for each search respectively. We have chosen not to change EPrints' default search configuration files, in order not to affect future EPrints' upgrades. So, for the simple search we add the file '''~eprints/archives/reponame/cfg/cfg.d/eprint_search_simple.pl''' with the content:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;$c-&amp;gt;{search}-&amp;gt;{simple} = &lt;br /&gt;
{&lt;br /&gt;
    search_fields =&amp;gt; [&lt;br /&gt;
        {&lt;br /&gt;
            id =&amp;gt; &amp;quot;q&amp;quot;,&lt;br /&gt;
            meta_fields =&amp;gt; [&lt;br /&gt;
                &amp;quot;documents&amp;quot;,&lt;br /&gt;
                &amp;quot;ml_title&amp;quot;,&lt;br /&gt;
                &amp;quot;abstract&amp;quot;,&lt;br /&gt;
                &amp;quot;creators_name&amp;quot;,&lt;br /&gt;
                &amp;quot;date&amp;quot; &lt;br /&gt;
            ]&lt;br /&gt;
        },&lt;br /&gt;
    ],&lt;br /&gt;
#    preamble_phrase =&amp;gt; &amp;quot;cgi/search:preamble&amp;quot;,&lt;br /&gt;
    title_phrase =&amp;gt; &amp;quot;cgi/search:simple_search&amp;quot;,&lt;br /&gt;
    citation =&amp;gt; &amp;quot;result&amp;quot;,&lt;br /&gt;
    page_size =&amp;gt; 20,&lt;br /&gt;
    order_methods =&amp;gt; {&lt;br /&gt;
        &amp;quot;byyear&amp;quot;      =&amp;gt; &amp;quot;-date/creators_name/title&amp;quot;,&lt;br /&gt;
        &amp;quot;byyearoldest&amp;quot;     =&amp;gt; &amp;quot;date/creators_name/title&amp;quot;,&lt;br /&gt;
        &amp;quot;byname&amp;quot;       =&amp;gt; &amp;quot;creators_name/-date/title&amp;quot;,&lt;br /&gt;
        &amp;quot;bytitle&amp;quot;      =&amp;gt; &amp;quot;title/creators_name/-date&amp;quot; &lt;br /&gt;
    },&lt;br /&gt;
    default_order =&amp;gt; &amp;quot;byyear&amp;quot;,&lt;br /&gt;
    show_zero_results =&amp;gt; 1,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And for the advanced search we add the file: '''~eprints/archives/reponame/cfg/cfg.d/eprint_search_advanced_local.pl''' that reads:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$c-&amp;gt;{search}-&amp;gt;{advanced} =&lt;br /&gt;
{&lt;br /&gt;
    search_fields =&amp;gt; [&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;documents&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;ml_title&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;creators_name&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;abstract&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;date&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;keywords&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;subjects&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;type&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;department&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;editors_name&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;ispublished&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;refereed&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;publication&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;documents.format&amp;quot; ] },&lt;br /&gt;
    ],&lt;br /&gt;
    preamble_phrase =&amp;gt; &amp;quot;cgi/advsearch:preamble&amp;quot;,&lt;br /&gt;
    title_phrase =&amp;gt; &amp;quot;cgi/advsearch:adv_search&amp;quot;,&lt;br /&gt;
    citation =&amp;gt; &amp;quot;result&amp;quot;,&lt;br /&gt;
    page_size =&amp;gt; 20,&lt;br /&gt;
    order_methods =&amp;gt; {&lt;br /&gt;
        &amp;quot;byyear&amp;quot;     =&amp;gt; &amp;quot;-date/creators_name/title&amp;quot;,&lt;br /&gt;
        &amp;quot;byyearoldest&amp;quot;   =&amp;gt; &amp;quot;date/creators_name/title&amp;quot;,&lt;br /&gt;
        &amp;quot;byname&amp;quot;     =&amp;gt; &amp;quot;creators_name/-date/title&amp;quot;,&lt;br /&gt;
        &amp;quot;bytitle&amp;quot;    =&amp;gt; &amp;quot;title/creators_name/-date&amp;quot; &lt;br /&gt;
    },&lt;br /&gt;
    default_order =&amp;gt; &amp;quot;byyear&amp;quot;,&lt;br /&gt;
    show_zero_results =&amp;gt; 1,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reloading our repository ==&lt;br /&gt;
In order for our changes to take effect, we should reload our repository by running:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./bin/epadmin reload reponame&amp;lt;/source&amp;gt;&lt;br /&gt;
within eprints user's home directory as user eprints.&lt;br /&gt;
&lt;br /&gt;
== Regenerating static files and abstracts ==&lt;br /&gt;
If our repository already contained records, we need to recreate static content such as static pages and abstracts. Hence, as eprints user we should run:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./bin/generate_abstracts reponame&lt;br /&gt;
$ ./bin/generate_static reponame&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
within eprints user's home directory.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Adding_multilang_fields&amp;diff=16180</id>
		<title>Adding multilang fields</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Adding_multilang_fields&amp;diff=16180"/>
		<updated>2024-02-08T14:00:01Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Add note about return value for 'get_value'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Howto]]&lt;br /&gt;
&lt;br /&gt;
EPrints' builtin fields are not multilingual, in the sense that there is only one version of each field -indirectly this means one language support. This page explains how to add multilingual versions of existing fields in EPrints and how they can be integrated with its subsystems.&lt;br /&gt;
&lt;br /&gt;
== Multilang fields and EPrints ==&lt;br /&gt;
EPrints supports the '''multilang''' field type (see [[API:EPrints/MetaField/Multilang]] for more details) which allows a user to insert different content for different languages. There are a few limitations with '''multilang''' fields though:&lt;br /&gt;
&lt;br /&gt;
* When its value is printed it is shown in all languages containing content.&lt;br /&gt;
* If a basic EPrints field's type is replaced to become '''multilang''' (like '''title''' and '''abstract'''), EPrints functionality breaks because it expects a single output.&lt;br /&gt;
&lt;br /&gt;
To address these limitations. this article explains how we can replace a basic field, the '''title''' field as an example, with a multilingual one.&lt;br /&gt;
&lt;br /&gt;
== Warning for already populated repositories ==&lt;br /&gt;
Once you follow this article's procedure, '''existing titles and abstracts''' will not be copied into their multilingual counterparts and '''access to them via the API will be lost'''! The users of this plugin are requested to use EPrints API to copy the values from the old fields to the new ones. A script that copies the '''title''' value of each eprint to '''ml_title''' field's '''en''' and '''el''' languages can be found here:[https://github.com/mamalos/eprints/blob/master/help_scripts/set_ml_title.pl]. Please, use this script at your own risk and don't forget to change its content to reflect the languages of your repository. The same script can be used for copying the '''abstract''' field's values to '''ml_abstract''' '''en''' and '''el''' by replacing title with abstract in this script.&lt;br /&gt;
&lt;br /&gt;
== How to add a custom, multilingual field ==&lt;br /&gt;
Replacing an EPrints basic field, like the '''title''' field, involves a few steps. First, a new field needs to be created that will be able to store information for different languages; this field will be of type '''multilang'''. Next, the basic field's type needs to be replaced with one that is able to use our newly created field as its storage place. This field type will use a function wrapper for storing and retrieving information from the '''multilang''' field, hence the '''title''' field will become a calculated field.&lt;br /&gt;
&lt;br /&gt;
So, in order to add multilingual support for the '''title''' field, the following actions need to take place:&lt;br /&gt;
&lt;br /&gt;
* A ''new field type needs to be created'' that will help our '''title''' field to implement some of EPrints logic. Our field type is called '''virtualwithvalue'''.&lt;br /&gt;
* A ''new '''multilang''' field needs to be created'' that will store our multilingual information. We will call this field '''ml_title'''.&lt;br /&gt;
* '''''ml_title''' field and '''title''' field's functionality need to be introduced to the EPrints system'' via a configuration file located in '''~eprints/archives/&amp;lt;reponame&amp;gt;/cfg/cfg.d/'''.&lt;br /&gt;
* ''EPrints' database needs to be updated'' to include the new field. &lt;br /&gt;
* ''The appropriate phrases need to be added'' for the '''ml_title''' field on each supported language.&lt;br /&gt;
* ''The '''title''' field needs to be replaced'' with '''ml_title''' field in the workflow.&lt;br /&gt;
* '''''ml_title''' field in the workflow will needs a custom lookup script''.&lt;br /&gt;
* ''The '''title''' field needs to be replaced with the '''ml_title''' field in the simple and advanced search scripts''.&lt;br /&gt;
* The ''repository needs to be reloaded''.&lt;br /&gt;
* ''Static files need to be regenerated'' if our repository already contains data.&lt;br /&gt;
The following sections explain each step in detail, and ''title''' and '''ml_title''' are used as our example fields. The code snippets are just for demonstration purposes - and proof of concept. If you want to see the final, working implementation, you should look at the source code of the [[MultiLang_Fields_Bazaar_Package]] plugin.&lt;br /&gt;
&lt;br /&gt;
== Adding a new field type (VirtualWithValue)==&lt;br /&gt;
In order to create a multiple-language field we have to create an appropriate field type. EPrints' '''MetaField''' (see [[API:EPrints/MetaField|MetaField]] article for details) is a perfect candidate for this, and we need to extend it and override its '''get_value''' and '''set_value''' functions for the field to work properly with the rest of EPrints API, as well as its '''get_property_defaults''' function to sort out warnings for default values. The following code could be a rough implementation of such a field:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;package EPrints::MetaField::Virtualwithvalue;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
use EPrints::MetaField;&lt;br /&gt;
&lt;br /&gt;
our @ISA = qw( EPrints::MetaField );&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
sub get_property_defaults&lt;br /&gt;
{&lt;br /&gt;
    my ( $self ) = @_;&lt;br /&gt;
    my %defaults = $self-&amp;gt;SUPER::get_property_defaults;&lt;br /&gt;
    $defaults{get_value} = $EPrints::MetaField::UNDEF;&lt;br /&gt;
    $defaults{set_value} = $EPrints::MetaField::UNDEF;&lt;br /&gt;
&lt;br /&gt;
    return %defaults;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub get_value&lt;br /&gt;
{&lt;br /&gt;
    my( $self, $object ) = @_;&lt;br /&gt;
    if ( defined $self-&amp;gt;get_property(&amp;quot;get_value&amp;quot;) )&lt;br /&gt;
    {&lt;br /&gt;
        return $self-&amp;gt;call_property( &amp;quot;get_value&amp;quot;, $object);&lt;br /&gt;
    }&lt;br /&gt;
    return undef; # This is important. Using just a 'return;' or no return statement may break your repository e.g. when an EPrint revision file tried to be created.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub set_value&lt;br /&gt;
{&lt;br /&gt;
     my( $self, $object, $value ) = @_;&lt;br /&gt;
     if ( defined $self-&amp;gt;get_property(&amp;quot;set_value&amp;quot;) )&lt;br /&gt;
     {&lt;br /&gt;
         return $self-&amp;gt;call_property( &amp;quot;set_value&amp;quot;, $object, $value);&lt;br /&gt;
     }&lt;br /&gt;
     return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We could save this file in '''~eprints/lib/plugins/EPrints/MetaField/Virtualwithvalue.pm'''.&lt;br /&gt;
&lt;br /&gt;
== Introducing ml_title field in EPrints and replacing title field's type==&lt;br /&gt;
To inform EPrints about our new field (that will be of type '''virtualwithvalue'''), we should create a configuration file, eg: '''~eprints/archives/&amp;lt;reponame&amp;gt;/cfg/cfg.d/zz_multilang_field.pl''' with content like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang='perl'&amp;gt;&lt;br /&gt;
#define local fields&lt;br /&gt;
my $local_fields = [&lt;br /&gt;
{&lt;br /&gt;
    name =&amp;gt; 'ml_title',&lt;br /&gt;
    type =&amp;gt; 'multilang',&lt;br /&gt;
    multiple =&amp;gt; 1,&lt;br /&gt;
    fields =&amp;gt; [ { sub_name =&amp;gt; &amp;quot;text&amp;quot;, type =&amp;gt; &amp;quot;longtext&amp;quot;, input_rows =&amp;gt; 3, make_single_value_orderkey =&amp;gt; 'EPrints::Extras::english_title_orderkey' } ],&lt;br /&gt;
    input_add_boxes =&amp;gt; 1,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    name =&amp;gt; 'title',&lt;br /&gt;
    type =&amp;gt; 'virtualwithvalue',&lt;br /&gt;
    virtual =&amp;gt; 1,&lt;br /&gt;
&lt;br /&gt;
    get_value =&amp;gt; sub&lt;br /&gt;
    {&lt;br /&gt;
        my ($eprint) = @_;&lt;br /&gt;
        if ($eprint-&amp;gt;is_set('ml_title'))&lt;br /&gt;
        {&lt;br /&gt;
            my $lang = $eprint-&amp;gt;repository-&amp;gt;get_langid;&lt;br /&gt;
            my $lang_set = 0;&lt;br /&gt;
            my $vals = $eprint-&amp;gt;get_value('ml_title');&lt;br /&gt;
            my $title = '';&lt;br /&gt;
            if (!$lang)&lt;br /&gt;
            {&lt;br /&gt;
                $lang_set = 1;&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                # set the default lang's text as title&lt;br /&gt;
                foreach my $v1 (@{$vals})&lt;br /&gt;
                {&lt;br /&gt;
                    if ($v1-&amp;gt;{lang} eq $lang)&lt;br /&gt;
                    {&lt;br /&gt;
                        $title = $v1-&amp;gt;{text};&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            # if the language is not set or I can't find an abstract in the &lt;br /&gt;
            # user's language, get the first object's text as abstract&lt;br /&gt;
            if ($lang_set or $title eq '')&lt;br /&gt;
            {&lt;br /&gt;
                $title = $vals-&amp;gt;[0]-&amp;gt;{text};&lt;br /&gt;
            }&lt;br /&gt;
            return $title;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
        return undef;&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    set_value =&amp;gt; sub&lt;br /&gt;
    {&lt;br /&gt;
        my ($eprint, $value) = @_;&lt;br /&gt;
        my $lang = 'en';&lt;br /&gt;
        #only use this on imports, NOT if the value is already set&lt;br /&gt;
        if ($eprint-&amp;gt;is_set('ml_title'))&lt;br /&gt;
        {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($value)&lt;br /&gt;
        {&lt;br /&gt;
            $eprint-&amp;gt;set_value('ml_title', [{lang=&amp;gt;$lang, text=&amp;gt;$value}]);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
#create lookup hash of local field names&lt;br /&gt;
my $local_fieldnames = {};&lt;br /&gt;
&lt;br /&gt;
foreach my $f (@{$local_fields})&lt;br /&gt;
{&lt;br /&gt;
    $local_fieldnames-&amp;gt;{$f-&amp;gt;{name}} = 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#merge in existing field configurations&lt;br /&gt;
foreach my $f (@{$c-&amp;gt;{fields}-&amp;gt;{eprint}})&lt;br /&gt;
{&lt;br /&gt;
    if (!$local_fieldnames-&amp;gt;{$f-&amp;gt;{name}})&lt;br /&gt;
    {&lt;br /&gt;
     push @{$local_fields}, $f;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#overwrite original array of configured fields&lt;br /&gt;
$c-&amp;gt;{fields}-&amp;gt;{eprint} = $local_fields;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where we can see that our new '''ml_title''' field is of type '''multilang''' and the '''title''' field's type has become '''virtualwithvalue'''. Moreover, the '''title''' field now implements the two aforementioned functions: '''get_value''' and '''set_value'''. Both these functions -whose names imply their functionality- are used by EPrints API, and their existence, as well as their return values, are critical for EPrints to work properly. The last statements of our example code show how a custom field can be added in the list of EPrints fields.&lt;br /&gt;
&lt;br /&gt;
What has happened in effect is that the '''title''' field has become a calculated field that gets or sets its value via its corresponding '''multilang''' field ('''ml_title'''). So, each new record now has a '''multilang''' field which it can access via the interface provided by the calculated field of type '''virtualwithvalue''', which is no other than EPrints' basic '''title''' field.&lt;br /&gt;
&lt;br /&gt;
The reason we didn't set the '''title''' field to be of type '''multilang''' in the first place is that many EPrints builtin functions expect only a single value from the '''title''' (and '''abstract''') field, and '''multilang''' fields don't support such functionality. Hence, doing so would cause EPrints to throw errors. By using and extending calculated fields (like '''MetaFields'''), we can calculate and produce always a single output for our '''title''' field (using the data stored in '''ml_title''' field) via its '''get_value''' function; its '''set_value''' function is used for populating our '''ml_title''' field's values. Our sample code prints output based on the user's language settings, but the programmer can do whatever they wish when overriding these functions, as long as their code return values that comply with EPrints' API.&lt;br /&gt;
&lt;br /&gt;
== Updating EPrints database to include the ml_title field ==&lt;br /&gt;
EPrints database is updated when the user eprints executes (from his home directory):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./bin/epadmin update reponame&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adding the appropriate phrases ==&lt;br /&gt;
EPrints phrases are not aware of our new field ('''ml_title'''), so we need to update them. In our example we update the phrases for the English and for the Greek languages ('''en''' and '''el''' respectively). We chose to add new files instead of changing the default ones so as to help EPrints upgrades. So, for the English language we can add the file '''~eprints/archives/reponame/cfg/lang/en/phrases/local.xml''' that contains the following information:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title&amp;quot;&amp;gt;Title&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_text&amp;quot;&amp;gt;Text&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_lang&amp;quot;&amp;gt;Language&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldhelp_ml_title&amp;quot;&amp;gt;The title of the item. The title should not end with a full stop, but may end with a question mark. There is no way to make italic text, please enter it normally. If you have a subtitle, it should be preceded with a colon [:]. Use capitals only for the first word and for proper nouns.&lt;br /&gt;
    &amp;lt;br/&amp;gt;Example: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;A brief history of time&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Example: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Life: an unauthorised biography&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Example: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Mathematics for engineers and scientists. 5th edition&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Example: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Ecosystems of the world. Vol. 26. Estuaries of the world&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Greek phrases can be added in file '''~eprints/archives/reponame/cfg/lang/el/phrases/local.xml''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title&amp;quot;&amp;gt;Τίτλος&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_text&amp;quot;&amp;gt;Κείμενο&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_help&amp;quot;&amp;gt;Το help τεξτ&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldname_ml_title_lang&amp;quot;&amp;gt;Γλώσσα&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;epp:phrase id=&amp;quot;eprint_fieldhelp_ml_title&amp;quot;&amp;gt;Ο τίτλος του τεκμηρίου. Ο τίτλος δεν πρέπει να τελειώνει με τελεία, αλλά μπορεί να τελειώνει με ερωτηματικό. Δεν υπάρχει τρόπος να γράψετε με πλάγια γράμματα, παρακαλώ χρησιμοποιήστε απλό κείμενο. Εάν έχετε έναν υπότιτλο, θα πρέπει να προηγείται η άνω και κάτω τελεία του υπότιτλου [:]. Χρησιμοποιήστε κεφαλαία γράμματα μόνο στην πρώτη λέξη και στα κύρια ονόματα.&lt;br /&gt;
    &amp;lt;br/&amp;gt;Παράδειγμα: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Μια σύντομη ιστορία&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Παράδειγμα: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Καβάφης: η βιογραφία&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Παράδειγμα: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Μαθηματικά για μηχανικούς και επιστήμονες. 5η έκδοση&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;br/&amp;gt;Παράδειγμα: &amp;lt;span class=&amp;quot;ep_form_example&amp;quot;&amp;gt;Οικοσυστήματα του πλανήτη. Τόμ. 26. Εκβολές του πλανήτη.&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Replacing the title field with ml_title field in the workflow ==&lt;br /&gt;
In order to use our new '''ml_title''' field in the workflow, we need to replace the existing one ('''title'''). So, the '''title''' needs to be commented out and the new '''multilang''' should be added. This means that '''~eprints/archives/reponame/cfg/workflows/eprint/default.xml''' is edited as follows:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&amp;lt;!--    &lt;br /&gt;
    &amp;lt;component&amp;gt;&amp;lt;field ref=&amp;quot;title&amp;quot; required=&amp;quot;yes&amp;quot; input_lookup_url=&amp;quot;{$config{rel_cgipath}}/users/lookup/title_duplicates&amp;quot; input_lookup_params=&amp;quot;id={eprintid}&amp;amp;amp;dataset=eprint&amp;amp;amp;field=title&amp;quot; /&amp;gt;&amp;lt;/component&amp;gt;&lt;br /&gt;
    &amp;lt;component&amp;gt;&amp;lt;field ref=&amp;quot;abstract&amp;quot;/&amp;gt;&amp;lt;/component&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;component&amp;gt;&amp;lt;field ref=&amp;quot;ml_title&amp;quot; required=&amp;quot;yes&amp;quot; input_lookup_url=&amp;quot;{$config{rel_cgipath}}/users/lookup/ml_title_duplicates&amp;quot; input_lookup_params=&amp;quot;id={eprintid}&amp;amp;amp;dataset=eprint&amp;amp;amp;field=ml_title&amp;quot;/&amp;gt;&amp;lt;/component&amp;gt;&lt;br /&gt;
    &amp;lt;component&amp;gt;&amp;lt;field ref=&amp;quot;ml_abstract&amp;quot;/&amp;gt;&amp;lt;/component&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
As can be seen, the default lookup script is replaced by the plugin's lookup script ('''ml_title_duplicates''') which supports our new '''ml_title''' field.&lt;br /&gt;
&lt;br /&gt;
== Adding a custom lookup script for ml_title autocompletion ==&lt;br /&gt;
We copy the default lookup script to a new one ('''~eprints/cgi/users/lookup/ml_title_duplicates in our example'''):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ cp ~eprints/cgi/users/lookup/title_duplicates ~eprints/cgi/users/lookup/ml_title_duplicates&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
and edit the SQL statement to contain '''ml_title''' instead of '''title''' (line 70 in EPrints 3.3.14):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
my $sql = &amp;quot;SELECT ep.eprintid, ml_title_text FROM eprint AS ep JOIN eprint_ml_title_text AS ml ON ep.eprintid = ml.eprintid WHERE &amp;quot;;&lt;br /&gt;
if ($dataset_name eq &amp;quot;eprint&amp;quot;) {&lt;br /&gt;
    $sql .= &amp;quot; $Q_eprint_status=&amp;quot; .  $db-&amp;gt;quote_value( &amp;quot;archive&amp;quot; ) . &amp;quot; AND &amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
$sql .= &amp;quot;ml.ml_title_text IS NOT NULL&amp;quot; .&lt;br /&gt;
    &amp;quot; AND ml.ml_title_text &amp;quot; .&lt;br /&gt;
    $db-&amp;gt;sql_LIKE() .&lt;br /&gt;
    $db-&amp;gt;quote_value( EPrints::Database::prep_like_value( $q ) . '%' );&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adding search support for the ml_title field ==&lt;br /&gt;
EPrints' search functionality is only aware of the '''title''' field, so its search mechanisms -which directly search EPrints' database- has no knowledge about '''ml_title'''. To address this, we should allow our search scripts to be able to search into '''ml_title''' instead of  '''title''', since '''title''' is now a calculated field and contains no information in EPrints database. To do so, we add two configuration files that add support for each search respectively. We have chosen not to change EPrints' default search configuration files, in order not to affect future EPrints' upgrades. So, for the simple search we add the file '''~eprints/archives/reponame/cfg/cfg.d/eprint_search_simple.pl''' with the content:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;$c-&amp;gt;{search}-&amp;gt;{simple} = &lt;br /&gt;
{&lt;br /&gt;
    search_fields =&amp;gt; [&lt;br /&gt;
        {&lt;br /&gt;
            id =&amp;gt; &amp;quot;q&amp;quot;,&lt;br /&gt;
            meta_fields =&amp;gt; [&lt;br /&gt;
                &amp;quot;documents&amp;quot;,&lt;br /&gt;
                &amp;quot;ml_title&amp;quot;,&lt;br /&gt;
                &amp;quot;abstract&amp;quot;,&lt;br /&gt;
                &amp;quot;creators_name&amp;quot;,&lt;br /&gt;
                &amp;quot;date&amp;quot; &lt;br /&gt;
            ]&lt;br /&gt;
        },&lt;br /&gt;
    ],&lt;br /&gt;
#    preamble_phrase =&amp;gt; &amp;quot;cgi/search:preamble&amp;quot;,&lt;br /&gt;
    title_phrase =&amp;gt; &amp;quot;cgi/search:simple_search&amp;quot;,&lt;br /&gt;
    citation =&amp;gt; &amp;quot;result&amp;quot;,&lt;br /&gt;
    page_size =&amp;gt; 20,&lt;br /&gt;
    order_methods =&amp;gt; {&lt;br /&gt;
        &amp;quot;byyear&amp;quot;      =&amp;gt; &amp;quot;-date/creators_name/title&amp;quot;,&lt;br /&gt;
        &amp;quot;byyearoldest&amp;quot;     =&amp;gt; &amp;quot;date/creators_name/title&amp;quot;,&lt;br /&gt;
        &amp;quot;byname&amp;quot;       =&amp;gt; &amp;quot;creators_name/-date/title&amp;quot;,&lt;br /&gt;
        &amp;quot;bytitle&amp;quot;      =&amp;gt; &amp;quot;title/creators_name/-date&amp;quot; &lt;br /&gt;
    },&lt;br /&gt;
    default_order =&amp;gt; &amp;quot;byyear&amp;quot;,&lt;br /&gt;
    show_zero_results =&amp;gt; 1,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And for the advanced search we add the file: '''~eprints/archives/reponame/cfg/cfg.d/eprint_search_advanced_local.pl''' that reads:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$c-&amp;gt;{search}-&amp;gt;{advanced} =&lt;br /&gt;
{&lt;br /&gt;
    search_fields =&amp;gt; [&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;documents&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;ml_title&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;creators_name&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;abstract&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;date&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;keywords&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;subjects&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;type&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;department&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;editors_name&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;ispublished&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;refereed&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;publication&amp;quot; ] },&lt;br /&gt;
        { meta_fields =&amp;gt; [ &amp;quot;documents.format&amp;quot; ] },&lt;br /&gt;
    ],&lt;br /&gt;
    preamble_phrase =&amp;gt; &amp;quot;cgi/advsearch:preamble&amp;quot;,&lt;br /&gt;
    title_phrase =&amp;gt; &amp;quot;cgi/advsearch:adv_search&amp;quot;,&lt;br /&gt;
    citation =&amp;gt; &amp;quot;result&amp;quot;,&lt;br /&gt;
    page_size =&amp;gt; 20,&lt;br /&gt;
    order_methods =&amp;gt; {&lt;br /&gt;
        &amp;quot;byyear&amp;quot;     =&amp;gt; &amp;quot;-date/creators_name/title&amp;quot;,&lt;br /&gt;
        &amp;quot;byyearoldest&amp;quot;   =&amp;gt; &amp;quot;date/creators_name/title&amp;quot;,&lt;br /&gt;
        &amp;quot;byname&amp;quot;     =&amp;gt; &amp;quot;creators_name/-date/title&amp;quot;,&lt;br /&gt;
        &amp;quot;bytitle&amp;quot;    =&amp;gt; &amp;quot;title/creators_name/-date&amp;quot; &lt;br /&gt;
    },&lt;br /&gt;
    default_order =&amp;gt; &amp;quot;byyear&amp;quot;,&lt;br /&gt;
    show_zero_results =&amp;gt; 1,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reloading our repository ==&lt;br /&gt;
In order for our changes to take effect, we should reload our repository by running:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./bin/epadmin reload reponame&amp;lt;/source&amp;gt;&lt;br /&gt;
within eprints user's home directory as user eprints.&lt;br /&gt;
&lt;br /&gt;
== Regenerating static files and abstracts ==&lt;br /&gt;
If our repository already contained records, we need to recreate static content such as static pages and abstracts. Hence, as eprints user we should run:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./bin/generate_abstracts reponame&lt;br /&gt;
$ ./bin/generate_static reponame&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
within eprints user's home directory.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Display_a_custom_response_during_downtime&amp;diff=16115</id>
		<title>Display a custom response during downtime</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Display_a_custom_response_during_downtime&amp;diff=16115"/>
		<updated>2023-09-07T09:35:00Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Update Apache method call (which doesn't exist in modern versions) with newer call to remote_ip&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Howto]]&lt;br /&gt;
[[Category:Management]]&lt;br /&gt;
&lt;br /&gt;
See also [[Creating a Maintenance Page]].&lt;br /&gt;
&lt;br /&gt;
We were recently migrating our database from an old server to a new one - which required a dump + load of data (rather than a replication). This meant we had a period of 3 hours where EPrints wouldn't be accessible.&lt;br /&gt;
&lt;br /&gt;
During this downtime, I wanted to to display a useful message, with a '503 Service unavailable' HTTP response.&lt;br /&gt;
This is how to achieve this using EPrints triggers:&lt;br /&gt;
'''NOTE''' if you are doing maintenance that means EPrints will not be able to connect to the database, the method below will not work, as EPrints will complain about not being able to connect to the database before processing the trigger. If you maintenance will result in the database being offline (rather than read-only), the maintenance page should be delivered using Apache. Please see https://stackoverflow.com/questions/622466/how-to-put-apache-website-to-503-temporary-down for some examples).&lt;br /&gt;
&lt;br /&gt;
# Create a file &amp;lt;code&amp;gt;~/archives/ARCHIVEID/cfg/cfg.d/a_MAINTENANCE.pl&amp;lt;/code&amp;gt;. The name of the file isn't important - but it should be alphabetically '''before''' any other config file that defined a URL_REWRITE trigger.&lt;br /&gt;
# Add the following to the file, altering the &amp;lt;code&amp;gt;maintenance_ip&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;maintenance_retry_after&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;maintenance_page_html&amp;lt;/code&amp;gt; appropriately. I'd keep the html page quite simple, but with enough info to help a human. Remember to escape any single-quotes in the HTML block with a backslash e.g. BAD: &amp;lt;code&amp;gt;we've&amp;lt;/code&amp;gt;; GOOD: &amp;lt;code&amp;gt;we\'ve&amp;lt;/code&amp;gt;.:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
# Set maintenance to 1 to respond with a 503 for requests, except those from the maintenance_ip.&lt;br /&gt;
$c-&amp;gt;{maintenance} = 0;&lt;br /&gt;
$c-&amp;gt;{maintenance_allowed_ip} = '127.0.0.1'; #set this to your IP address&lt;br /&gt;
&lt;br /&gt;
# set to a date/time after your maintenance will have finished, &lt;br /&gt;
# or a period (in seconds) that the maintenance will last for&lt;br /&gt;
$c-&amp;gt;{maintenance_retry_after} = 'Mon, 14 Mar 2016 12:00:00 GMT'; #set to a date/time after your maintenance will have finished&lt;br /&gt;
&lt;br /&gt;
use EPrints::Const;&lt;br /&gt;
$c-&amp;gt;add_trigger( EP_TRIGGER_URL_REWRITE, sub {&lt;br /&gt;
        my( %args ) = @_;&lt;br /&gt;
&lt;br /&gt;
        # args passed to EP_TRIGGER_URL_REWRITE are:&lt;br /&gt;
        #     request, lang, args, urlpath, cgipath, uri, secure, return_code&lt;br /&gt;
        my( $repository, $request, $return_code, $uri, $urlpath ) = @args{ qw( repository request return_code uri urlpath ) };&lt;br /&gt;
&lt;br /&gt;
        #check we're in maintenance mode&lt;br /&gt;
        if( $repository-&amp;gt;config( &amp;quot;maintenance&amp;quot; ) &amp;amp;&amp;amp; $repository-&amp;gt;config( &amp;quot;maintenance&amp;quot; ) == 1 ){&lt;br /&gt;
                # is there an IP we should allow through?&lt;br /&gt;
                # NB You might need to do other checks - e.g. X-Forwarded-For if you are behind a load-balancer&lt;br /&gt;
                # or for different versions of Apache (like here: https://github.com/eprints/eprints/issues/214)&lt;br /&gt;
                # if you're not sure, ask on the EPrints Tech list first!&lt;br /&gt;
                if( $repository-&amp;gt;config( &amp;quot;maintenance_allowed_ip&amp;quot; ) &amp;amp;&amp;amp; &lt;br /&gt;
                    $repository-&amp;gt;remote_ip eq $repository-&amp;gt;config( &amp;quot;maintenance_allowed_ip&amp;quot; ) ){&lt;br /&gt;
                        return EP_TRIGGER_OK;&lt;br /&gt;
                }&lt;br /&gt;
                elsif( $uri !~ /^$urlpath\/(style|images)\// ) # allow image/stylesheet requests &lt;br /&gt;
                                                               # through - so you can display a branded 503 page&lt;br /&gt;
                {&lt;br /&gt;
                        $request-&amp;gt;custom_response( Apache2::Const::HTTP_SERVICE_UNAVAILABLE, $c-&amp;gt;{maintenance_page_html} );&lt;br /&gt;
                        if( $repository-&amp;gt;config( &amp;quot;maintenance_retry_after&amp;quot; ) ){&lt;br /&gt;
                            $request-&amp;gt;err_headers_out-&amp;gt;{'Retry-After'} = $repository-&amp;gt;config( &amp;quot;maintenance_retry_after&amp;quot; );&lt;br /&gt;
                        }&lt;br /&gt;
                        # set the 503 response&lt;br /&gt;
                        ${$return_code} = EPrints::Const::HTTP_SERVICE_UNAVAILABLE;&lt;br /&gt;
                        # and don't process any more EP_TRIGGER_URL_REWRITE triggers.&lt;br /&gt;
                        return EP_TRIGGER_DONE;&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
} );&lt;br /&gt;
&lt;br /&gt;
# A simple maintenance page - not using the template (which will probably link to various other pages that aren't&lt;br /&gt;
# accessible during the maintenance window&lt;br /&gt;
$c-&amp;gt;{maintenance_page_html} = '&amp;lt;!DOCTYPE HTML&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=UTF-8&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
body {&lt;br /&gt;
    font-family: sans-serif;&lt;br /&gt;
    margin: 3em;&lt;br /&gt;
}&lt;br /&gt;
footer {&lt;br /&gt;
    font-size: 80%;&lt;br /&gt;
    margin-top:2em;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;###REPO NAME### - Maintenance&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;header&amp;gt;&lt;br /&gt;
&amp;lt;img src=&amp;quot;/images/sitelogo.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;h1&amp;gt;###REPO NAME### - Maintenance&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;/header&amp;gt;&lt;br /&gt;
&amp;lt;section&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Date/Time&amp;lt;/strong&amp;gt; We\'re currently doing things to the system.&amp;lt;br /&amp;gt;&lt;br /&gt;
We\'ll be back soon!&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;If you have any questions, please contact someone@somewhere.blah&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/section&amp;gt;&lt;br /&gt;
&amp;lt;footer&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;###REPO NAME###&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/footer&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Do a &amp;lt;code&amp;gt;~/bin/epadmin test ARCHIVEID&amp;lt;/code&amp;gt; to make sure you haven't done anything silly in the config file.&lt;br /&gt;
# Do a &amp;lt;code&amp;gt;~/bin/epafmin reload ARCHIVEID&amp;lt;/code&amp;gt; and check that nothing's changed&lt;br /&gt;
# When you want to turn the maintenance response on, change set: &amp;lt;code&amp;gt;$c-&amp;gt;{maintenance} = 1;&amp;lt;/code&amp;gt; and reload the archive.&lt;br /&gt;
# Check that you can get in from the IP specified, and that you get the 503 response from other IPs.&lt;br /&gt;
# Do a graceful restart of Apache - to stop the noisy 'repository had been reloaded' error messages.&lt;br /&gt;
# Do the maintenance, test.&lt;br /&gt;
# Change &amp;lt;code&amp;gt;$c-&amp;gt;{maintenance} = 0;&amp;lt;/code&amp;gt;, graceful restart Apache, test.&lt;br /&gt;
# Done!&lt;br /&gt;
&lt;br /&gt;
If you want to include the default CSS files in the 503 page, include &amp;lt;code&amp;gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;/style/auto-3.3.14.css&amp;quot;&amp;gt;&amp;lt;/code&amp;gt; in the maintenance_html_page -&amp;gt; head section (update it for your version of EPrints!).&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Redirect_specific_eprints_to_somewhere_else&amp;diff=15640</id>
		<title>Redirect specific eprints to somewhere else</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Redirect_specific_eprints_to_somewhere_else&amp;diff=15640"/>
		<updated>2023-02-16T21:09:59Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Create new page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is based on a question posed on the [http://mailman.ecs.soton.ac.uk/pipermail/eprints-tech/2023-February/thread.html#9203 EP-Tech mailing list: Adding 301 redir_permanent for some migrated items before 404 kicks in.], around approaches to redirect specific EPrints to different URLs (e.g. where certain items have been migrated to different services).&lt;br /&gt;
&lt;br /&gt;
There were two solutions suggested, and an additional (untested) approach, detailed below.&lt;br /&gt;
&lt;br /&gt;
* use an EPrints URL rewrite trigger&lt;br /&gt;
* use the `rewrite_exceptions` configuration, in combination with an Apache `RewriteMap`&lt;br /&gt;
* register a new PerlTransHandler to do rewrites&lt;br /&gt;
&lt;br /&gt;
The best approach will depend on the size of the repository, the percentage of items that need to be redirected, whether additional aspects (e.g. mapping document-level requests or export URLs) are needed.&lt;br /&gt;
&lt;br /&gt;
The `EP_TRIGGER_URL_REWRITE` will be triggered on each request - so it's important to keep the code 'quick' - and return quickly for URLs that are of no interest.&lt;br /&gt;
&lt;br /&gt;
The `rewrite_exceptions` array is searched for each request too - so having a very large array to search through may also slow your repository down.&lt;br /&gt;
&lt;br /&gt;
== EPrints URL rewrite trigger ==&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
# Save as e.g. EPRINTS_ROOT/archives/ARCHIVE_ID/cfg/cfg.d/z_url_rewrite_map.pl&lt;br /&gt;
# source is available from: https://gist.github.com/jesusbagpuss/2e9172a2ee94d4dcfc5f23a08486f3fe &lt;br /&gt;
# Maps specific URLs to be permanently redirected&lt;br /&gt;
&lt;br /&gt;
use EPrints::Const; # for trigger return values&lt;br /&gt;
&lt;br /&gt;
# define specific URLs that have been moved.&lt;br /&gt;
# If all the new URLs are to the same base URL, you could have e.g 1234 =&amp;gt; 5678 in the &lt;br /&gt;
#    hash, and prepend a static 'https://new.repo.com/' in the 'Location' line below.&lt;br /&gt;
# the hash could also be defined by reading data in from a file (e.g. csv)&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;{z_url_rewrite_map} = {&lt;br /&gt;
	'1234' =&amp;gt; 'https://abc.de/1/',&lt;br /&gt;
	'2345' =&amp;gt; 'https://abc.de/9/',&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;add_trigger( EP_TRIGGER_URL_REWRITE, sub {&lt;br /&gt;
	my( %o ) = @_;&lt;br /&gt;
&lt;br /&gt;
	# Available hash keys in %o&lt;br /&gt;
	#   request, lang (en), args (&amp;quot;&amp;quot; or &amp;quot;?foo=bar&amp;quot;), urlpath (&amp;quot;&amp;quot; or &amp;quot;/subdir&amp;quot;), cgipath (&amp;quot;/cgi&amp;quot; or &amp;quot;/subdir/cgi&amp;quot;)&lt;br /&gt;
	#   uri (/foo/bar), secure ( boolean ), return_code (set to trigger a return - stop stack of triggers), repository&lt;br /&gt;
&lt;br /&gt;
	my $redirect_map = $o{repository}-&amp;gt;get_conf( &amp;quot;z_url_rewrite_map&amp;quot; );&lt;br /&gt;
	return if !defined $redirect_map;&lt;br /&gt;
&lt;br /&gt;
	# Optimisation over the 404 handler regex...&lt;br /&gt;
	# If you have a long-standing repository, there may be EPrint URLs out in the wild that refer to repo.com/1234 (without trailing slash).&lt;br /&gt;
	# Currently, EPrints will redirect this to repo.com/1234/ - and then m#^/(\d+)/# (from 404 handler) would capture it.&lt;br /&gt;
	# This could result in multiple redirects ( /1234 --&amp;gt; /1234/ --&amp;gt; other server ) which isn't best practice for SEO.&lt;br /&gt;
	#&lt;br /&gt;
	# The first regex below will match `/1234` ,  `/1234/`, `/00001234`, `/00001234/` (zero-padded IDs were from old versions of EPrints - but may still be in use.&lt;br /&gt;
        # These are currently handled in EPrints::Apache::Rewrite with a redirect, so capturing them here stops one redirect loop.&lt;br /&gt;
        #&lt;br /&gt;
	# If your repo is _really_ old, you might also want to capture repo.com/archive/1234 or repo.com/archive/00001234...&lt;br /&gt;
	# ...I guess looking in the Apache logs will indicate if this is necessary!&lt;br /&gt;
&lt;br /&gt;
	if( defined $o{uri} &amp;amp;&amp;amp; ( $o{uri} =~ m#^/0{0,9}(\d+)(?&amp;gt;/|$)#  || $o{uri} =~ m#^/id/eprint/0{0,9}(\d+)/# ) )&lt;br /&gt;
	{ &lt;br /&gt;
		# We've got what looks like an EPrintID...&lt;br /&gt;
		# Is there a redirect map for it?&lt;br /&gt;
		if( defined $redirect_map-&amp;gt;{$1} ){&lt;br /&gt;
			EPrints::Apache::AnApache::send_status_line( $o{request}, 301, &amp;quot;Moved Permanently&amp;quot; );&lt;br /&gt;
			EPrints::Apache::AnApache::header_out( $o{request}, &amp;quot;Location&amp;quot;, &amp;quot;$redirect_map-&amp;gt;{$1}&amp;quot; );&lt;br /&gt;
			EPrints::Apache::AnApache::send_http_header( $o{request} );&lt;br /&gt;
&lt;br /&gt;
			${$o{return_code}} = EPrints::Const::DONE;&lt;br /&gt;
			return EP_TRIGGER_DONE;&lt;br /&gt;
		}&lt;br /&gt;
		# an EPrintID, but not redirected.&lt;br /&gt;
	}&lt;br /&gt;
	# not an EPrintID URL - just return (could explicitly set a trigger return value, but not necessary)&lt;br /&gt;
} );&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apache RewriteMap solution ==&lt;br /&gt;
&lt;br /&gt;
By default, EPrints will process all requests, so including additional directives in the Apache config doesn't work.&lt;br /&gt;
Luckily, EPrints provides a configuration variable for URL stubs to ''not'' be processed.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
# Save as e.g. EPRINTS_ROOT/archives/ARCHIVE_ID/cfg/cfg.d/z_rewrite_exceptions.pl - ***BUT CHECK YOUR CONFIG FOR AN EXISTING DEFINITION!!!***&lt;br /&gt;
$c-&amp;gt;{rewrite_exceptions} = [ '/1234/', '/2345/' ];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
URLs matching those specified will not be handled by the EPrints stack, allowing Apache to handle the requests.&lt;br /&gt;
The `newid` part shows how to map the 'exception' IDs to one new system (with new IDs).&lt;br /&gt;
The `newurl` part can be used to map the exception IDs to any URL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;apache&amp;quot;&amp;gt;&lt;br /&gt;
# In apache vhost config file&lt;br /&gt;
RewriteMap newid &amp;quot;txt:/etc/apache2/newid.txt&amp;quot;&lt;br /&gt;
RewriteMap newurl &amp;quot;txt:/etc/apache2/newurl.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
RewriteCond ${newid:$1|Unknown} !Unknown&lt;br /&gt;
RewriteRule &amp;quot;^/([0-9]+)/?$&amp;quot; &amp;quot;new.server/${newid:$1|$1}&amp;quot; [R,L]&lt;br /&gt;
&lt;br /&gt;
RewriteCond ${newurl:$1|Unknown} !Unknown&lt;br /&gt;
RewriteRule &amp;quot;^/([0-9]+)/?$&amp;quot; &amp;quot;${newurl:$1}&amp;quot; [R,L]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newid.txt file would contain something like:&lt;br /&gt;
  1234    1234&lt;br /&gt;
  2345    9876&lt;br /&gt;
&lt;br /&gt;
The newurl.txt file would contain something like:&lt;br /&gt;
  1234    https://new.host/item1000&lt;br /&gt;
  2345    https://some.other.host/42/life&lt;br /&gt;
&lt;br /&gt;
The Apache RewriteMap also allows other approaches - e.g. querying a database to find matches. Just make sure it's quick and stable!&lt;br /&gt;
&lt;br /&gt;
== PerlTransHandler (possible solution for proper perl geeks - completely untested!) ==&lt;br /&gt;
EPrints is added to the Apache configuration with the following config:&lt;br /&gt;
&lt;br /&gt;
    PerlTransHandler +EPrints::Apache::Rewrite&lt;br /&gt;
&lt;br /&gt;
The `+` before the module name tells Apache to load the specified module before using it. It's equivalent to including a specific `PerlModule Apache::Foo` line.&lt;br /&gt;
&lt;br /&gt;
[https://perl.apache.org/docs/2.0/user/handlers/http.html#PerlTransHandler `PerlTransHandler`] is a [https://perl.apache.org/docs/2.0/user/handlers/intro.html#Stacked_Handlers stacked handler].&lt;br /&gt;
This means you could write your own custom Perl module to handle the redirects:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
# save as e.g. EPRINTS_ROOT/lib/plugins/Custom/Rewrites.pm&lt;br /&gt;
# THIS APPROACH IS UNTESTED! (feel free to test it, and correct it ;)&lt;br /&gt;
package Custom::Rewrites;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
use Apache2::RequestRec ();&lt;br /&gt;
use Apache2::Const -compile =&amp;gt; qw(DECLINED HTTP_MOVED_PERMANENTLY);&lt;br /&gt;
&lt;br /&gt;
# default method name used by Apache Perl handlers&lt;br /&gt;
sub handler {&lt;br /&gt;
    my $r = shift;&lt;br /&gt;
&lt;br /&gt;
    my ( $id ) = $r-&amp;gt;uri =~ m#^/0{0,9}(\d+)(?&amp;gt;/|$)#; # matching id. could also capture pos, filename etc. if needed&lt;br /&gt;
&lt;br /&gt;
    # get a list of IDs/Locations somehow.&lt;br /&gt;
    # do some logic to work out if $id should be redirected, and to where - $new_location&lt;br /&gt;
    if( $needs_redirection )&lt;br /&gt;
    {&lt;br /&gt;
        $r-&amp;gt;err_headers_out-&amp;gt;add( Location =&amp;gt; &amp;quot;$new_location&amp;quot; );&lt;br /&gt;
        return Apache2::Const::HTTP_MOVED_PERMANENTLY;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # This ID does not need to be redirected. This handler returns 'DECLINED', and the next handler is passed the request to process&lt;br /&gt;
    return Apache2::Const::DECLINED;&lt;br /&gt;
}&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above handler can be added to the `PerlTransHandler` stack '''before''' the EPrints one in the `VirtualHost` definition:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;apache&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  ServerName eprints.somehwere&lt;br /&gt;
  ...&lt;br /&gt;
  ...&lt;br /&gt;
  # Handle redirects with custom module first&lt;br /&gt;
  PerlTransHandler +Custom::Rewrites&lt;br /&gt;
  # then fall back to 'normal' EPrints handling&lt;br /&gt;
  PerlTransHandler +EPrints::Apache::Rewrite&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[Custom handlers]]&lt;br /&gt;
* [http://mailman.ecs.soton.ac.uk/pipermail/eprints-tech/2022-May/008931.html EP-Tech discussion]&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Boolean_field&amp;diff=15624</id>
		<title>Boolean field</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Boolean_field&amp;diff=15624"/>
		<updated>2023-01-26T12:11:21Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* menu style */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{fieldtypes}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Inheritance ==&lt;br /&gt;
* [[Metadata]]&lt;br /&gt;
** [[Boolean field]]&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
Describes a simple yes/no value. Unless the field has the ''required'' property set, it can actually have a third setting of unset. This can be useful as it distinguishes between a &amp;quot;False&amp;quot; and a &amp;quot;don't know/haven't filled this in yet&amp;quot;. For example when asking if a paper is refereed, this is a boolean field. However it's not required as often someone isn't sure, and does not want to click &amp;quot;no&amp;quot; when that's not necessarily true.&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;3&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
| name || default || description &lt;br /&gt;
|-&lt;br /&gt;
| '''input_style''' || checkbox || May be one of (menu&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;radio&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;checkbox). This controls how the field is rendered in input forms. &lt;br /&gt;
&lt;br /&gt;
&amp;quot;checkbox&amp;quot; gives just a single HTML checkbox which can be ticked or not. It looks a bit rubbish, and does not provide a way to indicate an &amp;quot;unset&amp;quot; value.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;menu&amp;quot; gives an HTML &amp;quot;select&amp;quot; menu with two or three options. The third is &amp;quot;unspecified&amp;quot; and only available if the field is not a required field. &lt;br /&gt;
&lt;br /&gt;
&amp;quot;radio&amp;quot; gives an HTML radio buttons interface. It renders an html phrase with the true and false radio buttons placed in the phrase using pins. If the field is not required then a third radio button for &amp;quot;unspecified&amp;quot; appears below this.&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Required Phrases ==&lt;br /&gt;
&lt;br /&gt;
=== menu style ===&lt;br /&gt;
&lt;br /&gt;
If you use input_style=&amp;gt;&amp;quot;menu&amp;quot; then you need two phrases of the type:&lt;br /&gt;
&lt;br /&gt;
 ''datasetid'' + &amp;quot;_fieldopt_&amp;quot; + ''fieldname'' + &amp;quot;_TRUE&amp;quot;&lt;br /&gt;
 ''datasetid'' + &amp;quot;_fieldopt_&amp;quot; + ''fieldname'' + &amp;quot;_FALSE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
These control the display of the items in the menu.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;epp:phrase id=&amp;quot;eprint_fieldopt_myboolean_TRUE&amp;quot;&amp;gt;Certainly!&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
    &amp;lt;epp:phrase id=&amp;quot;eprint_fieldopt_myboolean_FALSE&amp;quot;&amp;gt;No way!&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== optional phrase to replace 'UNSPECIFIED' text ====&lt;br /&gt;
To overwrite the default 'UNSPECIFIED' option displayed when a boolean field is not required, a phrase with an underscore at the end can be used:&lt;br /&gt;
&lt;br /&gt;
 ''datasetid'' + &amp;quot;_fieldopt_&amp;quot; + ''fieldname'' + &amp;quot;_&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;epp:phrase id=&amp;quot;eprint_fieldopt_myboolean_&amp;quot;&amp;gt;Don't know.&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== radio style ===&lt;br /&gt;
&lt;br /&gt;
This uses a single phrase with two pins in it to indicate the locations of the radio buttons. The phrase id is:&lt;br /&gt;
&lt;br /&gt;
 ''datasetid'' + &amp;quot;_radio_&amp;quot; + ''fieldname''&lt;br /&gt;
&lt;br /&gt;
We suggest placing a &amp;lt;label&amp;gt; element around the radio button and it's title - as well as being good practice, this also means that in some browsers clicking on the text will select the button.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;epp:phrase id=&amp;quot;eprint_radio_myboolean&amp;quot;&amp;gt;&amp;lt;label&amp;gt;&amp;lt;epc:pin name=&amp;quot;true&amp;quot;/&amp;gt;Yes, I like cheese.&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;label&amp;gt;&amp;lt;epc:pin name=&amp;quot;false&amp;quot;/&amp;gt;No, cheese is bad.&amp;lt;/label&amp;gt;&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Database ==&lt;br /&gt;
&lt;br /&gt;
Boolean fields are stored in the database as&lt;br /&gt;
&lt;br /&gt;
 fieldname SET( 'TRUE', 'FALSE' )&lt;br /&gt;
&lt;br /&gt;
== API ==&lt;br /&gt;
&lt;br /&gt;
In the code these fields are stored as strings containing &amp;quot;TRUE&amp;quot;, &amp;quot;FALSE&amp;quot; or &amp;quot;&amp;quot;/undef if they are not set.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Category:User_Roles&amp;diff=15594</id>
		<title>Category:User Roles</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Category:User_Roles&amp;diff=15594"/>
		<updated>2022-12-14T08:58:24Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Created page with &amp;quot;Collection of pages relating to User roles and how to use them.&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Collection of pages relating to User roles and how to use them.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Listings_of_User_Roles_and_Privileges&amp;diff=15593</id>
		<title>Listings of User Roles and Privileges</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Listings_of_User_Roles_and_Privileges&amp;diff=15593"/>
		<updated>2022-12-14T08:57:19Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Plugins]]&lt;br /&gt;
[[Category:User Roles]]&lt;br /&gt;
This page is intended to be a near exhaustive listing of roles and privileges that can be assigned to a user to allow them to carry out certain actions.&lt;br /&gt;
&lt;br /&gt;
== User Roles ==&lt;br /&gt;
;admin&lt;br /&gt;
:[[#indexer/start|indexer/start]], [[#indexer/stop|indexer/stop]], [[#indexer/force_start|indexer/force_start]], [[#create_user|create_user]], [[#subject/edit|subject/edit]], [[#staff/user_search|staff/user_search]], [[#staff/history_search|staff/history_search]], [[#staff/issue_search|staff/issue_search]], [[#config/view/FILETYPE|config/view]], [[#config/view/FILETYPE|config/view/xml]], [[#config/view/FILETYPE|config/view/workflow]], [[#config/view/FILETYPE|config/view/citation]], [[#config/view/FILETYPE|config/view/phrase]], [[#config/view/FILETYPE|config/view/namedset]], [[#config/view/FILETYPE|config/view/template]], [[#config/view/FILETYPE|config/view/static]], [[#config/view/FILETYPE|config/view/autocomplete]], [[#config/view/FILETYPE|config/view/apache]], [[#config/view/FILETYPE|config/view/perl]], [[#config/test_email|config/test_email]], [[#config/imports|config/imports]], [[#config/add_field|config/add_field]], [[#config/remove_field|config/remove_field]],[[#config/regen_abstracts|config/regen_abstracts]], [[#config/regen_citations|config/regen_citations]], [[#config/regen_views|config/regen_views]], [[#config/edit/FILETYPE|config/edit/perl]], [[#storage/manager|storage_manager]], [[#repository/epm|repository/epm]], [[#event_queue/destroy|event_queue/destroy]], [[#event_queue/details/event_queue/details]], [[#event_queue/edit|event_queue/edit]], [[#event_queue/export|event_queue/export]], [[#event_queue/view|event_queue/view]], [[#eprint/STATUS/destroy:USERTYPE|eprint/destroy]], [[#eprint/STATUS/details:USERTYPE|eprint/details]], [[#eprint/STATUS/edit:USERTYPE|eprint/edit]], [[#eprint/STATUS/export:USERTYPE|eprint/export]], [[#eprint/STATUS/upsert:USERTYPE|eprint/upsert]], [[#eprint/STATUS/view:USERTYPE|eprint/view]], [[#eprint/STATUS/remove:USERTYPE|eprint/archive/remove]], [[#eprint/STATUS/edit:USERTYPE|eprint/archive/edit]], [[#file/destroy|file/destroy]], [[#file/export|file/export]], [[#file/view|file/view]], [[#import/view|import/view]], [[#import/edit|import/edit]], [[#saved_search/destroy|saved_search/destroy]], [[#saved_search/details|saved_search]], [[#saved_search/edit|saved_search/edit]], [[#saved_search/export|saved_search/export]], [[#saved_search/view|saved_search/view]], [[#user/remove:USERTYPE|user/remove]], [[#user/edit:USERTYPE|user/edit]], [[#user/view:USERTYPE|user/view]], [[#user/details:USERTYPE|user/details]], [[#user/destroy:USERTYPE|user/destroy]], [[#user/history:USERTYPE|user/history]], [[#user/staff/edit|user/staff/edit]], [[#repository/epm|repository/epm]]&lt;br /&gt;
;change-email&lt;br /&gt;
: ''Currently empty''&lt;br /&gt;
;change-user&lt;br /&gt;
: ''Currently empty''&lt;br /&gt;
;deposit&lt;br /&gt;
: [[#items|items]], [[#create_eprint|create_eprint]], [[#user/history:USERTYPE|user/history:owner]], [[#eprint/STATUS/view:USERTYPE|eprint/inbox/view:owner]], [[#eprint/STATUS/export:USERTYPE|eprint/inbox/export:owner]], [[#eprint/STATUS/summary:USERTYPE|eprint/inbox/summary:owner]], [[#eprint/STATUS/destroy:USERTYPE|eprint/inbox/destroy:owner]], [[#eprint/STATUS/deposit:USERTYPE|eprint/inbox/deposit:owner]], [[#eprint/STATUS/edit:USERTYPE|eprint/inbox/edit:owner]], [[#eprint/STATUS/remove:USERTYPE|eprint/inbox/remove:owner]], [[#eprint/STATUS/details:USERTYPE|eprint/inbox/details:owner]], [[#eprint/STATUS/history:USERTYPE|eprint/inbox/history:owner]], [[#eprint/STATUS/messages:USERTYPE|eprint/inbox/messages:owner]], [[#eprint/STATUS/issues:USERTYPE|eprint/inbox/issues:owner]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/inbox/use_as_template:owner]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/inbox/derive_version:owner]], [[#eprint/STATUS/view:USERTYPE|eprint/buffer/view:owner]], [[#eprint/STATUS/export:USERTYPE|eprint/buffer/export:owner]], [[#eprint/STATUS/summary:USERTYPE|eprint/buffer/summary:owner]], [[#eprint/STATUS/move_inbox:USER_TYPE|eprint/buffer/move_inbox:owner]], [[#eprint/STATUS/details:USERTYPE|eprint/buffer/details:owner]], [[#eprint/STATUS/history:USERTYPE|eprint/buffer/history:owner]], [[#eprint/STATUS/messages:USERTYPE|eprint/buffer/messages:owner]], [[#eprint/STATUS/request_removal:USERTYPE|eprint/buffer/request_removal:owner]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/buffer/use_as_template:owner]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/buffer/derive_version:owner]], [[#eprint/STATUS/view:USERTYPE|eprint/archive/view:owner]], [[#eprint/STATUS/export:USERTYPE|eprint/archive/export:owner]], [[#eprint/STATUS/summary:USERTYPE|eprint/archive/summary:owner]], [[#eprint/STATUS/details:USERTYPE|eprint/archive/details:owner]], [[#eprint/STATUS/history:USERTYPE|eprint/archive/history:owner]], [[#eprint/STATUS/messages:USERTYPE|eprint/archive/messages:owner]], [[#eprint/STATUS/request_removal:USERTYPE|eprint/archive/request_removal:owner]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/archive/use_as_template:owner]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/archive/derive_version:owner]], [[#eprint/STATUS/view:USERTYPE|eprint/deletion/view:owner]], [[#eprint/STATUS/export:USERTYPE|eprint/deletion/export:owner]], [[#eprint/STATUS/summary:USERTYPE|eprint/deletion/summary:owner]], [[#eprint/STATUS/details:USERTYPE|eprint/deletion/details:owner]], [[#eprint/STATUS/history:USERTYPE|eprint/deletion/history:owner]], [[#eprint/STATUS/messages:USERTYPE|eprint/deletion/messages:owner]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/deletion/use_as_template:owner]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/deletion/derive_version:owner]]&lt;br /&gt;
;general&lt;br /&gt;
: [[#user/view:USERTYPE|user/view:owner]], [[#user/details:USERTYPE|user/details:owner]], [[#user/history:USERTYPE|user/history:owner]]&lt;br /&gt;
;edit-config&lt;br /&gt;
: [[#config/edit/FILETYPE|config/edit]], [[#config/edit/FILETYPE|config/edit/xml]], [[#config/edit/FILETYPE|config/edit/workflow]], [[#config/edit/FILETYPE|config/edit/citation]], [[#config/edit/FILETYPE|config/edit/phrase]], [[#config/edit/FILETYPE|config/edit/namedset]], [[#config/edit/FILETYPE|config/edit/template]], [[#config/edit/FILETYPE|config/edit/static]], [[#config/edit/FILETYPE|config/edit/autocomplete]], [[#config/reload|config/reload]]&lt;br /&gt;
;edit-own-record&lt;br /&gt;
: [[#user/edit:USERTYPE|user/edit:owner]]&lt;br /&gt;
;editor&lt;br /&gt;
: [[#datasets|datasets]], [[#editorial_review|editorial_review]], [[#eprint/STATUS/view:USERTYPE|eprint/inbox/view:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/inbox/export:editor]], [[#eprint/STATUS/summary:USERTYPE|eprint/inbox/summary:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/inbox/export:editor]], [[#eprint/STATUS/details:USERTYPE|eprint/inbox/details:editor]], [[#eprint/STATUS/history:USERTYPE|eprint/inbox/history:editor]], [[#eprint/STATUS/messages:USERTYPE|eprint/inbox/messages:editor]], [[#eprint/STATUS/remove_with_email:USERTYPE|eprint/inbox/remove_with_email:editor]], [[#eprint/STATUS/move_archive:USERTYPE|eprint/inbox/move_archive:editor]], [[#eprint/STATUS/move_buffer:USERTYPE|eprint/inbox/move_buffer:editor]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/inbox/use_as_template:editor]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/inbox/derive_version:editor]], [[#eprint/STATUS/edit:USERTYPE|eprint/inbox/edit:editor]], [[#eprint/STATUS/takelock:USERTYPE|eprint/inbox/takelock:editor]], [[#eprint/STATUS/view:USERTYPE|eprint/buffer/view:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/buffer/export:editor]], [[#eprint/STATUS/summary:USERTYPE|eprint/buffer/summary:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/buffer/export:editor]], [[#eprint/STATUS/details:USERTYPE|eprint/buffer/details:editor]], [[#eprint/STATUS/history:USERTYPE|eprint/buffer/history:editor]], [[#eprint/STATUS/messages:USERTYPE|eprint/buffer/messages:editor]], [[#eprint/STATUS/issues:USERTYPE|eprint/buffer/issues:editor]], [[#eprint/STATUS/remove_with_email:USERTYPE|eprint/buffer/remove_with_email:editor]], [[#eprint/STATUS/reject_with_email:USERTYPE|eprint/buffer/reject_with_email:editor]], [[#eprint/STATUS/move_inbox:USERTYPE|eprint/buffer/move_inbox:editor]], [[#eprint/STATUS/move_archive:USERTYPE|eprint/buffer/move_archive:editor]], [[#eprint/STATUS/use+as_template:USERTYPE|eprint/buffer/use_as_template:editor]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/buffer/derive_version:editor]], [[#eprint/STATUS/edit:USERTYPE|eprint/buffer/edit:editor]], [[#eprint/STATUS/takelock:USERTYPE|eprint/buffer/takelock:editor]], [[#eprint/STATUS/view:USERTYPE|eprint/deletion/view:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/deletion/export:editor]], [[#eprint/STATUS/summary:USERTYPE|eprint/deletion/summary:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/deletion/export:editor]], [[#eprint/STATUS/details:USERTYPE|eprint/deletion/details:editor]], [[#eprint/STATUS/history:USERTYPE|eprint/deletion/history:editor]], [[#eprint/STATUS/messages:USERTYPE|eprint/deletion/messages:editor]], [[#eprint/STATUS/move_archive:USERTYPE|eprint/deletion/move_archive:editor]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/deletion/use_as_template:editor]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/deletion/derive_version:editor]], [[#eprint/STATUS/takelock:USERTYPE|eprint/deletion/takelock:editor]], &lt;br /&gt;
;rest&lt;br /&gt;
: [[#eprint/STATUS/rest/get:USERTYPE|eprint/archive/rest/get:editor]],  [[#eprint/STATUS/rest/put:USERTYPE|eprint/archive/rest/put:editor]],  [[#eprint/STATUS/rest/get:USERTYPE|eprint/buffer/rest/get:editor]],  [[#eprint/STATUS/rest/put:USERTYPE|eprint/buffer/rest/put:editor]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/inbox/rest/get:editor]], [[#eprint/STATUS/rest/put:USERTYPE|eprint/inbox/rest/put:editor]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/deletion/rest/get:editor]], [[#eprint/STATUS/rest/put:USERTYPE|eprint/deletion/rest/put:editor]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/inbox/rest/get:owner]],  [[#eprint/STATUS/rest/put:USERTYPE|eprint/inbox/rest/put:owner]],  [[#eprint/STATUS/rest/get:USERTYPE|eprint/buffer/rest/get:owner]],  [[#eprint/STATUS/rest/get:USERTYPE|eprint/archive/rest/get:owner]],  [[#eprint/STATUS/rest/get:USERTYPE|eprint/deletion/rest/get:owner]],  [[#user/rest/get:USERTYPE|user/rest/get:owner]],  [[#subject/rest/get|subject/rest/get]]&lt;br /&gt;
;saved-searches&lt;br /&gt;
: [[#saved_search|saved_search]], [[#create_saved_search|create_saved_search]], [[#saved_search/view:USERTYPE|saved_search/view:owner]], [[#saved_search/edit:USERTYPE|saved_search/edit:owner]], [[#saved_search/destroy:USERTYPE|saved_search/destroy:owner]]&lt;br /&gt;
;set-password&lt;br /&gt;
: [[#set-password|set-password]]&lt;br /&gt;
;staff-view &lt;br /&gt;
:  [[#eprint/STATUS/view:USERTYPE|eprint/inbox/view]], [[#eprint/STATUS/summary:USERTYPE|eprint/inbox/summary]], [[#eprint/STATUS/export:USERTYPE|eprint/inbox/export]], [[#eprint/STATUS/details:USERTYPE|eprint/inbox/details]], [[#eprint/STATUS/history:USERTYPE|eprint/inbox/history]], [[#eprint/STATUS/view:USERTYPE|eprint/buffer/view]], [[#eprint/STATUS/summary:USERTYPE|eprint/buffer/summary]], [[#eprint/STATUS/export:USERTYPE|eprint/buffer/export]], [[#eprint/STATUS/details:USERTYPE|eprint/buffer/details]], [[#eprint/STATUS/history:USERTYPE|eprint/buffer/history]], [[#eprint/STATUS/view:USERTYPE|eprint/archive/view]], [[#eprint/STATUS/export:USERTYPE|eprint/archive/export]], [[#eprint/STATUS/details:USERTYPE|eprint/archive/details]], [[#eprint/STATUS/history:USERTYPE|eprint/archive/history]], [[#eprint/STATUS/view:USERTYPE|eprint/deletion/view]], [[#eprint/STATUS/summary:USERTYPE|eprint/deletion/summary]], [[#eprint/STATUS/export:USERTYPE|eprint/deletion/export]], [[#eprint/STATUS/details:USERTYPE|eprint/deletion/details]], [[#eprint/STATUS/history:USERTYPE|eprint/deletion/history]], [[#eprint/search/staff:USERTYPE|eprint/search/staff]]  &lt;br /&gt;
;toolbox&lt;br /&gt;
: [[#toolbox|toolbox]]&lt;br /&gt;
;view-status&lt;br /&gt;
: [[#status|status]]&lt;br /&gt;
&lt;br /&gt;
== Roles used by User Types (as of EPrints 3.4.x) ==&lt;br /&gt;
;minuser&lt;br /&gt;
:general, edit-own-record, saved-searches, set-password, lock-username-to-email&lt;br /&gt;
;user&lt;br /&gt;
:general, edit-own-record, saved-searches, set-password, deposit, change-email&lt;br /&gt;
;editor&lt;br /&gt;
:general, edit-own-record, saved-searches, set-password, deposit, change-email, editor, view-status, staff-view&lt;br /&gt;
;admin&lt;br /&gt;
:general, edit-own-record, saved-searches, set-password, deposit, change-email, editor, view-status, staff-view, admin, edit-config&lt;br /&gt;
&lt;br /&gt;
== User Privileges ==&lt;br /&gt;
=== config ===&lt;br /&gt;
==== config/add_field ====&lt;br /&gt;
Add a bespoke field to a data object, using the web browser interface.&lt;br /&gt;
==== config/delete/FILETYPE ====&lt;br /&gt;
Delete a configuration file. This can optionally be restricted to a file of a particular '''FILETYPE''': ''autocomplete, citation, namedset, perl, phrase, static, template, workflow, xml''.  Some of these types can overlap, e.g. ''workflow'' is also ''xml''.&lt;br /&gt;
==== config/edit/FILETYPE ====&lt;br /&gt;
Edit a configuration file. This can optionally be restricted to a file of a particular '''FILETYPE''': ''autocomplete, citation, namedset, perl, phrase, static, template, workflow, xml''.  Some of these types can overlap, e.g. ''workflow'' is also ''xml''.&lt;br /&gt;
==== config/imports ====&lt;br /&gt;
Unused by default.  Intended for managing bulk imports to a repository archive.&lt;br /&gt;
==== config/regen_abstracts ====&lt;br /&gt;
Drops the abstract pages cache so abstract pages can be regenerated.&lt;br /&gt;
==== config/regen_citations ====&lt;br /&gt;
Drops the citations cache so citations can be regenerated.&lt;br /&gt;
==== config/regen_views ==== &lt;br /&gt;
Drops the browse view cache so browse view pages can be regenerated.&lt;br /&gt;
==== config/reload ====&lt;br /&gt;
Reload the repository configuration.&lt;br /&gt;
==== config/remove_field ====&lt;br /&gt;
Remove a field from a data object.  (Only fields created via the web browser interfaces, not pre-created through archive configuration).&lt;br /&gt;
==== config/test_email ====&lt;br /&gt;
View the &amp;quot;Send test email&amp;quot; page to send a test email to a specified address to confirm email sending is working as expected.&lt;br /&gt;
==== config/view/FILETYPE ====&lt;br /&gt;
View a configuration file. This can optionally be restricted to a file of a particular '''FILETYPE''': ''autocomplete, citation, namedset, perl, phrase, static, template, workflow, xml''.  Some of these types can overlap, e.g. ''workflow'' is also ''xml''.&lt;br /&gt;
&lt;br /&gt;
=== eprint ===&lt;br /&gt;
Some eprint privileges can be specialised by the '''STATUS''' of the the eprint (e.g. ''inbox'', ''buffer'', ''archive'' or  ''deletion'' and the '''USERTYPE''' (e.g. ''owner'' or ''editor'').  The privilege ''eprint/view'' would allow the user to view any eprint, ''eprint/archive/view'' would only allow them to view eprints in the live archive and ''eprint/inbox/view:owner'' would only allow them to view eprints in the user workarea if they were owned by the user.&lt;br /&gt;
==== create_eprint ====&lt;br /&gt;
Create a new eprint, which will initial appear in that user's workarea.&lt;br /&gt;
==== eprint_search ====&lt;br /&gt;
View and use eprint search across live archive.&lt;br /&gt;
==== eprint/reject_with_email ====&lt;br /&gt;
Reject the eprint under review (returning to user's workarea) and email eprint's owner about this.&lt;br /&gt;
==== eprint/remove_once_archived ====&lt;br /&gt;
Completely remove an eprint even if it is or has been in the live archive.&lt;br /&gt;
==== eprint/remove_with_email ====&lt;br /&gt;
Completely remove an eprint and email eprint's owner to about this.&lt;br /&gt;
==== eprint/staff/search ====&lt;br /&gt;
View and use full eprint search across all statuses of eprint.&lt;br /&gt;
==== eprint/STATUS/deposit:USERTYPE ====&lt;br /&gt;
Deposit an eprint.  Typically this would be just changing it status from ''inbox'' to ''buffer'', so the eprint can be reviewed.&lt;br /&gt;
==== eprint/STATUS/derive_version:USERTYPE ====&lt;br /&gt;
Create a new version of a chosen eprint.  Copying the metadata and setting the ''succeeds'' field to that of that chosen eprint.&lt;br /&gt;
==== eprint/STATUS/destroy:USERTYPE ====&lt;br /&gt;
Completely delete an existing eprint via &amp;quot;Manage records&amp;quot; page.&lt;br /&gt;
&lt;br /&gt;
==== eprint/STATUS/details:USERTYPE ====&lt;br /&gt;
View the ''Details'' tab for an eprint.&lt;br /&gt;
==== eprint/STATUS/edit:USERTYPE ====&lt;br /&gt;
Edit the metadata for an eprint&lt;br /&gt;
==== eprint/STATUS/export:USERTYPE ====&lt;br /&gt;
Export the metadata for an eprint in one or more different formats.&lt;br /&gt;
==== eprint/STATUS/history:USERTYPE ====&lt;br /&gt;
View the ''History'' tab for an eprint.&lt;br /&gt;
==== eprint/STATUS/issues:USERTYPE ====&lt;br /&gt;
View the ''Issues'' tab for an eprint.&lt;br /&gt;
==== eprint/STATUS/messages:USERTYPE ====&lt;br /&gt;
View the ''Messages'' tab for an eprint.&lt;br /&gt;
==== eprint/STATUS/move_archive:USERTYPE ====&lt;br /&gt;
Move an eprint to the live archive. (I.e. change its status, normally from ''buffer'' to ''archive'').&lt;br /&gt;
==== eprint/STATUS/move_buffer:USERTYPE ====&lt;br /&gt;
Move an eprint back to the review buffer. (I.e. change its status to ''buffer'').&lt;br /&gt;
==== eprint/STATUS/move_deletion:USERTYPE ====&lt;br /&gt;
Retire an eprint. (I.e. change its status, normally from ''archive'' to ''deletion'').&lt;br /&gt;
==== eprint/STATUS/move_inbox:USERTYPE ====&lt;br /&gt;
Move an eprint back to a user's workarea. (I.e. change its status, normally from ''buffer'' to ''inbox'').&lt;br /&gt;
==== eprint/STATUS/remove:USERTYPE ====&lt;br /&gt;
Completely remove an eprint.&lt;br /&gt;
==== eprint/STATUS/request_removal:USERTYPE ====&lt;br /&gt;
Request that an existing eprint is removed, (e.g. because it is a duplicate or has been added erroneously).&lt;br /&gt;
==== eprint/STATUS/rest/get:USERTYPE ====&lt;br /&gt;
An eprint's metadata can be retrieved using the REST API.&lt;br /&gt;
==== eprint/STATUS/rest/put:USERTYPE ====&lt;br /&gt;
An eprint's metadata can be set using the REST API.&lt;br /&gt;
==== eprint/STATUS/summary:USERTYPE ====&lt;br /&gt;
View the ''Summary''' tab of an eprint.&lt;br /&gt;
==== eprint/STATUS/takelock:USERTYPE ====&lt;br /&gt;
Take the edit lock on an eprint.&lt;br /&gt;
==== eprint/STATUS/upsert:USERTYPE ====&lt;br /&gt;
Overwrite the existing metadata for an eprint.  Typically with a PUT request via an API not through the repository's web browser interface.&lt;br /&gt;
==== eprint/STATUS/use_as_template:USERTYPE ====&lt;br /&gt;
Use metadata from a chosen eprint to create a new eprint, which is not a new version of that chosen eprint.&lt;br /&gt;
==== eprint/STATUS/view:USERTYPE ====&lt;br /&gt;
View an eprint and a rendering of its metadata&lt;br /&gt;
&lt;br /&gt;
=== event_queue ===&lt;br /&gt;
==== event_queue/destroy ====&lt;br /&gt;
Completely delete an event queue task.&lt;br /&gt;
==== event_queue/details ====&lt;br /&gt;
View the ''Details'' tab for an event queue task.&lt;br /&gt;
==== event_queue/edit ====&lt;br /&gt;
Edit an event queue task.  (E.g. change the time it should run or reset its status if it has failed.)&lt;br /&gt;
==== event_queue/export ====&lt;br /&gt;
Export the metadata for an event queue task. &lt;br /&gt;
==== event_queue/view ====&lt;br /&gt;
View the metadata for an event queue task.&lt;br /&gt;
&lt;br /&gt;
=== file ===&lt;br /&gt;
==== file/destroy ====&lt;br /&gt;
Completely delete a file record via &amp;quot;Manage records&amp;quot; page.&lt;br /&gt;
&lt;br /&gt;
==== file/export ====&lt;br /&gt;
Export the metadata for a file record.&lt;br /&gt;
==== file/view ====&lt;br /&gt;
View the metadata for a file record.&lt;br /&gt;
&lt;br /&gt;
=== import ===&lt;br /&gt;
==== import/view ====&lt;br /&gt;
View the metadata for an import.&lt;br /&gt;
==== import/edit ====&lt;br /&gt;
Edit the metadata for an import.&lt;br /&gt;
&lt;br /&gt;
=== indexer ===&lt;br /&gt;
==== indexer/force_start ====&lt;br /&gt;
Force start the indexer, if the repository thinks it is still running but no event queue tasks are being processed.&lt;br /&gt;
==== indexer/start ====&lt;br /&gt;
Start the indexer if it is not currently running.&lt;br /&gt;
==== indexer/stop ====&lt;br /&gt;
Stop the indexer if it is currently running.&lt;br /&gt;
&lt;br /&gt;
=== saved_search ===&lt;br /&gt;
Some saved search privileges can be specialised by '''USERTYPE''' (e.g. ''owner'').  The privilege ''saved_search/edit'' would allow the user to view any saved search record, ''saved_search/edit:owner'' would only allow them to edit their own saved search records.&lt;br /&gt;
==== create_saved_search ====&lt;br /&gt;
Create a new saved_search record.&lt;br /&gt;
==== saved_search ==== &lt;br /&gt;
View listing or a user's saved searches.&lt;br /&gt;
==== saved_search/destroy:USERTYPE ====&lt;br /&gt;
Completely delete a saved search record.&lt;br /&gt;
==== saved_search/details:USERTYPE ==== &lt;br /&gt;
View the ''Details'' tab for a saved search record.&lt;br /&gt;
==== saved_search/edit:USERTYPE ====&lt;br /&gt;
Edit the metadata for a saved search record.&lt;br /&gt;
==== saved_search/export:USERTYPE ====&lt;br /&gt;
Export the metadata for a saved search record.&lt;br /&gt;
==== saved_search/view:USERTYPE ====&lt;br /&gt;
View the metadata for a saved search record.&lt;br /&gt;
&lt;br /&gt;
=== staff ===&lt;br /&gt;
==== staff/user_search ==== &lt;br /&gt;
View and use the search over user records.&lt;br /&gt;
==== staff/history_search ==== &lt;br /&gt;
View and use the search over eprint history records.&lt;br /&gt;
==== staff/issue_search ====&lt;br /&gt;
View and use the search over eprint issue records.&lt;br /&gt;
&lt;br /&gt;
=== subject ===&lt;br /&gt;
==== subject/edit ====&lt;br /&gt;
View and edit the subject tree.&lt;br /&gt;
==== subject/rest/get ====&lt;br /&gt;
A subject's metadata can be retrieved using the REST API.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Some user privileges can be specialised by '''USERTYPE''' (e.g. ''owner'').  The privilege ''user/edit'' would allow the user to view any user record, ''user/edit:owner'' would only allow them to edit their own user record.&lt;br /&gt;
==== create_user ====&lt;br /&gt;
Create a new user.&lt;br /&gt;
==== user/destroy:USERTYPE ====&lt;br /&gt;
Completely delete a user record.&lt;br /&gt;
==== user/details:USERTYPE ====&lt;br /&gt;
View the ''Details'' tab of a user.&lt;br /&gt;
==== user/edit:USERTYPE ====&lt;br /&gt;
Edit a user's profile.&lt;br /&gt;
==== user/history:USERTYPE ====&lt;br /&gt;
View the ''History'' tab of a user.  This includes the changes (revisions) they made to any eprint record.&lt;br /&gt;
==== user/mediate ====&lt;br /&gt;
Whether a user can mediate for (i.e. act as) another user.  Required feature of [[SWORD]] API.&lt;br /&gt;
==== user/remove:USERTYPE ==== &lt;br /&gt;
Unused by default.  Intended for removing a user record. Use [[#user/destroy:USERTYPE|user/destroy:USERTYPE]] instead.&lt;br /&gt;
&lt;br /&gt;
==== user/staff/edit ====&lt;br /&gt;
Unused by default.  Intended for restricting parts of a user's profile to be edited by a repository admininistrator. &lt;br /&gt;
==== user/view:USERTYPE ====&lt;br /&gt;
View a user record's metadata.&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous ===&lt;br /&gt;
==== datasets ====&lt;br /&gt;
View the &amp;quot;Manage records&amp;quot; page.&lt;br /&gt;
==== editorial_review ====&lt;br /&gt;
View the &amp;quot;Review&amp;quot; page.&lt;br /&gt;
==== items ====&lt;br /&gt;
View the &amp;quot;Manage deposits&amp;quot; page.&lt;br /&gt;
==== repository/epm ====&lt;br /&gt;
View the &amp;quot;EPrints Bazaar&amp;quot; page and install Bazaar plugins.&lt;br /&gt;
==== set-password ====&lt;br /&gt;
Unused by default.  Intended for restricting whether a user can set their own password.&lt;br /&gt;
==== status ====&lt;br /&gt;
View the &amp;quot;Status&amp;quot; and &amp;quot;Database Schema&amp;quot; pages.&lt;br /&gt;
==== storage/manager ====&lt;br /&gt;
View the &amp;quot;Storage Manager&amp;quot; page.&lt;br /&gt;
==== toolbox ====&lt;br /&gt;
Use the toolbox CGI script (i.e. ''/cgi/toolbox/toolbox'') to carry out a operation provided by EPrints::Toolbox.  '''Dangerous''': Do not enable without good reason.&lt;br /&gt;
&lt;br /&gt;
== Public Role User Privileges ==&lt;br /&gt;
These privileges available to users without them needing to login.  This mainly pertains to REST requests you may or may not want accessible.&lt;br /&gt;
;+eprint/archive/rest/get&lt;br /&gt;
:REST request to get metadata for an eprint in the live archive&lt;br /&gt;
;+subject/archive/rest/get&lt;br /&gt;
:REST request to get metadata for a subject in the archive's subject tree.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=User_Roles_and_Privileges&amp;diff=15592</id>
		<title>User Roles and Privileges</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=User_Roles_and_Privileges&amp;diff=15592"/>
		<updated>2022-12-14T08:57:03Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:User Roles]]&lt;br /&gt;
This page is intended to provide a useful guide on how [[EPrints Glossary#User role|user roles]] and [[EPrints Glossary#User privilege|privileges]] work within EPrints repository software, expanding on the information already available at [[user_roles.pl]].&lt;br /&gt;
&lt;br /&gt;
A role in EPrints is made up of 1 or more privileges. Giving a user a role gives them all the privileges associated with that role. You can also give users additional privileges without giving them the full role. &lt;br /&gt;
&lt;br /&gt;
==Creating a role==&lt;br /&gt;
To create the role &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; you would do the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$c-&amp;gt;{roles}-&amp;gt;{&amp;quot;approve-hat&amp;quot;} = [&lt;br /&gt;
       &amp;quot;eprint/buffer/view:editor&amp;quot;,&lt;br /&gt;
       &amp;quot;eprint/buffer/summary:editor&amp;quot;,&lt;br /&gt;
       &amp;quot;eprint/buffer/details:editor&amp;quot;,&lt;br /&gt;
       &amp;quot;eprint/buffer/move_archive:editor&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The privileges listed above means the users given the &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; role can see the View, Summary, Details and Move to archive screen as an editor. Note because they cannot edit items [[Standard names |in the buffer]] they can't correct any mistakes they find. However they do have the power to move items to the archive. This means the &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; allows a user to see the metadata of an item and if they think it is correct move it to the archive. They cannot return it to the user or edit the metadata themselves.&lt;br /&gt;
&lt;br /&gt;
The quoting around the role name approve-hat is required, eprints will generate an error if the text is simply {approve-hat}.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tip: Ensure the role is in {roles} not {user_roles}!&lt;br /&gt;
&lt;br /&gt;
== Anatomy of a privilege ==&lt;br /&gt;
Many pre-existing privileges have a specific structure so they can be tested for generically.  Privileges on data objects use the dataset ID as the first part of the privilege and the last part as the action that can be carried out on that data object. E.g.&lt;br /&gt;
* eprint/view&lt;br /&gt;
* user/edit&lt;br /&gt;
* saved_search/export&lt;br /&gt;
As the eprint data object also has virtual datasets that are subsets of the eprint dataset, based on the status of the eprints these are often used as the second part of the privilege.  E.g.&lt;br /&gt;
* eprint/archive/view&lt;br /&gt;
* eprint/inbox/edit&lt;br /&gt;
* eprint/buffer/export&lt;br /&gt;
eprint and user data objects can also have an additional modifier to restrict the context in which the privilege permits access:&lt;br /&gt;
; eprint/inbox/view&amp;amp;#58;owner&lt;br /&gt;
: A user can only view eprints that they own in the user workarea.&lt;br /&gt;
; eprint/buffer/edit&amp;amp;#58;editor&lt;br /&gt;
: Only users with editorial scope for the eprint can edit it when it is in the review buffer&lt;br /&gt;
; user/view&amp;amp;#58;owner&lt;br /&gt;
: A user can only view their own user profile.&lt;br /&gt;
config privileges are typically use the specfic privilege they give access.  E.g.&lt;br /&gt;
* config/indexer&lt;br /&gt;
* config/regen_abstracts&lt;br /&gt;
* config/view&lt;br /&gt;
However, ''config/view'' and ''config/edit'' can be specialized to allow specific types of configuration file to be viewed or edited.  E.g.&lt;br /&gt;
* config/view/phrase&lt;br /&gt;
* config/edit/autocomplete&lt;br /&gt;
&lt;br /&gt;
== Creating a privilege ==&lt;br /&gt;
There is no special step to creating a privilege, simply define it where you would like it tested for. Equally, there is no specified format for new privileges tying them to (for example) screens.  As a result the following are all valid:&lt;br /&gt;
* &amp;quot;eprint/coindoi&amp;quot;&lt;br /&gt;
* &amp;quot;eprint/coindoiffff&amp;quot;&lt;br /&gt;
* &amp;quot;eprint/coindoi:editor&amp;quot;&lt;br /&gt;
However, to make sure the privilege is as intuitive as possible, it is best to stick as closely to the conventions described in &amp;quot;[[#Anatomy of a privilege|Anatomy of a privilege]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Assigning a role==&lt;br /&gt;
Now that you have created a role you want to give that to class of users. To give every regular user of the repository the &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; you add it to the list of roles for the user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{user} = [&lt;br /&gt;
        'general',&lt;br /&gt;
        'edit-own-record',&lt;br /&gt;
        'saved-searches',&lt;br /&gt;
        'set-password',&lt;br /&gt;
        'deposit',&lt;br /&gt;
        'change-email',&lt;br /&gt;
        'approve-hat',&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Rather than giving every user the role you can give it to individual users. Administer a users profile and add the name of the role to their list of additional roles.&lt;br /&gt;
&lt;br /&gt;
[[File:Approve-hat.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Assigning a user privilege==&lt;br /&gt;
You do not have to give a user a full role you can give them a privilege. The syntax is slightly different. Add the name of the privilege prefixed with a '+' to the list of roles. You can remove a privilege by prefixing it with a '-'.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{user} = [&lt;br /&gt;
        'general',&lt;br /&gt;
        'edit-own-record',&lt;br /&gt;
        'saved-searches',&lt;br /&gt;
        'set-password',&lt;br /&gt;
        'deposit',&lt;br /&gt;
        'change-email',&lt;br /&gt;
        'approve-hat',&lt;br /&gt;
        '+eprint/archive/edit:owner',&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also assign privileges to individual users through the web interface in the same way you can assign a role, remembering they will be listed as &amp;quot;roles&amp;quot;. (remember the '+' or '-')&lt;br /&gt;
&lt;br /&gt;
There is no need for users to log in again following a privilege change, eprints will pick it up automatically.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.&lt;br /&gt;
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.&lt;br /&gt;
* [[How to make a Screen for the Admin Section#Making the page appear|Screen plugin visibility]] - Example of making a new Screen Plugin appear using roles.&lt;br /&gt;
&lt;br /&gt;
[[Category:Manual]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=How_to_make_a_Screen_for_the_Admin_Section&amp;diff=15591</id>
		<title>How to make a Screen for the Admin Section</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=How_to_make_a_Screen_for_the_Admin_Section&amp;diff=15591"/>
		<updated>2022-12-14T08:56:29Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Howto]]&lt;br /&gt;
[[Category:Plugins]]&lt;br /&gt;
[[Category:User Roles]]&lt;br /&gt;
 Known to work for EPrints 3.2+ &lt;br /&gt;
&lt;br /&gt;
== The basic structure ==&lt;br /&gt;
To make a Screen plugin, you create a Perl Module in &amp;lt;code&amp;gt;[eprints]/archives/&amp;lt;ARCHIVE_ID&amp;gt;/cfg/plugins/EPrints/Plugin/Screen/&amp;lt;/code&amp;gt; with the following basic structure&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
package EPrints::Plugin::Screen::Mypackage;&lt;br /&gt;
&lt;br /&gt;
use EPrints::Plugin::Screen;&lt;br /&gt;
&lt;br /&gt;
@ISA = ( 'EPrints::Plugin::Screen' );&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
sub new&lt;br /&gt;
{&lt;br /&gt;
	my( $class, %params ) = @_;&lt;br /&gt;
	my $self = $class-&amp;gt;SUPER::new(%params);&lt;br /&gt;
	$self-&amp;gt;{priv} = undef;&lt;br /&gt;
	$self-&amp;gt;{appears} = [&lt;br /&gt;
		{ &lt;br /&gt;
			place =&amp;gt; &amp;quot;admin_actions_editorial&amp;quot;, # see notes below&lt;br /&gt;
			position =&amp;gt; 1450, &lt;br /&gt;
		},&lt;br /&gt;
	];&lt;br /&gt;
	return $self;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub can_be_viewed&lt;br /&gt;
{&lt;br /&gt;
	my( $self ) = @_;&lt;br /&gt;
	return $self-&amp;gt;allow( &amp;quot;my/conf/value&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub render&lt;br /&gt;
{&lt;br /&gt;
	my( $self ) = @_;&lt;br /&gt;
	my $session = $self-&amp;gt;{session};&lt;br /&gt;
        my $user = $session-&amp;gt;current_user;&lt;br /&gt;
&lt;br /&gt;
        my $p = $session-&amp;gt;make_doc_fragment;&lt;br /&gt;
&lt;br /&gt;
        # create page contents:&lt;br /&gt;
        my $h = $session-&amp;gt;make_element( &amp;quot;h3&amp;quot; );&lt;br /&gt;
        $h-&amp;gt;appendChild($session-&amp;gt;make_text( &amp;quot;Look up organisations known to OA-RJ&amp;quot; ));&lt;br /&gt;
        $p-&amp;gt;appendChild($h);&lt;br /&gt;
&lt;br /&gt;
	return $p&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In theory, one should be able to have multiple bits of functionality (view a little, view a lot, edit, etc), simply by testing for different values of &amp;lt;code&amp;gt;$self-&amp;gt;allow( &amp;quot;my/conf/value&amp;quot; )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The locations ==&lt;br /&gt;
Where the link for the page appears is defined by &amp;lt;code&amp;gt;$self-&amp;gt;{appears}-&amp;gt;[''n'']-&amp;gt;{place}&amp;lt;/code&amp;gt; (in the &amp;lt;code&amp;gt;new&amp;lt;/code&amp;gt; function.)&lt;br /&gt;
&lt;br /&gt;
We are defining a screen that appears in the &amp;quot;admin&amp;quot; area, and there are 4 tabs defined within the admin screen:&lt;br /&gt;
* admin_actions_editorial&lt;br /&gt;
* admin_actions_system&lt;br /&gt;
* admin_actions_config&lt;br /&gt;
* admin_actions_misc&lt;br /&gt;
&lt;br /&gt;
Other places the link can appear are&lt;br /&gt;
* unknown to me&lt;br /&gt;
&lt;br /&gt;
== Making the page appear ==&lt;br /&gt;
There are three steps to making a page appear:&lt;br /&gt;
&lt;br /&gt;
1. The screen plugin should test for ''view-ability''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# in EPrints::Plugin::Screen::Mypackage&lt;br /&gt;
sub can_be_viewed&lt;br /&gt;
{&lt;br /&gt;
	my( $self ) = @_;&lt;br /&gt;
	return $self-&amp;gt;allow( &amp;quot;my/conf/value&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
2 The ''User'' DataObject needs to list the privilege under a role:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  # In EPrints::DataObj::User&lt;br /&gt;
  foo_bar =&amp;gt; [&lt;br /&gt;
    &amp;quot;my/view/value&amp;quot;,&lt;br /&gt;
  ],&lt;br /&gt;
  foo_baz =&amp;gt; [&lt;br /&gt;
    &amp;quot;my/view/value&amp;quot;,&lt;br /&gt;
    &amp;quot;my/conf/value&amp;quot;,&lt;br /&gt;
  ],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
3 The user_roles.pl file needs to make the role available to the user-type:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# in [eprints]/archive/&amp;lt;ARCHIVE_ID&amp;gt;/cfg/cfg/user_roles.pl&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{user} = [qw{&lt;br /&gt;
	// truncated&lt;br /&gt;
	foo_bar&lt;br /&gt;
}],&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{admin} = [qw{&lt;br /&gt;
        // truncated&lt;br /&gt;
	foo_baz&lt;br /&gt;
}],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Return to the main [[Screen_Plugins]] page.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.&lt;br /&gt;
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=User_Roles_and_Privileges&amp;diff=15590</id>
		<title>User Roles and Privileges</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=User_Roles_and_Privileges&amp;diff=15590"/>
		<updated>2022-12-14T08:51:34Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to provide a useful guide on how [[EPrints Glossary#User role|user roles]] and [[EPrints Glossary#User privilege|privileges]] work within EPrints repository software, expanding on the information already available at [[user_roles.pl]].&lt;br /&gt;
&lt;br /&gt;
A role in EPrints is made up of 1 or more privileges. Giving a user a role gives them all the privileges associated with that role. You can also give users additional privileges without giving them the full role. &lt;br /&gt;
&lt;br /&gt;
==Creating a role==&lt;br /&gt;
To create the role &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; you would do the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$c-&amp;gt;{roles}-&amp;gt;{&amp;quot;approve-hat&amp;quot;} = [&lt;br /&gt;
       &amp;quot;eprint/buffer/view:editor&amp;quot;,&lt;br /&gt;
       &amp;quot;eprint/buffer/summary:editor&amp;quot;,&lt;br /&gt;
       &amp;quot;eprint/buffer/details:editor&amp;quot;,&lt;br /&gt;
       &amp;quot;eprint/buffer/move_archive:editor&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The privileges listed above means the users given the &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; role can see the View, Summary, Details and Move to archive screen as an editor. Note because they cannot edit items [[Standard names |in the buffer]] they can't correct any mistakes they find. However they do have the power to move items to the archive. This means the &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; allows a user to see the metadata of an item and if they think it is correct move it to the archive. They cannot return it to the user or edit the metadata themselves.&lt;br /&gt;
&lt;br /&gt;
The quoting around the role name approve-hat is required, eprints will generate an error if the text is simply {approve-hat}.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tip: Ensure the role is in {roles} not {user_roles}!&lt;br /&gt;
&lt;br /&gt;
== Anatomy of a privilege ==&lt;br /&gt;
Many pre-existing privileges have a specific structure so they can be tested for generically.  Privileges on data objects use the dataset ID as the first part of the privilege and the last part as the action that can be carried out on that data object. E.g.&lt;br /&gt;
* eprint/view&lt;br /&gt;
* user/edit&lt;br /&gt;
* saved_search/export&lt;br /&gt;
As the eprint data object also has virtual datasets that are subsets of the eprint dataset, based on the status of the eprints these are often used as the second part of the privilege.  E.g.&lt;br /&gt;
* eprint/archive/view&lt;br /&gt;
* eprint/inbox/edit&lt;br /&gt;
* eprint/buffer/export&lt;br /&gt;
eprint and user data objects can also have an additional modifier to restrict the context in which the privilege permits access:&lt;br /&gt;
; eprint/inbox/view&amp;amp;#58;owner&lt;br /&gt;
: A user can only view eprints that they own in the user workarea.&lt;br /&gt;
; eprint/buffer/edit&amp;amp;#58;editor&lt;br /&gt;
: Only users with editorial scope for the eprint can edit it when it is in the review buffer&lt;br /&gt;
; user/view&amp;amp;#58;owner&lt;br /&gt;
: A user can only view their own user profile.&lt;br /&gt;
config privileges are typically use the specfic privilege they give access.  E.g.&lt;br /&gt;
* config/indexer&lt;br /&gt;
* config/regen_abstracts&lt;br /&gt;
* config/view&lt;br /&gt;
However, ''config/view'' and ''config/edit'' can be specialized to allow specific types of configuration file to be viewed or edited.  E.g.&lt;br /&gt;
* config/view/phrase&lt;br /&gt;
* config/edit/autocomplete&lt;br /&gt;
&lt;br /&gt;
== Creating a privilege ==&lt;br /&gt;
There is no special step to creating a privilege, simply define it where you would like it tested for. Equally, there is no specified format for new privileges tying them to (for example) screens.  As a result the following are all valid:&lt;br /&gt;
* &amp;quot;eprint/coindoi&amp;quot;&lt;br /&gt;
* &amp;quot;eprint/coindoiffff&amp;quot;&lt;br /&gt;
* &amp;quot;eprint/coindoi:editor&amp;quot;&lt;br /&gt;
However, to make sure the privilege is as intuitive as possible, it is best to stick as closely to the conventions described in &amp;quot;[[#Anatomy of a privilege|Anatomy of a privilege]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Assigning a role==&lt;br /&gt;
Now that you have created a role you want to give that to class of users. To give every regular user of the repository the &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; you add it to the list of roles for the user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{user} = [&lt;br /&gt;
        'general',&lt;br /&gt;
        'edit-own-record',&lt;br /&gt;
        'saved-searches',&lt;br /&gt;
        'set-password',&lt;br /&gt;
        'deposit',&lt;br /&gt;
        'change-email',&lt;br /&gt;
        'approve-hat',&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Rather than giving every user the role you can give it to individual users. Administer a users profile and add the name of the role to their list of additional roles.&lt;br /&gt;
&lt;br /&gt;
[[File:Approve-hat.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Assigning a user privilege==&lt;br /&gt;
You do not have to give a user a full role you can give them a privilege. The syntax is slightly different. Add the name of the privilege prefixed with a '+' to the list of roles. You can remove a privilege by prefixing it with a '-'.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{user} = [&lt;br /&gt;
        'general',&lt;br /&gt;
        'edit-own-record',&lt;br /&gt;
        'saved-searches',&lt;br /&gt;
        'set-password',&lt;br /&gt;
        'deposit',&lt;br /&gt;
        'change-email',&lt;br /&gt;
        'approve-hat',&lt;br /&gt;
        '+eprint/archive/edit:owner',&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also assign privileges to individual users through the web interface in the same way you can assign a role, remembering they will be listed as &amp;quot;roles&amp;quot;. (remember the '+' or '-')&lt;br /&gt;
&lt;br /&gt;
There is no need for users to log in again following a privilege change, eprints will pick it up automatically.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.&lt;br /&gt;
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.&lt;br /&gt;
* [[How to make a Screen for the Admin Section#Making the page appear|Screen plugin visibility]] - Example of making a new Screen Plugin appear using roles.&lt;br /&gt;
&lt;br /&gt;
[[Category:Manual]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=User_Roles_and_Privileges&amp;diff=15589</id>
		<title>User Roles and Privileges</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=User_Roles_and_Privileges&amp;diff=15589"/>
		<updated>2022-12-14T08:50:56Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Additional see-also link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to provide a useful guide on how [[EPrints Glossary#User role|user roles]] and [[EPrints Glossary#User privilege|privileges]] work within EPrints repository software, expanding on the information already available at [[user_roles.pl]].&lt;br /&gt;
&lt;br /&gt;
A role in EPrints is made up of 1 or more privileges. Giving a user a role gives them all the privileges associated with that role. You can also give users additional privileges without giving them the full role. &lt;br /&gt;
&lt;br /&gt;
==Creating a role==&lt;br /&gt;
To create the role &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; you would do the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$c-&amp;gt;{roles}-&amp;gt;{&amp;quot;approve-hat&amp;quot;} = [&lt;br /&gt;
       &amp;quot;eprint/buffer/view:editor&amp;quot;,&lt;br /&gt;
       &amp;quot;eprint/buffer/summary:editor&amp;quot;,&lt;br /&gt;
       &amp;quot;eprint/buffer/details:editor&amp;quot;,&lt;br /&gt;
       &amp;quot;eprint/buffer/move_archive:editor&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The privileges listed above means the users given the &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; role can see the View, Summary, Details and Move to archive screen as an editor. Note because they cannot edit items [[Standard names |in the buffer]] they can't correct any mistakes they find. However they do have the power to move items to the archive. This means the &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; allows a user to see the metadata of an item and if they think it is correct move it to the archive. They cannot return it to the user or edit the metadata themselves.&lt;br /&gt;
&lt;br /&gt;
The quoting around the role name approve-hat is required, eprints will generate an error if the text is simply {approve-hat}.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tip: Ensure the role is in {roles} not {user_roles}!&lt;br /&gt;
&lt;br /&gt;
== Anatomy of a privilege ==&lt;br /&gt;
Many pre-existing privileges have a specific structure so they can be tested for generically.  Privileges on data objects use the dataset ID as the first part of the privilege and the last part as the action that can be carried out on that data object. E.g.&lt;br /&gt;
* eprint/view&lt;br /&gt;
* user/edit&lt;br /&gt;
* saved_search/export&lt;br /&gt;
As the eprint data object also has virtual datasets that are subsets of the eprint dataset, based on the status of the eprints these are often used as the second part of the privilege.  E.g.&lt;br /&gt;
* eprint/archive/view&lt;br /&gt;
* eprint/inbox/edit&lt;br /&gt;
* eprint/buffer/export&lt;br /&gt;
eprint and user data objects can also have an additional modifier to restrict the context in which the privilege permits access:&lt;br /&gt;
; eprint/inbox/view&amp;amp;#58;owner&lt;br /&gt;
: A user can only view eprints that they own in the user workarea.&lt;br /&gt;
; eprint/buffer/edit&amp;amp;#58;editor&lt;br /&gt;
: Only users with editorial scope for the eprint can edit it when it is in the review buffer&lt;br /&gt;
; user/view&amp;amp;#58;owner&lt;br /&gt;
: A user can only view their own user profile.&lt;br /&gt;
config privileges are typically use the specfic privilege they give access.  E.g.&lt;br /&gt;
* config/indexer&lt;br /&gt;
* config/regen_abstracts&lt;br /&gt;
* config/view&lt;br /&gt;
However, ''config/view'' and ''config/edit'' can be specialized to allow specific types of configuration file to be viewed or edited.  E.g.&lt;br /&gt;
* config/view/phrase&lt;br /&gt;
* config/edit/autocomplete&lt;br /&gt;
&lt;br /&gt;
== Creating a privilege ==&lt;br /&gt;
There is no special step to creating a privilege, simply define it where you would like it tested for. Equally, there is no specified format for new privileges tying them to (for example) screens.  As a result the following are all valid:&lt;br /&gt;
* &amp;quot;eprint/coindoi&amp;quot;&lt;br /&gt;
* &amp;quot;eprint/coindoiffff&amp;quot;&lt;br /&gt;
* &amp;quot;eprint/coindoi:editor&amp;quot;&lt;br /&gt;
However, to make sure the privilege is as intuitive as possible, it is best to stick as closely to the conventions described in &amp;quot;[[#Anatomy of a privilege|Anatomy of a privilege]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Assigning a role==&lt;br /&gt;
Now that you have created a role you want to give that to class of users. To give every regular user of the repository the &amp;lt;code&amp;gt;approve-hat&amp;lt;/code&amp;gt; you add it to the list of roles for the user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{user} = [&lt;br /&gt;
        'general',&lt;br /&gt;
        'edit-own-record',&lt;br /&gt;
        'saved-searches',&lt;br /&gt;
        'set-password',&lt;br /&gt;
        'deposit',&lt;br /&gt;
        'change-email',&lt;br /&gt;
        'approve-hat',&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Rather than giving every user the role you can give it to individual users. Administer a users profile and add the name of the role to their list of additional roles.&lt;br /&gt;
&lt;br /&gt;
[[File:Approve-hat.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Assigning a user privilege==&lt;br /&gt;
You do not have to give a user a full role you can give them a privilege. The syntax is slightly different. Add the name of the privilege prefixed with a '+' to the list of roles. You can remove a privilege by prefixing it with a '-'.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{user} = [&lt;br /&gt;
        'general',&lt;br /&gt;
        'edit-own-record',&lt;br /&gt;
        'saved-searches',&lt;br /&gt;
        'set-password',&lt;br /&gt;
        'deposit',&lt;br /&gt;
        'change-email',&lt;br /&gt;
        'approve-hat',&lt;br /&gt;
        '+eprint/archive/edit:owner',&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also assign privileges to individual users through the web interface in the same way you can assign a role, remembering they will be listed as &amp;quot;roles&amp;quot;. (remember the '+' or '-')&lt;br /&gt;
&lt;br /&gt;
There is no need for users to log in again following a privilege change, eprints will pick it up automatically.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.&lt;br /&gt;
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.&lt;br /&gt;
* [[How to make a Screen for the Admin Section#Making the page appear|Screen plugin visibility]] - Example of making a new Screen Plugin appear using roles.&lt;br /&gt;
[[Category:Manual]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=How_to_make_a_Screen_for_the_Admin_Section&amp;diff=15588</id>
		<title>How to make a Screen for the Admin Section</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=How_to_make_a_Screen_for_the_Admin_Section&amp;diff=15588"/>
		<updated>2022-12-14T08:43:48Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Formatting changes; additional links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Howto]][[Category:Plugins]]&lt;br /&gt;
 Known to work for EPrints 3.2+ &lt;br /&gt;
&lt;br /&gt;
== The basic structure ==&lt;br /&gt;
To make a Screen plugin, you create a Perl Module in &amp;lt;code&amp;gt;[eprints]/archives/&amp;lt;ARCHIVE_ID&amp;gt;/cfg/plugins/EPrints/Plugin/Screen/&amp;lt;/code&amp;gt; with the following basic structure&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
package EPrints::Plugin::Screen::Mypackage;&lt;br /&gt;
&lt;br /&gt;
use EPrints::Plugin::Screen;&lt;br /&gt;
&lt;br /&gt;
@ISA = ( 'EPrints::Plugin::Screen' );&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
sub new&lt;br /&gt;
{&lt;br /&gt;
	my( $class, %params ) = @_;&lt;br /&gt;
	my $self = $class-&amp;gt;SUPER::new(%params);&lt;br /&gt;
	$self-&amp;gt;{priv} = undef;&lt;br /&gt;
	$self-&amp;gt;{appears} = [&lt;br /&gt;
		{ &lt;br /&gt;
			place =&amp;gt; &amp;quot;admin_actions_editorial&amp;quot;, # see notes below&lt;br /&gt;
			position =&amp;gt; 1450, &lt;br /&gt;
		},&lt;br /&gt;
	];&lt;br /&gt;
	return $self;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub can_be_viewed&lt;br /&gt;
{&lt;br /&gt;
	my( $self ) = @_;&lt;br /&gt;
	return $self-&amp;gt;allow( &amp;quot;my/conf/value&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub render&lt;br /&gt;
{&lt;br /&gt;
	my( $self ) = @_;&lt;br /&gt;
	my $session = $self-&amp;gt;{session};&lt;br /&gt;
        my $user = $session-&amp;gt;current_user;&lt;br /&gt;
&lt;br /&gt;
        my $p = $session-&amp;gt;make_doc_fragment;&lt;br /&gt;
&lt;br /&gt;
        # create page contents:&lt;br /&gt;
        my $h = $session-&amp;gt;make_element( &amp;quot;h3&amp;quot; );&lt;br /&gt;
        $h-&amp;gt;appendChild($session-&amp;gt;make_text( &amp;quot;Look up organisations known to OA-RJ&amp;quot; ));&lt;br /&gt;
        $p-&amp;gt;appendChild($h);&lt;br /&gt;
&lt;br /&gt;
	return $p&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In theory, one should be able to have multiple bits of functionality (view a little, view a lot, edit, etc), simply by testing for different values of &amp;lt;code&amp;gt;$self-&amp;gt;allow( &amp;quot;my/conf/value&amp;quot; )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The locations ==&lt;br /&gt;
Where the link for the page appears is defined by &amp;lt;code&amp;gt;$self-&amp;gt;{appears}-&amp;gt;[''n'']-&amp;gt;{place}&amp;lt;/code&amp;gt; (in the &amp;lt;code&amp;gt;new&amp;lt;/code&amp;gt; function.)&lt;br /&gt;
&lt;br /&gt;
We are defining a screen that appears in the &amp;quot;admin&amp;quot; area, and there are 4 tabs defined within the admin screen:&lt;br /&gt;
* admin_actions_editorial&lt;br /&gt;
* admin_actions_system&lt;br /&gt;
* admin_actions_config&lt;br /&gt;
* admin_actions_misc&lt;br /&gt;
&lt;br /&gt;
Other places the link can appear are&lt;br /&gt;
* unknown to me&lt;br /&gt;
&lt;br /&gt;
== Making the page appear ==&lt;br /&gt;
There are three steps to making a page appear:&lt;br /&gt;
&lt;br /&gt;
1. The screen plugin should test for ''view-ability''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# in EPrints::Plugin::Screen::Mypackage&lt;br /&gt;
sub can_be_viewed&lt;br /&gt;
{&lt;br /&gt;
	my( $self ) = @_;&lt;br /&gt;
	return $self-&amp;gt;allow( &amp;quot;my/conf/value&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
2 The ''User'' DataObject needs to list the privilege under a role:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  # In EPrints::DataObj::User&lt;br /&gt;
  foo_bar =&amp;gt; [&lt;br /&gt;
    &amp;quot;my/view/value&amp;quot;,&lt;br /&gt;
  ],&lt;br /&gt;
  foo_baz =&amp;gt; [&lt;br /&gt;
    &amp;quot;my/view/value&amp;quot;,&lt;br /&gt;
    &amp;quot;my/conf/value&amp;quot;,&lt;br /&gt;
  ],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
3 The user_roles.pl file needs to make the role available to the user-type:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# in [eprints]/archive/&amp;lt;ARCHIVE_ID&amp;gt;/cfg/cfg/user_roles.pl&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{user} = [qw{&lt;br /&gt;
	// truncated&lt;br /&gt;
	foo_bar&lt;br /&gt;
}],&lt;br /&gt;
$c-&amp;gt;{user_roles}-&amp;gt;{admin} = [qw{&lt;br /&gt;
        // truncated&lt;br /&gt;
	foo_baz&lt;br /&gt;
}],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Return to the main [[Screen_Plugins]] page.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.&lt;br /&gt;
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Contribute:_Plugins/ImportPluginsAWS&amp;diff=13795</id>
		<title>Contribute: Plugins/ImportPluginsAWS</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Contribute:_Plugins/ImportPluginsAWS&amp;diff=13795"/>
		<updated>2021-05-24T11:13:59Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Code formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Contribute]]&lt;br /&gt;
[[Category:Plugins]]&lt;br /&gt;
= Import Plugin Tutorial 2: Amazon Web Services =&lt;br /&gt;
&lt;br /&gt;
In the [[Contribute:_Plugins/ImportPluginsCSV|last tutorial]] we created an import plugin that took data which needed very little modification to import into the respository. The column names in the [http://en.wikipedia.org/wiki/Comma-Separated_Values CSV] file matched the names of metadata fields present in the repository. In this tutorial we'll look at importing data that needs some modification to be imported, needs more error checking and is obtained in a different way.&lt;br /&gt;
&lt;br /&gt;
We will be using Amazon's E-Commerce Webservice to import books from their website into our respository given a list of [http://en.wikipedia.org/wiki/ASIN ASIN].&lt;br /&gt;
&lt;br /&gt;
We will be accessing the service using a [http://en.wikipedia.org/wiki/REST REST] approach, communicating with the server using URL parameters and retrieving an XML document in response to our request. It is also possible to access their services using [http://en.wikipedia.org/wiki/SOAP SOAP], but that will not be discussed here.&lt;br /&gt;
&lt;br /&gt;
= Before You Start =&lt;br /&gt;
&lt;br /&gt;
== Amazon Web Services ==&lt;br /&gt;
To use Amazon's web services you must first signup for an account [http://aws.amazon.com here]. Their site has extensive documentation on the services that they offer as well as example programs including some written in Perl.&lt;br /&gt;
&lt;br /&gt;
== Required Modules ==&lt;br /&gt;
To prepare for this tutorial you should make sure the [http://search.cpan.org/~gaas/libwww-perl-5.805/lib/LWP/UserAgent.pm LWP::UserAgent] module is installed. The following command as root, or using sudo should work.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cpan LWP::UserAgent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= AWS.pm = &lt;br /&gt;
The code in the section below should be placed in a file called CSV.pm in the directory created previously, and MyPlugins should be changed to the name of that directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package EPrints::Plugin::Import::MyPlugins::AWS;&lt;br /&gt;
&lt;br /&gt;
use EPrints::Plugin::Import::TextFile;&lt;br /&gt;
use strict;&lt;br /&gt;
use URI::Escape;&lt;br /&gt;
&lt;br /&gt;
our @ISA = ('EPrints::Plugin::Import::TextFile');&lt;br /&gt;
&lt;br /&gt;
my $endpoint = 'http://ecs.amazonaws.co.uk/onca/xml';&lt;br /&gt;
my $accesskey = '&amp;lt;YOURAMAZONWSKEY&amp;gt;';&lt;br /&gt;
my $service = 'AWSECommerceService';&lt;br /&gt;
my $operation = 'ItemLookup';&lt;br /&gt;
my $version = '2007-07-16';&lt;br /&gt;
my $responsegroup = 'Large';&lt;br /&gt;
&lt;br /&gt;
sub new&lt;br /&gt;
{&lt;br /&gt;
        my( $class, %params ) = @_;&lt;br /&gt;
        my $self = $class-&amp;gt;SUPER::new( %params );&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = 'AWS';&lt;br /&gt;
        $self-&amp;gt;{visible} = 'all';&lt;br /&gt;
        $self-&amp;gt;{produce} = [ 'list/eprint' , 'dataobj/eprint'];&lt;br /&gt;
&lt;br /&gt;
        my $rc = EPrints::Utils::require_if_exists('LWP::UserAgent');&lt;br /&gt;
        unless ($rc)&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;{visible} = '';&lt;br /&gt;
                $self-&amp;gt;{error} = 'Unable to load required module LWP::UserAgent';&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return $self;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub input_fh&lt;br /&gt;
{&lt;br /&gt;
        my( $plugin, %opts ) = @_;&lt;br /&gt;
        my @ids;&lt;br /&gt;
        my $fh = $opts{fh};&lt;br /&gt;
&lt;br /&gt;
        my @records = &amp;lt;$fh&amp;gt;;&lt;br /&gt;
        foreach my $input_data (@records)&lt;br /&gt;
        {&lt;br /&gt;
                my $epdata = $plugin-&amp;gt;convert_input($input_data);&lt;br /&gt;
                next unless defined $epdata;&lt;br /&gt;
&lt;br /&gt;
                my $dataobj = $plugin-&amp;gt;epdata_to_dataobj($opts{dataset},$epdata);&lt;br /&gt;
                if( defined $dataobj )&lt;br /&gt;
                {&lt;br /&gt;
                        push @ids, $dataobj-&amp;gt;get_id;&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return EPrints::List-&amp;gt;new(&lt;br /&gt;
                        dataset =&amp;gt; $opts{dataset},&lt;br /&gt;
                        session =&amp;gt; $plugin-&amp;gt;{session},&lt;br /&gt;
                        ids=&amp;gt;\@ids );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub convert_input&lt;br /&gt;
{&lt;br /&gt;
        my ($plugin, $input) = @_;&lt;br /&gt;
        my %output = ();&lt;br /&gt;
&lt;br /&gt;
        $input =~ m/([A-Za-z0-9]+)/;&lt;br /&gt;
        $input = $1;&lt;br /&gt;
&lt;br /&gt;
        my $request =&lt;br /&gt;
                &amp;quot;$endpoint?&amp;quot;.&lt;br /&gt;
                &amp;quot;Service=$service&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;AWSAccessKeyId=$accesskey&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;Operation=$operation&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;ItemId=$input&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;Version=$version&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;ResponseGroup=$responsegroup&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        my $ua = LWP::UserAgent-&amp;gt;new;&lt;br /&gt;
        $ua-&amp;gt;timeout(30);&lt;br /&gt;
        my $response = $ua-&amp;gt;get($request);&lt;br /&gt;
&lt;br /&gt;
        my $dom = EPrints::XML::parse_xml_string($response-&amp;gt;content);&lt;br /&gt;
&lt;br /&gt;
        my $rep =&lt;br /&gt;
                $dom-&amp;gt;getElementsByTagName('Items')-&amp;gt;item(0)-&amp;gt;&lt;br /&gt;
                getElementsByTagName('Request')-&amp;gt;item(0);&lt;br /&gt;
&lt;br /&gt;
        my $reptext =&lt;br /&gt;
                EPrints::Utils::tree_to_utf8($rep-&amp;gt;getElementsByTagName('IsValid')-&amp;gt;item(0));&lt;br /&gt;
&lt;br /&gt;
        unless ($reptext eq 'True') &lt;br /&gt;
        {&lt;br /&gt;
                $plugin-&amp;gt;error('Invalid AWS Request');&lt;br /&gt;
                return undef;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        #Get Item Object&lt;br /&gt;
        my $item =&lt;br /&gt;
                $dom-&amp;gt;getElementsByTagName('Items')-&amp;gt;item(0)-&amp;gt;&lt;br /&gt;
                getElementsByTagName('Item')-&amp;gt;item(0);&lt;br /&gt;
&lt;br /&gt;
        unless (defined $item) &lt;br /&gt;
        {&lt;br /&gt;
                $plugin-&amp;gt;error('No Item element found');&lt;br /&gt;
                return undef;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my $attr = $item-&amp;gt;getElementsByTagName('ItemAttributes')-&amp;gt;item(0);&lt;br /&gt;
&lt;br /&gt;
        my $pg = EPrints::Utils::tree_to_utf8($attr-&amp;gt;getElementsByTagName('ProductGroup')-&amp;gt;item(0));&lt;br /&gt;
&lt;br /&gt;
        unless ($pg eq 'Book') &lt;br /&gt;
        {&lt;br /&gt;
                $plugin-&amp;gt;error('Product is not a book.');&lt;br /&gt;
                return undef;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $output{type} = 'book';&lt;br /&gt;
        $output{refereed} = 'FALSE';&lt;br /&gt;
        $output{ispublished} = 'pub';&lt;br /&gt;
&lt;br /&gt;
        my $title = $attr-&amp;gt;getElementsByTagName('Title')-&amp;gt;item(0);&lt;br /&gt;
        $output{title} = EPrints::Utils::tree_to_utf8($title);&lt;br /&gt;
&lt;br /&gt;
        my $url = $item-&amp;gt;getElementsByTagName('DetailPageURL')-&amp;gt;item(0);&lt;br /&gt;
        $output{official_url} = uri_unescape(EPrints::Utils::tree_to_utf8($url));&lt;br /&gt;
&lt;br /&gt;
        my $isbn = $attr-&amp;gt;getElementsByTagName('ISBN')-&amp;gt;item(0);&lt;br /&gt;
        if (defined $isbn)&lt;br /&gt;
        {&lt;br /&gt;
                $output{isbn} = EPrints::Utils::tree_to_utf8($isbn);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my $pages = $attr-&amp;gt;getElementsByTagName('NumberOfPages')-&amp;gt;item(0);&lt;br /&gt;
        if (defined $pages)&lt;br /&gt;
        {&lt;br /&gt;
                $output{pages} = EPrints::Utils::tree_to_utf8($pages);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my $publisher = $attr-&amp;gt;getElementsByTagName('Publisher')-&amp;gt;item(0);&lt;br /&gt;
        if (defined $publisher)&lt;br /&gt;
        {&lt;br /&gt;
                $output{publisher} = EPrints::Utils::tree_to_utf8($publisher);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my $pubdate = $attr-&amp;gt;getElementsByTagName('PublicationDate')-&amp;gt;item(0);&lt;br /&gt;
        if (defined $pubdate)&lt;br /&gt;
        {&lt;br /&gt;
                $output{date} = EPrints::Utils::tree_to_utf8($pubdate);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return \%output;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= In More Detail =&lt;br /&gt;
We will use the URI::Escape module in this plugin. As it is included with EPrints we don't need to check if it exists first.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use URI::Escape;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we setup a number of values for parameters that will be part of our web service requests. The endpoint variable determines which server will be sent the request. Here we have used the UK server, but by changing the [http://en.wikipedia.org/wiki/TLD TLD] we can use the US, Canadian, German or French servers.&lt;br /&gt;
&lt;br /&gt;
The accesskey variable stores the access key you will have gained from signing up to Amazon earlier. You should use the normal access key and not the secret one.&lt;br /&gt;
&lt;br /&gt;
Here we use the ItemLookup operation of the AWSECommerceService with the 2007-07-16 version of the API. Other operations allow searching for items, but here we want to look up specific products. Finally the variable responsegroup determines the amount and nature of the information returned, we select &amp;quot;Large&amp;quot; in this case, which gives us more information about the item.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
my $endpoint = 'http://ecs.amazonaws.co.uk/onca/xml';&lt;br /&gt;
my $accesskey = '&amp;lt;YOURAMAZONWSKEY&amp;gt;';&lt;br /&gt;
my $service = 'AWSECommerceService';&lt;br /&gt;
my $operation = 'ItemLookup';&lt;br /&gt;
my $version = '2007-07-16';&lt;br /&gt;
my $responsegroup = 'Large';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Constructor ==&lt;br /&gt;
The constructor is similar to the one used for the [Contribute:_Plugins/ImportPluginsCSV CSV plugin], except this one will import individual eprints, given an [http://en.wikipedia.org/wiki/ASIN ASIN].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $self-&amp;gt;{produce} = [ 'list/eprint' , 'dataobj/eprint'];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Like we imported Text::CSV in the [Contribute:_Plugins/ImportPluginsCSV last tutorial], here we import LWP::UserAgent which will be used for making requests to the web service.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $rc = EPrints::Utils::require_if_exists('LWP::UserAgent');&lt;br /&gt;
        unless ($rc)&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;{visible} = '';&lt;br /&gt;
                $self-&amp;gt;{error} = 'Unable to load required module LWP::UserAgent';&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Input ==&lt;br /&gt;
=== input_fh ===&lt;br /&gt;
This method is similar to the one used in the [Contribute:_Plugins/ImportPluginsCSV CSV plugin], but doesn't have to do quite so much work.&lt;br /&gt;
&lt;br /&gt;
First we create the array to hold our imported eprint ids.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my @ids;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next we read all the lines in the supplied file handle into our records array.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $fh = $opts{fh};&lt;br /&gt;
&lt;br /&gt;
        my @records = &amp;lt;$fh&amp;gt;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we iterate over each record, running convert_input on it, importing it into our repository and adding the id to our array.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        foreach my $input_data (@records)&lt;br /&gt;
        {&lt;br /&gt;
                my $epdata = $plugin-&amp;gt;convert_input($input_data);&lt;br /&gt;
                next unless defined $epdata;&lt;br /&gt;
&lt;br /&gt;
                my $dataobj = $plugin-&amp;gt;epdata_to_dataobj($opts{dataset},$epdata);&lt;br /&gt;
                if( defined $dataobj )&lt;br /&gt;
                {&lt;br /&gt;
                        push @ids, $dataobj-&amp;gt;get_id;&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we return a List object of the items imported.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        return EPrints::List-&amp;gt;new(&lt;br /&gt;
                        dataset =&amp;gt; $opts{dataset},&lt;br /&gt;
                        session =&amp;gt; $plugin-&amp;gt;{session},&lt;br /&gt;
                        ids=&amp;gt;\@ids );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== convert_input ===&lt;br /&gt;
&lt;br /&gt;
[http://en.wikipedia.org/wiki/ASIN ASINs] are strings which identify a product. Here we remove any non-alphanumerical characters which are surrounding the [http://en.wikipedia.org/wiki/ASIN ASIN].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $input =~ m/([A-Za-z0-9]+)/;&lt;br /&gt;
        $input = $1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We form the request from the variables we created earlier and the [http://en.wikipedia.org/wiki/ASIN ASIN] we have just obtained.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $request =&lt;br /&gt;
                &amp;quot;$endpoint?&amp;quot;.&lt;br /&gt;
                &amp;quot;Service=$service&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;AWSAccessKeyId=$accesskey&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;Operation=$operation&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;ItemId=$input&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;Version=$version&amp;amp;&amp;quot;.&lt;br /&gt;
                &amp;quot;ResponseGroup=$responsegroup&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We now send the request, by creating a new LWP::UserAgent object, setting its timeout to 30 seconds and then performing the request using HTTP GET.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $ua = LWP::UserAgent-&amp;gt;new;&lt;br /&gt;
        $ua-&amp;gt;timeout(30);&lt;br /&gt;
        my $response = $ua-&amp;gt;get($request);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then create a [http://en.wikipedia.org/wiki/Document_Object_Model DOM] object from the XML document returned.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $dom = EPrints::XML::parse_xml_string($response-&amp;gt;content);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each request contains an Items element within the root element of the document which contains a Request element. This element contains an element IsValid. This element will contain the value True or False depending on whether a valid request was made or not.&lt;br /&gt;
&lt;br /&gt;
Here we obtain the Request element and check that the IsValid element within it contains the value True. If it doesn't we  call the error method and return undef.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $rep =&lt;br /&gt;
                $dom-&amp;gt;getElementsByTagName(&amp;quot;Items&amp;quot;)-&amp;gt;item(0)-&amp;gt;&lt;br /&gt;
                getElementsByTagName('Request')-&amp;gt;item(0);&lt;br /&gt;
&lt;br /&gt;
        my $reptext =&lt;br /&gt;
                EPrints::Utils::tree_to_utf8($rep-&amp;gt;getElementsByTagName('IsValid')-&amp;gt;item(0));&lt;br /&gt;
&lt;br /&gt;
        unless ($reptext eq 'True') &lt;br /&gt;
        {&lt;br /&gt;
                $plugin-&amp;gt;error('Invalid AWS Request');&lt;br /&gt;
                return undef;&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The product found with the ItemLookup method is contained within an Item element within the Items element. Here we attempt to get that element and raise the error and return undef if we can't.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $item =&lt;br /&gt;
                $dom-&amp;gt;getElementsByTagName('Items')-&amp;gt;item(0)-&amp;gt;&lt;br /&gt;
                getElementsByTagName('Item')-&amp;gt;item(0);&lt;br /&gt;
&lt;br /&gt;
        unless (defined $item) &lt;br /&gt;
        {&lt;br /&gt;
                $plugin-&amp;gt;error('No Item element found');&lt;br /&gt;
                return undef;&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each item contains an ItemAttributes element which contains most of the metadata about an item.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $attr = $item-&amp;gt;getElementsByTagName('ItemAttributes')-&amp;gt;item(0);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For some specialised repositories it might make sense to import DVDs, computer games and electronic equipment, but we're just going to deal with books. The ProductGroup element within the ItemAttributes element tells you what sort of item we're dealing with. We're looking for the value 'Book'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $pg = EPrints::Utils::tree_to_utf8($attr-&amp;gt;getElementsByTagName('ProductGroup')-&amp;gt;item(0));&lt;br /&gt;
&lt;br /&gt;
        unless ($pg eq 'Book') &lt;br /&gt;
        {&lt;br /&gt;
                $plugin-&amp;gt;error('Product is not a book.');&lt;br /&gt;
                return undef;&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we set a few fields without consulting the imported data. We know this is a book, so we set the type. We assume that it has not been refereed. We also assume it has been published, because we can buy it. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $output{type} = 'book';&lt;br /&gt;
        $output{refereed} = 'FALSE';&lt;br /&gt;
        $output{ispublished} = 'pub';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We get and set the title.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $title = $attr-&amp;gt;getElementsByTagName('Title')-&amp;gt;item(0);&lt;br /&gt;
        $output{title} = EPrints::Utils::tree_to_utf8($title);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we set the official URL to the Amazon product page. We have to do a bit of extra work using the uri_unescape method from the URI::Escape package to convert URI escape codes into characters.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $url = $item-&amp;gt;getElementsByTagName('DetailPageURL')-&amp;gt;item(0);&lt;br /&gt;
        $output{official_url} = uri_unescape(EPrints::Utils::tree_to_utf8($url));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can set the [http://en.wikipedia.org/wiki/ISBN ISBN]. Note that the [http://en.wikipedia.org/wiki/ISBN ISBN] is often the same as the [http://en.wikipedia.org/wiki/ASIN ASIN].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $isbn = $attr-&amp;gt;getElementsByTagName('ISBN')-&amp;gt;item(0);&lt;br /&gt;
        if (defined $isbn)&lt;br /&gt;
        {&lt;br /&gt;
                $output{isbn} = EPrints::Utils::tree_to_utf8($isbn);&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can set the number of pages.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $pages = $attr-&amp;gt;getElementsByTagName('NumberOfPages')-&amp;gt;item(0);&lt;br /&gt;
        if (defined $pages)&lt;br /&gt;
        {&lt;br /&gt;
                $output{pages} = EPrints::Utils::tree_to_utf8($pages);&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can set the publisher.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $publisher = $attr-&amp;gt;getElementsByTagName('Publisher')-&amp;gt;item(0);&lt;br /&gt;
        if (defined $publisher)&lt;br /&gt;
        {&lt;br /&gt;
                $output{publisher} = EPrints::Utils::tree_to_utf8($publisher);&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can set the publication date and finally return our output hash.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        my $pubdate = $attr-&amp;gt;getElementsByTagName('PublicationDate')-&amp;gt;item(0);&lt;br /&gt;
        if (defined $pubdate)&lt;br /&gt;
        {&lt;br /&gt;
                $output{date} = EPrints::Utils::tree_to_utf8($pubdate);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return \%output;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Testing Your Plugin =&lt;br /&gt;
After restarting your webserver go to the Import Items screen from the Manage Deposits screen. If you can't find this, make sure you're logged in.&lt;br /&gt;
&lt;br /&gt;
We'll start by collecting a few ASINS. Go to [http://www.amazon.co.uk Amazon] and pick a few books. The URL for each project page is in the form http://www.amazon.co.uk/Combination-of-title-an-author/dp/ASIN... Collect a few different ASINS.&lt;br /&gt;
&lt;br /&gt;
Now we'll demonstrate importing from Amazon with a few sample ASINs.&lt;br /&gt;
Type this into the &amp;quot;Cut and Paste Records&amp;quot; box:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
0946719616&lt;br /&gt;
0297843877&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;AWS&amp;quot; from the Select import format drop down menu and click &amp;quot;Test Run + Import&amp;quot;. You should end up at the Manage Deposits screen with the following message being displayed &amp;quot;Import completed: 2 item(s) imported.&amp;quot;.&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Frequently_Asked_Questions&amp;diff=13787</id>
		<title>Frequently Asked Questions</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Frequently_Asked_Questions&amp;diff=13787"/>
		<updated>2021-05-21T11:19:21Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Source formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:FAQ]]&lt;br /&gt;
[[Category:Management]]&lt;br /&gt;
[[Category: Out of Date]]&lt;br /&gt;
[[Category: Obsolete]]&lt;br /&gt;
&lt;br /&gt;
This all needs sorting out, it's just being grabbed from the old wiki for now.&lt;br /&gt;
&lt;br /&gt;
* [[Copyright and License FAQ]]&lt;br /&gt;
* [[Metadata FAQ]]&lt;br /&gt;
* [[Searching FAQ]]&lt;br /&gt;
* [[OAI FAQ]]&lt;br /&gt;
* [[How much will it cost?]]&lt;br /&gt;
&lt;br /&gt;
== What operating systems can we use? ==&lt;br /&gt;
&lt;br /&gt;
EPrints should work on any Linux operating system. We use Ubuntu (Debian) and Redhat Enterprise Linux.&lt;br /&gt;
&lt;br /&gt;
Running EPrints on Microsoft Windows is possible but strongly not recommended.  It can be very difficult to get all the necessary dependencies in place.  If you want to get EPrints running but do not have as computer running a Linux operating system.  You could install [https://www.virtualbox.org/wiki/Downloads VirtualBox] and then create a Ubuntu or Redhat &amp;quot;virtual machine&amp;quot; (VM) to run on top of your Windows operating system.  Alternatively, you could install [https://docs.docker.com/docker-for-windows/install/ Docker Desktop for Windows] and [[Installing EPrints using Docker|install EPrints using Docker]].  However, both these methods are only recommended for testing or demoing EPrints.  If you intend to run EPrints long-term you should install on a dedicated Linux server or virtual machine.&lt;br /&gt;
&lt;br /&gt;
== What computer do we need? ==&lt;br /&gt;
Any modern physical PC (server or desktop) or a virtual machine should be more than capable of running EPrints.  A suggested minimum specification for running a live service:&lt;br /&gt;
* 2GB RAM &lt;br /&gt;
* 20GB disk space&lt;br /&gt;
* 100Mb/s network speed&lt;br /&gt;
&lt;br /&gt;
== How much will it cost to set up? ==&lt;br /&gt;
&lt;br /&gt;
Most of the costs are staff time. Equipment costs are a PC, an internet connection and a BACKUP STRATEGY. Please remember to budget for backups.&lt;br /&gt;
&lt;br /&gt;
EPrints, and all the other software required to make it work, are available for no cost. At some point in the future EPrints may offer some pay-services, but the core software will remain zero cost and freely available to all.&lt;br /&gt;
&lt;br /&gt;
See [[How much will it cost?]]&lt;br /&gt;
&lt;br /&gt;
== How much disk space will we need? ==&lt;br /&gt;
The main usage of disk space will be the uploaded files for the publications, (e.g. PDF, Word documents, etc.).  On average an eprint item will have associated files (e.g. uploaded PDF and thumbnail and preview images of that PDF) that take up 2MB of disk space.  So for every extra 500 eprint items you will need an extra 1GB of disk.  However, if you intend to upload lots of videos, images, are large documents, then this requirement will be higher.  On top of the space needed for uploaded documents and associated files you will need approximately 5GB for installing the operating system.  The disk space required by the database is difficult to determine, as this is dependent on a number of different factors but 1MB per eprint item.&lt;br /&gt;
=== Example usage requirements ===&lt;br /&gt;
* Small repository: 1000 eprint items&lt;br /&gt;
** Operating system: 5GB&lt;br /&gt;
** Upload and associated files: 2MB x 1000 = 2GB&lt;br /&gt;
** Database: 1MB x 1000 = 1GB&lt;br /&gt;
** '''TOTAL:''' 8GB (15GB to give room for expansion)&lt;br /&gt;
* Medium-sized repository: 10,000 eprint items&lt;br /&gt;
** Operating system: 5GB&lt;br /&gt;
** Upload and associated files: 2MB x 10,000 = 20GB&lt;br /&gt;
** Database: 1MB x 10,000 = 10GB&lt;br /&gt;
** '''TOTAL:''' 35GB (50GB to give room for expansion)&lt;br /&gt;
* Large repository: 100,000 eprint items&lt;br /&gt;
** Operating system: 5GB&lt;br /&gt;
** Upload and associated files: 2MB x 10,000 = 200GB&lt;br /&gt;
** Database: 1MB x 10,000 = 100GB&lt;br /&gt;
** '''TOTAL:''' 305GB (350-400GB to give room for expansion)&lt;br /&gt;
&lt;br /&gt;
== Is it possible when depositing a document, to just point to an &amp;quot;alternative location&amp;quot; rather than have the full text copied and held in the eprint archive? ==&lt;br /&gt;
&lt;br /&gt;
Yes, and to suppress the normal warning about no documents attached look in '''[archive_root]/cfg/cfg.d/eprint_warnings.pl'''.&lt;br /&gt;
&lt;br /&gt;
== I need to run apache as a user other than &amp;quot;eprints&amp;quot;, what do I do to make EPrints work in this situation? ==&lt;br /&gt;
&lt;br /&gt;
Example, apache is running as user &amp;quot;apache&amp;quot;.&lt;br /&gt;
* Make all the eprints files owned by &amp;quot;apache&amp;quot; instead of &amp;quot;eprints&amp;quot;&lt;br /&gt;
* Edit SystemSettings?.pm to tell eprints to run as user &amp;quot;apache&amp;quot;&lt;br /&gt;
* You'll need to run all command line scripts as user &amp;quot;apache&amp;quot;&lt;br /&gt;
* All eprints cron jobs should be owned by user &amp;quot;apache&amp;quot; &lt;br /&gt;
&lt;br /&gt;
If you are installing a new copy of eprints, you can specify the user and group to use when you run 'configure'. Do&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
./configure --help &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
for details.&lt;br /&gt;
&lt;br /&gt;
== How do I get the body HTML of a page without the template around it? ==&lt;br /&gt;
This is handy for dynamically linking EPrints content into other sites.&lt;br /&gt;
&lt;br /&gt;
For &amp;quot;view&amp;quot; pages you need to add the option &amp;lt;code&amp;gt;include=&amp;gt;1&amp;lt;/code&amp;gt; to the view configuration.  This will cause generate_views to make a ''.include'' page in addition to the ''.html'' page. The ''.include'' page will have no template around it.&lt;br /&gt;
&lt;br /&gt;
For dynamic pages, those under ''/cgi/'', you can add the cgi parameter &amp;lt;code&amp;gt;mainonly=yes&amp;lt;/code&amp;gt;.  E.g. &amp;lt;code&amp;gt;http://tryme.demo.eprints-hosting.org/cgi/latest?mainonly=yes&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How do I get statistics on number of deposits per month? ==&lt;br /&gt;
&lt;br /&gt;
This rather grim bit of SQL should work, although datestamp is the last modified date, not the submission OR creation date, it should still give a good indication.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
select count(*), year(datestamp), month(datestamp)&lt;br /&gt;
from archive&lt;br /&gt;
group by year(datestamp),month(datestamp)&lt;br /&gt;
order by year(datestamp),month(datestamp);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I've edited the template (or other config file) but nothing seems to have changed - why? ==&lt;br /&gt;
&lt;br /&gt;
While EPrints tries to automatically reload when a configuration file is changed you may need to reload the Web server for changes to take effect. See also the [[API:bin/epadmin|epadmin reload]], the [[API:bin/generate_static|generate_static]] and [[API:bin/generate_views|generate_views]] commands.&lt;br /&gt;
&lt;br /&gt;
= Installation Related Questions =&lt;br /&gt;
 &lt;br /&gt;
== When running a script I get the error; &amp;quot;Insecure dependency in mkdir while running with -T switch&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
This usually indicates you are running an eprints script as root. Don't do that; become user 'eprints' instead.&lt;br /&gt;
&lt;br /&gt;
== title and fulltext search returns no results, but date search does ==&lt;br /&gt;
&lt;br /&gt;
The indexer daemon is probably not running or is not working correctly, see [[API:bin/indexer]].&lt;br /&gt;
&lt;br /&gt;
== I don't want to give epadmin my mysql root password. What is the alternative? ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
 mysql&amp;gt; CREATE DATABASE myrepo;&lt;br /&gt;
 Query OK, 1 row affected (0.06 sec)&lt;br /&gt;
&lt;br /&gt;
 mysql&amp;gt; GRANT ALL PRIVILEGES ON myrepo.* TO myrepo@localhost IDENTIFIED BY 'secret';&lt;br /&gt;
 Query OK, 0 rows affected (0.52 sec)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then provide the database name, user name and password to the '''[[API:bin/epadmin|epadmin]] create''' command.&lt;br /&gt;
&lt;br /&gt;
==  How do I get a value for a field of an eprint (without using any SQL)? ==&lt;br /&gt;
&lt;br /&gt;
(assuming the eprint is in the main archive, and has eprintid number 23)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $ds = $repo-&amp;gt;dataset( &amp;quot;eprint&amp;quot; );&lt;br /&gt;
my $eprint = $ds-&amp;gt;dataobj( 23 );&lt;br /&gt;
my $value = $eprint-&amp;gt;value( &amp;quot;editors&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[API:EPrints/DataObj]].&lt;br /&gt;
&lt;br /&gt;
== How can I get a utf8 string of the name of a subject, given its subjectid? ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub get_subject_name_string&lt;br /&gt;
{&lt;br /&gt;
	my( $session, $subjectid ) = @_;&lt;br /&gt;
	my $subj = EPrints::Subject-&amp;gt;new( $session, $subjectid ); &lt;br /&gt;
	if( !defined $subj ) &lt;br /&gt;
	{&lt;br /&gt;
		return &amp;quot;errer, unknown subject: $subjectid&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	return EPrints::Utils::tree_to_utf8( $subj-&amp;gt;render_description() );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&amp;diff=13786</id>
		<title>Setting up HTTPS using Let's Encrypt</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&amp;diff=13786"/>
		<updated>2021-05-21T11:15:10Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Manual}}&lt;br /&gt;
By default EPrints does not come setup to use HTTPS.  This is because you need to generate a SSL certificate and if this is not signed by a known Certificate Authority a user's web browser is likely to complain vigorously.  In the past it has typically costed a fair amount of money to obtain a SSL certificate from your hosting provider.  However, now there is [https://letsencrypt.org/ Let's Encrypt] it is possible to get a certificate for free.  This is not to say you should use Let's Encrypt in all cases.  UK academic institutions should continue to obtain their SSL certificates through Jisc and other institutions/organisations may already have similar arrangements for obtaining SSL certificates.&lt;br /&gt;
&lt;br /&gt;
As well as being free, Let's Encrypt has an automated way for renewing certificates.  However, it should be noted that the length of its certificates is a lot shorter at just 3 months.  As the renewal process is automatic, this time period is more appropriate to maximise security.  Let's Encrypt's certificate generation requires your EPrints repository to be publicly accessible.  Beneath are instructions on how to set up EPrints to enable HTTPS with a Let's Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
1. Go to the https://certbot.eff.org/ and follow the instructions for your web server and operating system (the former will almost always be Apache) and follow the instructions provided.&lt;br /&gt;
&lt;br /&gt;
2. When you get to the point of running the certbot command you want the certificate only so should type as the root user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
certbot --apache certonly&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Take a note of the path to were your certificate, key and CA chain have been saved.  This will probably be something like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt; &lt;br /&gt;
/etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. If you have not already done so, create an directory called &amp;lt;tt&amp;gt;ssl&amp;lt;/tt&amp;gt; inside your archive's directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir EPRINTS_PATH/archives/REPOID/ssl/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. Create a file inside the new ssl directory called &amp;lt;tt&amp;gt;securevhost.conf&amp;lt;/tt&amp;gt; and include the following contents, amending the &amp;lt;tt&amp;gt;ServerName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSLCertificateFile&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSLCertificateKeyFile&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;SSLCertificateChainFile&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Include&amp;lt;/tt&amp;gt; as appropriate at least.  You will note that this configuration also enables [https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security HTTP Strict Transport Security (HSTS)] for additional security.  This ensures that after the first time you visit HTTPS for a particular site in your web browser, all future HTTP requests for this hostname will automatically be converted by your browser to HTTPS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;apache&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     ServerName YOUR-REPOSITORY-DOMAIN:443&lt;br /&gt;
 &lt;br /&gt;
     # Enable HSTS&lt;br /&gt;
     Header always set Strict-Transport-Security &amp;quot;max-age=63072000;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     SSLEngine on&lt;br /&gt;
     SSLProtocol all -SSLv2 -SSLv3&lt;br /&gt;
     SSLHonorCipherOrder on&lt;br /&gt;
     SSLCipherSuite HIGH:!aNULL:!eNULL:!kECDH:!aDH:!RC4:!3DES:!CAMELLIA:!MD5:!PSK:!SRP:!KRB5:@STRENGTH&lt;br /&gt;
 &lt;br /&gt;
     SSLCertificateFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/cert.pem&lt;br /&gt;
     SSLCertificateKeyFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/privkey.pem&lt;br /&gt;
     SSLCertificateChainFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/chain.pem&lt;br /&gt;
 &lt;br /&gt;
     SetEnvIf User-Agent &amp;quot;.*MSIE.*&amp;quot; \&lt;br /&gt;
         nokeepalive ssl-unclean-shutdown \&lt;br /&gt;
         downgrade-1.0 force-response-1.0&lt;br /&gt;
 &lt;br /&gt;
     LogLevel warn&lt;br /&gt;
     ErrorLog logs/ssl_error_log    &lt;br /&gt;
     TransferLog logs/ssl_access_log&lt;br /&gt;
     CustomLog logs/ssl_request_log \&lt;br /&gt;
         &amp;quot;%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \&amp;quot;%r\&amp;quot; %b&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     Include EPRINTS_PATHH/cfg/apache_ssl/REPOID.conf&lt;br /&gt;
 &lt;br /&gt;
     PerlTransHandler +EPrints::Apache::Rewrite&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
6. If you have not already done so, add a configuration file at &amp;lt;tt&amp;gt;/opt/eprints3/archives/REPOID/cfg/cfg.d/https.pl&amp;lt;/tt&amp;gt; with the following configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
 $c-&amp;gt;{securehost} = $c-&amp;gt;{host};&lt;br /&gt;
 $c-&amp;gt;{secureport} = 443;&lt;br /&gt;
 $c-&amp;gt;{http_root} = undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7. Now you will need to regenerate the rest of your Apache configuration for EPrints with the following command run as the EPrints user. (Substitute the path as appropriate):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
/opt/eprints3/bin/generate_apacheconf --system --replace&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
8. Apache will not yet have been setup to include the Apache configuration file you created in step 5.  To include this, you will need to edit the file in your Apache configuration directory (&amp;lt;tt&amp;gt;/etc/httpd/&amp;lt;/tt&amp;gt; on RHEL/CentOS/Fedora and &amp;lt;tt&amp;gt;/etc/apache2/&amp;lt;/tt&amp;gt; on Debian/Ubuntu) and find the file that contains the line &amp;lt;tt&amp;gt;cfg/apache.conf&amp;lt;/tt&amp;gt;, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /etc/httpd/&lt;br /&gt;
grep -r &amp;quot;cfg/apache.conf&amp;quot; *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
9. Once you have found it you will need to edit it and add the following line, changing the path as appropriate:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;apache&amp;quot;&amp;gt;&lt;br /&gt;
Include EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
10. Now, (as root or using sudo) test that the Apache configuration is correct and fix any issues if necessary:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apachectl configtest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
11. Restart Apache and check whether you can access your EPrints repository using HTTPS in a web browser:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apachectl restart&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
12. If the guide on cerbot.eff.org you used in step 1 tells you to to setup a cron job then follow those instructions.  The easiest way to do this is probably to run &amp;lt;tt&amp;gt;crontab -e&amp;lt;/tt&amp;gt; as root and add the following cron job, substituting the minute (43) and hours (6,18) for you own choice maintaining a 12 hour gap between the hours:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
 43 6,18 * * * certbot renew&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Additional Notes ==&lt;br /&gt;
&lt;br /&gt;
The default EPrints Apache Rewrite handler declines any requests to a URL containing &amp;lt;code&amp;gt;/.&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This means that the challenge/response for a LetsEncrypt certificate renewal that uses the &amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt; path will fail.&lt;br /&gt;
&lt;br /&gt;
To make this work you could add a location block to your Apache config, to ensure the &amp;lt;code&amp;gt;/.well-known/&amp;lt;/code&amp;gt; are not handled by EPrints, or use an EPrints URL rewrite trigger to handle the request:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#this could be saved into e.g. [EPRINTS_ROOT]/lib/cfg.d/z_rewrite_url_LetsEncrypt.pl&lt;br /&gt;
&lt;br /&gt;
# import Apache constant e.g. 'OK'&lt;br /&gt;
use EPrints::Apache::AnApache;&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;add_trigger( EP_TRIGGER_URL_REWRITE, sub {&lt;br /&gt;
        my( %o ) = @_;&lt;br /&gt;
&lt;br /&gt;
        # if the incoming request matches the LetsEncrypt challenge URL...&lt;br /&gt;
        if( $o{uri} =~ m!^${o{urlpath}}/\.well-known/acme-challenge/! )&lt;br /&gt;
        {&lt;br /&gt;
                # and the LetsEncrypt renewal process has put the file in EPRINTS_ROOT/archives/ARCHIVEID/html/.well-known/acme-challenge/&lt;br /&gt;
                if( -f $o{repository}-&amp;gt;get_conf( &amp;quot;htdocs_path&amp;quot; ).$o{uri} )&lt;br /&gt;
                {&lt;br /&gt;
                        # reply with an HTTP '200' &lt;br /&gt;
                        ${$o{return_code}} = OK;&lt;br /&gt;
                        # and return the file reqested&lt;br /&gt;
                        $o{request}-&amp;gt;filename( $o{repository}-&amp;gt;get_conf( &amp;quot;htdocs_path&amp;quot; ).$o{uri} );&lt;br /&gt;
                }&lt;br /&gt;
                # and say that we've handled the request - so no more triggers should be run.&lt;br /&gt;
                return EP_TRIGGER_DONE;&lt;br /&gt;
        }&lt;br /&gt;
} );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&amp;diff=13785</id>
		<title>Setting up HTTPS using Let's Encrypt</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&amp;diff=13785"/>
		<updated>2021-05-21T11:12:34Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Manual}}&lt;br /&gt;
By default EPrints does not come setup to use HTTPS.  This is because you need to generate a SSL certificate and if this is not signed by a known Certificate Authority a user's web browser is likely to complain vigorously.  In the past it has typically costed a fair amount of money to obtain a SSL certificate from your hosting provider.  However, now there is [https://letsencrypt.org/ Let's Encrypt] it is possible to get a certificate for free.  This is not to say you should use Let's Encrypt in all cases.  UK academic institutions should continue to obtain their SSL certificates through Jisc and other institutions/organisations may already have similar arrangements for obtaining SSL certificates.&lt;br /&gt;
&lt;br /&gt;
As well as being free, Let's Encrypt has an automated way for renewing certificates.  However, it should be noted that the length of its certificates is a lot shorter at just 3 months.  As the renewal process is automatic, this time period is more appropriate to maximise security.  Let's Encrypt's certificate generation requires your EPrints repository to be publicly accessible.  Beneath are instructions on how to set up EPrints to enable HTTPS with a Let's Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
1. Go to the https://certbot.eff.org/ and follow the instructions for your web server and operating system (the former will almost always be Apache) and follow the instructions provided.&lt;br /&gt;
&lt;br /&gt;
2. When you get to the point of running the certbot command you want the certificate only so should type as the root user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
certbot --apache certonly&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Take a note of the path to were your certificate, key and CA chain have been saved.  This will probably be something like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt; &lt;br /&gt;
/etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. If you have not already done so, create an directory called &amp;lt;tt&amp;gt;ssl&amp;lt;/tt&amp;gt; inside your archive's directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir EPRINTS_PATH/archives/REPOID/ssl/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. Create a file inside the new ssl directory called &amp;lt;tt&amp;gt;securevhost.conf&amp;lt;/tt&amp;gt; and include the following contents, amending the &amp;lt;tt&amp;gt;ServerName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSLCertificateFile&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSLCertificateKeyFile&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;SSLCertificateChainFile&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Include&amp;lt;/tt&amp;gt; as appropriate at least.  You will note that this configuration also enables [https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security HTTP Strict Transport Security (HSTS)] for additional security.  This ensures that after the first time you visit HTTPS for a particular site in your web browser, all future HTTP requests for this hostname will automatically be converted by your browser to HTTPS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;apache&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ServerName YOUR-REPOSITORY-DOMAIN:443&lt;br /&gt;
 &lt;br /&gt;
     # Enable HSTS&lt;br /&gt;
     Header always set Strict-Transport-Security &amp;quot;max-age=63072000;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     SSLEngine on&lt;br /&gt;
     SSLProtocol all -SSLv2 -SSLv3&lt;br /&gt;
     SSLHonorCipherOrder on&lt;br /&gt;
     SSLCipherSuite HIGH:!aNULL:!eNULL:!kECDH:!aDH:!RC4:!3DES:!CAMELLIA:!MD5:!PSK:!SRP:!KRB5:@STRENGTH&lt;br /&gt;
 &lt;br /&gt;
     SSLCertificateFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/cert.pem&lt;br /&gt;
     SSLCertificateKeyFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/privkey.pem&lt;br /&gt;
     SSLCertificateChainFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/chain.pem&lt;br /&gt;
 &lt;br /&gt;
     SetEnvIf User-Agent &amp;quot;.*MSIE.*&amp;quot; \&lt;br /&gt;
         nokeepalive ssl-unclean-shutdown \&lt;br /&gt;
         downgrade-1.0 force-response-1.0&lt;br /&gt;
 &lt;br /&gt;
     LogLevel warn&lt;br /&gt;
     ErrorLog logs/ssl_error_log    &lt;br /&gt;
     TransferLog logs/ssl_access_log&lt;br /&gt;
     CustomLog logs/ssl_request_log \&lt;br /&gt;
         &amp;quot;%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \&amp;quot;%r\&amp;quot; %b&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     Include EPRINTS_PATHH/cfg/apache_ssl/REPOID.conf&lt;br /&gt;
 &lt;br /&gt;
     PerlTransHandler +EPrints::Apache::Rewrite&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
6. If you have not already done so, add a configuration file at &amp;lt;tt&amp;gt;/opt/eprints3/archives/REPOID/cfg/cfg.d/https.pl&amp;lt;/tt&amp;gt; with the following configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
 $c-&amp;gt;{securehost} = $c-&amp;gt;{host};&lt;br /&gt;
 $c-&amp;gt;{secureport} = 443;&lt;br /&gt;
 $c-&amp;gt;{http_root} = undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7. Now you will need to regenerate the rest of your Apache configuration for EPrints with the following command run as the EPrints user. (Substitute the path as appropriate):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
/opt/eprints3/bin/generate_apacheconf --system --replace&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
8. Apache will not yet have been setup to include the Apache configuration file you created in step 5.  To include this, you will need to edit the file in your Apache configuration directory (&amp;lt;tt&amp;gt;/etc/httpd/&amp;lt;/tt&amp;gt; on RHEL/CentOS/Fedora and &amp;lt;tt&amp;gt;/etc/apache2/&amp;lt;/tt&amp;gt; on Debian/Ubuntu) and find the file that contains the line &amp;lt;tt&amp;gt;cfg/apache.conf&amp;lt;/tt&amp;gt;, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /etc/httpd/&lt;br /&gt;
grep -r &amp;quot;cfg/apache.conf&amp;quot; *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
9. Once you have found it you will need to edit it and add the following line, changing the path as appropriate:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;apache&amp;quot;&amp;gt;&lt;br /&gt;
Include EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
10. Now, (as root or using sudo) test that the Apache configuration is correct and fix any issues if necessary:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apachectl configtest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
11. Restart Apache and check whether you can access your EPrints repository using HTTPS in a web browser:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apachectl restart&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
12. If the guide on cerbot.eff.org you used in step 1 tells you to to setup a cron job then follow those instructions.  The easiest way to do this is probably to run &amp;lt;tt&amp;gt;crontab -e&amp;lt;/tt&amp;gt; as root and add the following cron job, substituting the minute (43) and hours (6,18) for you own choice maintaining a 12 hour gap between the hours:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
 43 6,18 * * * certbot renew&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Additional Notes ==&lt;br /&gt;
&lt;br /&gt;
The default EPrints Apache Rewrite handler declines any requests to a URL containing &amp;lt;code&amp;gt;/.&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This means that the challenge/response for a LetsEncrypt certificate renewal that uses the &amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt; path will fail.&lt;br /&gt;
&lt;br /&gt;
To make this work you could add a location block to your Apache config, to ensure the &amp;lt;code&amp;gt;/.well-known/&amp;lt;/code&amp;gt; are not handled by EPrints, or use an EPrints URL rewrite trigger to handle the request:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#this could be saved into e.g. [EPRINTS_ROOT]/lib/cfg.d/z_rewrite_url_LetsEncrypt.pl&lt;br /&gt;
&lt;br /&gt;
# import Apache constant e.g. 'OK'&lt;br /&gt;
use EPrints::Apache::AnApache;&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;add_trigger( EP_TRIGGER_URL_REWRITE, sub {&lt;br /&gt;
        my( %o ) = @_;&lt;br /&gt;
&lt;br /&gt;
        # if the incoming request matches the LetsEncrypt challenge URL...&lt;br /&gt;
        if( $o{uri} =~ m!^${o{urlpath}}/\.well-known/acme-challenge/! )&lt;br /&gt;
        {&lt;br /&gt;
                # and the LetsEncrypt renewal process has put the file in EPRINTS_ROOT/archives/ARCHIVEID/html/.well-known/acme-challenge/&lt;br /&gt;
                if( -f $o{repository}-&amp;gt;get_conf( &amp;quot;htdocs_path&amp;quot; ).$o{uri} )&lt;br /&gt;
                {&lt;br /&gt;
                        # reply with an HTTP '200' &lt;br /&gt;
                        ${$o{return_code}} = OK;&lt;br /&gt;
                        # and return the file reqested&lt;br /&gt;
                        $o{request}-&amp;gt;filename( $o{repository}-&amp;gt;get_conf( &amp;quot;htdocs_path&amp;quot; ).$o{uri} );&lt;br /&gt;
                }&lt;br /&gt;
                # and say that we've handled the request - so no more triggers should be run.&lt;br /&gt;
                return EP_TRIGGER_DONE;&lt;br /&gt;
        }&lt;br /&gt;
} );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&amp;diff=13784</id>
		<title>Setting up HTTPS using Let's Encrypt</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&amp;diff=13784"/>
		<updated>2021-05-21T11:11:27Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Syntax highlighting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Manual}}&lt;br /&gt;
By default EPrints does not come setup to use HTTPS.  This is because you need to generate a SSL certificate and if this is not signed by a known Certificate Authority a user's web browser is likely to complain vigorously.  In the past it has typically costed a fair amount of money to obtain a SSL certificate from your hosting provider.  However, now there is [https://letsencrypt.org/ Let's Encrypt] it is possible to get a certificate for free.  This is not to say you should use Let's Encrypt in all cases.  UK academic institutions should continue to obtain their SSL certificates through Jisc and other institutions/organisations may already have similar arrangements for obtaining SSL certificates.&lt;br /&gt;
&lt;br /&gt;
As well as being free, Let's Encrypt has an automated way for renewing certificates.  However, it should be noted that the length of its certificates is a lot shorter at just 3 months.  As the renewal process is automatic, this time period is more appropriate to maximise security.  Let's Encrypt's certificate generation requires your EPrints repository to be publicly accessible.  Beneath are instructions on how to set up EPrints to enable HTTPS with a Let's Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
1. Go to the https://certbot.eff.org/ and follow the instructions for your web server and operating system (the former will almost always be Apache) and follow the instructions provided.&lt;br /&gt;
&lt;br /&gt;
2. When you get to the point of running the certbot command you want the certificate only so should type as the root user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
certbot --apache certonly&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Take a note of the path to were your certificate, key and CA chain have been saved.  This will probably be something like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt; &lt;br /&gt;
/etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. If you have not already done so, create an directory called &amp;lt;tt&amp;gt;ssl&amp;lt;/tt&amp;gt; inside your archive's directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir EPRINTS_PATH/archives/REPOID/ssl/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. Create a file inside the new ssl directory called &amp;lt;tt&amp;gt;securevhost.conf&amp;lt;/tt&amp;gt; and include the following contents, amending the &amp;lt;tt&amp;gt;ServerName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSLCertificateFile&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSLCertificateKeyFile&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;SSLCertificateChainFile&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Include&amp;lt;/tt&amp;gt; as appropriate at least.  You will note that this configuration also enables [https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security HTTP Strict Transport Security (HSTS)] for additional security.  This ensures that after the first time you visit HTTPS for a particular site in your web browser, all future HTTP requests for this hostname will automatically be converted by your browser to HTTPS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;apache&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ServerName YOUR-REPOSITORY-DOMAIN:443&lt;br /&gt;
 &lt;br /&gt;
     # Enable HSTS&lt;br /&gt;
     Header always set Strict-Transport-Security &amp;quot;max-age=63072000;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     SSLEngine on&lt;br /&gt;
     SSLProtocol all -SSLv2 -SSLv3&lt;br /&gt;
     SSLHonorCipherOrder on&lt;br /&gt;
     SSLCipherSuite HIGH:!aNULL:!eNULL:!kECDH:!aDH:!RC4:!3DES:!CAMELLIA:!MD5:!PSK:!SRP:!KRB5:@STRENGTH&lt;br /&gt;
 &lt;br /&gt;
     SSLCertificateFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/cert.pem&lt;br /&gt;
     SSLCertificateKeyFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/privkey.pem&lt;br /&gt;
     SSLCertificateChainFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/chain.pem&lt;br /&gt;
 &lt;br /&gt;
     SetEnvIf User-Agent &amp;quot;.*MSIE.*&amp;quot; \&lt;br /&gt;
         nokeepalive ssl-unclean-shutdown \&lt;br /&gt;
         downgrade-1.0 force-response-1.0&lt;br /&gt;
 &lt;br /&gt;
     LogLevel warn&lt;br /&gt;
     ErrorLog logs/ssl_error_log    &lt;br /&gt;
     TransferLog logs/ssl_access_log&lt;br /&gt;
     CustomLog logs/ssl_request_log \&lt;br /&gt;
         &amp;quot;%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \&amp;quot;%r\&amp;quot; %b&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     Include EPRINTS_PATHH/cfg/apache_ssl/REPOID.conf&lt;br /&gt;
 &lt;br /&gt;
     PerlTransHandler +EPrints::Apache::Rewrite&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
6. If you have not already done so, add a configuration file at &amp;lt;tt&amp;gt;/opt/eprints3/archives/REPOID/cfg/cfg.d/https.pl&amp;lt;/tt&amp;gt; with the following configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
 $c-&amp;gt;{securehost} = $c-&amp;gt;{host};&lt;br /&gt;
 $c-&amp;gt;{secureport} = 443;&lt;br /&gt;
 $c-&amp;gt;{http_root} = undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7. Now you will need to regenerate the rest of your Apache configuration for EPrints with the following command run as the EPrints user. (Substitute the path as appropriate):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
/opt/eprints3/bin/generate_apacheconf --system --replace&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
8. Apache will not yet have been setup to include the Apache configuration file you created in step 5.  To include this, you will need to edit the file in your Apache configuration directory (&amp;lt;tt&amp;gt;/etc/httpd/&amp;lt;/tt&amp;gt; on RHEL/CentOS/Fedora and &amp;lt;tt&amp;gt;/etc/apache2/&amp;lt;/tt&amp;gt; on Debian/Ubuntu) and find the file that contains the line &amp;lt;tt&amp;gt;cfg/apache.conf&amp;lt;/tt&amp;gt;, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /etc/httpd/&lt;br /&gt;
grep -r &amp;quot;cfg/apache.conf&amp;quot; *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
9. Once you have found it you will need to edit it and add the following line, changing the path as appropriate:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;apache&amp;quot;&amp;gt;&lt;br /&gt;
Include EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
10. Now, (as root or using sudo) test that the Apache configuration is correct and fix any issues if necessary:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apachectl configtest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
11. Restart Apache and check whether you can access your EPrints repository using HTTPS in a web browser:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apachectl restart&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
12. If the guide on cerbot.eff.org you used in step 1 tells you to to setup a cron job then follow those instructions.  The easiest way to do this is probably to run &amp;lt;tt&amp;gt;crontab -e&amp;lt;/tt&amp;gt; as root and add the following cron job, substituting the minute (43) and hours (6,18) for you own choice maintaining a 12 hour gap between the hours:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cron&amp;quot;&amp;gt;&lt;br /&gt;
 43 6,18 * * * certbot renew&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Additional Notes ==&lt;br /&gt;
&lt;br /&gt;
The default EPrints Apache Rewrite handler declines any requests to a URL containing &amp;lt;code&amp;gt;/.&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This means that the challenge/response for a LetsEncrypt certificate renewal that uses the &amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt; path will fail.&lt;br /&gt;
&lt;br /&gt;
To make this work you could add a location block to your Apache config, to ensure the &amp;lt;code&amp;gt;/.well-known/&amp;lt;/code&amp;gt; are not handled by EPrints, or use an EPrints URL rewrite trigger to handle the request:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#this could be saved into e.g. [EPRINTS_ROOT]/lib/cfg.d/z_rewrite_url_LetsEncrypt.pl&lt;br /&gt;
&lt;br /&gt;
# import Apache constant e.g. 'OK'&lt;br /&gt;
use EPrints::Apache::AnApache;&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;add_trigger( EP_TRIGGER_URL_REWRITE, sub {&lt;br /&gt;
        my( %o ) = @_;&lt;br /&gt;
&lt;br /&gt;
        # if the incoming request matches the LetsEncrypt challenge URL...&lt;br /&gt;
        if( $o{uri} =~ m!^${o{urlpath}}/\.well-known/acme-challenge/! )&lt;br /&gt;
        {&lt;br /&gt;
                # and the LetsEncrypt renewal process has put the file in EPRINTS_ROOT/archives/ARCHIVEID/html/.well-known/acme-challenge/&lt;br /&gt;
                if( -f $o{repository}-&amp;gt;get_conf( &amp;quot;htdocs_path&amp;quot; ).$o{uri} )&lt;br /&gt;
                {&lt;br /&gt;
                        # reply with an HTTP '200' &lt;br /&gt;
                        ${$o{return_code}} = OK;&lt;br /&gt;
                        # and return the file reqested&lt;br /&gt;
                        $o{request}-&amp;gt;filename( $o{repository}-&amp;gt;get_conf( &amp;quot;htdocs_path&amp;quot; ).$o{uri} );&lt;br /&gt;
                }&lt;br /&gt;
                # and say that we've handled the request - so no more triggers should be run.&lt;br /&gt;
                return EP_TRIGGER_DONE;&lt;br /&gt;
        }&lt;br /&gt;
} );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=HTTPS-only_and_HSTS&amp;diff=13783</id>
		<title>HTTPS-only and HSTS</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=HTTPS-only_and_HSTS&amp;diff=13783"/>
		<updated>2021-05-21T11:06:32Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Add the HSTS header */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{manual}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Authentication]]&lt;br /&gt;
&lt;br /&gt;
== HTTPS with EPrints ==&lt;br /&gt;
&lt;br /&gt;
See the pages in [[:Category:Authentication|Category Authentication]] for how to setup up HTTPS on EPrints, for example:&lt;br /&gt;
&lt;br /&gt;
*[[How_to_use_EPrints_with_HTTPS|How to use EPrints with HTTPS]]&lt;br /&gt;
*[[Setting_up_HTTPS_using_Let%27s_Encrypt|Setting up HTTPS using Let's Encrypt]]&lt;br /&gt;
&lt;br /&gt;
The following is a description of how to configure EPrints so that all content, not just login pages, is served over HTTPS.&lt;br /&gt;
&lt;br /&gt;
== Google Best Practices for HTTPS==&lt;br /&gt;
&lt;br /&gt;
The following are the best practices specified by [https://support.google.com/webmasters/answer/6073543?hl=en&amp;amp;ref_topic=6001951 Google]&lt;br /&gt;
&lt;br /&gt;
* HSTS Headers on HTTPS&lt;br /&gt;
* No “Mixed Content” warnings/errors&lt;br /&gt;
* Links point to HTTPS locations&lt;br /&gt;
* 301 Redirects from HTTP to HTTPS&lt;br /&gt;
&lt;br /&gt;
== HSTS ==&lt;br /&gt;
&lt;br /&gt;
To summarize how HSTS works, if a browser (Chrome, Firefix, IE) sees the HSTS header in the HTTPS response, and there are no certificate errors or mixed content warnings or anything (if it is green), then the next time a user of that browser requests the HTTP page of that site, the browser will modify the request from an HTTP to a HTTPS request.   The browser will remember that setting for as long as you specify &amp;lt;tt&amp;gt;max-age&amp;lt;/tt&amp;gt; to be.  This means that even with HSTS, it is still possible to request and receive content over HTTP.  To close that down, a server redirect is necessary, so those browsers that haven’t seen the HSTS header in the past that happen to try to go to HTTP will get that initial redirect to HTTPS.&lt;br /&gt;
&lt;br /&gt;
== Implementing HTTPS-only with HSTS on an EPrints repository ==&lt;br /&gt;
&lt;br /&gt;
=== Changes to archive's cfg.d/10_core.pl ===&lt;br /&gt;
&lt;br /&gt;
Initialize the following variables to be the https URL (i.e., https://&amp;lt;nowiki&amp;gt;YOUR-REPOSITORY-DOMAIN&amp;lt;/nowiki&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
 $c-&amp;gt;{host} = &amp;quot;YOUR-REPOSITORY-DOMAIN&amp;quot;; &lt;br /&gt;
 $c-&amp;gt;{http_url} = 'https://YOUR-REPOSITORY-DOMAIN';&lt;br /&gt;
 $c-&amp;gt;{http_cgiurl} = 'https://YOUR-REPOSITORY-DOMAIN/cgi';&lt;br /&gt;
 $c-&amp;gt;{base_url} = &amp;quot;https://$c-&amp;gt;{host}&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changes to archive's &amp;lt;tt&amp;gt;cfg/lang/LANGID/templates/default.xml&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;/cfg/lang/LANGID/static/*.XPAGE&amp;lt;/tt&amp;gt; files ===&lt;br /&gt;
&lt;br /&gt;
* Remove any hard coded links to HTTP&lt;br /&gt;
* If you have Google Search included as an XPAGE file, call on the Google API (and any other APIs) using HTTPS.&lt;br /&gt;
&lt;br /&gt;
=== Changes to Apache config files ===&lt;br /&gt;
&lt;br /&gt;
==== Add the HSTS header ====&lt;br /&gt;
&lt;br /&gt;
Edit [[Template:Securevhost.conf|EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf]] and add the following HSTS header after ther &amp;lt;tt&amp;gt;ServerName&amp;lt;/tt&amp;gt; line.  The max-age variable is a time in seconds for how long the HSTS settings should be remembered by the browser.  15780000 is six months, which is a long time, you may want to set it to a shorter time while testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;apache&amp;quot;&amp;gt;&lt;br /&gt;
 Header set Strict-Transport-Security &amp;quot;max-age=15780000&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Include this file from the core apache conf file for the secure port (443) in &amp;lt;tt&amp;gt;/etc/&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Add 301 redirects to secure port from HTTP (port 80) ====&lt;br /&gt;
&lt;br /&gt;
By making the above changes to the archive's &amp;lt;tt&amp;gt;cfg.d/10_core.pl&amp;lt;/tt&amp;gt;, if you use [https://github.com/eprints/eprints/commit/c29574dbdcd49c67f3aea522998960f2eb19f544 this patch] or are running [https://github.com/eprints/eprints the latest revision of EPrints on GitHub], &amp;lt;tt&amp;gt;/bin/generate_apacheconf&amp;lt;/tt&amp;gt; will generate an &amp;lt;tt&amp;gt;/cfg/apache/REPOID.conf&amp;lt;/tt&amp;gt;, which automatically redirects HTTP to HTTPS.  Otherwise, this can be achieved by modifying &amp;lt;tt&amp;gt;/cfg/apache/REPOID.conf&amp;lt;/tt&amp;gt; to the following, substituting your domain as appropriate:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
RedirectPermanent / https://YOUR-REPOSITORY-DOMAIN/  &lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=HTTPS-only_and_HSTS&amp;diff=13782</id>
		<title>HTTPS-only and HSTS</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=HTTPS-only_and_HSTS&amp;diff=13782"/>
		<updated>2021-05-21T11:04:32Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Changes to archive's cfg/lang/LANGID/templates/default.xml, and /cfg/lang/LANGID/static/*.XPAGE files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{manual}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Authentication]]&lt;br /&gt;
&lt;br /&gt;
== HTTPS with EPrints ==&lt;br /&gt;
&lt;br /&gt;
See the pages in [[:Category:Authentication|Category Authentication]] for how to setup up HTTPS on EPrints, for example:&lt;br /&gt;
&lt;br /&gt;
*[[How_to_use_EPrints_with_HTTPS|How to use EPrints with HTTPS]]&lt;br /&gt;
*[[Setting_up_HTTPS_using_Let%27s_Encrypt|Setting up HTTPS using Let's Encrypt]]&lt;br /&gt;
&lt;br /&gt;
The following is a description of how to configure EPrints so that all content, not just login pages, is served over HTTPS.&lt;br /&gt;
&lt;br /&gt;
== Google Best Practices for HTTPS==&lt;br /&gt;
&lt;br /&gt;
The following are the best practices specified by [https://support.google.com/webmasters/answer/6073543?hl=en&amp;amp;ref_topic=6001951 Google]&lt;br /&gt;
&lt;br /&gt;
* HSTS Headers on HTTPS&lt;br /&gt;
* No “Mixed Content” warnings/errors&lt;br /&gt;
* Links point to HTTPS locations&lt;br /&gt;
* 301 Redirects from HTTP to HTTPS&lt;br /&gt;
&lt;br /&gt;
== HSTS ==&lt;br /&gt;
&lt;br /&gt;
To summarize how HSTS works, if a browser (Chrome, Firefix, IE) sees the HSTS header in the HTTPS response, and there are no certificate errors or mixed content warnings or anything (if it is green), then the next time a user of that browser requests the HTTP page of that site, the browser will modify the request from an HTTP to a HTTPS request.   The browser will remember that setting for as long as you specify &amp;lt;tt&amp;gt;max-age&amp;lt;/tt&amp;gt; to be.  This means that even with HSTS, it is still possible to request and receive content over HTTP.  To close that down, a server redirect is necessary, so those browsers that haven’t seen the HSTS header in the past that happen to try to go to HTTP will get that initial redirect to HTTPS.&lt;br /&gt;
&lt;br /&gt;
== Implementing HTTPS-only with HSTS on an EPrints repository ==&lt;br /&gt;
&lt;br /&gt;
=== Changes to archive's cfg.d/10_core.pl ===&lt;br /&gt;
&lt;br /&gt;
Initialize the following variables to be the https URL (i.e., https://&amp;lt;nowiki&amp;gt;YOUR-REPOSITORY-DOMAIN&amp;lt;/nowiki&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
 $c-&amp;gt;{host} = &amp;quot;YOUR-REPOSITORY-DOMAIN&amp;quot;; &lt;br /&gt;
 $c-&amp;gt;{http_url} = 'https://YOUR-REPOSITORY-DOMAIN';&lt;br /&gt;
 $c-&amp;gt;{http_cgiurl} = 'https://YOUR-REPOSITORY-DOMAIN/cgi';&lt;br /&gt;
 $c-&amp;gt;{base_url} = &amp;quot;https://$c-&amp;gt;{host}&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changes to archive's &amp;lt;tt&amp;gt;cfg/lang/LANGID/templates/default.xml&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;/cfg/lang/LANGID/static/*.XPAGE&amp;lt;/tt&amp;gt; files ===&lt;br /&gt;
&lt;br /&gt;
* Remove any hard coded links to HTTP&lt;br /&gt;
* If you have Google Search included as an XPAGE file, call on the Google API (and any other APIs) using HTTPS.&lt;br /&gt;
&lt;br /&gt;
=== Changes to Apache config files ===&lt;br /&gt;
&lt;br /&gt;
==== Add the HSTS header ====&lt;br /&gt;
&lt;br /&gt;
Edit [[Template:Securevhost.conf|EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf]] and add the following HSTS header after ther &amp;lt;tt&amp;gt;ServerName&amp;lt;/tt&amp;gt; line.  The max-age variable is a time in seconds for how long the HSTS settings should be remembered by the browser.  15780000 is six months, which is a long time, you may want to set it to a shorter time while testing.&lt;br /&gt;
&lt;br /&gt;
 Header set Strict-Transport-Security &amp;quot;max-age=15780000&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Include this file from the core apache conf file for the secure port (443) in &amp;lt;tt&amp;gt;/etc/&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Add 301 redirects to secure port from HTTP (port 80) ====&lt;br /&gt;
&lt;br /&gt;
By making the above changes to the archive's &amp;lt;tt&amp;gt;cfg.d/10_core.pl&amp;lt;/tt&amp;gt;, if you use [https://github.com/eprints/eprints/commit/c29574dbdcd49c67f3aea522998960f2eb19f544 this patch] or are running [https://github.com/eprints/eprints the latest revision of EPrints on GitHub], &amp;lt;tt&amp;gt;/bin/generate_apacheconf&amp;lt;/tt&amp;gt; will generate an &amp;lt;tt&amp;gt;/cfg/apache/REPOID.conf&amp;lt;/tt&amp;gt;, which automatically redirects HTTP to HTTPS.  Otherwise, this can be achieved by modifying &amp;lt;tt&amp;gt;/cfg/apache/REPOID.conf&amp;lt;/tt&amp;gt; to the following, substituting your domain as appropriate:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
RedirectPermanent / https://YOUR-REPOSITORY-DOMAIN/  &lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=HTTPS-only_and_HSTS&amp;diff=13781</id>
		<title>HTTPS-only and HSTS</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=HTTPS-only_and_HSTS&amp;diff=13781"/>
		<updated>2021-05-21T11:04:07Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Changes to archive's cfg/lang/LANGID/templates/default.xml, and /cfg/lang/LANGID/static/*.XPAGE files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{manual}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Authentication]]&lt;br /&gt;
&lt;br /&gt;
== HTTPS with EPrints ==&lt;br /&gt;
&lt;br /&gt;
See the pages in [[:Category:Authentication|Category Authentication]] for how to setup up HTTPS on EPrints, for example:&lt;br /&gt;
&lt;br /&gt;
*[[How_to_use_EPrints_with_HTTPS|How to use EPrints with HTTPS]]&lt;br /&gt;
*[[Setting_up_HTTPS_using_Let%27s_Encrypt|Setting up HTTPS using Let's Encrypt]]&lt;br /&gt;
&lt;br /&gt;
The following is a description of how to configure EPrints so that all content, not just login pages, is served over HTTPS.&lt;br /&gt;
&lt;br /&gt;
== Google Best Practices for HTTPS==&lt;br /&gt;
&lt;br /&gt;
The following are the best practices specified by [https://support.google.com/webmasters/answer/6073543?hl=en&amp;amp;ref_topic=6001951 Google]&lt;br /&gt;
&lt;br /&gt;
* HSTS Headers on HTTPS&lt;br /&gt;
* No “Mixed Content” warnings/errors&lt;br /&gt;
* Links point to HTTPS locations&lt;br /&gt;
* 301 Redirects from HTTP to HTTPS&lt;br /&gt;
&lt;br /&gt;
== HSTS ==&lt;br /&gt;
&lt;br /&gt;
To summarize how HSTS works, if a browser (Chrome, Firefix, IE) sees the HSTS header in the HTTPS response, and there are no certificate errors or mixed content warnings or anything (if it is green), then the next time a user of that browser requests the HTTP page of that site, the browser will modify the request from an HTTP to a HTTPS request.   The browser will remember that setting for as long as you specify &amp;lt;tt&amp;gt;max-age&amp;lt;/tt&amp;gt; to be.  This means that even with HSTS, it is still possible to request and receive content over HTTP.  To close that down, a server redirect is necessary, so those browsers that haven’t seen the HSTS header in the past that happen to try to go to HTTP will get that initial redirect to HTTPS.&lt;br /&gt;
&lt;br /&gt;
== Implementing HTTPS-only with HSTS on an EPrints repository ==&lt;br /&gt;
&lt;br /&gt;
=== Changes to archive's cfg.d/10_core.pl ===&lt;br /&gt;
&lt;br /&gt;
Initialize the following variables to be the https URL (i.e., https://&amp;lt;nowiki&amp;gt;YOUR-REPOSITORY-DOMAIN&amp;lt;/nowiki&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
 $c-&amp;gt;{host} = &amp;quot;YOUR-REPOSITORY-DOMAIN&amp;quot;; &lt;br /&gt;
 $c-&amp;gt;{http_url} = 'https://YOUR-REPOSITORY-DOMAIN';&lt;br /&gt;
 $c-&amp;gt;{http_cgiurl} = 'https://YOUR-REPOSITORY-DOMAIN/cgi';&lt;br /&gt;
 $c-&amp;gt;{base_url} = &amp;quot;https://$c-&amp;gt;{host}&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changes to archive's &amp;lt;tt&amp;gt;cfg/lang/LANGID/templates/default.xml&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;/cfg/lang/LANGID/static/*.XPAGE&amp;lt;/tt&amp;gt; files ===&lt;br /&gt;
&lt;br /&gt;
Remove any hard coded links to HTTP&lt;br /&gt;
If you have Google Search included as an XPAGE file,&lt;br /&gt;
call on the Google API (and any other APIs) using HTTPS.&lt;br /&gt;
&lt;br /&gt;
=== Changes to Apache config files ===&lt;br /&gt;
&lt;br /&gt;
==== Add the HSTS header ====&lt;br /&gt;
&lt;br /&gt;
Edit [[Template:Securevhost.conf|EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf]] and add the following HSTS header after ther &amp;lt;tt&amp;gt;ServerName&amp;lt;/tt&amp;gt; line.  The max-age variable is a time in seconds for how long the HSTS settings should be remembered by the browser.  15780000 is six months, which is a long time, you may want to set it to a shorter time while testing.&lt;br /&gt;
&lt;br /&gt;
 Header set Strict-Transport-Security &amp;quot;max-age=15780000&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Include this file from the core apache conf file for the secure port (443) in &amp;lt;tt&amp;gt;/etc/&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Add 301 redirects to secure port from HTTP (port 80) ====&lt;br /&gt;
&lt;br /&gt;
By making the above changes to the archive's &amp;lt;tt&amp;gt;cfg.d/10_core.pl&amp;lt;/tt&amp;gt;, if you use [https://github.com/eprints/eprints/commit/c29574dbdcd49c67f3aea522998960f2eb19f544 this patch] or are running [https://github.com/eprints/eprints the latest revision of EPrints on GitHub], &amp;lt;tt&amp;gt;/bin/generate_apacheconf&amp;lt;/tt&amp;gt; will generate an &amp;lt;tt&amp;gt;/cfg/apache/REPOID.conf&amp;lt;/tt&amp;gt;, which automatically redirects HTTP to HTTPS.  Otherwise, this can be achieved by modifying &amp;lt;tt&amp;gt;/cfg/apache/REPOID.conf&amp;lt;/tt&amp;gt; to the following, substituting your domain as appropriate:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
RedirectPermanent / https://YOUR-REPOSITORY-DOMAIN/  &lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=How_to_customise_thumbnails&amp;diff=13780</id>
		<title>How to customise thumbnails</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=How_to_customise_thumbnails&amp;diff=13780"/>
		<updated>2021-05-21T11:02:08Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Based on EPrints-3.3.10.&lt;br /&gt;
&lt;br /&gt;
To customise the size and type of thumbnails generated by eprints you can create archive-based configuration.&lt;br /&gt;
The steps below show how to add a new thumbnail size, and render it the way *I* want it.&lt;br /&gt;
&lt;br /&gt;
The default thumbnails are generated by: &amp;lt;code&amp;gt;~/perl_lib/EPrints/Plugin/Convert/Thumbnails.pm&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I wanted to add a new size 160x90px, called 'homepage' (to fit in with the institution's branding).&lt;br /&gt;
To make your own set of thumbnail sizes, edit &amp;lt;code&amp;gt;~/archives/ARCHIVEID/cfg/cfg.d/plugins.pl&amp;lt;/code&amp;gt;.&lt;br /&gt;
I added the following to the file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$c-&amp;gt;{plugins}-&amp;gt;{'Convert::Thumbnails'}-&amp;gt;{params}-&amp;gt;{sizes} = {(&lt;br /&gt;
        small =&amp;gt; [66,50],&lt;br /&gt;
        homepage =&amp;gt; [160, 90], # new size - others are copied from Thumbnails.pm&lt;br /&gt;
        medium =&amp;gt; [200,150],&lt;br /&gt;
        preview =&amp;gt; [400,300],&lt;br /&gt;
        lightbox =&amp;gt; [640,480],&lt;br /&gt;
)};&lt;br /&gt;
$c-&amp;gt;{thumbnail_types} = sub {&lt;br /&gt;
        my( $list, $repo, $doc ) = @_;&lt;br /&gt;
        push @$list, qw( homepage ); # add new size to list of files to be generated&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default this will produce a thumbnail that will fit into a box 160x90px - a proportionally scaled down version of the original. The 'small' thumbnail size produces a cropped version of the original. This is a better option for my needs, but it has a grey 1px border around it - that I don't want.&lt;br /&gt;
&lt;br /&gt;
To alter the thumbnails I need to add the following to &amp;lt;code&amp;gt;~/archives/ARCHIVEID/cfg/cfg.d/plugins.pl&amp;lt;/code&amp;gt; - which is a slightly modified version of the &amp;lt;code&amp;gt;sub call_convert&amp;lt;/code&amp;gt; copied from Thumbnails.pl&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$c-&amp;gt;{plugins}-&amp;gt;{'Convert::Thumbnails'}-&amp;gt;{params}-&amp;gt;{call_convert} = sub {&lt;br /&gt;
	my( $self, $dir, $doc, $src, $geom, $size ) = @_;&lt;br /&gt;
&lt;br /&gt;
	my $convert = $self-&amp;gt;{'convert'};&lt;br /&gt;
	my $version = $self-&amp;gt;convert_version;&lt;br /&gt;
&lt;br /&gt;
	if (!defined($geom)) {&lt;br /&gt;
		EPrints::abort(&amp;quot;NO GEOM&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	my $fn = $size . &amp;quot;.jpg&amp;quot;;&lt;br /&gt;
	my $dst = &amp;quot;$dir/$fn&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	$geom = &amp;quot;$geom-&amp;gt;[0]x$geom-&amp;gt;[1]&amp;quot;;&lt;br /&gt;
# JPEG&lt;br /&gt;
# Read this: http://www.imagemagick.org/script/command-line-processing.php#geometry&lt;br /&gt;
# for details of the convert geom options.&lt;br /&gt;
#&lt;br /&gt;
	if( $size eq &amp;quot;small&amp;quot; )&lt;br /&gt;
	{&lt;br /&gt;
		# attempt to create a thumbnail that fits within the given dimensions&lt;br /&gt;
		# geom^ requires 6.3.8&lt;br /&gt;
		if( $version &amp;gt; 6.3 )&lt;br /&gt;
		{&lt;br /&gt;
			$self-&amp;gt;_system($convert, &amp;quot;-strip&amp;quot;, &amp;quot;-colorspace&amp;quot;, &amp;quot;RGB&amp;quot;, &amp;quot;-background&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-thumbnail&amp;quot;,&amp;quot;$geom^&amp;quot;, &amp;quot;-gravity&amp;quot;, &amp;quot;center&amp;quot;, &amp;quot;-extent&amp;quot;, $geom, &amp;quot;-bordercolor&amp;quot;, &amp;quot;gray&amp;quot;, &amp;quot;-border&amp;quot;, &amp;quot;1x1&amp;quot;, $src.&amp;quot;[0]&amp;quot;, &amp;quot;JPEG:$dst&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
		else&lt;br /&gt;
		{&lt;br /&gt;
			$self-&amp;gt;_system($convert, &amp;quot;-strip&amp;quot;, &amp;quot;-colorspace&amp;quot;, &amp;quot;RGB&amp;quot;, &amp;quot;-background&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-thumbnail&amp;quot;,&amp;quot;$geom&amp;gt;&amp;quot;, &amp;quot;-extract&amp;quot;, $geom, &amp;quot;-bordercolor&amp;quot;, &amp;quot;gray&amp;quot;, &amp;quot;-border&amp;quot;, &amp;quot;1x1&amp;quot;, $src.&amp;quot;[0]&amp;quot;, &amp;quot;JPEG:$dst&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	elsif( $size eq &amp;quot;homepage&amp;quot; ) # This is the new section to deal with the new 'homepage' size&lt;br /&gt;
	{&lt;br /&gt;
		# attempt to create a thumbnail that fits within the given dimensions&lt;br /&gt;
		# geom^ requires 6.3.8&lt;br /&gt;
		if( $version &amp;gt; 6.3 )&lt;br /&gt;
		{&lt;br /&gt;
			# homepage thumbnails don't want a border on them!&lt;br /&gt;
			$self-&amp;gt;_system($convert, &amp;quot;-strip&amp;quot;, &amp;quot;-colorspace&amp;quot;, &amp;quot;RGB&amp;quot;, &amp;quot;-background&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-thumbnail&amp;quot;,&amp;quot;$geom^&amp;quot;, &amp;quot;-gravity&amp;quot;, &amp;quot;center&amp;quot;, &amp;quot;-extent&amp;quot;, $geom, &amp;quot;-bordercolor&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-border&amp;quot;, &amp;quot;0x0&amp;quot;, $src.&amp;quot;[0]&amp;quot;, &amp;quot;JPEG:$dst&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
		else&lt;br /&gt;
		{&lt;br /&gt;
			# homepage thumbnails don't want a border on them!&lt;br /&gt;
			$self-&amp;gt;_system($convert, &amp;quot;-strip&amp;quot;, &amp;quot;-colorspace&amp;quot;, &amp;quot;RGB&amp;quot;, &amp;quot;-background&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-thumbnail&amp;quot;,&amp;quot;$geom&amp;gt;&amp;quot;, &amp;quot;-extract&amp;quot;, $geom, &amp;quot;-bordercolor&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-border&amp;quot;, &amp;quot;0x0&amp;quot;, $src.&amp;quot;[0]&amp;quot;, &amp;quot;JPEG:$dst&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	elsif( $size eq &amp;quot;medium&amp;quot; )&lt;br /&gt;
	{&lt;br /&gt;
		$self-&amp;gt;_system($convert, &amp;quot;-strip&amp;quot;, &amp;quot;-colorspace&amp;quot;, &amp;quot;RGB&amp;quot;, &amp;quot;-trim&amp;quot;, &amp;quot;+repage&amp;quot;, &amp;quot;-size&amp;quot;, &amp;quot;$geom&amp;quot;, &amp;quot;-thumbnail&amp;quot;,&amp;quot;$geom&amp;gt;&amp;quot;, &amp;quot;-background&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-gravity&amp;quot;, &amp;quot;center&amp;quot;, &amp;quot;-extent&amp;quot;, $geom, &amp;quot;-bordercolor&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-border&amp;quot;, &amp;quot;0x0&amp;quot;, $src.&amp;quot;[0]&amp;quot;, &amp;quot;JPEG:$dst&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		$self-&amp;gt;_system($convert, &amp;quot;-strip&amp;quot;, &amp;quot;-colorspace&amp;quot;, &amp;quot;RGB&amp;quot;, &amp;quot;-background&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-thumbnail&amp;quot;,&amp;quot;$geom&amp;gt;&amp;quot;, &amp;quot;-extract&amp;quot;, $geom, &amp;quot;-bordercolor&amp;quot;, &amp;quot;white&amp;quot;, &amp;quot;-border&amp;quot;, &amp;quot;0x0&amp;quot;, $src.&amp;quot;[0]&amp;quot;, &amp;quot;JPEG:$dst&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if( -s $dst )&lt;br /&gt;
	{&lt;br /&gt;
		return ($fn);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return ();&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To test the new thumbnail generation, find an eprint with some good images attached to it. In the example below I'll use '1234', and assume the original image is called 'file.jpg' and is the first document in the eprint (this only matters for the URL to view the image in the browser with).&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;code&amp;gt;~/bin/epadmin redo_thumbnails ARCHIVEID 1234 --verbose&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should see the convert command being run - and the new size filename being created e.g.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Starting EPrints Repository.&lt;br /&gt;
Connecting to DB ... done.&lt;br /&gt;
Redoing thumbnails for document 1234&lt;br /&gt;
/usr/bin/convert -strip -colorspace RGB -background white -thumbnail 160x90^ -gravity center -extent 160x90 -bordercolor white -border 0x0 /opt/eprints3/archives/digitallibrary/documents/disk0/00/00/12/34/01/file.jpg[0] JPEG:/tmp/_NyUoqmsuZ/homepage.jpg&lt;br /&gt;
/usr/bin/convert ... JPEG:/tmp/XR51ieKBCj/lightbox.jpg&lt;br /&gt;
/usr/bin/convert ... JPEG:/tmp/fCOP2BPoa2/preview.jpg&lt;br /&gt;
/usr/bin/convert ... JPEG:/tmp/zLEip1ewUq/medium.jpg&lt;br /&gt;
/usr/bin/convert ... JPEG:/tmp/weRJwQPgNT/small.jpg&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NB The lines for lightbox, preview, medium and small.jpg have been truncated for clarity.&lt;br /&gt;
&lt;br /&gt;
You should now be able to view the new thumbnails in a browser: &lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://your.repo.url/1234/1.hashomepageThumbnailVersion/file.jpg&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&amp;diff=13778</id>
		<title>How to display specific contributors</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&amp;diff=13778"/>
		<updated>2021-05-21T10:07:41Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Method 2 - EPScript logic - foreach */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Based on this question, asked on the Tech list:&lt;br /&gt;
''How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?''&lt;br /&gt;
&lt;br /&gt;
'''Note:''' The question on the tech list specified EPrints 3.4.2. The below is based on 3.3.16, but may be useful as a starting point.&lt;br /&gt;
&lt;br /&gt;
Below are three approaches that may do what you need.&lt;br /&gt;
&lt;br /&gt;
== Method 1 - EPScript function ==&lt;br /&gt;
1) In EPScript, there is an undocumented function - &amp;lt;code&amp;gt;filter_compound_list&amp;lt;/code&amp;gt; which accepts:&lt;br /&gt;
* a field (''contributors'')&lt;br /&gt;
* a sub-field name to filter on (''type'')&lt;br /&gt;
* a value to filter to (''http://www.loc.gov/loc.terms/relators/THS'') &lt;br /&gt;
* the field to return (''name'')&lt;br /&gt;
&lt;br /&gt;
This can produce a text-string of one field from the compound field. If a thesis had two supervisors, the following example would produce:&lt;br /&gt;
&lt;br /&gt;
''Smith, John and Bond, James''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:if test=&amp;quot;contributors&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;epc:print expr=&amp;quot;filter_compound_list(contributors,'type','http://www.loc.gov/loc.terms/relators/THS','name')&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Method 2 - EPScript logic - ''foreach'' ==&lt;br /&gt;
&lt;br /&gt;
This method is a bit more flexible, but you have to construct the values from the parts manually. It does allow you to reference the &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; sub-field if required.&lt;br /&gt;
It also may leave empty wrapping elements in the output (e.g. the &amp;lt;code&amp;gt;ul&amp;lt;/code&amp;gt; in the example below if there are contributors, but none are the required type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;epc:if test=&amp;quot;contributors&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;epc:foreach expr=&amp;quot;contributors&amp;quot; iterator=&amp;quot;contr&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;epc:if test=&amp;quot;$contr{type}='http://www.loc.gov/loc.terms/relators/THS'&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;li&amp;gt;&lt;br /&gt;
          &amp;lt;epc:print expr=&amp;quot;$contr{name}{given}&amp;quot; /&amp;gt; &amp;lt;epc:print expr=&amp;quot;$contr{name}{family}&amp;quot; /&amp;gt;&lt;br /&gt;
          &amp;lt;epc:if test=&amp;quot;$contr{id}&amp;quot;&amp;gt;(&amp;lt;epc:print expr=&amp;quot;$contr{id}&amp;quot;/&amp;gt;)&amp;lt;/epc:if&amp;gt;&lt;br /&gt;
        &amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
    &amp;lt;/epc:foreach&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Method 3 - Custom EPScript function ==&lt;br /&gt;
This is the most complex, but also offers the most flexibility - if you're able to understand the &amp;lt;code&amp;gt;EPrints::Script::Compiled&amp;lt;/code&amp;gt; module and write your own functions.&lt;br /&gt;
&lt;br /&gt;
There are two parts - adding custom methods to EPScript, and calling them from the citation file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; line&amp;gt;&lt;br /&gt;
### This should be added to a file e.g. EPRINTS_ROOT/archives/ARCHIVEID/cfg/cfg.d/z_epscript_additions.pl&lt;br /&gt;
&lt;br /&gt;
# Open block&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
# Write into EPrints::Script::Compiled&lt;br /&gt;
package EPrints::Script::Compiled;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
# Example usage in citation file:&lt;br /&gt;
#&lt;br /&gt;
#  &amp;lt;epc:if test=&amp;quot;$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS',1)&amp;quot;&amp;gt;&lt;br /&gt;
#    &amp;lt;h2&amp;gt;&amp;lt;epc:phrase ref=&amp;quot;contributor_type_typename_http://www.loc.gov/loc.terms/relators/THS&amp;quot;/&amp;gt;&amp;lt;/h2&amp;gt;&lt;br /&gt;
#    &amp;lt;epc:print expr=&amp;quot;$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS')&amp;quot;/&amp;gt;&lt;br /&gt;
#  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# The first call includes the 'test' parameter, which can be used to determine whether surrounding&lt;br /&gt;
# elements need to be displayed - in the above example the &amp;lt;h2&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
sub run_render_contributors_filtered&lt;br /&gt;
{&lt;br /&gt;
        my( $self, $state, $eprint, $contributor_type, $test ) = @_;&lt;br /&gt;
&lt;br /&gt;
        if( !defined $eprint-&amp;gt;[0] || ref($eprint-&amp;gt;[0]) ne &amp;quot;EPrints::DataObj::EPrint&amp;quot; )&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;runtime_error( &amp;quot;Can only call render_contributors_filtered() on eprint objects not &amp;quot;.&lt;br /&gt;
                        ref($eprint-&amp;gt;[0]) );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if( !defined $contributor_type )&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;runtime_error( &amp;quot;You need to specify a contributor type you want to render.&amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my @filtered_contributors = grep{ defined $_-&amp;gt;{type} &amp;amp;&amp;amp; $_-&amp;gt;{type} eq $contributor_type-&amp;gt;[0] } @{ $eprint-&amp;gt;[0]-&amp;gt;value( &amp;quot;contributors&amp;quot; ) };&lt;br /&gt;
&lt;br /&gt;
        if( $test )&lt;br /&gt;
        {&lt;br /&gt;
                return [ 0, &amp;quot;BOOLEAN&amp;quot; ] if( scalar @filtered_contributors &amp;lt; 1 );&lt;br /&gt;
                return [ 1, &amp;quot;BOOLEAN&amp;quot; ];&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # NB this is based on EPrints::Extras::render_related_url&lt;br /&gt;
        # It is over-complicated for this use-case, as we could just use&lt;br /&gt;
        # $state-&amp;gt;{session}-&amp;gt;render_name( $row-&amp;gt;{name} )&lt;br /&gt;
        # but if other compound fields are being used with similar code&lt;br /&gt;
        # being able to get to the 'render_value' for the sub fields is useful.&lt;br /&gt;
&lt;br /&gt;
        my $field = $eprint-&amp;gt;[0]-&amp;gt;dataset-&amp;gt;field( &amp;quot;contributors&amp;quot; );&lt;br /&gt;
        my $f = $field-&amp;gt;get_property( &amp;quot;fields_cache&amp;quot; );&lt;br /&gt;
        my $fmap = {};&lt;br /&gt;
        foreach my $field_conf ( @{$f} )&lt;br /&gt;
        {&lt;br /&gt;
                my $fieldname = $field_conf-&amp;gt;{name};&lt;br /&gt;
                my $field = $field-&amp;gt;{dataset}-&amp;gt;get_field( $fieldname );&lt;br /&gt;
                $fmap-&amp;gt;{$field_conf-&amp;gt;{sub_name}} = $field;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my $ul = $state-&amp;gt;{session}-&amp;gt;make_element( &amp;quot;ul&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
        foreach my $row ( @filtered_contributors  )&lt;br /&gt;
        {&lt;br /&gt;
                my $li = $state-&amp;gt;{session}-&amp;gt;make_element( &amp;quot;li&amp;quot; );&lt;br /&gt;
                $li-&amp;gt;appendChild( $fmap-&amp;gt;{name}-&amp;gt;render_single_value( $state-&amp;gt;{session}, $row-&amp;gt;{name} ) );&lt;br /&gt;
                if( defined $row-&amp;gt;{id} )&lt;br /&gt;
                {&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( &amp;quot; (&amp;quot; ) );&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( $row-&amp;gt;{id} ) );&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( &amp;quot;)&amp;quot; ) );&lt;br /&gt;
                }&lt;br /&gt;
                $ul-&amp;gt;appendChild( $li );&lt;br /&gt;
        }&lt;br /&gt;
        return [ $ul, &amp;quot;XHTML&amp;quot; ];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} #End block&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example is also available at: https://gist.github.com/jesusbagpuss/2efc96ed05cf9121b925063a20677120&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&amp;diff=13777</id>
		<title>How to display specific contributors</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&amp;diff=13777"/>
		<updated>2021-05-21T10:06:21Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Method 3 - Custom EPScript function */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Based on this question, asked on the Tech list:&lt;br /&gt;
''How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?''&lt;br /&gt;
&lt;br /&gt;
'''Note:''' The question on the tech list specified EPrints 3.4.2. The below is based on 3.3.16, but may be useful as a starting point.&lt;br /&gt;
&lt;br /&gt;
Below are three approaches that may do what you need.&lt;br /&gt;
&lt;br /&gt;
== Method 1 - EPScript function ==&lt;br /&gt;
1) In EPScript, there is an undocumented function - &amp;lt;code&amp;gt;filter_compound_list&amp;lt;/code&amp;gt; which accepts:&lt;br /&gt;
* a field (''contributors'')&lt;br /&gt;
* a sub-field name to filter on (''type'')&lt;br /&gt;
* a value to filter to (''http://www.loc.gov/loc.terms/relators/THS'') &lt;br /&gt;
* the field to return (''name'')&lt;br /&gt;
&lt;br /&gt;
This can produce a text-string of one field from the compound field. If a thesis had two supervisors, the following example would produce:&lt;br /&gt;
&lt;br /&gt;
''Smith, John and Bond, James''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:if test=&amp;quot;contributors&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;epc:print expr=&amp;quot;filter_compound_list(contributors,'type','http://www.loc.gov/loc.terms/relators/THS','name')&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Method 2 - EPScript logic - ''foreach'' ==&lt;br /&gt;
&lt;br /&gt;
This method is a bit more flexible, but you have to construct the values from the parts manually. It does allow you to reference the &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; sub-field if required.&lt;br /&gt;
It also may leave empty wrapping elements in the output (e.g. the &amp;lt;code&amp;gt;ul&amp;lt;/code&amp;gt; in the example below if there are contributors, but none are the required type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:if test=&amp;quot;contributors&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;epc:foreach expr=&amp;quot;contributors&amp;quot; iterator=&amp;quot;contr&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;epc:if test=&amp;quot;$contr{type}='http://www.loc.gov/loc.terms/relators/THS'&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;li&amp;gt;&lt;br /&gt;
          &amp;lt;epc:print expr=&amp;quot;$contr{name}{given}&amp;quot; /&amp;gt; &amp;lt;epc:print expr=&amp;quot;$contr{name}{family}&amp;quot; /&amp;gt;&lt;br /&gt;
          &amp;lt;epc:if test=&amp;quot;$contr{id}&amp;quot;&amp;gt;(&amp;lt;epc:print expr=&amp;quot;$contr{id}&amp;quot;/&amp;gt;)&amp;lt;/epc:if&amp;gt;&lt;br /&gt;
        &amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
    &amp;lt;/epc:foreach&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Method 3 - Custom EPScript function ==&lt;br /&gt;
This is the most complex, but also offers the most flexibility - if you're able to understand the &amp;lt;code&amp;gt;EPrints::Script::Compiled&amp;lt;/code&amp;gt; module and write your own functions.&lt;br /&gt;
&lt;br /&gt;
There are two parts - adding custom methods to EPScript, and calling them from the citation file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; line&amp;gt;&lt;br /&gt;
### This should be added to a file e.g. EPRINTS_ROOT/archives/ARCHIVEID/cfg/cfg.d/z_epscript_additions.pl&lt;br /&gt;
&lt;br /&gt;
# Open block&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
# Write into EPrints::Script::Compiled&lt;br /&gt;
package EPrints::Script::Compiled;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
# Example usage in citation file:&lt;br /&gt;
#&lt;br /&gt;
#  &amp;lt;epc:if test=&amp;quot;$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS',1)&amp;quot;&amp;gt;&lt;br /&gt;
#    &amp;lt;h2&amp;gt;&amp;lt;epc:phrase ref=&amp;quot;contributor_type_typename_http://www.loc.gov/loc.terms/relators/THS&amp;quot;/&amp;gt;&amp;lt;/h2&amp;gt;&lt;br /&gt;
#    &amp;lt;epc:print expr=&amp;quot;$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS')&amp;quot;/&amp;gt;&lt;br /&gt;
#  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# The first call includes the 'test' parameter, which can be used to determine whether surrounding&lt;br /&gt;
# elements need to be displayed - in the above example the &amp;lt;h2&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
sub run_render_contributors_filtered&lt;br /&gt;
{&lt;br /&gt;
        my( $self, $state, $eprint, $contributor_type, $test ) = @_;&lt;br /&gt;
&lt;br /&gt;
        if( !defined $eprint-&amp;gt;[0] || ref($eprint-&amp;gt;[0]) ne &amp;quot;EPrints::DataObj::EPrint&amp;quot; )&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;runtime_error( &amp;quot;Can only call render_contributors_filtered() on eprint objects not &amp;quot;.&lt;br /&gt;
                        ref($eprint-&amp;gt;[0]) );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if( !defined $contributor_type )&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;runtime_error( &amp;quot;You need to specify a contributor type you want to render.&amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my @filtered_contributors = grep{ defined $_-&amp;gt;{type} &amp;amp;&amp;amp; $_-&amp;gt;{type} eq $contributor_type-&amp;gt;[0] } @{ $eprint-&amp;gt;[0]-&amp;gt;value( &amp;quot;contributors&amp;quot; ) };&lt;br /&gt;
&lt;br /&gt;
        if( $test )&lt;br /&gt;
        {&lt;br /&gt;
                return [ 0, &amp;quot;BOOLEAN&amp;quot; ] if( scalar @filtered_contributors &amp;lt; 1 );&lt;br /&gt;
                return [ 1, &amp;quot;BOOLEAN&amp;quot; ];&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # NB this is based on EPrints::Extras::render_related_url&lt;br /&gt;
        # It is over-complicated for this use-case, as we could just use&lt;br /&gt;
        # $state-&amp;gt;{session}-&amp;gt;render_name( $row-&amp;gt;{name} )&lt;br /&gt;
        # but if other compound fields are being used with similar code&lt;br /&gt;
        # being able to get to the 'render_value' for the sub fields is useful.&lt;br /&gt;
&lt;br /&gt;
        my $field = $eprint-&amp;gt;[0]-&amp;gt;dataset-&amp;gt;field( &amp;quot;contributors&amp;quot; );&lt;br /&gt;
        my $f = $field-&amp;gt;get_property( &amp;quot;fields_cache&amp;quot; );&lt;br /&gt;
        my $fmap = {};&lt;br /&gt;
        foreach my $field_conf ( @{$f} )&lt;br /&gt;
        {&lt;br /&gt;
                my $fieldname = $field_conf-&amp;gt;{name};&lt;br /&gt;
                my $field = $field-&amp;gt;{dataset}-&amp;gt;get_field( $fieldname );&lt;br /&gt;
                $fmap-&amp;gt;{$field_conf-&amp;gt;{sub_name}} = $field;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my $ul = $state-&amp;gt;{session}-&amp;gt;make_element( &amp;quot;ul&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
        foreach my $row ( @filtered_contributors  )&lt;br /&gt;
        {&lt;br /&gt;
                my $li = $state-&amp;gt;{session}-&amp;gt;make_element( &amp;quot;li&amp;quot; );&lt;br /&gt;
                $li-&amp;gt;appendChild( $fmap-&amp;gt;{name}-&amp;gt;render_single_value( $state-&amp;gt;{session}, $row-&amp;gt;{name} ) );&lt;br /&gt;
                if( defined $row-&amp;gt;{id} )&lt;br /&gt;
                {&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( &amp;quot; (&amp;quot; ) );&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( $row-&amp;gt;{id} ) );&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( &amp;quot;)&amp;quot; ) );&lt;br /&gt;
                }&lt;br /&gt;
                $ul-&amp;gt;appendChild( $li );&lt;br /&gt;
        }&lt;br /&gt;
        return [ $ul, &amp;quot;XHTML&amp;quot; ];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} #End block&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example is also available at: https://gist.github.com/jesusbagpuss/2efc96ed05cf9121b925063a20677120&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&amp;diff=13776</id>
		<title>How to display specific contributors</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&amp;diff=13776"/>
		<updated>2021-05-20T23:03:49Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Method 3 - Custom EPScript function */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Based on this question, asked on the Tech list:&lt;br /&gt;
''How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?''&lt;br /&gt;
&lt;br /&gt;
'''Note:''' The question on the tech list specified EPrints 3.4.2. The below is based on 3.3.16, but may be useful as a starting point.&lt;br /&gt;
&lt;br /&gt;
Below are three approaches that may do what you need.&lt;br /&gt;
&lt;br /&gt;
== Method 1 - EPScript function ==&lt;br /&gt;
1) In EPScript, there is an undocumented function - &amp;lt;code&amp;gt;filter_compound_list&amp;lt;/code&amp;gt; which accepts:&lt;br /&gt;
* a field (''contributors'')&lt;br /&gt;
* a sub-field name to filter on (''type'')&lt;br /&gt;
* a value to filter to (''http://www.loc.gov/loc.terms/relators/THS'') &lt;br /&gt;
* the field to return (''name'')&lt;br /&gt;
&lt;br /&gt;
This can produce a text-string of one field from the compound field. If a thesis had two supervisors, the following example would produce:&lt;br /&gt;
&lt;br /&gt;
''Smith, John and Bond, James''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:if test=&amp;quot;contributors&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;epc:print expr=&amp;quot;filter_compound_list(contributors,'type','http://www.loc.gov/loc.terms/relators/THS','name')&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Method 2 - EPScript logic - ''foreach'' ==&lt;br /&gt;
&lt;br /&gt;
This method is a bit more flexible, but you have to construct the values from the parts manually. It does allow you to reference the &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; sub-field if required.&lt;br /&gt;
It also may leave empty wrapping elements in the output (e.g. the &amp;lt;code&amp;gt;ul&amp;lt;/code&amp;gt; in the example below if there are contributors, but none are the required type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:if test=&amp;quot;contributors&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;epc:foreach expr=&amp;quot;contributors&amp;quot; iterator=&amp;quot;contr&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;epc:if test=&amp;quot;$contr{type}='http://www.loc.gov/loc.terms/relators/THS'&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;li&amp;gt;&lt;br /&gt;
          &amp;lt;epc:print expr=&amp;quot;$contr{name}{given}&amp;quot; /&amp;gt; &amp;lt;epc:print expr=&amp;quot;$contr{name}{family}&amp;quot; /&amp;gt;&lt;br /&gt;
          &amp;lt;epc:if test=&amp;quot;$contr{id}&amp;quot;&amp;gt;(&amp;lt;epc:print expr=&amp;quot;$contr{id}&amp;quot;/&amp;gt;)&amp;lt;/epc:if&amp;gt;&lt;br /&gt;
        &amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
    &amp;lt;/epc:foreach&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Method 3 - Custom EPScript function ==&lt;br /&gt;
This is the most complex, but also offers the most flexibility - if you're able to understand the &amp;lt;code&amp;gt;EPrints::Script::Compiled&amp;lt;/code&amp;gt; module and write your own functions.&lt;br /&gt;
&lt;br /&gt;
There are two parts - adding custom methods to EPScript, and calling them from the citation file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
### This should be added to a file e.g. EPRINTS_ROOT/archives/ARCHIVEID/cfg/cfg.d/z_epscript_additions.pl&lt;br /&gt;
&lt;br /&gt;
# Open block&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
# Write into EPrints::Script::Compiled&lt;br /&gt;
package EPrints::Script::Compiled;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
# Example usage in citation file:&lt;br /&gt;
#&lt;br /&gt;
#  &amp;lt;epc:if test=&amp;quot;$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS',1)&amp;quot;&amp;gt;&lt;br /&gt;
#    &amp;lt;h2&amp;gt;&amp;lt;epc:phrase ref=&amp;quot;contributor_type_typename_http://www.loc.gov/loc.terms/relators/THS&amp;quot;/&amp;gt;&amp;lt;/h2&amp;gt;&lt;br /&gt;
#    &amp;lt;epc:print expr=&amp;quot;$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS')&amp;quot;/&amp;gt;&lt;br /&gt;
#  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# The first call includes the 'test' parameter, which can be used to determine whether surrounding&lt;br /&gt;
# elements need to be displayed - in the above example the &amp;lt;h2&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
sub run_render_contributors_filtered&lt;br /&gt;
{&lt;br /&gt;
        my( $self, $state, $eprint, $contributor_type, $test ) = @_;&lt;br /&gt;
&lt;br /&gt;
        if( !defined $eprint-&amp;gt;[0] || ref($eprint-&amp;gt;[0]) ne &amp;quot;EPrints::DataObj::EPrint&amp;quot; )&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;runtime_error( &amp;quot;Can only call render_contributors_filtered() on eprint objects not &amp;quot;.&lt;br /&gt;
                        ref($eprint-&amp;gt;[0]) );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if( !defined $contributor_type )&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;runtime_error( &amp;quot;You need to specify a contributor type you want to render.&amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my @filtered_contributors = grep{ defined $_-&amp;gt;{type} &amp;amp;&amp;amp; $_-&amp;gt;{type} eq $contributor_type-&amp;gt;[0] } @{ $eprint-&amp;gt;[0]-&amp;gt;value( &amp;quot;contributors&amp;quot; ) };&lt;br /&gt;
&lt;br /&gt;
        if( $test )&lt;br /&gt;
        {&lt;br /&gt;
                return [ 0, &amp;quot;BOOLEAN&amp;quot; ] if( scalar @filtered_contributors &amp;lt; 1 );&lt;br /&gt;
                return [ 1, &amp;quot;BOOLEAN&amp;quot; ];&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # NB this is based on EPrints::Extras::render_related_url&lt;br /&gt;
        # It is over-complicated for this use-case, as we could just use&lt;br /&gt;
        # $state-&amp;gt;{session}-&amp;gt;render_name( $row-&amp;gt;{name} )&lt;br /&gt;
        # but if other compound fields are being used with similar code&lt;br /&gt;
        # being able to get to the 'render_value' for the sub fields is useful.&lt;br /&gt;
&lt;br /&gt;
        my $field = $eprint-&amp;gt;[0]-&amp;gt;dataset-&amp;gt;field( &amp;quot;contributors&amp;quot; );&lt;br /&gt;
        my $f = $field-&amp;gt;get_property( &amp;quot;fields_cache&amp;quot; );&lt;br /&gt;
        my $fmap = {};&lt;br /&gt;
        foreach my $field_conf ( @{$f} )&lt;br /&gt;
        {&lt;br /&gt;
                my $fieldname = $field_conf-&amp;gt;{name};&lt;br /&gt;
                my $field = $field-&amp;gt;{dataset}-&amp;gt;get_field( $fieldname );&lt;br /&gt;
                $fmap-&amp;gt;{$field_conf-&amp;gt;{sub_name}} = $field;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my $ul = $state-&amp;gt;{session}-&amp;gt;make_element( &amp;quot;ul&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
        foreach my $row ( @filtered_contributors  )&lt;br /&gt;
        {&lt;br /&gt;
                my $li = $state-&amp;gt;{session}-&amp;gt;make_element( &amp;quot;li&amp;quot; );&lt;br /&gt;
                $li-&amp;gt;appendChild( $fmap-&amp;gt;{name}-&amp;gt;render_single_value( $state-&amp;gt;{session}, $row-&amp;gt;{name} ) );&lt;br /&gt;
                if( defined $row-&amp;gt;{id} )&lt;br /&gt;
                {&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( &amp;quot; (&amp;quot; ) );&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( $row-&amp;gt;{id} ) );&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( &amp;quot;)&amp;quot; ) );&lt;br /&gt;
                }&lt;br /&gt;
                $ul-&amp;gt;appendChild( $li );&lt;br /&gt;
        }&lt;br /&gt;
        return [ $ul, &amp;quot;XHTML&amp;quot; ];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} #End block&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example is also available at: https://gist.github.com/jesusbagpuss/2efc96ed05cf9121b925063a20677120&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&amp;diff=13775</id>
		<title>How to display specific contributors</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&amp;diff=13775"/>
		<updated>2021-05-20T23:00:04Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: Created page with &amp;quot;Based on this question, asked on the Tech list: ''How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?''  '''Note:''' The question on the tech...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Based on this question, asked on the Tech list:&lt;br /&gt;
''How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?''&lt;br /&gt;
&lt;br /&gt;
'''Note:''' The question on the tech list specified EPrints 3.4.2. The below is based on 3.3.16, but may be useful as a starting point.&lt;br /&gt;
&lt;br /&gt;
Below are three approaches that may do what you need.&lt;br /&gt;
&lt;br /&gt;
== Method 1 - EPScript function ==&lt;br /&gt;
1) In EPScript, there is an undocumented function - &amp;lt;code&amp;gt;filter_compound_list&amp;lt;/code&amp;gt; which accepts:&lt;br /&gt;
* a field (''contributors'')&lt;br /&gt;
* a sub-field name to filter on (''type'')&lt;br /&gt;
* a value to filter to (''http://www.loc.gov/loc.terms/relators/THS'') &lt;br /&gt;
* the field to return (''name'')&lt;br /&gt;
&lt;br /&gt;
This can produce a text-string of one field from the compound field. If a thesis had two supervisors, the following example would produce:&lt;br /&gt;
&lt;br /&gt;
''Smith, John and Bond, James''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:if test=&amp;quot;contributors&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;epc:print expr=&amp;quot;filter_compound_list(contributors,'type','http://www.loc.gov/loc.terms/relators/THS','name')&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Method 2 - EPScript logic - ''foreach'' ==&lt;br /&gt;
&lt;br /&gt;
This method is a bit more flexible, but you have to construct the values from the parts manually. It does allow you to reference the &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; sub-field if required.&lt;br /&gt;
It also may leave empty wrapping elements in the output (e.g. the &amp;lt;code&amp;gt;ul&amp;lt;/code&amp;gt; in the example below if there are contributors, but none are the required type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;epc:if test=&amp;quot;contributors&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;epc:foreach expr=&amp;quot;contributors&amp;quot; iterator=&amp;quot;contr&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;epc:if test=&amp;quot;$contr{type}='http://www.loc.gov/loc.terms/relators/THS'&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;li&amp;gt;&lt;br /&gt;
          &amp;lt;epc:print expr=&amp;quot;$contr{name}{given}&amp;quot; /&amp;gt; &amp;lt;epc:print expr=&amp;quot;$contr{name}{family}&amp;quot; /&amp;gt;&lt;br /&gt;
          &amp;lt;epc:if test=&amp;quot;$contr{id}&amp;quot;&amp;gt;(&amp;lt;epc:print expr=&amp;quot;$contr{id}&amp;quot;/&amp;gt;)&amp;lt;/epc:if&amp;gt;&lt;br /&gt;
        &amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
    &amp;lt;/epc:foreach&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Method 3 - Custom EPScript function ==&lt;br /&gt;
This is the most complex, but also offers the most flexibility - if you're able to understand the &amp;lt;code&amp;gt;EPrints::Script::Compiled&amp;lt;/code&amp;gt; module and write your own functions.&lt;br /&gt;
&lt;br /&gt;
There are two parts - adding custom methods to EPScript, and calling them from the citation file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
# Open block&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
# Write into EPrints::Script::Compiled&lt;br /&gt;
package EPrints::Script::Compiled;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
# Example usage in citation file:&lt;br /&gt;
#&lt;br /&gt;
#  &amp;lt;epc:if test=&amp;quot;$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS',1)&amp;quot;&amp;gt;&lt;br /&gt;
#    &amp;lt;h2&amp;gt;&amp;lt;epc:phrase ref=&amp;quot;contributor_type_typename_http://www.loc.gov/loc.terms/relators/THS&amp;quot;/&amp;gt;&amp;lt;/h2&amp;gt;&lt;br /&gt;
#    &amp;lt;epc:print expr=&amp;quot;$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS')&amp;quot;/&amp;gt;&lt;br /&gt;
#  &amp;lt;/epc:if&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# The first call includes the 'test' parameter, which can be used to determine whether surrounding&lt;br /&gt;
# elements need to be displayed - in the above example the &amp;lt;h2&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
sub run_render_contributors_filtered&lt;br /&gt;
{&lt;br /&gt;
        my( $self, $state, $eprint, $contributor_type, $test ) = @_;&lt;br /&gt;
&lt;br /&gt;
        if( !defined $eprint-&amp;gt;[0] || ref($eprint-&amp;gt;[0]) ne &amp;quot;EPrints::DataObj::EPrint&amp;quot; )&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;runtime_error( &amp;quot;Can only call render_contributors_filtered() on eprint objects not &amp;quot;.&lt;br /&gt;
                        ref($eprint-&amp;gt;[0]) );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if( !defined $contributor_type )&lt;br /&gt;
        {&lt;br /&gt;
                $self-&amp;gt;runtime_error( &amp;quot;You need to specify a contributor type you want to render.&amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my @filtered_contributors = grep{ defined $_-&amp;gt;{type} &amp;amp;&amp;amp; $_-&amp;gt;{type} eq $contributor_type-&amp;gt;[0] } @{ $eprint-&amp;gt;[0]-&amp;gt;value( &amp;quot;contributors&amp;quot; ) };&lt;br /&gt;
&lt;br /&gt;
        if( $test )&lt;br /&gt;
        {&lt;br /&gt;
                return [ 0, &amp;quot;BOOLEAN&amp;quot; ] if( scalar @filtered_contributors &amp;lt; 1 );&lt;br /&gt;
                return [ 1, &amp;quot;BOOLEAN&amp;quot; ];&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # NB this is based on EPrints::Extras::render_related_url&lt;br /&gt;
        # It is over-complicated for this use-case, as we could just use&lt;br /&gt;
        # $state-&amp;gt;{session}-&amp;gt;render_name( $row-&amp;gt;{name} )&lt;br /&gt;
        # but if other compound fields are being used with similar code&lt;br /&gt;
        # being able to get to the 'render_value' for the sub fields is useful.&lt;br /&gt;
&lt;br /&gt;
        my $field = $eprint-&amp;gt;[0]-&amp;gt;dataset-&amp;gt;field( &amp;quot;contributors&amp;quot; );&lt;br /&gt;
        my $f = $field-&amp;gt;get_property( &amp;quot;fields_cache&amp;quot; );&lt;br /&gt;
        my $fmap = {};&lt;br /&gt;
        foreach my $field_conf ( @{$f} )&lt;br /&gt;
        {&lt;br /&gt;
                my $fieldname = $field_conf-&amp;gt;{name};&lt;br /&gt;
                my $field = $field-&amp;gt;{dataset}-&amp;gt;get_field( $fieldname );&lt;br /&gt;
                $fmap-&amp;gt;{$field_conf-&amp;gt;{sub_name}} = $field;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my $ul = $state-&amp;gt;{session}-&amp;gt;make_element( &amp;quot;ul&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
        foreach my $row ( @filtered_contributors  )&lt;br /&gt;
        {&lt;br /&gt;
                my $li = $state-&amp;gt;{session}-&amp;gt;make_element( &amp;quot;li&amp;quot; );&lt;br /&gt;
                $li-&amp;gt;appendChild( $fmap-&amp;gt;{name}-&amp;gt;render_single_value( $state-&amp;gt;{session}, $row-&amp;gt;{name} ) );&lt;br /&gt;
                if( defined $row-&amp;gt;{id} )&lt;br /&gt;
                {&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( &amp;quot; (&amp;quot; ) );&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( $row-&amp;gt;{id} ) );&lt;br /&gt;
                        $li-&amp;gt;appendChild( $state-&amp;gt;{session}-&amp;gt;make_text( &amp;quot;)&amp;quot; ) );&lt;br /&gt;
                }&lt;br /&gt;
                $ul-&amp;gt;appendChild( $li );&lt;br /&gt;
        }&lt;br /&gt;
        return [ $ul, &amp;quot;XHTML&amp;quot; ];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} #End block&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example is also available at: https://gist.github.com/jesusbagpuss/2efc96ed05cf9121b925063a20677120&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&amp;diff=13511</id>
		<title>Setting up HTTPS using Let's Encrypt</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&amp;diff=13511"/>
		<updated>2020-12-14T12:06:07Z</updated>

		<summary type="html">&lt;p&gt;Libjlrs: /* Additional Notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Manual}}&lt;br /&gt;
By default EPrints does not come setup to use HTTPS.  This is because you need to generate a SSL certificate and if this is not signed by a known Certificate Authority a user's web browser is likely to complain vigorously.  In the past it has typically costed a fair amount of money to obtain a SSL certificate from your hosting provider.  However, now there is [https://letsencrypt.org/ Let's Encrypt] it is possible to get a certificate for free.  This is not to say you should use Let's Encrypt in all cases.  UK academic institutions should continue to obtain their SSL certificates through Jisc and other institutions/organisations may already have similar arrangements for obtaining SSL certificates.&lt;br /&gt;
&lt;br /&gt;
As well as being free, Let's Encrypt has an automated way for renewing certificates.  However, it should be noted that the length of its certificates is a lot shorter at just 3 months.  As the renewal process is automatic, this time period is more appropriate to maximise security.  Let's Encrypt's certificate generation requires your EPrints repository to be publicly accessible.  Beneath are instructions on how to set up EPrints to enable HTTPS with a Let's Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
1. Go to the https://certbot.eff.org/ and follow the instructions for your web server and operating system (the former will almost always be Apache) and follow the instructions provided.&lt;br /&gt;
&lt;br /&gt;
2. When you get to the point of running the certbot command you want the certificate only so should type as the root user:&lt;br /&gt;
&lt;br /&gt;
 certbot --apache certonly&lt;br /&gt;
&lt;br /&gt;
3. Take a note of the path to were your certificate, key and CA chain have been saved.  This will probably be something like&lt;br /&gt;
 &lt;br /&gt;
 /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/&lt;br /&gt;
&lt;br /&gt;
4. If you have not already done so, create an directory called &amp;lt;tt&amp;gt;ssl&amp;lt;/tt&amp;gt; inside your archive's directory, i.e.&lt;br /&gt;
&lt;br /&gt;
 mkdir EPRINTS_PATH/archives/REPOID/ssl/&lt;br /&gt;
&lt;br /&gt;
5. Create a file inside the new ssl directory called &amp;lt;tt&amp;gt;securevhost.conf&amp;lt;/tt&amp;gt; and include the following contents, amending the &amp;lt;tt&amp;gt;ServerName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSLCertificateFile&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSLCertificateKeyFile&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;SSLCertificateChainFile&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Include&amp;lt;/tt&amp;gt; as appropriate at least.  You will note that this configuration also enables [https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security HTTP Strict Transport Security (HSTS)] for additional security.  This ensures that after the first time you visit HTTPS for a particular site in your web browser, all future HTTP requests for this hostname will automatically be converted by your browser to HTTPS.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ServerName YOUR-REPOSITORY-DOMAIN:443&lt;br /&gt;
 &lt;br /&gt;
     # Enable HSTS&lt;br /&gt;
     Header always set Strict-Transport-Security &amp;quot;max-age=63072000;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     SSLEngine on&lt;br /&gt;
     SSLProtocol all -SSLv2 -SSLv3&lt;br /&gt;
     SSLHonorCipherOrder on&lt;br /&gt;
     SSLCipherSuite HIGH:!aNULL:!eNULL:!kECDH:!aDH:!RC4:!3DES:!CAMELLIA:!MD5:!PSK:!SRP:!KRB5:@STRENGTH&lt;br /&gt;
 &lt;br /&gt;
     SSLCertificateFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/cert.pem&lt;br /&gt;
     SSLCertificateKeyFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/privkey.pem&lt;br /&gt;
     SSLCertificateChainFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/chain.pem&lt;br /&gt;
 &lt;br /&gt;
     SetEnvIf User-Agent &amp;quot;.*MSIE.*&amp;quot; \&lt;br /&gt;
         nokeepalive ssl-unclean-shutdown \&lt;br /&gt;
         downgrade-1.0 force-response-1.0&lt;br /&gt;
 &lt;br /&gt;
     LogLevel warn&lt;br /&gt;
     ErrorLog logs/ssl_error_log    &lt;br /&gt;
     TransferLog logs/ssl_access_log&lt;br /&gt;
     CustomLog logs/ssl_request_log \&lt;br /&gt;
         &amp;quot;%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \&amp;quot;%r\&amp;quot; %b&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     Include EPRINTS_PATHH/cfg/apache_ssl/REPOID.conf&lt;br /&gt;
 &lt;br /&gt;
     PerlTransHandler +EPrints::Apache::Rewrite&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
6. If you have not already done so, add a configuration file at &amp;lt;tt&amp;gt;/opt/eprints3/archives/REPOID/cfg/cfg.d/https.pl&amp;lt;/tt&amp;gt; with the following configuration:&lt;br /&gt;
&lt;br /&gt;
 $c-&amp;gt;{securehost} = $c-&amp;gt;{host};&lt;br /&gt;
 $c-&amp;gt;{secureport} = 443;&lt;br /&gt;
 $c-&amp;gt;{http_root} = undef;&lt;br /&gt;
&lt;br /&gt;
7. Now you will need to regenerate the rest of your Apache configuration for EPrints with the following command run as the EPrints user. (Substitute the path as appropriate):&lt;br /&gt;
&lt;br /&gt;
 /opt/eprints3/bin/generate_apacheconf --system --replace&lt;br /&gt;
&lt;br /&gt;
8. Apache will not yet have been setup to include the Apache configuration file you created in step 5.  To include this, you will need to edit the file in your Apache configuration directory (&amp;lt;tt&amp;gt;/etc/httpd/&amp;lt;/tt&amp;gt; on RHEL/CentOS/Fedora and &amp;lt;tt&amp;gt;/etc/apache2/&amp;lt;/tt&amp;gt; on Debian/Ubuntu) and find the file that contains the line &amp;lt;tt&amp;gt;cfg/apache.conf&amp;lt;/tt&amp;gt;, e.g.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/httpd/&lt;br /&gt;
 grep -r &amp;quot;cfg/apache.conf&amp;quot; *&lt;br /&gt;
&lt;br /&gt;
9. Once you have found it you will need to edit it and add the following line, changing the path as appropriate:&lt;br /&gt;
&lt;br /&gt;
 Include EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf&lt;br /&gt;
&lt;br /&gt;
10. Now, (as root or using sudo) test that the Apache configuration is correct and fix any issues if necessary:&lt;br /&gt;
&lt;br /&gt;
 apachectl configtest&lt;br /&gt;
&lt;br /&gt;
11. Restart Apache and check whether you can access your EPrints repository using HTTPS in a web browser:&lt;br /&gt;
&lt;br /&gt;
 apachectl restart&lt;br /&gt;
&lt;br /&gt;
12. If the guide on cerbot.eff.org you used in step 1 tells you to to setup a cron job then follow those instructions.  The easiest way to do this is probably to run &amp;lt;tt&amp;gt;crontab -e&amp;lt;/tt&amp;gt; as root and add the following cron job, substituting the minute (43) and hours (6,18) for you own choice maintaining a 12 hour gap between the hours:&lt;br /&gt;
&lt;br /&gt;
 43 6,18 * * * certbot renew&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Additional Notes ==&lt;br /&gt;
&lt;br /&gt;
The default EPrints Apache Rewrite handler declines any requests to a URL containing &amp;lt;code&amp;gt;/.&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This means that the challenge/response for a LetsEncrypt certificate renewal that uses the &amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt; path will fail.&lt;br /&gt;
&lt;br /&gt;
To make this work you could add a location block to your Apache config, to ensure the &amp;lt;code&amp;gt;/.well-known/&amp;lt;/code&amp;gt; are not handled by EPrints, or use an EPrints URL rewrite trigger to handle the request:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#this could be saved into e.g. [EPRINTS_ROOT]/lib/cfg.d/z_rewrite_url_LetsEncrypt.pl&lt;br /&gt;
&lt;br /&gt;
# import Apache constant e.g. 'OK'&lt;br /&gt;
use EPrints::Apache::AnApache;&lt;br /&gt;
&lt;br /&gt;
$c-&amp;gt;add_trigger( EP_TRIGGER_URL_REWRITE, sub {&lt;br /&gt;
        my( %o ) = @_;&lt;br /&gt;
&lt;br /&gt;
        # if the incoming request matches the LetsEncrypt challenge URL...&lt;br /&gt;
        if( $o{uri} =~ m!^${o{urlpath}}/\.well-known/acme-challenge/! )&lt;br /&gt;
        {&lt;br /&gt;
                # and the LetsEncrypt renewal process has put the file in EPRINTS_ROOT/archives/ARCHIVEID/html/.well-known/acme-challenge/&lt;br /&gt;
                if( -f $o{repository}-&amp;gt;get_conf( &amp;quot;htdocs_path&amp;quot; ).$o{uri} )&lt;br /&gt;
                {&lt;br /&gt;
                        # reply with an HTTP '200' &lt;br /&gt;
                        ${$o{return_code}} = OK;&lt;br /&gt;
                        # and return the file reqested&lt;br /&gt;
                        $o{request}-&amp;gt;filename( $o{repository}-&amp;gt;get_conf( &amp;quot;htdocs_path&amp;quot; ).$o{uri} );&lt;br /&gt;
                }&lt;br /&gt;
                # and say that we've handled the request - so no more triggers should be run.&lt;br /&gt;
                return EP_TRIGGER_DONE;&lt;br /&gt;
        }&lt;br /&gt;
} );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Libjlrs</name></author>
		
	</entry>
</feed>