@@ -134,6 +134,36 @@ $results->dispose;

my $page = $session->make_doc_fragment();
my $type = $session->get_citation_type( $ds, $citation );

my $feeds_conf = $session->config( "latest_tool_feeds" );
if ( defined $feeds_conf )
{
my $feeds = $session->make_element( "div", class=>"ep_latest_tool_feeds" );
foreach my $feed_type (keys $feeds_conf)
{
if ( defined $feeds_conf->{$feed_type}->{enabled} && $feeds_conf->{$feed_type}->{enabled} )
{
my $feed = $session->make_element( "span", class=>"ep_search_feed" );
my $feed_icon_link = $session->make_element( "a", href=>"/cgi/latest_tool?output=$feed_type" );
my $feed_icon_link_icon = $session->make_element( "img", alt=>"[feed]", src=>"/style/images/feed-icon-14x14.png", border=>"0" );
$feed_icon_link->appendChild($feed_icon_link_icon);
$feed->appendChild($feed_icon_link);
my $feed_link = $session->make_element( "a", href=>"/cgi/latest_tool?output=$feed_type" );
if ( defined $feeds_conf->{$feed_type}->{label} )
{
$feed_link->appendText($feeds_conf->{$feed_type}->{label});
}
else
{
$feed_link->appendText($feed_type);
}
$feed->appendChild($feed_link);
$feeds->appendChild($feed);
}
}
$page->appendChild($feeds);
}

my $container;
if( $type eq "table_row" )
{
@@ -101,6 +101,7 @@ if( !defined $verb )
}
elsif( !exists $GRAMMAR{$verb} )
{
$verb = "error";
unshift @errors,
render_oai_error( $repo, "badVerb", "The value of the verb argument is not a legal OAI-PMH verb" ),
render_oai_error( $repo, "badArgument", "Bad verb argument" );
@@ -20,7 +20,7 @@ exit( 1 ) unless( defined $session );

EPrints::ScreenProcessor->process(
session => $session,
url => "/cgi/request_doc",
url => $session->config( "http_root" ) . "/request_doc",
screenid => "Public::RequestCopy",
);
$session->terminate;
@@ -62,7 +62,7 @@ if( defined($repo->param( "dataset" )) )
}
}

if( $datasetid =~ /^(advanced)|(simple)$/ )
if( $datasetid =~ /^(advanced|simple)$/ )
{
$searchid = $datasetid;
$datasetid = "archive";
@@ -2,22 +2,22 @@

{
my $uri = URI->new( "http://" );
if( EPrints::Utils::is_set( $c->{host} ) )
{
$uri->scheme( "http" );
$uri->host( $c->{host} );
$uri->port( $c->{port} );
$uri = $uri->canonical;
$uri->path( $c->{http_root} );
}
else
{
$uri->scheme( "https" );
$uri->host( $c->{securehost} );
$uri->port( $c->{secureport} );
$uri = $uri->canonical;
$uri->path( $c->{https_root} );
}
if( EPrints::Utils::is_set( $c->{securehost} ) )
{
$uri->scheme( "https" );
$uri->host( $c->{securehost} );
$uri->port( $c->{secureport} );
$uri = $uri->canonical;
$uri->path( $c->{https_root} );
}
else
{
$uri->scheme( "http" );
$uri->host( $c->{host} );
$uri->port( $c->{port} );
$uri = $uri->canonical;
$uri->path( $c->{http_root} );
}

# EPrints base URL without trailing slash
$c->{base_url} = "$uri";
@@ -40,9 +40,10 @@ =head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
@@ -14,9 +14,10 @@ =head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
@@ -114,6 +114,7 @@
name => 'abstract',
type => 'longtext',
input_rows => 10,
render_single_value => 'render_paras',
},

{
@@ -168,9 +169,10 @@ =head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
@@ -3,7 +3,7 @@
{
my( $eprint ) = @_;

my $type = $eprint->value( "type" ) || "";
my $type = $eprint->value( "type" );
if( $type eq "monograph" || $type eq "thesis" )
{
unless( $eprint->is_set( "institution" ) )
@@ -49,9 +49,10 @@ =head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
@@ -94,7 +94,7 @@
# Applies to all subclasses of Id: Text, Longtext, Url etc.
if( $field->isa( "EPrints::MetaField::Id" ) )
{
if( length($v) > $field->property( "maxlength" ) )
if( EPrints::Utils::is_set( $v ) && length($v) > $field->property( "maxlength" ) )
{
push @problems,
$repository->html_phrase( "validate:truncated",
@@ -113,9 +113,10 @@ =head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END

This file was deleted.

@@ -31,35 +31,4 @@
}

return $frag;
};

=head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
=for LICENSE BEGIN
This file is part of EPrints 3.4 L<http://www.eprints.org/>.
EPrints 3.4 and this file are released under the terms of the
GNU Lesser General Public License version 3 as published by
the Free Software Foundation unless otherwise stated.
EPrints 3.4 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.
You should have received a copy of the GNU Lesser General Public
License along with EPrints 3.4.
If not, see L<http://www.gnu.org/licenses/>.
=for LICENSE END
}
@@ -1,7 +1,12 @@
#lib inc for the publication flavour. starts from base path (e.g. /opt/eprints3)
#pathes are separated by ; (semi-colon) and should not contain spaces
#back ones overwrite front ones.

flavours/pub_lib;site_lib;ingredients/bazaar;

# The library include paths for the flavour.
# All paths are relative to the install path, eg /opt/eprints3.
# Entries may be separated by semi-colons (;) pr line breaks.
# Anything after a # is considered as a comment.
# The include path is constructed in the order in which the entries are encountered in the inc file.
# If several files of the same name are encountered in multiple directories, the last one encountered will be used.
# An include file will typically refer to a flavour specific directory and a set of ingredients.
# Wildcards are also supported, eg to include all ingredients, use "ingredients/*"
# There is an abbreviated form for "flavours:", "f:", eg "f:pub_lib", and similarly "i:" for ingredients.

flavours/pub_lib
ingredients/bazaar
@@ -48,7 +48,7 @@ Welcome to <epc:phrase ref="archive_name" />. <a href="http://www.eprints.org/d/
</div></div>

<p style="margin-top: 2em; font-size: 90%">
<epc:phrase ref="archive_name" /> supports <a href="http://www.openarchives.org"><abbr title="Open Archives Protocol for Metadata Harvesting v2.0">OAI 2.0</abbr></a> with a base URL of <tt><epc:print expr="$config{perl_url}" />/oai2</tt>
<epc:phrase ref="archive_name" /> supports <a href="http://www.openarchives.org"><abbr title="Open Archives Protocol for Metadata Harvesting v2.0">OAI 2.0</abbr></a> with a base URL of <code><epc:print expr="$config{perl_url}" />/oai2</code>
</p>


@@ -21,7 +21,7 @@
<input type="submit" value="Start defining policies" class="ep_form_action_button" />
</form>

<p>Add your policies to: <tt><epc:print expr="$config{config_path}" />/lang/en/static/policies.xpage</tt></p>
<p>Add your policies to: <code><epc:print expr="$config{config_path}" />/lang/en/static/policies.xpage</code></p>



@@ -179,9 +179,14 @@ sub convert_dataobj

# Probably a DOI
push @dcdata, $plugin->simple_value( $eprint, id_number => "relation" );
# .. not a default field but added by several IRs
push @dcdata, $plugin->simple_value( $eprint, doi => "relation" );

# export id_number field as DC.identifier # SHEFFHALLAM-168
push @dcdata, $plugin->simple_value( $eprint, id_number => "identifier" );
# export id_number field as doi, if it matches the regx # SHEFFHALLAM-176:
if (EPrints::Utils::is_set( $eprint->get_value("id_number") ) &&
$eprint->get_value("id_number") =~ m|^10\.\d{4,9}/[-._;()/:A-Z0-9]+$|i)
{
push @dcdata, $plugin->simple_value( $eprint, id_number => "doi" );
}
# If no documents, may still have an eprint-level language
push @dcdata, $plugin->simple_value( $eprint, language => "language" );

@@ -47,9 +47,9 @@ sub input_text_fh
my @ids;

my $pid = $plugin->param( "pid" );
my $session = $plugin->{repository};
my $use_prefix = $plugin->param( "use_prefix" ) || 1;
my $doi_field = $plugin->param( "doi_field" ) || 'id_number';
my $session = $plugin->{repository};
my $use_prefix = $plugin->param( "use_prefix" ) || 1;
my $doi_field = $plugin->param( "doi_field" ) || 'id_number';

unless( $pid )
{
@@ -64,6 +64,11 @@ sub input_text_fh
$doi =~ s/\s+$//;

next unless length($doi);
my $obj = EPrints::DOI->parse( $doi );
if( $obj )
{
$doi = $obj->to_string( noprefix => !$use_prefix );
}

#some doi's in the repository may have the "doi:" prefix and others may not, so we need to check both cases - rwf1v07:27/01/2016
my $doi2 = $doi;
@@ -200,10 +205,8 @@ sub convert_input
my( $plugin, $data ) = @_;

my $epdata = {};
my $use_prefix = $plugin->param( "use_prefix" );
my $doi_field = $plugin->param( "doi_field" );
$use_prefix = 1 unless defined ( $use_prefix );
$doi_field = "id_number" unless defined ( $doi_field );
my $use_prefix = $plugin->param( "use_prefix" ) || 1;
my $doi_field = $plugin->param( "doi_field" ) || "id_number";

if( defined $data->{creators} )
{
@@ -234,10 +237,16 @@ sub convert_input
if( defined $data->{"doi"} )
{
#Use doi field identified from config parameter, in case it has been customised. Alan Stiles, Open University 20140408
$epdata->{$doi_field} = $data->{"doi"};
my $doi = $data->{"doi"};
$doi =~ s/^\s*doi:\s*//gi;
$epdata->{official_url} = "http://dx.doi.org/$doi";
my $doi = EPrints::DOI->parse( $data->{"doi"} );
if( $doi )
{
$epdata->{$doi_field} = $doi->to_string( noprefix=>!$use_prefix );
$epdata->{official_url} = $doi->to_uri->as_string;
}
else
{
$epdata->{$doi_field} = $data->{"doi"};
}
}
if( defined $data->{"volume_title"} )
{
@@ -310,9 +319,10 @@ sub url_encode
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
@@ -15,16 +15,17 @@
# Define the EPM sources
push @{$c->{epm_sources}}, {
name => "EPrints Bazaar",
base_url => "http://bazaar.eprints.org",
base_url => "https://bazaar.eprints.org",
};

=head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.

Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/

=for COPYRIGHT END
@@ -32,6 +32,7 @@ package EPrints::DataObj::EPM;

@ISA = ( 'EPrints::DataObj' );

use EPrints::Plugin::Screen::EPMC;
use strict;

our $MAX_SIZE = 2097152;
@@ -1173,9 +1174,10 @@ sub is_set
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
@@ -35,7 +35,7 @@ sub map

my $sources = $repo->config( "epm", "sources" );
$sources = [
{ name => "EPrints Bazaar", base_url => "http://bazaar.eprints.org/" }
{ name => "EPrints Bazaar", base_url => "https://bazaar.eprints.org/" }
] if !defined $sources;

foreach my $source (@$sources)
@@ -144,7 +144,7 @@ sub accolades
my( $_ua, $_base_url ) = @_;

my $ua = ( $_ua ) ? $_ua : LWP::UserAgent->new;
my $base_url = ( $_base_url ) ? $_base_url : "http://bazaar.eprints.org/";
my $base_url = ( $_base_url ) ? $_base_url : "https://bazaar.eprints.org/";

# my $ua = $self->{ua};
# my $ua = LWP::UserAgent->new;
@@ -226,9 +226,10 @@ sub epm_by_eprintid
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
@@ -47,7 +47,7 @@ sub properties_from

$processor->{sources} = $repo->config( "epm", "sources" );
$processor->{sources} = [
{ name => "EPrints Bazaar", base_url => "http://bazaar.eprints.org/" },
{ name => "EPrints Bazaar", base_url => "https://bazaar.eprints.org/" },
] if !defined $processor->{sources};
}

@@ -167,9 +167,10 @@ sub render
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
Copyright 2016 University of Southampton.
EPrints 3.4 preview 2 is supplied by EPrints Services.
This software is supplied as is and is for demonstration purposes.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
@@ -2,24 +2,24 @@

{
my $uri = URI->new( "http://" );
if( EPrints::Utils::is_set( $c->{host} ) )
{
$uri->scheme( "http" );
$uri->host( $c->{host} );
$uri->port( $c->{port} );
$uri = $uri->canonical;
$uri->path( $c->{http_root} );
}
else
{
$uri->scheme( "https" );
$uri->host( $c->{securehost} );
$uri->port( $c->{secureport} );
$uri = $uri->canonical;
$uri->path( $c->{https_root} );
}

# EPrints base URL without trailing slash
if( EPrints::Utils::is_set( $c->{securehost} ) )
{
$uri->scheme( "https" );
$uri->host( $c->{securehost} );
$uri->port( $c->{secureport} );
$uri = $uri->canonical;
$uri->path( $c->{https_root} );
}
else
{
$uri->scheme( "http" );
$uri->host( $c->{host} );
$uri->port( $c->{port} );
$uri = $uri->canonical;
$uri->path( $c->{http_root} );
}

# EPrints base URL without trailing slash and http URL with
$c->{base_url} = "$uri";
# CGI base URL without trailing slash
$c->{perl_url} = "$uri/cgi";
@@ -31,6 +31,10 @@
# Will match http://yourrepo/myspecial/cgi
#$c->{rewrite_exceptions} = [];

#if turned on, the abstract page url will be: http://domain.com/id/eprint/43/. This format helps google scholar to index eprints repository.
#if turned off: http://domain.com/43/
$c->{use_long_url_format} = 0;

=head1 COPYRIGHT
=for COPYRIGHT BEGIN
@@ -9,7 +9,8 @@
######################################################################

$c->{latest_tool_modes} = {
default => { citation => "result" }
default => { citation => "result" },
fplatest => { citation => "result", max => 3 }
};

# Example of a latest_tool mode. This makes a mode=articles option
@@ -23,7 +24,12 @@
# max => 20
# }


# Make sure the appropriate Export plugins are also enabled.
$c->{latest_tool_feeds} = {
# Atom => { enabled => 1, "label" => "Atom" },
# RSS => { enabled => 1, "label" => "RSS 1.0" },
RSS2 => { enabled => 1, "label" => "RSS 2.0" },
};

=head1 COPYRIGHT
@@ -177,13 +177,13 @@

if( $eprint->dataset->has_field( "id_number" ) && $eprint->is_set( "id_number" ) )
{
my $doi = $eprint->get_value( "id_number" );
if( $doi =~ s/^doi:/info:doi\// )
my $doi = EPrints::DOI->parse( $eprint->get_value( "id_number" ) );
if ( $doi )
{
$o{"graph"}->add(
subject => $eprint_uri,
predicate => "owl:sameAs",
object => "<$doi>" );
subject => $eprint_uri,
predicate => "owl:sameAs",
object => "<$doi>" );
}
}

@@ -96,7 +96,7 @@
{
$value = $v;
}
next if !EPrints::Utils::is_set( $value );
next if !EPrints::Utils::is_set( $value ) || ref($value) ne "";
$tg->index_text( $value );
$tg->increase_termpos();
next if length($value) > 200; # Xapian term length limit-ish
@@ -118,6 +118,7 @@
$langid, # TODO: non-English ordervalues?
$dataset
);
next if ref($ordervalue) ne "";
my $key = $dataset->base_id . '.' . $field->name . '.' . $langid;
$doc->add_value( $field_pos{$key}, $ordervalue );
}
@@ -14,12 +14,18 @@
var eprints_http_cgiroot = %s;
var eprints_oai_archive_id = %s;
var eprints_logged_in = %s;
var eprints_logged_in_userid = %s;
var eprints_logged_in_username = %s;
var eprints_logged_in_usertype = %s;
EOJ
(map { EPrints::Utils::js_string( $_ ) }
$repo->current_url( host => 1, path => 'static' ),
$repo->current_url( host => 1, path => 'cgi' ),
EPrints::OpenArchives::archive_id( $repo ) ),
defined $repo->current_user ? 'true' : 'false',
defined $repo->current_user ? $repo->current_user->get_id : 0,
defined $repo->current_user ? '"' . $repo->current_user->get_value("username") . '"' : '""',
defined $repo->current_user ? '"' . $repo->current_user->get_value("usertype") . '"' : '""', # is this safe to share?
)) );
$head->appendChild( $repo->xml->create_text_node( "\n " ) );
my $style = $head->appendChild( $repo->xml->create_element( "style",
@@ -48,7 +48,7 @@
</epc:choose>
</epc:if>
<epc:if test="!$doc.is_public() and $item.contact_email().is_set() and eprint_status = 'archive'">
| <a href="{$config{http_cgiurl}}/request_doc?docid={$doc{docid}"><epc:phrase ref="request:button" /></a>
| <a href="/request_doc?docid={$doc{docid}"><epc:phrase ref="request:button" /></a>
</epc:if>

<ul>
@@ -0,0 +1,17 @@
<?xml version="1.0" ?>
<cite:citation xmlns="http://www.w3.org/1999/xhtml"
xmlns:cite="http://eprints.org/ep3/citation"
xmlns:epc="http://eprints.org/ep3/control">

<cite:linkhere><span class="ep_name_citation"><epc:choose>
<epc:when test="$item{name}.is_set()">
<epc:choose>
<epc:when test="$item{name}{given}"><epc:print expr="$item{name}{given}"/></epc:when>
<epc:when test="email"><epc:print expr="email"/></epc:when>
<epc:otherwise><epc:print expr="username"/></epc:otherwise>
</epc:choose>
</epc:when>
<epc:when test="email"><epc:print expr="email"/></epc:when>
<epc:otherwise><epc:print expr="username"/></epc:otherwise>
</epc:choose></span></cite:linkhere>
</cite:citation>
@@ -894,7 +894,7 @@ Phrases related to the Manage Metadata Fields tool.
<epp:phrase id="Plugin/Screen/MetaField/Commit:commit_help">
<p>Note: For this to work the web server must have write access to the var, phrases and workflow directories for this repository.</p>

<p>When you commit this new metadata field its configuration will be written to the metadata fields configuration file and the appropriate columns added to the database. If you specified a name and help phrase for this field they will be added to the <tt>fields.xml</tt> phrases file for each language you specified (see also the <a href="http://eprints.org/d/?keyword=PhraseConfigFile&amp;filename=lang/en/phrases/fields.xml">phrases documentation</a>).</p>
<p>When you commit this new metadata field its configuration will be written to the metadata fields configuration file and the appropriate columns added to the database. If you specified a name and help phrase for this field they will be added to the <code>fields.xml</code> phrases file for each language you specified (see also the <a href="http://eprints.org/d/?keyword=PhraseConfigFile&amp;filename=lang/en/phrases/fields.xml">phrases documentation</a>).</p>

<p>If this field is being added to the Eprints dataset it will also be added to the Eprints submission workflow (see also the <a href="http://eprints.org/d/?keyword=WorkflowConfigFile&amp;filename=workflows/eprint/default.xml">workflow documentation</a>).</p>

@@ -1104,7 +1104,7 @@ For more information see <a href="http://eprints.org/d/?keyword=MetaFields">Meta
<epp:phrase id="metafield_fieldhelp_datasetid">The repository dataset to link the object identifier to (e.g. "eprint").</epp:phrase>
<epp:phrase id="metafield_fieldname_set_name">Named Set Filename</epp:phrase>
<epp:phrase id="metafield_fieldname_fields_set_name">Named Set</epp:phrase>
<epp:phrase id="metafield_fieldhelp_set_name">The name of the file to read the option values from (in <tt>/cfg/namedsets</tt>).</epp:phrase>
<epp:phrase id="metafield_fieldhelp_set_name">The name of the file to read the option values from (in <code>/cfg/namedsets</code>).</epp:phrase>
<epp:phrase id="metafield_fieldname_options">Set Options</epp:phrase>
<epp:phrase id="metafield_fieldname_fields_options">Options</epp:phrase>
<epp:phrase id="metafield_fieldhelp_options">A comma-separated list of values to choose from (e.g. <em>london,paris,new_york</em>)). You will need to create phrases for every defined option.</epp:phrase>
@@ -1351,7 +1351,7 @@ For more information see <a href="http://eprints.org/d/?keyword=MetaFields">Meta
<div style="padding: 0.3em; background-color: black; color: white; font-weight: bold;"><epc:pin name="action"/> by <epc:pin name="cause"/> at <epc:pin name="when"/></div>
<div style="padding: 0.3em; margin-bottom: 2em; border: solid 1px black;"><epc:pin name="details"/></div>
</epp:phrase>
<epp:phrase id="lib/history:xmlblock"><pre style="margin: 0 0 0 0; padding: 3px 3px 3px 3px; border-left: 1px dashed black; border-bottom: 1px dashed black; font-size: 13px;"><epc:pin name="xml"/></pre></epp:phrase>
<epp:phrase id="lib/history:xmlblock"><pre style="margin: 0 0 0 0; padding: 3px 3px 3px 3px; border-left: 1px dashed black; border-bottom: 1px dashed black; font-size: 100%;"><epc:pin name="xml"/></pre></epp:phrase>
<epp:phrase id="lib/history:no_such_item"><epc:pin name="datasetid"/> <epc:pin name="objectid"/> does not exist. It may have been erased.</epp:phrase>

<epp:phrase id="history_fieldname_action">Action</epp:phrase>
@@ -1845,7 +1845,7 @@ User Area CGI Scripts
<epp:phrase id="cgi/users/change_email:no_email"><p>You did not actually supply a new email address.</p></epp:phrase>
<epp:phrase id="cgi/users/change_email:mail_sent"><p>An email has been sent to <b><epc:pin name="email"/></b> containing the code required to confirm this new email address.</p><p>This code is only valid for <epc:pin name="maxdelta" />.</p></epp:phrase>
<epp:phrase id="cgi/users/change_email:changeemail">Email Change Request</epp:phrase>
<epp:phrase id="cgi/users/change_email:email_exists"><p>A user with the email address <tt><epc:pin name="email"/></tt> already exists.</p><p>If this is your email address, you should just <a href="../reset_password">reset your password</a>.</p></epp:phrase>
<epp:phrase id="cgi/users/change_email:email_exists"><p>A user with the email address <code><epc:pin name="email"/></code> already exists.</p><p>If this is your email address, you should just <a href="../reset_password">reset your password</a>.</p></epp:phrase>

<!-- status -->

@@ -1942,7 +1942,7 @@ User Area CGI Scripts
<epp:phrase id="Plugin/Screen/Admin/Config:description">View configuration files for this repository.</epp:phrase>
<epp:phrase id="Plugin/Screen/Admin/Config:back_to_config"><p><epc:pin name="link">View other configuration files</epc:pin>.</p></epp:phrase>

<epp:phrase id="Plugin/Screen/Admin/Config/View:enable_editing">To enable configuration file editing add the <tt><epc:pin name="privilege"/></tt> privilege to your user role.</epp:phrase>
<epp:phrase id="Plugin/Screen/Admin/Config/View:enable_editing">To enable configuration file editing add the <code><epc:pin name="privilege"/></code> privilege to your user role.</epp:phrase>
<epp:phrase id="Plugin/Screen/Admin/Config/View/Apache:page_title">View config file: <epc:pin name="file" /></epp:phrase>
<epp:phrase id="Plugin/Screen/Admin/Config/View/Autocomplete:page_title">View config file: <epc:pin name="file" /></epp:phrase>
<epp:phrase id="Plugin/Screen/Admin/Config/View/Citation:page_title">View config file: <epc:pin name="file" /></epp:phrase>
@@ -2043,7 +2043,7 @@ User Area CGI Scripts
<epp:phrase id="cgi/login:bind">yes (more secure)</epp:phrase>
<epp:phrase id="cgi/login:dont_bind">no (more convenient)</epp:phrase>
<epp:phrase id="cgi/login:failed">Incorrect username or password.</epp:phrase>
<epp:phrase id="cgi/login:logged_in_as"><p>You are already logged in as <epc:pin name="name"/>.</p> <p>If you wish to log in as a different user you must <a href="{$config{http_url}}/users/logout">Logout</a> first.</p></epp:phrase>
<epp:phrase id="cgi/login:logged_in_as"><p>You are already logged in as <epc:pin name="name"/>.</p> <p>If you wish to log in as a different user you must <a href="{$config{http_url}}/logout">Logout</a> first.</p></epp:phrase>
<epp:phrase id="cgi/login:title">Login</epp:phrase>
<epp:phrase id="cgi/login:message">Login successful.</epp:phrase>
<epp:phrase id="cgi/login:link_text"><p>You may now view <epc:pin name="link">your requested document</epc:pin>.</p></epp:phrase>
@@ -2230,10 +2230,10 @@ Public CGI Scripts
<epp:phrase id="cgi/register:action_submit">Register</epp:phrase>
<epp:phrase id="cgi/register:title">Register</epp:phrase>
<epp:phrase id="cgi/register:missing_field"><p>You have not filled in the &quot;<epc:pin name="fieldname"/>&quot; field.</p></epp:phrase>
<epp:phrase id="cgi/register:email_exists"><p>A user with the email address <tt><epc:pin name="email"/></tt> already exists.</p><p>Rather than register, you should just <a href="reset_password">reset your password</a>.</p></epp:phrase>
<epp:phrase id="cgi/register:email_denied"><p>Registration not allowed from this email address: <tt><epc:pin name="email"/></tt>.</p></epp:phrase>
<epp:phrase id="cgi/register:username_exists"><p>Another user already has the username <tt><epc:pin name="username"/></tt>.</p></epp:phrase>
<epp:phrase id="cgi/register:created_new_user"><p>You have registered with username <big><strong><tt><epc:pin name="username"/></tt></strong></big>.</p><p>This registration <em>will not</em> be activated until you visit the confirmation URL which has been emailed to <tt><epc:pin name="email"/></tt></p>
<epp:phrase id="cgi/register:email_exists"><p>A user with the email address <code><epc:pin name="email"/></code> already exists.</p><p>Rather than register, you should just <a href="reset_password">reset your password</a>.</p></epp:phrase>
<epp:phrase id="cgi/register:email_denied"><p>Registration not allowed from this email address: <code><epc:pin name="email"/></code>.</p></epp:phrase>
<epp:phrase id="cgi/register:username_exists"><p>Another user already has the username <code><epc:pin name="username"/></code>.</p></epp:phrase>
<epp:phrase id="cgi/register:created_new_user"><p>You have registered with username <big><strong><code><epc:pin name="username"/></code></strong></big>.</p><p>This registration <em>will not</em> be activated until you visit the confirmation URL which has been emailed to <code><epc:pin name="email"/></code></p>
</epp:phrase>
<epp:phrase id="cgi/register:account">Registration</epp:phrase>
<epp:phrase id="cgi/register:error">Error</epp:phrase>
@@ -3112,7 +3112,7 @@ PY = 2006 and OG = (Cambridge)<br />
<epp:phrase id="Plugin/Import/DefaultXML:unexpected_xml">Expected only text, found: <epc:pin name="xml" /></epp:phrase>
<epp:phrase id="Plugin/Import/DefaultXML:file_imports_disabled">Attempt to import eprint with document data expressed as a local filename. This is a security hole in normal use, and is disabled. It *is* useful when bulk importing and may be enabled by setting enable_file_imports.</epp:phrase>
<epp:phrase id="Plugin/Import/DefaultXML:file_not_exists">Could not locate file for import: <epc:pin name="href" />.</epp:phrase>
<epp:phrase id="Plugin/Import/DOI:invalid_doi">Unrecognised or invalid doi: <epc:pin name="doi" />.<br />Remote service said: <tt><epc:pin name="msg"/></tt></epp:phrase>
<epp:phrase id="Plugin/Import/DOI:invalid_doi">Unrecognised or invalid doi: <epc:pin name="doi" />.<br />Remote service said: <code><epc:pin name="msg"/></code></epp:phrase>
<epp:phrase id="Plugin/Import/DOI:duplicate_doi"><strong>Duplicate DOI: <epc:pin name="doi" /></strong>.<br />This DOI already exists in the repository: <br /><epc:pin name="msg"/></epp:phrase>

<!-- Convert plugins -->
@@ -3588,7 +3588,7 @@ PY = 2006 and OG = (Cambridge)<br />

<!-- Captcha -->

<epp:phrase id="validate:recaptcha_mismatch">The words you entered for the captcha weren't correct.</epp:phrase>
<epp:phrase id="validate:recaptcha_mismatch">There was an error with the reCAPTCHA. Please try again.</epp:phrase>
<epp:phrase id="user_fieldname_captcha">Captcha Challenge</epp:phrase>
<epp:phrase id="user_fieldhelp_captcha">To prevent robots from filling in this form you must verify this captcha.</epp:phrase>

@@ -4002,4 +4002,15 @@ To create a blank EPM entire a new id in the input and click <epc:phrase ref="Pl
<epp:phrase id="summary_page:actions"><h3>Actions (login required)</h3></epp:phrase>
<epp:phrase id="summary_page:download">Download</epp:phrase>

<!--
EPrint Template Field
-->
<epp:phrase id="eprint_fieldname_template">Template</epp:phrase>
<epp:phrase id="eprint_fieldhelp_template">Choose a template to change the way this EPrint is displayed.</epp:phrase>
<epp:phrase id="template_typename_default">Default</epp:phrase>



</epp:phrases>
@@ -48,7 +48,7 @@ Welcome to <epc:phrase ref="archive_name" />. <a href="http://www.eprints.org/d/
</div></div>

<p style="margin-top: 2em; font-size: 90%">
<epc:phrase ref="archive_name" /> supports <a href="http://www.openarchives.org"><abbr title="Open Archives Protocol for Metadata Harvesting v2.0">OAI 2.0</abbr></a> with a base URL of <tt><epc:print expr="$config{perl_url}" />/oai2</tt>
<epc:phrase ref="archive_name" /> supports <a href="http://www.openarchives.org"><abbr title="Open Archives Protocol for Metadata Harvesting v2.0">OAI 2.0</abbr></a> with a base URL of <code><epc:print expr="$config{perl_url}" />/oai2</code>
</p>


@@ -21,7 +21,7 @@
<input type="submit" value="Start defining policies" class="ep_form_action_button" />
</form>

<p>Add your policies to: <tt><epc:print expr="$config{config_path}" />/lang/en/static/policies.xpage</tt></p>
<p>Add your policies to: <code><epc:print expr="$config{config_path}" />/lang/en/static/policies.xpage</code></p>



@@ -0,0 +1,56 @@
function validateHistorySearch()
{
//reset warning div
var warning = document.getElementById('ep_messages');
var warning_content = document.getElementById('warning_content');
warning.className = "history_warning";
warning_content.innerHTML = "";

var problems = [];

var start_date_string = document.getElementById('start_date').value;
var end_date_string = document.getElementById('end_date').value;

var date_re = /^(\d{4})-?(\d{1,2})?-?(\d{1,2})?$/;

var start_date_result = date_re.test(start_date_string);
var end_date_result = date_re.test(end_date_string);

if( start_date_string != "" && !start_date_result )
{
problems.push("Invalid start date");
}
if( end_date_string != "" && !end_date_result )
{
problems.push("Invalid end date");
}

var start_date = new Date(start_date_string);
var end_date = new Date(end_date_string);
if( end_date <= start_date )
{
problems.push("End date must be after start date");
}

if( problems.length == 0 )
{
return true;
}
else
{
warning.classList.add("show");
var ul = document.createElement('ul');
for( var i = 0; i < problems.length; i++)
{
var li = document.createElement('li');
li.appendChild( document.createTextNode(problems[i]) );
ul.appendChild(li);
}
warning_content.appendChild(ul);

return false;
}



}
@@ -26,11 +26,6 @@ To add a Captcha to document requests add a cfg.d containing:
$c->{recaptcha}->{private_key} = "your private key";
$c->{recaptcha}->{public_key} = "your public key";
$c->add_dataset_field( "request", {
name => "captcha",
type => "recaptcha",
});
Then uncomment the following line to add the captcha to the form:
<component surround="None"><field ref="captcha" /></component>
@@ -301,6 +301,7 @@ use EPrints::DataObj::Triple;
use EPrints::DataObj::UploadProgress;
use EPrints::DataObj::User;
use EPrints::DataSet;
use EPrints::DOI;
use EPrints::Email;
use EPrints::Extras;
use EPrints::Index;
@@ -524,7 +525,7 @@ sub abort
</head>
<body>
<h1>EPrints System Error</h1>
<p><tt>$htmlerrmsg</tt></p>
<p><code>$htmlerrmsg</code></p>
</body>
</html>
END
@@ -632,7 +633,7 @@ sub abort
</head>
<body>
<h1>EPrints System Error</h1>
<p><tt>$htmlerrmsg</tt></p>
<p><code>$htmlerrmsg</code></p>
</body>
</html>
END
@@ -22,6 +22,7 @@ sub apache_conf
my $id = $repo->get_id;
my $adminemail = $repo->config( "adminemail" );
my $host = $repo->config( "host" );
$host = $repo->config( "securehost" ) if !EPrints::Utils::is_set( $host ) && EPrints::Utils::is_set( $repo->config( "securehost" ) );
my $port = $repo->config( "port" );
$port = 80 if !defined $port;
my $hostport = $host;
@@ -69,41 +70,39 @@ EOC
ServerName $host
$aliases
ServerAdmin $adminemail
Include $base_path/cfg/perl_module_isolation_vhost.conf
<Location "$http_root">
PerlSetVar EPrints_ArchiveID $id
Options +ExecCGI
<IfModule mod_authz_core.c>
Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Allow from all
</IfModule>
</Location>
EOC

# backwards compatibility
my $apachevhost = $repo->config( "config_path" )."/apachevhost.conf";
if( -e $apachevhost )
{
$conf .= " # Include any legacy directives\n";
$conf .= " Include $apachevhost\n\n";
}
# check if we enabled site-wide https
$http_url = $repo->config("http_url") || "";
if ( substr( $http_url, 0, 5 ) ne "https")
{
# backwards compatibility
$conf .= " Include $base_path/cfg/perl_module_isolation_vhost.conf\n\n";
$conf .= _location( $http_root, $id );
my $apachevhost = $repo->config( "config_path" )."/apachevhost.conf";
if( -e $apachevhost )
{
$conf .= " # Include any legacy directives\n";
$conf .= " Include $apachevhost\n\n";
}

$conf .= <<EOC;
$conf .= <<EOC;
# Note that PerlTransHandler can't go inside
# a "Location" block as it occurs before the
# Location is known.
PerlTransHandler +EPrints::Apache::Rewrite
</VirtualHost>
EOC
}
else
{
$http_url = $http_url . '/' if substr( $http_url, -1 ) ne '/';
$conf .= " RedirectPermanent / $http_url\n";
}

$conf .= "</VirtualHost>\n\n";

return $conf;
}
@@ -139,6 +138,28 @@ sub apache_secure_conf
EOC
}

sub _location
{
my( $http_root, $id, $secure ) = @_;

$secure = $secure ? 'PerlSetVar EPrints_Secure yes' : '';

return <<EOC;
<Location "$http_root">
PerlSetVar EPrints_ArchiveID $id
$secure
Options +ExecCGI
<IfModule mod_authz_core.c>
Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Allow from all
</IfModule>
</Location>
EOC
}

1;

=head1 COPYRIGHT
@@ -148,6 +169,7 @@ EOC
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
This software may be used with permission and must not be redistributed.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
@@ -1001,7 +1001,7 @@ sub handler

my $user = $repo->current_user;

my( $rc, $owner ) = on_behalf_of( $repo, $r, $user );
my( $rc, $owner ) = $self->on_behalf_of( $user );
return $rc if $rc != OK;

# Subject URI's redirect to the top of that particular subject tree
@@ -1756,12 +1756,15 @@ sub servicedocument

my $user = $repo->current_user;
EPrints->abort( "unprotected" ) if !defined $user; # Rewrite foobar
my $on_behalf_of = on_behalf_of( $repo, $r, $user );
if( $on_behalf_of->{status} != OK )
my ( $status, $on_behalf_of ) = $self->on_behalf_of( $user );
if( $status != OK )
{
return sword_error( $repo, $r, %$on_behalf_of );
return $self->sword_error(
status => HTTP_FORBIDDEN,
href => "http://purl.org/net/sword/error/TargetOwnerUnknown",
summary => "Target user unknown or no permission to act on-behalf-of",
);
}
$on_behalf_of = $on_behalf_of->{on_behalf_of};

# SERVICE and WORKSPACE DEFINITION

@@ -1855,13 +1858,10 @@ sub servicedocument

sub on_behalf_of
{
my( $repo, $r, $user ) = @_;
my( $self, $user ) = @_;

my $err = {
status => HTTP_FORBIDDEN,
href => "http://purl.org/net/sword/error/TargetOwnerUnknown",
summary => "Target user unknown or no permission to act on-behalf-of",
};
my $repo = $self->repository;
my $r = $self->request;

my $on_behalf_of =
$r->headers_in->{'On-Behalf-Of'} || # SWORD 2.0
@@ -1871,9 +1871,9 @@ sub on_behalf_of

my $owner = $repo->user_by_username( $on_behalf_of );

return sword_error($repo, $r, %$err )
return ( HTTP_FORBIDDEN, undef )
if !defined $owner;
return sword_error($repo, $r, %$err )
return ( HTTP_FORBIDDEN, undef )
if !$user->allow( "user/mediate", $owner );

return( OK, $owner );
@@ -141,7 +141,7 @@ sub handler
return $rc if defined $rc;

# /archive/ redirect
if( $uri =~ m! ^$urlpath/archive/(.*) !x )
if( $uri =~ m! ^$urlpath/archive/+(.*) !x )
{
return redir( $r, "$urlpath/$1$args" );
}
@@ -318,7 +318,7 @@ sub handler
}

# sitemap.xml (nb. only works if site is in root / of domain.)
if( $uri =~ m! ^$urlpath/sitemap(?:-sc)\.xml$ !x )
if( $uri =~ m! ^$urlpath/sitemap(?:-sc)?\.xml$ !x )
{
$r->handler( 'perl-script' );

@@ -419,7 +419,7 @@ if ($repository->config("use_long_url_format"))
#this will serve a document, static files(.include files) or abstract page.
my $accept = EPrints::Apache::AnApache::header_in( $r, "Accept" );
my $method = eval {$r->method} || "";
if ( $method eq "GET" ## request method must be GET
if ( ( $method eq "GET" || $method eq "HEAD" ) ## request method must be GET or HEAD
&& (index(lc($accept), "text/html") != -1 || index(lc($accept),"*/*") != -1 || $accept eq "" ) ## header must be text/html, or */*, or undef
&& ($uri !~ m!^${urlpath}/id/eprint/0*[1-9][0-9]*/contents$! ) ## uri must not be id/eprint/XX/contents
&& ($uri =~ s! ^${urlpath}/id/eprint/(0*)([1-9][0-9]*)\b !!x ) ## uri must be id/eprint/XX
@@ -592,7 +592,7 @@ if(not $repository->config("use_long_url_format"))
# print STDERR "** EPRINT ** no current user, uri is '$uri' args are '$args' eprintid is '$eprintid' ($v)\n" unless $user;
# print STDERR "** EPRINT ** current user is " . $user->get_value("username") . "\n" if $user;

if( !$user && $v && $v eq "1" )
if( !$user && defined $v && $v == 1 )
{
my $redir_url = "${login_url}?target=${uri}${eprintid}";
return redir( $r, $redir_url );
@@ -608,7 +608,7 @@ if(not $repository->config("use_long_url_format"))
# Only allow specific users to access abstract pages.
{
my $v = $repository->get_conf( "login_required_for_eprints", "enable" );
if( $v )
if( defined $v && $v == 1 )
{
# if we are here then access to abstracts etc are restricted, and we are logged in as a user
my $fn = $repository->get_conf( "eprints_access_restrictions_callback" );
@@ -835,6 +835,16 @@ if(not $repository->config("use_long_url_format"))
return OK;
}

sub redir_permanent
{
my( $r, $url ) = @_;

EPrints::Apache::AnApache::send_status_line( $r, 301, "Moved Permanently" );
EPrints::Apache::AnApache::header_out( $r, "Location", $url );
EPrints::Apache::AnApache::send_http_header( $r );
return DONE;
}

sub redir
{
my( $r, $url ) = @_;
@@ -41,11 +41,17 @@ sub handler
last;
}
if( !defined $robots )
{
{
my $http_cgiroot = $repository->config( 'http_cgiroot' );
my $https_cgiroot = $repository->config( 'https_cgiroot' );
$robots = <<END;
User-agent: *
Disallow: /cgi/
Disallow: $http_cgiroot/
END
if( $http_cgiroot ne $https_cgiroot )
{
$robots .= "\nDisallow: $https_cgiroot/";
}
}

my $sitemap = "Sitemap: ".$repository->config( 'http_url' )."/sitemap.xml";
@@ -358,9 +358,9 @@ END
$urlh2=~s/'/&squot;/g;
$msg.=<<END;
<p>Cut and paste HTML for pop-up window:</p>
<div style="margin-left: 10px"><tt>
<div style="margin-left: 10px"><code>
&lt;a href="#" onclick="javascript:window.open( '$urlh2', 'transclude_window', 'width=666, height=444, scrollbars');"&gt;$title&lt;/a&gt;
</tt></div>
</code></div>
</div>
END
}
@@ -0,0 +1,324 @@
######################################################################
#
# EPrints::DOI
#
######################################################################
#
#
######################################################################

=pod
=for Pod2Wiki
=head1 NAME
B<EPrints::DOI> - DOI utility methods
=head1 DESCRIPTION
This module contains utility methods for parsing and displaying DOIs.
=head1 SYNOPSIS
use EPrints;
my $doi = DOI->parse( "doi:10.1000/foo#bar" );
print "Parsed $doi\n";
# => "Parsed 10.1000/foo#bar"
my $uri = $doi->to_uri;
# => URI->new("https://doi.org/10.1000/foo%23bar")
=head1 METHODS
=over 4
=cut

package EPrints::DOI;

use URI::Escape;

use warnings;
use strict;

use overload
'""' => \&_stringify,
'.' => \&_cat,
'.=' => \&_cat0;

#
# Creates a new DOI object.
#
# %opts = (
# dir => $directory_code,
# reg => $registrant_code,
# dss => $doi_suffix_string,
# )
#
# `dir` is always "10"
#
# A DOI looks like: "${dir}.${reg}/${dss}"
#
sub new
{
my( $class, %opts ) = @_;

my %self = ();

my @keys = qw/ dir reg dss /;
@self{ @keys } = @opts{ @keys };

bless \%self, $class;
}

=item B<< $new_doi = $doi->clone >>
Creates a new DOI which is a copy of this one.
=cut

sub clone
{
my( $self ) = @_;
return ref($self)->new( %{$self} );
}

#
# Adds $rest to dss on a new DOI.
#
sub _cat
{
my( $self, $rest ) = @_;
return $self->clone->_cat0( $rest );
}

#
# Adds $rest to dss of this DOI.
#
sub _cat0
{
my( $self, $rest ) = @_;

$self->{dss} .= $rest;
return $self;
}

=item B<< $doi = EPrints::DOI->parse( $string, %opts ) >>
Parses a DOI from a string.
Recognises the common forms:
=over 2
=item *
"doi:10.1000/foo#bar"
=item *
"https://doi.org/10.1000/foo%23bar"
=item *
"info:doi/10.1000/foo%23bar"
=back
etc.
Returns C<undef> if parsing fails.
Options:
=over 2
=item B<< test => 1 >>
Just tests that the string is parseable, and returns a boolean value.
=back
=cut

sub parse
{
my( $class, $string, %opts ) = @_;

my $doi = "$string";

if( $doi =~ s!^https?://(?:(?:dx\.)?doi\.org|doi\.acm\.org|doi\.ieeecomputersociety\.org)/+(?:doi:)?!!i )
{
# It looks like a HTTP proxy URL.
$doi = uri_unescape( $doi );
}
elsif( $doi =~ s!^info:doi/!!i )
{
# It looks like an info URI.
$doi = uri_unescape( $doi );
}
else
{
# It's probably a DOI string.
$doi =~ s!^doi:!!i;

# final sanity check
if( $doi =~ m!^10.[^/]+%2F!i )
{
$doi = uri_unescape( $doi );
}
}

utf8::decode( $doi ) unless utf8::is_utf8( $doi );

# ANSI/NISO Z39.84-2005
# <http://www.niso.org/apps/group_public/download.php/6587/Syntax%20for%20the%20Digital%20Object%20Identifier.pdf>
if( $doi =~ m!^(10)\.([^/]+)/(\p{Graph}(?:[^/]\p{Graph}*)?)! )
{
# FIXME: $2 and $3 may contain characters outside of /\p{Graph}/
return 1 if $opts{test};
return $class->new( dir=>$1, reg=>$2, dss=>$3 );
}
else
{
return 0 if $opts{test};
#warn "'$string' is not a valid DOI string";
return undef;
}
}

=item B<< $string = $doi->to_string >>
Returns a simple string representation of this DOI.
For example "doi:10.1000/foo#bar"
=over 4
=item B<< noprefix => 1 >>
Disable the 'doi:' prefix (enabled by default).
=back
=cut

sub to_string
{
my( $self, %opts ) = @_;
return ( $opts{noprefix} ? '' : 'doi:' )
. $self->{dir}
. '.'
. $self->{reg}
. '/'
. $self->{dss};
}

sub _stringify
{
return shift->to_string;
}

#
# Returns a percent-encoded "dir.reg/dss" string.
#
sub _uri_path
{
my( $self ) = @_;
return $self->{dir}
. '.'
. uri_escape_utf8( $self->{reg} )
. '/'
. uri_escape_utf8( $self->{dss} );
}

#
# Returns an "info:doi/..." URI string.
#
sub _info_uri
{
my( $self ) = @_;
return 'info:doi/' . $self->_uri_path;
}

#
# Returns a "https://doi.org/..." URI string.
#
sub _http_url
{
my( $self ) = @_;
return 'https://doi.org/' . $self->_uri_path;
}

=item B<< $uri = $doi->to_uri( %opts ) >>
Returns a URI.
For example: "https://doi.org/10.1000/foo%23bar"
=over 4
=item B<< info => 1 >>
Returns an 'info:' URI instead of 'https:'.
=back
=cut

sub to_uri
{
my( $self, %opts ) = @_;

if( $opts{info} )
{
return URI->new( $self->_info_uri );
}
else
{
return URI->new( $self->_http_url );
}
}

######################################################################
=pod
=back
=cut
######################################################################

1; # For use/require success


=head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2017 Queensland University of Technology.
=for COPYRIGHT END
=for LICENSE BEGIN
This file is part of EPrints L<http://www.eprints.org/>.
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.
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.
You should have received a copy of the GNU Lesser General Public
License along with EPrints. If not, see L<http://www.gnu.org/licenses/>.
=for LICENSE END
@@ -1167,8 +1167,8 @@ sub render_citation_link
{
my( $self , $style , %params ) = @_;

$params{url} = $self->get_url;
$params{url} = $self->get_url unless $params{url};

return $self->render_citation( $style, %params );
}

@@ -1737,6 +1737,10 @@ Show thumbnail/preview only on public docs.
Show thumbnail/preview on all docs if poss.
=item with_link => 0
Do not link.
=back
=cut
@@ -1746,6 +1750,7 @@ sub render_icon_link
my( $self, %opts ) = @_;

$opts{public} = 1 unless defined $opts{public};
$opts{with_link} = 1 unless defined $opts{with_link};
if( $opts{public} && !$self->is_public )
{
$opts{preview} = 0;
@@ -1778,15 +1783,23 @@ sub render_icon_link
$aopts{onmouseover} = "EPJS_ShowPreview( event, '$preview_id' );";
$aopts{onmouseout} = "EPJS_HidePreview( event, '$preview_id' );";
}
my $a = $self->{session}->make_element( "a", %aopts );
$a->appendChild( $self->{session}->make_element(
my $f = $self->{session}->make_doc_fragment;
my $img = $self->{session}->make_element(
"img",
class=>"ep_doc_icon",
alt=>"[img]",
src=>$self->icon_url( public=>$opts{public} ),
border=>0 ));
my $f = $self->{session}->make_doc_fragment;
$f->appendChild( $a ) ;
border=>0 );
if ( $opts{with_link} )
{
my $a = $self->{session}->make_element( "a", %aopts );
$a->appendChild( $img );
$f->appendChild( $a );
}
else
{
$f->appendChild( $img );
}
if( $opts{preview} )
{
my $preview = $self->{session}->make_element( "div",
@@ -244,6 +244,7 @@ sub get_system_field_info
make_value_orderkey => "EPrints::DataObj::EPrint::order_issues_newest_open_timestamp",
render_value=>"EPrints::DataObj::EPrint::render_issues",
volatile => 1,
export_as_xml => 0,
},

{ name=>"item_issues_count", type=>"int", volatile=>1 },
@@ -261,6 +262,7 @@ sub get_system_field_info
render_value=>"EPrints::DataObj::EPrint::render_edit_lock",
},

{ name=>"template", type=>"namedset", set_name=>"template", required=>1 },
)
}

@@ -2051,7 +2053,9 @@ sub in_editorial_scope_of
my $searches = $possible_editor->get_value( 'editperms' );
if( scalar @{$searches} == 0 )
{
return 1;
# test for editperms_none_by_default role, if absent allow edit as per previous versions
my $has_role = $possible_editor->has_role( 'editperms_none_by_default' );
return ($has_role) ? 0 : 1;
}

foreach my $s ( @{$searches} )
@@ -290,8 +290,9 @@ sub _execute
my $rc = eval { $plugin->$action( @params ) };
if( $@ )
{
$self->message( "error", $xml->create_text_node( "Error during execution: $@" ) );
$self->set_value( "description", $@ );
my $error_message = $@;
$self->message( "error", $xml->create_text_node( "Error during execution: $error_message" ) );
$self->set_value( "description", $error_message );
return EPrints::Const::HTTP_INTERNAL_SERVER_ERROR;
}

@@ -944,8 +944,9 @@ sub characters
{
use bytes;
$_ .= $data->{Data};
print $tmpfile MIME::Base64::decode_base64( substr($_,0,length($_) - length($_)%77) );
$_ = substr($_,length($_) - length($_)%77);
$_ =~ s/\s+//g;
print $tmpfile MIME::Base64::decode_base64( substr($_,0,length($_) - length($_)%4) );
$_ = substr($_,length($_) - length($_)%4);
}
}
}
@@ -52,7 +52,7 @@ sub get_system_field_info
{ name=>"userid", type=>"itemref",
datasetid=>"user", required=>0 },

{ name=>"email", type=>"text", required=>1 },
{ name=>"email", type=>"email", required=>1 },

{ name=>"requester_email", type=>"email", required=>1 },

@@ -62,6 +62,7 @@ sub get_system_field_info

{ name=>"code", type=>"text", required=>0 },

{ name => "captcha",type => "recaptcha" },
);
}

@@ -313,18 +313,18 @@ sub remove_all


######################################################################
# =pod
#
# =item $subject = EPrints::DataObj::Subject::create( $session, $id, $name, $parents, $depositable )
#
# Creates a new subject in the database. $id is the ID of the subject,
# $name is a multilang data structure with the name of the subject in
# one or more languages. eg. { en=>"Trousers", en-us=>"Pants}. $parents
# is a reference to an array containing the ID's of one or more other
# subjects (don't make loops!). If $depositable is true then eprints may
# belong to this subject.
#
# =cut
=pod
=item $subject = EPrints::DataObj::Subject::create( $session, $id, $name, $parents, $depositable )
Creates a new subject in the database. $id is the ID of the subject,
$name is a multilang data structure with the name of the subject in
one or more languages. eg. { en=>"Trousers", en-us=>"Pants}. $parents
is a reference to an array containing the ID's of one or more other
subjects (don't make loops!). If $depositable is true then eprints may
belong to this subject.
=cut
######################################################################

sub create
@@ -348,15 +348,15 @@ sub create
}

######################################################################
# =pod
#
# =item $dataobj = EPrints::DataObj::Subject->create_from_data( $session, $data, $dataset )
#
# Returns undef if a bad (or no) subjectid is specified.
#
# Otherwise calls the parent method in EPrints::DataObj.
#
# =cut
=pod
=item $dataobj = EPrints::DataObj::Subject->create_from_data( $session, $data, $dataset )
Returns undef if a bad (or no) subjectid is specified.
Otherwise calls the parent method in EPrints::DataObj.
=cut
######################################################################

sub create_from_data
@@ -384,11 +384,13 @@ END
}

######################################################################
#
# @subject_ids = $subject->_get_ancestors
#
# Get the ancestors of a given subject.
#
=pod
=item @subject_ids = $subject->_get_ancestors
Get the ancestors of a given subject.
=cut
######################################################################

sub _get_ancestors
@@ -408,13 +410,17 @@ sub _get_ancestors
return @ancestors;
}

######################################################################
=pod
=item $subject = $subject->top()
Returns the subject that is at the top of this subject's tree (which may be this subject).
Returns undef if the subject is not part of a tree.
=cut
######################################################################

sub top
{
@@ -643,19 +649,6 @@ sub get_paths
return @paths;
}


######################################################################
#
# ( $tags, $labels ) = get_postable( $session, $user )
#
# Returns a list of the subjects that can be posted to by $user. They
# are returned in a tuple, the first element being a reference to an
# array of tags (for the ordering) and the second being a reference
# to the hash mapping tags to full names. [STATIC]
#
######################################################################


######################################################################
=pod
@@ -714,11 +707,13 @@ sub get_subjects
}

######################################################################
#
# $subjects = $subject->_get_subjects2( $postableonly, $hidenode, $nestids, $subjectmap, $rmap, $prefix )
#
# Recursive function used by get_subjects.
#
=pod
=item $subjects = $subject->_get_subjects2( $postableonly, $hidenode, $nestids, $subjectmap, $rmap, $prefix )
Recursive function used by get_subjects.
=cut
######################################################################

sub _get_subjects2
@@ -822,17 +817,19 @@ sub get_all
}

######################################################################
#
# @eprints = $subject->posted_eprints( $dataset )
#
# Deprecated. This method is no longer used by eprints, and may be
# removed in a later release.
#
# Return all the eprints which are in this subject (or below it in
# the tree, its children etc.) It searches all fields of type subject.
#
# $dataset is the dataset to return eprints from.
#
=pod
=item @eprints = $subject->posted_eprints( $dataset )
Deprecated. This method is no longer used by eprints, and may be
removed in a later release.
Return all the eprints which are in this subject (or below it in
the tree, its children etc.) It searches all fields of type subject.
$dataset is the dataset to return eprints from.
=cut
######################################################################

sub posted_eprints
@@ -948,6 +945,17 @@ sub valid_id
# {
# }

######################################################################
=pod
=item $subj->render_description()
undocumented
=cut
######################################################################
#

sub render_description
{
my( $self ) = @_;
@@ -207,6 +207,10 @@ sub get_system_field_info
text_index => 0,
volatile => 1,
},
{
name => "captcha",
type => "recaptcha",
}
)
};

@@ -579,12 +583,8 @@ sub owned_eprints_list
}

my $list = &$fn( $self->{session}, $self, $opts{dataset} );
if (!$searchexp->is_blank()) { $list = $list->intersect( $searchexp->perform_search ); }


#MBA-85 (rwf1v07/08/03/2018): if statement doesn't return true when search filter comprises of eprint state and so intersect doesn't happen
#as 'get_users_owned_eprints' is used so rarely, and because this if statement only seems to check if there is nothing to do, seems harmless to remove it
#if (!$searchexp->is_blank()) { $list = $list->intersect( $searchexp->perform_search ); }
$list = $list->intersect( $searchexp->perform_search );
return $list;
}

@@ -818,6 +818,28 @@ and modify this record.
=cut
######################################################################

sub get_url
{
my( $self ) = @_;

return $self->get_control_url;
}


######################################################################
=pod
=begin InternalDoc
=item $url = $dataobj->get_control_url
Returns the URL for the control page for this user.
=end InternalDoc
=cut
######################################################################

sub get_control_url
{
my( $self ) = @_;
@@ -161,6 +161,7 @@ sub build_connection_string
{
$dsn.= ";mysql_socket=".$params{dbsock};
}
$dsn.= ";mysql_enable_utf8=1";
return $dsn;
}

@@ -1093,7 +1094,8 @@ sub create_index

return 1 unless @columns;

my $index_name = join('_', $table, $columns[0], scalar @columns );
# Note: limit to 64 characters
my $index_name = join('_', substr($columns[0], 0, 60), scalar @columns - 1 );

my $sql = sprintf("CREATE INDEX %s ON %s (%s)",
$self->quote_identifier( $index_name ),
@@ -1120,7 +1122,7 @@ sub create_unique_index
return 1 unless @columns;

# MySQL max index name length is 64 chars
my $index_name = substr(join("_",$table,@columns),0,63);
my $index_name = substr(join("_",@columns),0,63);

my $sql = "CREATE UNIQUE INDEX $index_name ON $table(".join(',',map { $self->quote_identifier($_) } @columns).")";

@@ -250,7 +250,7 @@ sub render_related_url
{
my $li = $session->make_element( "li" );
my $link = $session->render_link( $row->{url} );
if( defined $row->{type} )
if( EPrints::Utils::is_set( $row->{type} ) )
{
$link->appendChild( $fmap->{type}->render_single_value( $session, $row->{type} ) );
}
@@ -300,32 +300,19 @@ If the field looks like it contains a DOI then link it.

sub render_possible_doi
{
my( $session, $field, $value ) = @_;
my( $session, $field, $value ) = @_;

$value = "" unless defined $value;
if( $value =~ m!^
(?:https?://(?:dx\.)?doi\.org/)? # add this again later anyway
(?:doi:?\s*)? # don't need any namespace stuff
(10(\.[^./]+)+/.+) # the actual DOI => $1
!ix )
{
# The only part we care about is the actual DOI.
$value = $1;
}
else
my $doi = EPrints::DOI->parse( $value );
if( !$doi )
{
# Doesn't look like a DOI we can turn into a link,
# so just render it as-is.
return $session->make_text( $value );
}

my $url = "https://doi.org/$value";
my $link = $session->render_link( $url, "_blank" );
my $render_as_is = $session->get_conf( "render_possible_doi_as_is" );
$render_as_is ||= 0;
$link->appendChild( $session->make_text( $url ) ) unless $render_as_is;
$link->appendChild( $session->make_text( $value ) ) if $render_as_is;
return $link;
my $link = $session->render_link( $doi->to_uri, "_blank" );
$link->appendChild( $session->make_text( $doi->to_string( noprefix=>1 ) ) );
return $link;
}


@@ -9,30 +9,20 @@


=pod
=head1 NAME
B<EPrints::Index::Tokenizer> - text indexing utility methods
=head1 DESCRIPTION
This module provides utility methods for processing free text into indexable things.
=head1 METHODS
=over 4
=cut

package EPrints::Index::Tokenizer;

######################################################################
=pod
=item @words = EPrints::Index::Tokenizer::split_words( $session, $utext )
Splits a utf8 string into individual words.
=cut
######################################################################

@@ -53,34 +43,24 @@ sub split_words

return split /[^\w']+/, $utext;
}
=item @terms = EPrints::Index::Tokenizer::split_search_value( $session, $value )
Splits and returns $value into search terms.
=cut
sub split_search_value
{
my( $session, $value ) = @_;
# transliterate to English
$value = apply_mapping( $session, $value );
return split /[^\w'\*]+/, $value;
}

######################################################################
=pod
=item $utext2 = EPrints::Index::Tokenizer::apply_mapping( $session, $utext )
Replaces certain unicode characters with ASCII equivalents and returns
the new string.
This is used before indexing words so that things like umlauts will
be ignored when searching.
=cut
######################################################################

@@ -107,108 +87,109 @@ sub apply_mapping

# This map is used to convert Unicode characters
# to ASCII characters below 127, in the word index.
# This means that the word Fête is indexed as 'fete' and
# "fete" or "fête" will match it.
# This means that the word Fête is indexed as 'fete' and
# "fete" or "fête" will match it.
# There's no reason mappings have to be a single character.

$EPrints::Index::FREETEXT_CHAR_MAPPING = {
chr(0x0027) => "'", # '
chr(0x00a1) => '!', # ¡
chr(0x00a2) => 'c', # ¢
chr(0x00a3) => 'L', # £
chr(0x00a4) => 'o', # ¤
chr(0x00a5) => 'Y', # ¥
chr(0x00a6) => '|', # ¦
chr(0x00a7) => 'S', # §
chr(0x00a8) => '"', # ¨
chr(0x00a9) => '(c)', # ©
chr(0x00aa) => 'a', # ª
chr(0x00ab) => '<<', # «
chr(0x00ac) => '-', # ¬
chr(0x00ad) => '-', # ­
chr(0x00ae) => '(R)', # ®
chr(0x00af) => '-', # ¯
chr(0x00b0) => 'o', # °
chr(0x00b1) => '+-', # ±
chr(0x00b2) => '2', # ²
chr(0x00b3) => '3', # ³
chr(0x00b5) => 'u', # µ
chr(0x00b6) => 'q', #
chr(0x00b7) => '.', # ·
chr(0x00b8) => ',', # ¸
chr(0x00b9) => '1', # ¹
chr(0x00ba) => 'o', # º
chr(0x00bb) => '>>', # »
chr(0x00bc) => '1/4', # ¼
chr(0x00bd) => '1/2', # ½
chr(0x00be) => '3/4', # ¾
chr(0x00bf) => '?', # ¿
chr(0x00c0) => 'A', # À
chr(0x00c1) => 'A', # Á
chr(0x00c2) => 'A', # Â
chr(0x00c3) => 'A', # Ã
chr(0x00c4) => 'Ae', # Ä
chr(0x00c6) => 'AE', # Æ
chr(0x00c7) => 'C', # Ç
chr(0x00c8) => 'E', # È
chr(0x00c9) => 'E', # É
chr(0x00ca) => 'E', # Ê
chr(0x00cb) => 'E', # Ë
chr(0x00cc) => 'I', # Ì
chr(0x00cd) => 'I', # Í
chr(0x00ce) => 'I', # Î
chr(0x00cf) => 'I', # Ï
chr(0x00d0) => 'D', # Ð
chr(0x00d1) => 'N', # Ñ
chr(0x00d2) => 'O', # Ò
chr(0x00d3) => 'O', # Ó
chr(0x00d4) => 'O', # Ô
chr(0x00d5) => 'O', # Õ
chr(0x00d6) => 'Oe', # Ö
chr(0x00d7) => 'x', # ×
chr(0x00d8) => 'O', # Ø
chr(0x00d9) => 'U', # Ù
chr(0x00da) => 'U', # Ú
chr(0x00db) => 'U', # Û
chr(0x00dc) => 'Ue', # Ü
chr(0x00dd) => 'Y', # Ý
chr(0x00de) => 'TH', # Þ
chr(0x00df) => 'ss', # ß
chr(0x00e0) => 'a', # à
chr(0x00e1) => 'a', # á
chr(0x00e2) => 'a', # â
chr(0x00e3) => 'a', # ã
chr(0x00e4) => 'ae', # ä
chr(0x00e5) => 'a', # å
chr(0x00e6) => 'ae', # æ
chr(0x00e7) => 'c', # ç
chr(0x00e8) => 'e', # è
chr(0x00e9) => 'e', # é
chr(0x00ea) => 'e', # ê
chr(0x00eb) => 'e', # ë
chr(0x00ec) => 'i', # ì
chr(0x00ed) => 'i', # í
chr(0x00ee) => 'i', # î
chr(0x00ef) => 'i', # ï
chr(0x00f0) => 'd', # ð
chr(0x00f1) => 'n', # ñ
chr(0x00f2) => 'o', # ò
chr(0x00f3) => 'o', # ó
chr(0x00f4) => 'o', # ô
chr(0x00f5) => 'o', # õ
chr(0x00f6) => 'oe', # ö
chr(0x00f7) => '/', # ÷
chr(0x00f8) => 'oe', # ø
chr(0x00f9) => 'u', # ù
chr(0x00fa) => 'u', # ú
chr(0x00fb) => 'u', # û
chr(0x00fc) => 'ue', # ü
chr(0x00fd) => 'y', # ý
chr(0x00fe) => 'th', # þ
chr(0x00ff) => 'y', # ÿ
chr(0x00a1) => '!', # ¡
chr(0x00a2) => 'c', # ¢
chr(0x00a3) => 'L', # £
chr(0x00a4) => 'o', # ¤
chr(0x00a5) => 'Y', # ¥
chr(0x00a6) => '|', # ¦
chr(0x00a7) => 'S', # §
chr(0x00a8) => '"', # ¨
chr(0x00a9) => '(c)', # ©
chr(0x00aa) => 'a', # ª
chr(0x00ab) => '<<', # «
chr(0x00ac) => '-', # ¬
chr(0x00ad) => '-', # ­
chr(0x00ae) => '(R)', # ®
chr(0x00af) => '-', # ¯
chr(0x00b0) => 'o', # °
chr(0x00b1) => '+-', # ±
chr(0x00b2) => '2', # ²
chr(0x00b3) => '3', # ³
chr(0x00b5) => 'u', # µ
chr(0x00b6) => 'q', #
chr(0x00b7) => '.', # ·
chr(0x00b8) => ',', # ¸
chr(0x00b9) => '1', # ¹
chr(0x00ba) => 'o', # º
chr(0x00bb) => '>>', # »
chr(0x00bc) => '1/4', # ¼
chr(0x00bd) => '1/2', # ½
chr(0x00be) => '3/4', # ¾
chr(0x00bf) => '?', # ¿
chr(0x00c0) => 'A', # À
chr(0x00c1) => 'A', # Á
chr(0x00c2) => 'A', # Â
chr(0x00c3) => 'A', # Ã
chr(0x00c4) => 'Ae', # Ä
chr(0x00c6) => 'AE', # Æ
chr(0x00c7) => 'C', # Ç
chr(0x00c8) => 'E', # È
chr(0x00c9) => 'E', # É
chr(0x00ca) => 'E', # Ê
chr(0x00cb) => 'E', # Ë
chr(0x00cc) => 'I', # Ì
chr(0x00cd) => 'I', # Í
chr(0x00ce) => 'I', # Î
chr(0x00cf) => 'I', # Ï
chr(0x00d0) => 'D', # Ð
chr(0x00d1) => 'N', # Ñ
chr(0x00d2) => 'O', # Ò
chr(0x00d3) => 'O', # Ó
chr(0x00d4) => 'O', # Ô
chr(0x00d5) => 'O', # Õ
chr(0x00d6) => 'Oe', # Ö
chr(0x00d7) => 'x', # ×
chr(0x00d8) => 'O', # Ø
chr(0x00d9) => 'U', # Ù
chr(0x00da) => 'U', # Ú
chr(0x00db) => 'U', # Û
chr(0x00dc) => 'Ue', # Ü
chr(0x00dd) => 'Y', # Ý
chr(0x00de) => 'TH', # Þ
chr(0x00df) => 'ss', # ß
chr(0x00e0) => 'a', # à
chr(0x00e1) => 'a', # á
chr(0x00e2) => 'a', # â
chr(0x00e3) => 'a', # ã
chr(0x00e4) => 'ae', # ä
chr(0x00e5) => 'a', # å
chr(0x00e6) => 'ae', # æ
chr(0x00e7) => 'c', # ç
chr(0x00e8) => 'e', # è
chr(0x00e9) => 'e', # é
chr(0x00ea) => 'e', # ê
chr(0x00eb) => 'e', # ë
chr(0x00ec) => 'i', # ì
chr(0x00ed) => 'i', # í
chr(0x00ee) => 'i', # î
chr(0x00ef) => 'i', # ï
chr(0x00f0) => 'd', # ð
chr(0x00f1) => 'n', # ñ
chr(0x00f2) => 'o', # ò
chr(0x00f3) => 'o', # ó
chr(0x00f4) => 'o', # ô
chr(0x00f5) => 'o', # õ
chr(0x00f6) => 'oe', # ö
chr(0x00f7) => '/', # ÷
chr(0x00f8) => 'oe', # ø
chr(0x00f9) => 'u', # ù
chr(0x00fa) => 'u', # ú
chr(0x00fb) => 'u', # û
chr(0x00fc) => 'ue', # ü
chr(0x00fd) => 'y', # ý
chr(0x00fe) => 'th', # þ
chr(0x00ff) => 'y', # ÿ
chr(0x0150) => 'o', # ~O
chr(0x0170) => 'u', # ~U
chr(0x0171) => 'u', # ~u
chr(0x2019) => "'", #
};

# Minimum size word to normally index.
@@ -233,7 +214,7 @@ $EPrints::Index::FREETEXT_ALWAYS_WORDS = {
"ok" => 1
};

# Chars which seperate words. Pretty much anything except
# Chars which separate words. Pretty much anything except
# A-Z a-z 0-9 and single quote '

# If you want to add other seperator characters then they
@@ -271,32 +252,19 @@ foreach my $mapping (
1;

=head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
http://www.eprints.org/eprints-3.4/
Copyright 2000-2011 University of Southampton.
=for COPYRIGHT END
=for LICENSE BEGIN
This file is part of EPrints 3.4 L<http://www.eprints.org/>.
EPrints 3.4 and this file are released under the terms of the
GNU Lesser General Public License version 3 as published by
the Free Software Foundation unless otherwise stated.
EPrints 3.4 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.
This file is part of EPrints L<http://www.eprints.org/>.
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.
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.
You should have received a copy of the GNU Lesser General Public
License along with EPrints 3.4.
If not, see L<http://www.gnu.org/licenses/>.
License along with EPrints. If not, see L<http://www.gnu.org/licenses/>.
=for LICENSE END
@@ -1855,18 +1855,21 @@ this returns the name of the option in the current language.

sub render_value_label
{
my( $self, $value ) = @_;
return $self->get_value_label( $self->repository, $value );
my( $self, $value, %opts ) = @_;
return $self->get_value_label( $self->repository, $value, %opts );
}
sub get_value_label
{
my( $self, $session, $value ) = @_;
my( $self, $session, $value, %opts ) = @_;

if( !EPrints::Utils::is_set( $value ) && $opts{fallback_phrase} )
{
return $session->html_phrase( $opts{fallback_phrase} );
}
return $session->make_text( $value );
}



# if( $self->is_type( "id" ) )
# {
# return $session->get_repository->call(
@@ -2263,7 +2266,9 @@ sub render_search_description

my $valuedesc = $self->render_search_value(
$session,
$value );
$value,
$merge,
$match );

return $session->html_phrase(
$phraseid,
@@ -2273,7 +2278,7 @@ sub render_search_description

sub render_search_value
{
my( $self, $session, $value ) = @_;
my( $self, $session, $value, $merge, $match ) = @_;

return $session->make_text( '"'.$value.'"' );
}
@@ -15,14 +15,19 @@ B<EPrints::MetaField::Recaptcha> - a Captcha
=head1 DESCRIPTION
This field renders a Captcha (a test that only humans can easily pass). It uses the "reCaptcha" service (http://recaptcha.net/). A single database text column is used to store the captcha error code.
Please refer to the notes in [EPRINTS_ROOT]/archives/[ARCHIVEID]/cfg/cfg.d/recaptcha.pl.
Two configuration options are required to define the reCaptcha keys:
If this files does not exist, copy [EPRINTS_ROOT]/lib/defaultcfg/cfg.d/recaptcha.pl.example
to the path above and edit it.
$c->{recaptcha}->{private_key} = "PRIVATE_KEY";
$c->{recaptcha}->{public_key} = "PUBLIC_KEY";
This field uses the Google "reCAPTCHA" service (https://www.google.com/recaptcha/intro/) and
renders a Captcha (a test that humans can easily pass, but robots shouldn't be able to).
You can get these keys by registering at http://recaptcha.net/.
Note:
This MetaField was updated in October 2017 to reCAPTCHA v2.
The previous version of reCAPTCHA will cease to work in March 2018.
Kudos to Matthew Kerwin (https://github.com/phluid61) for most of the work on the new version.
=over 4
@@ -34,6 +39,7 @@ use EPrints::MetaField::Id;
@ISA = qw( EPrints::MetaField::Id );

use strict;
use JSON;

sub is_virtual { 1 }

@@ -50,39 +56,37 @@ sub render_input_field_actual

my $frag = $session->make_doc_fragment;

my $url = URI->new( "https://www.google.com/recaptcha/api/challenge" );
$url->query_form(
k => $public_key,
error => $value,
);
my $url = URI->new( "https://www.google.com/recaptcha/api.js" );

$frag->appendChild( $session->make_javascript( undef,
src => $url,
async => 'async',
defer => 'defer'
) );

my $script = $frag->appendChild( $session->make_javascript( undef,
src => $url ) );
$frag->appendChild( $session->make_element( "div",
class => "g-recaptcha",
'data-sitekey' => $public_key,
) );

$url = URI->new( "https://www.google.com/recaptcha/api/noscript" );
$url->query_form(
k => $public_key,
error => $value,
);
# No-Script, for users with javascript diabled
$url = URI->new( "https://www.google.com/recaptcha/api/fallback" );
$url->query_form( k => $public_key );

my $noscript = $frag->appendChild( $session->make_element( "noscript" ) );
$noscript->appendChild( $session->make_element( "iframe",
src => $url,
height => "300",
width => "500",
height => "422",
width => "302",
frameborder => "0"
) );
) );
$noscript->appendChild( $session->make_element( "br" ) );
$noscript->appendChild( $session->make_element( "textarea",
name => "recaptcha_challenge_field",
id => "g-recaptcha-response",
name => "g-recaptcha-response",
rows => "3",
cols => "40"
) );
$noscript->appendChild( $session->make_element( "input",
type => "hidden",
name => "recaptcha_response_field",
value => "manual_challenge"
) );
) );

return $frag;
}
@@ -92,44 +96,47 @@ sub form_value_actual
my( $self, $repo, $object, $basename ) = @_;

my $private_key = $repo->config( "recaptcha", "private_key" );

my $remote_ip = $repo->remote_ip;
my $challenge = $repo->param( "recaptcha_challenge_field" );
my $response = $repo->param( "recaptcha_response_field" );
my $timeout = $repo->config( "recaptcha", "timeout" ) || 5;

if( !defined $private_key )
{
$repo->log( "recaptcha private_key not set" );
return undef;
}

# don't bother reCaptcha if the user didn't enter the data
if( !EPrints::Utils::is_set( $challenge ) || !EPrints::Utils::is_set( $response ) )
my $response = $repo->param( "g-recaptcha-response" );
if( !EPrints::Utils::is_set( $response ) )
{
return "invalid-captcha-sol";
}

my $url = URI->new( "http://www.google.com/recaptcha/api/verify" );
my $url = URI->new( "https://www.google.com/recaptcha/api/siteverify" );

my $ua = LWP::UserAgent->new();
$ua->env_proxy;
$ua->timeout( $timeout ); #LWP default timeout is 180 seconds.

my $r = $ua->post( $url, [
privatekey => $private_key,
remoteip => $remote_ip,
challenge => $challenge,
my $r = $ua->post( "https://www.google.com/recaptcha/api/siteverify", [
secret => $private_key,
response => $response
]);

my $recaptcha_error;
]);

# the request returned a response - but we have to check whether the human (or otherwise)
# passed the Captcha
if( $r->is_success )
{
my( $success, $recaptcha_error ) = split /\n/, $r->content;
if( defined($success) && lc($success) eq "true" )
my $hash = decode_json( $r->content );
if( !$hash->{success} )
{
return undef
my $recaptcha_error = 'unknown-error';
my $codes = $hash->{'error-codes'};
if( $codes && scalar @{$codes} )
{
$recaptcha_error = join '+', @{$codes};
}
return $recaptcha_error;
}
return $recaptcha_error;
return undef; #success!
}

# error talking to recaptcha, so lets continue to avoid blocking the user
@@ -185,4 +192,3 @@ License along with EPrints 3.4.
If not, see L<http://www.gnu.org/licenses/>.
=for LICENSE END
@@ -63,7 +63,7 @@ sub render_single_value

sub make_searchexp
{
my( $self, $session, $value, $basename ) = @_;
my( $self, $session, $value, $basename, $obj ) = @_;

my $dataset = $session->dataset( $self->{datasetid} );

@@ -94,6 +94,17 @@ sub make_searchexp
if( defined($conf_key) )
{
$fields = $session->config( $conf_key );
#if we've been passed a function, get the array from that
if( ref( $fields ) eq "CODE" )
{
$fields = $self->call_property( "fieldnames_config",
$self,
$session,
$value,
$dataset,
$obj );
}

}
else
{
@@ -141,7 +152,7 @@ sub get_basic_input_elements

# cjg - make help an option?

my $searchexp = $self->make_searchexp( $session, $value, $basename."_" );
my $searchexp = $self->make_searchexp( $session, $value, $basename."_", $obj );

foreach my $sf ( $searchexp->get_non_filter_searchfields )
{
@@ -241,6 +241,15 @@ sub render_set_input
}
foreach my $opt ( @{$tags} )
{
# "group" set options under headings
my $phraseid = $self->{confid}."_optheading_".$self->{name}."_".$opt;
if( $session->get_lang->has_phrase( $phraseid ) )
{
my $div = $session->make_element( "div", class => "ep_optheading" );
$div->appendChild( $session->html_phrase( $phraseid ) );
$list->appendChild( $div );
}

my $row;
if( $input_style eq "long" )
{
@@ -527,7 +536,7 @@ sub get_property_defaults
$defaults{input_tags} = $EPrints::MetaField::UNDEF;
$defaults{render_option} = $EPrints::MetaField::UNDEF;
$defaults{render_max_search_values} = 5;
$defaults{text_index} = 0;
$defaults{text_index} = 1;
$defaults{sql_index} = 1;
$defaults{match} = "EQ";
$defaults{merge} = "ANY";
@@ -37,20 +37,6 @@ BEGIN

use EPrints::MetaField::Set;

sub render_single_value
{
my( $self, $session, $value ) = @_;

my $subject = new EPrints::DataObj::Subject( $session, $value );
if( !defined $subject )
{
return $session->make_text( "?? $value ??" );
}

return $subject->render_with_path(
$session,
$self->get_property( "top" ) );
}

sub render_option
{
@@ -175,6 +161,136 @@ sub get_value_label
return $subj->render_description();
}


## Input single subject node, e.g. HJ
## Output the subject html text. e.g. HJ Public Finance
sub render_single_value
{
my( $self, $session, $value ) = @_;
my $subject = new EPrints::DataObj::Subject( $session, $value );
if( !defined $subject )
{
return $session->make_text( "?? $value ??" );
}
return $subject->render_description();
}

sub render_value
{
my( $self, $session, $value, $alllangs, $nolink, $object ) = @_;
unless( EPrints::Utils::is_set( $value ) )
{
if( $self->{render_quiet} )
{
return $session->make_doc_fragment;
}
else
{
# maybe should just return nothing
return $session->html_phrase(
"lib/metafield:unspecified",
fieldname => $self->render_name( $session ) );
}
}
my @value;
if ( $self->get_property( "multiple") )
{
@value = @{$value};
}
else
{
@value = ($value);
}

my @rendered_values = ();

my $first = 1;
my $html = $session->make_doc_fragment();

if( $self->{render_quiet} )
{
@value = grep { EPrints::Utils::is_set( $_ ) } @value;
}

foreach my $i (0..$#value) ##subjects assigned to the eprint
{
if( $i > 0 )
{
my $phraseid = "lib/metafield:join_".$self->get_type;
if( $i == $#value && $session->get_lang->has_phrase(
"$phraseid.last", $session ) )
{
$phraseid .= ".last";
}
elsif( $i == 1 && $session->get_lang->has_phrase(
"$phraseid.first", $session ) )
{
$phraseid .= ".first";
}
$html->appendChild( $session->html_phrase( $phraseid ) );
}
$html->appendChild(
$self->render_value_sepa_link(
$session,
$value[$i],
$alllangs,
$nolink,
$object ) );
}
return $html;
}


## Internal function by the render_value above.
## Renders subject path with individual links.
sub render_value_sepa_link
{
my( $self, $session, $value, $alllangs, $nolink, $object ) = @_;

my $rendered = $self->render_value_withopts( $session, $value, $nolink, $object );


my $subject = new EPrints::DataObj::Subject( $session, $value );
my $v = $session->make_doc_fragment();
return $v unless $subject;
my @paths = $subject->get_paths( $session, $self->get_property( "top" ) );

my $first = 1;
foreach( @paths )
{
if( $first )
{
$first = 0;
}
else
{
$v->appendChild( $session->html_phrase(
"lib/metafield:join_subject" ) );
# nb. using one from metafield!
}
my $first = 1;
foreach( @{$_} )
{
if( !$first )
{
$v->appendChild( $session->html_phrase(
"lib/metafield:join_subject_parts" ) );
}
$first = 0;
$v->appendChild( $self->render_value_no_multiple(
$session,
$_->get_id(),
$alllangs,
$nolink,
$object ) );
}
}
return $v;
}




sub render_search_set_input
{
my( $self, $session, $searchfield ) = @_;
@@ -566,20 +566,20 @@ sub call_convert
# geom^ requires 6.3.8
if( $version > 6.3 )
{
$self->_system($convert, "-strip", "-colorspace", "RGB", "-background", "white", "-thumbnail","$geom^", "-gravity", "center", "-extent", $geom, "-bordercolor", "gray", "-border", "1x1", $src."[0]", "JPEG:$dst");
$self->_system($convert, "-strip", "-colorspace", "sRGB", "-background", "white", "-thumbnail","$geom^", "-gravity", "center", "-extent", $geom, "-bordercolor", "gray", "-border", "1x1", $src."[0]", "JPEG:$dst");
}
else
{
$self->_system($convert, "-strip", "-colorspace", "RGB", "-background", "white", "-thumbnail","$geom>", "-extract", $geom, "-bordercolor", "gray", "-border", "1x1", $src."[0]", "JPEG:$dst");
$self->_system($convert, "-strip", "-colorspace", "sRGB", "-background", "white", "-thumbnail","$geom>", "-extract", $geom, "-bordercolor", "gray", "-border", "1x1", $src."[0]", "JPEG:$dst");
}
}
elsif( $size eq "medium" )
{
$self->_system($convert, "-strip", "-colorspace", "RGB", "-trim", "+repage", "-size", "$geom", "-thumbnail","$geom>", "-background", "white", "-gravity", "center", "-extent", $geom, "-bordercolor", "white", "-border", "0x0", $src."[0]", "JPEG:$dst");
$self->_system($convert, "-strip", "-colorspace", "sRGB", "-trim", "+repage", "-size", "$geom", "-thumbnail","$geom>", "-background", "white", "-gravity", "center", "-extent", $geom, "-bordercolor", "white", "-border", "0x0", $src."[0]", "JPEG:$dst");
}
else
{
$self->_system($convert, "-strip", "-colorspace", "RGB", "-background", "white", "-thumbnail","$geom>", "-extract", $geom, "-bordercolor", "white", "-border", "0x0", $src."[0]", "JPEG:$dst");
$self->_system($convert, "-strip", "-colorspace", "sRGB", "-background", "white", "-thumbnail","$geom>", "-extract", $geom, "-bordercolor", "white", "-border", "0x0", $src."[0]", "JPEG:$dst");
}

if( -s $dst )
@@ -317,7 +317,7 @@ sub export
return if $doc->value( "eprintid" ) != $self->{workflow}->{item}->id;

my $hide = $self->{session}->param( "docid" );
$hide = !defined($hide) || $hide ne $docid;
#$hide = !defined($hide) || $hide ne $docid;
$frag = $self->_render_doc_div( $doc, $hide );
}

@@ -17,7 +17,7 @@ sub render

my $content_class="";

my $surround = $self->{session}->make_element( "div", class => "ep_sr_component" );
my $surround = $self->{session}->make_element( "div", class => "ep_sr_component", id => $component->{prefix} );
$surround->appendChild( $self->{session}->make_element( "a", name=>$component->{prefix} ) );
foreach my $field_id ( $component->get_fields_handled )
{
@@ -15,7 +15,7 @@ sub render
{
my( $self, $component ) = @_;

my $surround = $self->{session}->make_element( "div", class => "ep_sr_none" );
my $surround = $self->{session}->make_element( "div", class => "ep_sr_none", id => $component->{prefix} );
$surround->appendChild( $self->{session}->make_element( "a", name=>$component->{prefix} ) );
foreach my $field_id ( $component->get_fields_handled )
{
@@ -120,9 +120,7 @@ sub action_newsearch
sub run_search
{
my( $self ) = @_;

my $list = $self->{processor}->{search}->perform_search();

my $error = $self->{processor}->{search}->{error};
if( defined $error )
{
@@ -132,17 +130,21 @@ sub run_search

# we want to filter the search results by an arbitrary criteria
my $dataset_id = $list->{dataset}->base_id();
my $v = $self->{session}->get_conf( "login_required_for_${dataset_id}s", "enable" );
my $v = $self->{session}->get_conf( "login_required_for_${dataset_id}s", "enable" ); #if defined, callback function can be called, if set to 1 will hide abstracts to non-logged in users

my $fn = $self->{session}->get_conf( "${dataset_id}s_access_restrictions_callback" );
if( $v && defined $fn )
{
# if we are here then access to abstracts etc are restricted by way of a callback fn, and we are logged in as a user, this should be extended to viewing search results too
# if we are here then access to abstracts/search results etc are restricted by way of a callback fn
my $sconf = $self->{processor}->{sconf};
my $mode = $sconf->{mode} || "search";

my $user = $self->{session}->current_user;
my @ids;
$list->map( sub
{
my( $session, $dataset, $item ) = @_;
my $rv = &{$fn}( $item, $user, "search" );
my $rv = &{$fn}( $item, $user, $mode );
push @ids, $item->get_id() if $rv != 0;
# print STDERR "[" . $item->get_id() . "]=[$rv]\n";
} );
@@ -340,6 +342,13 @@ sub render_title
return $self->{processor}->{search}->render_conditions_description;
}

#allow a title to be defined rather than a title_phrase
my $title = $self->{processor}->{sconf}->{title};
if( defined $title )
{
return $title;
}

my $phraseid = $self->{processor}->{sconf}->{"title_phrase"};
if( defined $phraseid )
{
@@ -501,6 +510,9 @@ sub render_export_bar
my $url = $self->export_url( $id );
my $span = $plugin->render_export_icon( $type, $url );

#add class to span so we can use CSS on it
$span->setAttribute('class', $span->getAttribute('class') . ' ep_search_' . $id );

if( $type eq "tool" )
{
$tools->appendChild( $session->make_text( " " ) );
@@ -105,6 +105,15 @@ sub action_add_format
my $filename = $epdata->{main};
return if !defined $filename;

# remove leading/trailing whitespace from filename used on filesystem
my $f = 0;
while ( defined $epdata->{files}[$f] )
{
my $tmp_filename = $epdata->{files}[$f]->{filename};
$tmp_filename =~ s/^\s+|\s+$//g;
$epdata->{files}[$f++]->{filename} = $tmp_filename;
}

my $list;
my $doc = $eprint->create_subdataobj( "documents", $epdata );
if( defined $doc )
@@ -124,7 +124,9 @@ sub get_filters
my @f = @{$user->preference( $pref ) || []};
if( !scalar @f )
{
@f = ( inbox=>1, buffer=>1, archive=>1, deletion=>1 );
# sf2 - 2010-08-04 - define local filters
my $lf = $self->{session}->config( "items_filters" );
@f = ( defined $lf ) ? @$lf : ( inbox=>1, buffer=>1, archive=>1, deletion=>1 );
}

foreach my $i (0..$#f)
@@ -203,7 +205,7 @@ sub render
$options{title} = $self->html_phrase( "help_title" );
$options{content} = $repo->html_phrase( $phraseid );
$options{collapsed} = 1;
$options{show_icon_url} = "$imagesurl/help.png";
$options{show_icon_url} = "$imagesurl/help.gif";
my $box = $repo->make_element( "div", style=>"text-align: left" );
$box->appendChild( EPrints::Box::render( %options ) );
$chunk->appendChild( $box );
@@ -239,13 +241,19 @@ sub render_items
]};

my $filter_div = $session->make_element( "div", class=>"ep_items_filters" );
foreach my $f ( qw/ inbox buffer archive deletion / )
# EPrints Services/tmb 2011-02-15 add opportunity to bypass hardcoded order
my @order = @{ $session->config( 'items_filters_order' ) || [] };
@order = qw/ inbox buffer archive deletion / unless( scalar(@order) );
# EPrints Services/tmb end
foreach my $f ( @order )
{
my $url = URI->new( $session->current_url() );
my %q = $self->hidden_bits;
$q{"set_show_$f"} = !$filters{$f};
$url->query_form( %q );
my $link = $session->render_link( $url );
# http://servicesjira.eprints.org:8080/browse/RCA-175
$link->setAttribute( 'class', "ep_items_filters_$f" );
if( $filters{$f} )
{
$link->appendChild( $session->make_element(
@@ -263,7 +271,7 @@ sub render_items
$link->appendChild( $session->make_text( " " ) );
$link->appendChild( $session->html_phrase( "eprint_fieldopt_eprint_status_$f" ) );
$filter_div->appendChild( $link );
$filter_div->appendChild( $session->make_text( ". " ) );
#$filter_div->appendChild( $session->make_text( ". " ) );
}

my $columns = $session->current_user->get_value( "items_fields" );
@@ -472,29 +480,26 @@ sub render_items

=for COPYRIGHT BEGIN

Copyright 2018 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.

http://www.eprints.org/eprints-3.4/
Copyright 2000-2011 University of Southampton.

=for COPYRIGHT END

=for LICENSE BEGIN

This file is part of EPrints 3.4 L<http://www.eprints.org/>.
This file is part of EPrints L<http://www.eprints.org/>.

EPrints 3.4 and this file are released under the terms of the
GNU Lesser General Public License version 3 as published by
the Free Software Foundation unless otherwise stated.
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.

EPrints 3.4 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.
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.

You should have received a copy of the GNU Lesser General Public
License along with EPrints 3.4.
If not, see L<http://www.gnu.org/licenses/>.
License along with EPrints. If not, see L<http://www.gnu.org/licenses/>.

=for LICENSE END