<?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=Laci%40degas.ceu.hu</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=Laci%40degas.ceu.hu"/>
	<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/Special:Contributions/Laci@degas.ceu.hu"/>
	<updated>2026-05-04T01:22:37Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.8</generator>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6551</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6551"/>
		<updated>2009-08-01T22:42:54Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Caveats */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing, login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# data entered to the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to the unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''[http://en.wikipedia.org/wiki/C'est_la_vie C'est la vie]''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp which should be checked to be recent. It also means that '''the secure and eprint servers must synchronize their clocks'''.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an [http://en.wikipedia.org/wiki/Oracle oracle] to tell whether the password is correct or not (ideal utility for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]).&lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d+$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 3.1.3. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6550</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6550"/>
		<updated>2009-08-01T22:34:38Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Patching Apache::Login */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing, login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# data entered to the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to the unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp which should be checked to be recent. It also means that '''the secure and eprint servers must synchronize their clocks'''.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an [http://en.wikipedia.org/wiki/Oracle oracle] to tell whether the password is correct or not (ideal utility for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]).&lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d+$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 3.1.3. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6549</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6549"/>
		<updated>2009-08-01T22:28:55Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Caveats */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing, login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# data entered to the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to the unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp which should be checked to be recent. It also means that '''the secure and eprint servers must synchronize their clocks'''.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an [http://en.wikipedia.org/wiki/Oracle oracle] to tell whether the password is correct or not (ideal utility for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]).&lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d+$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 1.3.1. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6548</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6548"/>
		<updated>2009-08-01T22:25:40Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Caveats */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing, login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# data entered to the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to the unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp which should be checked to be recent. It also means that '''the secure and eprint servers must synchronize their clocks'''.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal utility for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]).&lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d+$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 1.3.1. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6547</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6547"/>
		<updated>2009-08-01T22:23:18Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Caveats */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing, login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# data entered to the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to the unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp which should be checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal utility for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]).&lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d+$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 1.3.1. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6546</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6546"/>
		<updated>2009-08-01T22:21:40Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing, login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp which should be checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal utility for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]).&lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d+$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 1.3.1. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6529</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6529"/>
		<updated>2009-07-27T20:08:44Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Receive data script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing, login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp which should be checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal utility for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]).&lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d+$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 1.3.1. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6528</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6528"/>
		<updated>2009-07-27T19:53:26Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Caveats */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing, login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp which should be checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal utility for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]).&lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 1.3.1. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6527</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6527"/>
		<updated>2009-07-27T19:48:08Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing, login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 1.3.1. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6526</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6526"/>
		<updated>2009-07-27T19:46:51Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Patching Apache::Login */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 1.3.1. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Finally save the file.&lt;br /&gt;
&lt;br /&gt;
==Define &amp;quot;external_login_address&amp;quot;==&lt;br /&gt;
Add the definition of this variable to the file [[archives/ARCHIVEID/cfg/cfg.d/]][[user_login.pl]]:&lt;br /&gt;
  $c-&amp;gt;{external_login_address} = &amp;quot;&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/login&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
In the same file you can define the sub ''check_user_password'' as explained in [[LDAP]] and [[LDAP user_login.pl]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6525</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6525"/>
		<updated>2009-07-27T19:31:58Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Patching Apache::Login */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
We are making two changes to the ''perl_lib/EPrints/Apache/Login.pm'' module. First, always store the URI of the referring page in the hidden ''target'' variable. Second, set the address of the login page to the value of the configuration variable ''external_login_address'' whenever it is defined.&lt;br /&gt;
&lt;br /&gt;
The instructions below are for Eprints version 1.3.1. Locate the line&lt;br /&gt;
 my $form = $session-&amp;gt;render_form( &amp;quot;POST&amp;quot; );&lt;br /&gt;
in the above module (it should be line 122). Replace it by the following:&lt;br /&gt;
 ##CSL Always use the &amp;quot;target&amp;quot; variable, and&lt;br /&gt;
 ## redirect to &amp;quot;external_login_address&amp;quot;&lt;br /&gt;
 my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
 if(! defined($target) ){&lt;br /&gt;
       $target = $session-&amp;gt;get_uri;&lt;br /&gt;
 }&lt;br /&gt;
 my $form = $session-&amp;gt;render_form(&lt;br /&gt;
   &amp;quot;POST&amp;quot;,&lt;br /&gt;
   $session-&amp;gt;get_repository-&amp;gt;get_conf(&amp;quot;external_login_address&amp;quot;) );&lt;br /&gt;
If ''external_login_address'' is not defined, it has the same effect as the old code.&lt;br /&gt;
Roll down to line 142 and comment out this line (add # signs at the beginning):&lt;br /&gt;
 ## my $target = $session-&amp;gt;param( &amp;quot;target&amp;quot; );&lt;br /&gt;
Save the file.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6524</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6524"/>
		<updated>2009-07-27T19:01:14Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Secure login script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    ## CHANGE THIS ADDRESS TO YOUR EPRINT SERRVER'S&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6523</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6523"/>
		<updated>2009-07-27T19:00:07Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Secure login script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server. And, of course, the script must be executable by the apache process.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Category:Howto&amp;diff=6522</id>
		<title>Category:Howto</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Category:Howto&amp;diff=6522"/>
		<updated>2009-07-27T18:57:48Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* User Accounts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== User Accounts ==&lt;br /&gt;
&lt;br /&gt;
* [[LDAP]]&lt;br /&gt;
** slightly more complex [[LDAP user login.pl]] example with account auto-creation&lt;br /&gt;
* [[Removing User Registration]]&lt;br /&gt;
* [[CAS|How to use a CAS server to authenticate users in eprints]]&lt;br /&gt;
* [[Secure login|Light weight secure login]]&lt;br /&gt;
&lt;br /&gt;
== Eprints config (global) ==&lt;br /&gt;
&lt;br /&gt;
* [[setting up email]]&lt;br /&gt;
&lt;br /&gt;
== Eprints archive config ==&lt;br /&gt;
&lt;br /&gt;
* [[How to Create Cover Images in EPrints 3]]&lt;br /&gt;
* [[HOW TO: Add a New Field|How to add a New Field]]&lt;br /&gt;
* [[Add a parallel authentication routine]]. This is a real-world example, which alters the user table, over-rides the default methods for fields, and makes changes to the way a user is authenticated&lt;br /&gt;
* [[Adding a Field to a Live Repository]]&lt;br /&gt;
* [[How to add the structure of an organisation]]&lt;br /&gt;
&lt;br /&gt;
== Migration and Importing ==&lt;br /&gt;
&lt;br /&gt;
* [[Importing from Endnote]]&lt;br /&gt;
* [[How to import users from another archive and keep their passwords]]&lt;br /&gt;
&lt;br /&gt;
== Development Environment ==&lt;br /&gt;
&lt;br /&gt;
* [[EclipseEpicPerlDebug|How to set up EPrints in Eclipse using EPIC and the Perl Debugger]]&lt;br /&gt;
&lt;br /&gt;
== User Interface ==&lt;br /&gt;
&lt;br /&gt;
* [[Web Interface Style and Images]]&lt;br /&gt;
* [[GUI Submission with no Documents]]&lt;br /&gt;
* [[Browse By Person]]&lt;br /&gt;
* [[Adding a link to the Front Page]]&lt;br /&gt;
* [[Contact and Information Pages]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6519</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6519"/>
		<updated>2009-07-27T16:40:13Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Crypto routines */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value. And it should be the same in both copies.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6518</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6518"/>
		<updated>2009-07-27T16:39:29Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Crypto routines */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is never encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6517</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6517"/>
		<updated>2009-07-27T16:37:30Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Receive data script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
While we made a lot of effort to protect the integrity and secrecy of the username and the data, nothing prevents a bad guy to submit bogus data to our secure script! Thus we  relocate to the eprints repository addresses only, and accept the &amp;quot;relocate&amp;quot; argument only if it starts with a slash.&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is not encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6516</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6516"/>
		<updated>2009-07-27T16:28:52Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Secure login script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is not encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6515</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6515"/>
		<updated>2009-07-27T16:28:17Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Receive data script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
This script receives the encrypted data from the secure server, decrypts it and logs in the user. A 1 second delay is inserted if there is a problem with the credentials.&lt;br /&gt;
&lt;br /&gt;
This script should be copied to the ''eprints/cgi/receive_data''. It calls the ''check_user_password'' configuration procedure if it is defined.&lt;br /&gt;
 ######################################################&lt;br /&gt;
 # receive_data&lt;br /&gt;
 # Part of EPrints 3.1&lt;br /&gt;
 # Author: Laszlo Csirmaz&lt;br /&gt;
 # You are free to use/modify this script&lt;br /&gt;
 ######################################################&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;
 my $redirect_to=&amp;quot;/cgi/users/home&amp;quot;;&lt;br /&gt;
 my $loginparams=&amp;quot;&amp;quot;;&lt;br /&gt;
 my $OK=1;&lt;br /&gt;
 my $arg = $session-&amp;gt;param('Q');&lt;br /&gt;
 if( $arg &amp;amp;&amp;amp; length($arg) &amp;gt; 10 ){ #sanity check&lt;br /&gt;
    $arg = _DecodeValue($arg);&lt;br /&gt;
    ## it is target:loginparams:uname:pw:timenow&lt;br /&gt;
    $arg = &amp;quot;/cgi/users/home::::&amp;quot; if(!$arg);&lt;br /&gt;
    my @list = split(/:/,$arg);&lt;br /&gt;
    for my $i(0..4){&lt;br /&gt;
       $list[$i]=&amp;quot;&amp;quot; if(!$list[$i]);&lt;br /&gt;
       $list[$i] =~ s/%c/:/g; $list[$i] =~ s/%a/%/g;&lt;br /&gt;
    }&lt;br /&gt;
    $OK=0 if( $list[4] !~ /^\d$/ );&lt;br /&gt;
    if($OK){&lt;br /&gt;
       my $timediff = int(time/60) - $list[4];&lt;br /&gt;
       #allow a 2 minute window&lt;br /&gt;
       $OK=0 if( $timediff&amp;lt;-1 || $timediff &amp;gt; 2 );&lt;br /&gt;
    }&lt;br /&gt;
    $redirect_to = $list[0] if($list[0] =~ m#/# );&lt;br /&gt;
    $loginparams = $list[1];&lt;br /&gt;
    if($OK){&lt;br /&gt;
       if( $session-&amp;gt;valid_login($list[2],$list[3] ) ){&lt;br /&gt;
          my $user = EPrints::DataObj::User::user_with_username(&lt;br /&gt;
                $session,$list[2]);&lt;br /&gt;
          $session-&amp;gt;login($user);&lt;br /&gt;
          $OK=2;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 sleep 1 if( $OK != 2 ); # some problem, don't hurry&lt;br /&gt;
 my $host = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;host&amp;quot; );&lt;br /&gt;
 my $port = $session-&amp;gt;{repository}-&amp;gt;get_conf( &amp;quot;port&amp;quot; );&lt;br /&gt;
 $redirect_to = &amp;quot;&amp;lt;nowiki&amp;gt;http://$host&amp;lt;/nowiki&amp;gt;&amp;quot;.($port!=80 :&amp;quot;:$port&amp;quot;:&amp;quot;&amp;quot;). $redirect_to;&lt;br /&gt;
 $redirect_to .= &amp;quot;?$loginparams&amp;quot; if($loginparams);&lt;br /&gt;
 $session-&amp;gt;redirect( $redirect_to );&lt;br /&gt;
 $session-&amp;gt;terminate;&lt;br /&gt;
 exit 0;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!-- COPY CRYPTO ROUTINES HERE --&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is not encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6514</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6514"/>
		<updated>2009-07-27T16:00:48Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Secure login script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
This script receives the login page over a secure connection. It encrypts the username, password, and other arguments, and relocates the page to eprints' ''receive_data'' page.&lt;br /&gt;
&lt;br /&gt;
Using the secure site configuration above, this script should be copied to ''/opt/cgi-bin/eprints/login'' after changing the address to your own eprint server.&lt;br /&gt;
&lt;br /&gt;
 ##!/usr/bin/perl -w&lt;br /&gt;
 ## secure login script for eprints&lt;br /&gt;
 ## encrypt and automatically forward to /eprints&lt;br /&gt;
 ## Author: Laszlo Csirmaz, 2009&lt;br /&gt;
 ## You are free to use this script&lt;br /&gt;
 use strict;&lt;br /&gt;
 sub _RelocateTo {&lt;br /&gt;
    my $arg=shift;&lt;br /&gt;
    &amp;quot;&amp;lt;nowiki&amp;gt;http://eprints.umb.edu/cgi/receive_data?Q=$arg&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;-- COPY THE CRYPTO ROUTINES HERE --&amp;gt;&lt;br /&gt;
 sub _html2ascii {&lt;br /&gt;
    my $v=shift;&lt;br /&gt;
    $v=&amp;quot;&amp;quot; if(! defined $v);&lt;br /&gt;
    $v=~ tr/+/ /;&lt;br /&gt;
    $v=~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&amp;quot;C&amp;quot;,hex($1))/eg;&lt;br /&gt;
    return $v;&lt;br /&gt;
 }&lt;br /&gt;
 my $P={};&lt;br /&gt;
 my $ct=$ENV{'CONTENT_TYPE');&lt;br /&gt;
 if($ct &amp;amp;&amp;amp; $ct =~ /multipart/i ){&lt;br /&gt;
    use CGI qw( :cgi :form );&lt;br /&gt;
    my $req=new CGI; # read all data in&lt;br /&gt;
    my @pm=$req-&amp;gt;param;&lt;br /&gt;
    foreach my $key (@pm) {&lt;br /&gt;
      $P-&amp;gt;{$key} = _html2ascii($req-&amp;gt;param($ley));&lt;br /&gt;
    } &lt;br /&gt;
 } elsif ( $ENV{'REQUEST_METHOD'} !~ /^get/i ) {&lt;br /&gt;
    my $pm=&amp;quot;&amp;quot;; while(&amp;lt;&amp;gt;){ $pm .= $_; }&lt;br /&gt;
    my @pms=split(/&amp;amp;/,$pm);&lt;br /&gt;
    foreach my $elem(@pms) {&lt;br /&gt;
       my($t,$v)=split(/=/,$elem);&lt;br /&gt;
       next if(! defined($t) );&lt;br /&gt;
       $P-&amp;gt;{_html2ascii($t)} = _html2ascii($v);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 ## we return the following arguments:&lt;br /&gt;
 ##  target, loginparams, username, pw, timestamp&lt;br /&gt;
 my $arg=&amp;quot;&amp;quot;;&lt;br /&gt;
 for my $item ($P-&amp;gt;{target},$P-&amp;gt;{loginparams},&lt;br /&gt;
      $P-&amp;gt;{login_username}, $P-&amp;gt;{login_password} ){&lt;br /&gt;
    $item=&amp;quot;&amp;quot; if(! $item)[&lt;br /&gt;
    # replace '%' by '%a' and replace ':' by '%c'&lt;br /&gt;
    $item =~ s/%/%a/g; $item =~ s/:/%c/g;&lt;br /&gt;
    $arg .= &amp;quot;$item:&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 my $addr = _RelocateTo( _EncodeValue( $arg . int(time/60) ) );&lt;br /&gt;
 print &amp;quot;Content-Type: text/html; charset=utf-8\n&amp;quot;,&lt;br /&gt;
    &amp;quot;Location: $addr\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Redirected&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;This page should automatically relocated. If not,\n&amp;quot;,&lt;br /&gt;
    &amp;quot;please &amp;lt;a href=\&amp;quot;$addr\&amp;quot;&amp;gt;click here&amp;lt;/a&amp;gt;.\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;,&lt;br /&gt;
    &amp;quot;\n&amp;quot;;&lt;br /&gt;
 exit 0;&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is not encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6513</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6513"/>
		<updated>2009-07-27T15:26:46Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Crypto routines */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
These routines perform encryption and decryption. It is a lightweight version of more sophisticated ones, but (at least I hope) it is sufficient for this application. After the source there are some remarks for those interested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:4px; background-color: #ffe0e0;border:1px solid #a06060;&amp;quot;&amp;gt;'''Warning!''' The secret phrase in the second line should be changed to some secret value.&amp;lt;/div&amp;gt;&lt;br /&gt;
 sub _secret { &lt;br /&gt;
   &amp;quot;Whatever is your secret phrase, give anything here&amp;quot;; &lt;br /&gt;
 }&lt;br /&gt;
 sub _intto64 { #a MIME64 type encoding&lt;br /&gt;
    my $c=shift;&lt;br /&gt;
    $c &amp;amp;=0x3F;&lt;br /&gt;
    if($c&amp;lt;10){ return chr(48+$c); }&lt;br /&gt;
    if($c&amp;lt;10+26){ return chr($c-10+65); }&lt;br /&gt;
    if($c&amp;lt;10+26+26){ return chr($c-10-26+97); }&lt;br /&gt;
    if($c==62){ return '_'; }&lt;br /&gt;
    return '-';&lt;br /&gt;
 }&lt;br /&gt;
 sub _encode64 { #encoding three bytes to four chars&lt;br /&gt;
    my($a,$b,$c)=@_;&lt;br /&gt;
    $a &amp;amp;= 0xFF; $b &amp;amp;= 0xFF; $c &amp;amp;= 0xFF;&lt;br /&gt;
    return _intto64($a&amp;gt;&amp;gt;2)._intto64(($a&amp;lt;&amp;lt;4)|($b&amp;gt;&amp;gt;4)).&lt;br /&gt;
       _intto64(($b&amp;lt;&amp;lt;2)|($c&amp;gt;&amp;gt;6))._intto64($c);&lt;br /&gt;
 }&lt;br /&gt;
 sub _from64 { #decoding of the above&lt;br /&gt;
    my $c=ord(shift||&amp;quot;0&amp;quot;);&lt;br /&gt;
    if($c==95){ return 62;}&lt;br /&gt;
    if($c==45){ return 63;}&lt;br /&gt;
    if($c&amp;lt;48+10){ return $c-48; }&lt;br /&gt;
    if($c&amp;lt;65+26){ return $c-65+10; }&lt;br /&gt;
    return $c-97+10+26;&lt;br /&gt;
 }&lt;br /&gt;
 sub _decode64 { # decoding four chars to three bytes&lt;br /&gt;
    my($s)=shift;&lt;br /&gt;
    my ($r1,$r2,$r3,$r4)=(&lt;br /&gt;
       _from64($s),_from64(substr($s,1)),&lt;br /&gt;
       _from64(substr($s,2)),_from64(substr($s,3)));&lt;br /&gt;
    return ($r1&amp;lt;&amp;lt;18)|($r2&amp;lt;&amp;lt;12)|($r3&amp;lt;&amp;lt;6)|$r4;&lt;br /&gt;
 }&lt;br /&gt;
 sub _EncodeValue { ## encoded value should not end in a space&lt;br /&gt;
    my($id) = @_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my $salt=substr(Digest::MD5::md5_hex($id, _secret()),0,8);&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0; my $ssid=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed); my $idlen=length($id);&lt;br /&gt;
    $id .= &amp;quot;  &amp;quot;; # pad message by spaces&lt;br /&gt;
    for(my $i=0;$i&amp;lt;$idlen;$i+=3){&lt;br /&gt;
       #encode $id[0],$id[1],$id[2] as 4 chars&lt;br /&gt;
       my $v=rand(0x1000000);&lt;br /&gt;
       $ssid .= _encode64(ord(substr($id,$i))^($v&amp;gt;&amp;gt;16),&lt;br /&gt;
                          ord(substr($id,$i+1))^($v&amp;gt;&amp;gt;8),&lt;br /&gt;
                          ord(substr($id,$i+2))^$v);&lt;br /&gt;
    }&lt;br /&gt;
    return $salt.$ssid;&lt;br /&gt;
 }&lt;br /&gt;
 sub _DecodeValue {&lt;br /&gt;
    my($s)=@_;&lt;br /&gt;
    use Digest::MD5;&lt;br /&gt;
    my($salt,$ssid)=(substr($s,0,8),substr($s,8));&lt;br /&gt;
    my $sstr=Digest::MD5::md5($salt, _secret());&lt;br /&gt;
    my $seed=0;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;8;$i++){$seed=($seed&amp;lt;&amp;lt;8)+ord(substr($sstr,$i));}&lt;br /&gt;
    srand($seed);&lt;br /&gt;
    my $id=&amp;quot;&amp;quot;;&lt;br /&gt;
    for(my $i=0;$i&amp;lt;length($ssid)-3;$i+=4){&lt;br /&gt;
        #decode next four chars&lt;br /&gt;
        my $v=rand(0x1000000)^_decode64(substr($ssid,$i));&lt;br /&gt;
        $id .= chr($v&amp;gt;&amp;gt;16) . chr(0xff&amp;amp;($v&amp;gt;&amp;gt;8)) . chr(0xff&amp;amp;$v);&lt;br /&gt;
    }&lt;br /&gt;
    $id =~ s/ +$//; ## strip spaces at the end&lt;br /&gt;
    # $salt and $chksum should be equal&lt;br /&gt;
    $id=&amp;quot;&amp;quot; if ($salt ne substr(Digest::MD5::md5_hex($id, _secret()),0,8));&lt;br /&gt;
    return $id;&lt;br /&gt;
 }&lt;br /&gt;
'''Remarks:'''&lt;br /&gt;
*The MIME64-like encoding uses letters (both lower and upper case), digits and the characters - (minus) and _ (underscore). These are safe to use in an URL.&lt;br /&gt;
*Both encoding and decoding uses MD5 as the building block. The first eight characters of the ciphertext (encoded string) is used for two purposes. First, it acts as a salt, namely it is added to the secret phrase to derive the seed of the random number generator; second it is used to check message integrity, namely it should match the MD5 hash of the message ''and'' the secret phrase.&lt;br /&gt;
*Messages to be encrypted (plaintext) should not end by a space (spaces are used to pad the plaintext to have length divisible by three)&lt;br /&gt;
*The encryption is deterministic. Such a scheme is insecure in general. In our case, however, the plaintext contains a timestamp, thus - supposedly - the same message is not encrypted twice.&lt;br /&gt;
*Weak points of the scheme: only 32 bit MAC (and seed) value, and relying on perl's pseudorandom function.&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6512</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6512"/>
		<updated>2009-07-27T14:54:18Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6511</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6511"/>
		<updated>2009-07-27T14:53:31Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A simple secure login&lt;br /&gt;
&lt;br /&gt;
When logging into eprints, both username and password travel openly. Usually it is not a problem as eprints has its own authenticating mechanism, and stealing an eprints password gives the intruder very limited power. However when using centralized authentication (e.g., by [[LDAP]]) then protecting the password is more important. To prevent sniffing login pages usually use secure connection. Here we discuss an easy way to set up eprints to use encoded password traffic.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==The idea==&lt;br /&gt;
&lt;br /&gt;
Change the destination of the eprints login page to a secure host. On the secure host a script receives the data: login name and password (and maybe others), encodes it, and forwards the request with the encrypted data as payload to an unencrypted eprints page. The eprints page decrypts the data and uses it for authentication.&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
You need a ''secure http server'' on the same main domain as your your eprints server. For example, if eprints can be reached on the web address ''&amp;lt;nowiki&amp;gt;http://eprints.umb.edu&amp;lt;/nowiki&amp;gt;'', then the secure server must have domain name ending with ''umb.edu'', for example ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should set up a cgi executable directory on the secure host. The apache config extract below does exactly this so that ''&amp;lt;nowiki&amp;gt;https://secure.umb.edu/eprints/whatever&amp;lt;/nowiki&amp;gt;'' requests the script ''/opt/cgi-bin/eprints/whatever'' to be executed:&lt;br /&gt;
 &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
  DocumentRoot &amp;quot;/opt/secure&amp;quot;&lt;br /&gt;
  SSLEngine on&lt;br /&gt;
  ScriptAlias /eprints/  /opt/cgi-bin/eprints/&lt;br /&gt;
  &amp;lt;Directory &amp;quot;/opt/cgi-bin/eprints&amp;quot;&amp;gt;&lt;br /&gt;
      AllowOverride None&lt;br /&gt;
      Options +ExecCGI -MultiView +SymLinksIfOwnerMatch&lt;br /&gt;
      Order allow,deny&lt;br /&gt;
      Allow from all&lt;br /&gt;
  &amp;lt;/Directory&amp;gt;&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the [[#Secure login script|Secure login script]] below into the ''/opt/cgi-bin/eprints/'' directory (or whatever directory you've set up above); copy the [[#Receive data script|receive data script]] into eprints' ''/cgi/'' directory. &lt;br /&gt;
&lt;br /&gt;
Finally [[#Patching Apache::Login |patch the Apache::Login module]] of eprints so that everything works smoothly.&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The login process now works as follows.&lt;br /&gt;
# when a page requires authentication, it creates a &amp;quot;login page&amp;quot; with destination at the secure web site&lt;br /&gt;
# the &amp;quot;login page&amp;quot; is sent encrypted to the secure site&lt;br /&gt;
# the secure site encrypts the payload, and redirects the browser to an unencrypted eprints page ''receive_data''&lt;br /&gt;
# ''receive_data'' decrypts the payload, checks credentials, logs in the user if everything checks, and then redirects the browser to the originating page.&lt;br /&gt;
&lt;br /&gt;
What is lost in this process of two redirects is the error message when authentication fails. ''Receive_data'' cannot display the error message as its URL should not be displayed on the user's screen. The final page - which is the original one as well - cannot distinguish between an unsuccessful login and a reload, thus cannot display the error message as well. ''C'est la vie''.&lt;br /&gt;
&lt;br /&gt;
The encrypted data the ''receive_data'' page receives can be a replay of a sniffed older communication. Thus this data should contain a timestamp and checked to be recent.&lt;br /&gt;
&lt;br /&gt;
The secure site can also check the credentials, and relay the result only. Interestingly, the result should be sent encrypted, as otherwise the secure site could be used as an oracle to tell whether the password is correct or not (ideal for a [http://en.wikipedia.org/wiki/Dictionary_attack dictionary attack]). &lt;br /&gt;
&lt;br /&gt;
==Secure login script==&lt;br /&gt;
&lt;br /&gt;
==Receive data script==&lt;br /&gt;
&lt;br /&gt;
==Crypto routines==&lt;br /&gt;
&lt;br /&gt;
==Patching Apache::Login==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Category:Manual&amp;diff=6510</id>
		<title>Category:Manual</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Category:Manual&amp;diff=6510"/>
		<updated>2009-07-26T21:12:12Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: New page: ===Main articles in this category===  * Getting Started * Installation * EPrints configuration * Branding/Logos&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Main articles in this category===&lt;br /&gt;
&lt;br /&gt;
* [[Getting Started]]&lt;br /&gt;
* [[Installation]]&lt;br /&gt;
* [[EPrints configuration]]&lt;br /&gt;
* [[Branding/Logos]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6509</id>
		<title>Secure login</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Secure_login&amp;diff=6509"/>
		<updated>2009-07-26T21:02:26Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: New page: Lightweight secure login   Category:Howto&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lightweight secure login&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6499</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6499"/>
		<updated>2009-07-24T12:59:57Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Options available for the views config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Views ==&lt;br /&gt;
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;
|}&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;
    variation =&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;
&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 costum 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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6498</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6498"/>
		<updated>2009-07-24T12:59:21Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Views */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Views ==&lt;br /&gt;
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;
== 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 use 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;
|}&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;
    variation =&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;
&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 costum 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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6486</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6486"/>
		<updated>2009-07-23T11:57:06Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Views */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Views ==&lt;br /&gt;
Conceptually a ''view'' is a browsable list of eprints split into ''menus'' and a ''list''.&lt;br /&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;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu1&amp;lt;/div&amp;gt;&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;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item1_1 ------&amp;lt;/div&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;font-size:10px&amp;quot;&amp;gt;---&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu2&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; font-size:10px&amp;quot;&amp;gt; &amp;amp;nbsp; Item1_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_1 -----&amp;lt;/div&amp;gt; &lt;br /&gt;
|&amp;lt;span style=&amp;quot;font-size:10px&amp;quot;&amp;gt;---&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; &amp;amp;nbsp; LIST &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt; &lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&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;
== 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 use 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;
|}&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;
    variation =&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;
&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 costum 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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6485</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6485"/>
		<updated>2009-07-23T11:55:37Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Options available for the views config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Views ==&lt;br /&gt;
Conceptually a ''view'' is a browsable list of eprints split into ''menus'' and a ''list''.&lt;br /&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;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu1&amp;lt;/div&amp;gt;&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;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item1_1 ------&amp;lt;/div&amp;gt;&lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu2&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; font-size:10px&amp;quot;&amp;gt; &amp;amp;nbsp; Item1_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_1 -----&amp;lt;/div&amp;gt; &lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; &amp;amp;nbsp; LIST &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt; &lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&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 use 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;
|}&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;
    variation =&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;
&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 costum 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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6484</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6484"/>
		<updated>2009-07-23T09:00:35Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Options available for the views config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Views ==&lt;br /&gt;
Conceptually a ''view'' is a browsable list of eprints split into ''menus'' and a ''list''.&lt;br /&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;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu1&amp;lt;/div&amp;gt;&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;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item1_1 ------&amp;lt;/div&amp;gt;&lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu2&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; font-size:10px&amp;quot;&amp;gt; &amp;amp;nbsp; Item1_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_1 -----&amp;lt;/div&amp;gt; &lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; &amp;amp;nbsp; LIST &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt; &lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &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 browse 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 the [[#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;
|}&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;
    variation =&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;
&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 costum 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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6483</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6483"/>
		<updated>2009-07-23T08:59:10Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Basic options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Views ==&lt;br /&gt;
Conceptually a ''view'' is a browsable list of eprints split into ''menus'' and a ''list''.&lt;br /&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;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu1&amp;lt;/div&amp;gt;&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;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item1_1 ------&amp;lt;/div&amp;gt;&lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu2&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; font-size:10px&amp;quot;&amp;gt; &amp;amp;nbsp; Item1_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_1 -----&amp;lt;/div&amp;gt; &lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; &amp;amp;nbsp; LIST &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt; &lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &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 the [[#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;
|}&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;
    variation =&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;
&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 costum 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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6482</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6482"/>
		<updated>2009-07-23T08:43:32Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Options available for the views config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Views ==&lt;br /&gt;
Conceptually a ''view'' is a browsable list of eprints split into ''menus'' and a ''list''.&lt;br /&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;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu1&amp;lt;/div&amp;gt;&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;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item1_1 ------&amp;lt;/div&amp;gt;&lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu2&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; font-size:10px&amp;quot;&amp;gt; &amp;amp;nbsp; Item1_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_1 -----&amp;lt;/div&amp;gt; &lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; &amp;amp;nbsp; LIST &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt; &lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &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 the [[#Menu options|menu definitions]].&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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 &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&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&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&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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the menu chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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:&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;
===Menu 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;
|fields&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 &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&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&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&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&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&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&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.&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&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&lt;br /&gt;
|A costum 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&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&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6481</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6481"/>
		<updated>2009-07-23T08:42:58Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Options available for the views config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Views ==&lt;br /&gt;
Conceptually a ''view'' is a browsable list of eprints split into ''menus'' and a ''list''.&lt;br /&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;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu1&amp;lt;/div&amp;gt;&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;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item1_1 ------&amp;lt;/div&amp;gt;&lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu2&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; font-size:10px&amp;quot;&amp;gt; &amp;amp;nbsp; Item1_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_1 -----&amp;lt;/div&amp;gt; &lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; &amp;amp;nbsp; LIST &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt; &lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &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 the [[#menu|menu definitions]].&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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 &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&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&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&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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the menu chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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:&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;
===Menu 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;
|fields&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 &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&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&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&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&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&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&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.&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&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&lt;br /&gt;
|A costum 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&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&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6480</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6480"/>
		<updated>2009-07-23T08:38:45Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Options avaible for the views config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Views ==&lt;br /&gt;
Conceptually a ''view'' is a browsable list of eprints split into ''menus'' and a ''list''.&lt;br /&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;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu1&amp;lt;/div&amp;gt;&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;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item1_1 ------&amp;lt;/div&amp;gt;&lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt;Menu2&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; style=&amp;quot;border-color:black; border-style:solid; border-width:0 1px; text-align: left; font-size:10px&amp;quot;&amp;gt; &amp;amp;nbsp; Item1_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_1 -----&amp;lt;/div&amp;gt; &lt;br /&gt;
| --&amp;gt;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; &amp;amp;nbsp; LIST &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt; &lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; Item2_2 &amp;lt;/div&amp;gt;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
| &amp;lt;div width=&amp;quot;100%&amp;quot; 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;gt; &amp;amp;nbsp; ....&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;amp;nbsp;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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 &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&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&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&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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the menu chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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:&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;
===Menu 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;
|fields&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 &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&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&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&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&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&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&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.&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&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&lt;br /&gt;
|A costum 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&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&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6474</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6474"/>
		<updated>2009-07-21T10:10:53Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Variations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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 &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&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&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&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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the menu chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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:&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;
===Menu 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;
|fields&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 &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&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&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&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&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&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&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.&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&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&lt;br /&gt;
|A costum 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&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&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6473</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6473"/>
		<updated>2009-07-21T10:10:05Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Variations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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 &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&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&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&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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the menu chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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, determines how the final list is rendered. Variation is an array of strings, such as&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:&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;
===Menu 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;
|fields&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 &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&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&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&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&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&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&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.&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&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&lt;br /&gt;
|A costum 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&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&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6472</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6472"/>
		<updated>2009-07-21T10:06:16Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* View list options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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 &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&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&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&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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the menu chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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, determines how the final list is rendered. Variations is an array of strings, such as&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'' 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:&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;
{|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&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 &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&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&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&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&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&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&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.&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&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&lt;br /&gt;
|A costum 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&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&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6459</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6459"/>
		<updated>2009-07-16T14:26:58Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Phrases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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 &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&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&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&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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
&lt;br /&gt;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations, if defined, determines how the final list is rendered. Variations is an array of strings, such as&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'' 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:&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;
{|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&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 &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&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&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&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&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&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&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.&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&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&lt;br /&gt;
|A costum 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&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&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6458</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6458"/>
		<updated>2009-07-16T14:26:34Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Phrases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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 &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&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&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&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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
&lt;br /&gt;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations, if defined, determines how the final list is rendered. Variations is an array of strings, such as&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'' 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:&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;
{|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&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 &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&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&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&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&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&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&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.&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&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&lt;br /&gt;
|A costum 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&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&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6457</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6457"/>
		<updated>2009-07-16T14:24:16Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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 &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&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&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&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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
&lt;br /&gt;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations, if defined, determines how the final list is rendered. Variations is an array of strings, such as&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'' 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:&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;
{|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&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 &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&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&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&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&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&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&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.&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&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&lt;br /&gt;
|A costum 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&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&lt;br /&gt;
|if set, the first section is included in the front page.&lt;br /&gt;
|}&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_eprints_&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_eprints_&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_eprints_&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_eprints_divisions&amp;quot;&amp;gt;Divisions&amp;lt;/epp:phrase&amp;gt;&lt;br /&gt;
 &amp;lt;epp:phrase id=&amp;quot;viewtitle_eprints_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_eprints_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;
&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;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6456</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6456"/>
		<updated>2009-07-16T12:33:41Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* nocount */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
&lt;br /&gt;
===Options in menus===&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&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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
&lt;br /&gt;
When set to 'plain' turns of 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;
==Phrases==&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6455</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6455"/>
		<updated>2009-07-16T12:32:48Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Variations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
&lt;br /&gt;
===Options in menus===&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&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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
&lt;br /&gt;
When set to 'plain' turns of 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;
==Phrases==&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nocount====&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6454</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6454"/>
		<updated>2009-07-16T12:18:37Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Options in menus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
&lt;br /&gt;
===Options in menus===&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&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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
|&lt;br /&gt;
  jump=plain&lt;br /&gt;
&lt;br /&gt;
Turns of the 'jump to' text before the list of subheading navigation links.&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;
==Phrases==&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nocount====&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6453</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6453"/>
		<updated>2009-07-16T12:18:11Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* View list options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===View list options===&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
==Options in menus==&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&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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
|&lt;br /&gt;
  jump=plain&lt;br /&gt;
&lt;br /&gt;
Turns of the 'jump to' text before the list of subheading navigation links.&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;
==Phrases==&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nocount====&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6452</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6452"/>
		<updated>2009-07-16T12:17:47Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Phrases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==View list options==&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
&lt;br /&gt;
==Options in menus==&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&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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
|&lt;br /&gt;
  jump=plain&lt;br /&gt;
&lt;br /&gt;
Turns of the 'jump to' text before the list of subheading navigation links.&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;
==Phrases==&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nocount====&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6451</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6451"/>
		<updated>2009-07-16T12:17:07Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Options in menus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==View list options==&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
&lt;br /&gt;
==Options in menus==&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&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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
|&lt;br /&gt;
  jump=plain&lt;br /&gt;
&lt;br /&gt;
Turns of the 'jump to' text before the list of subheading navigation links.&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;
===Phrases===&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nocount====&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6450</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6450"/>
		<updated>2009-07-16T12:16:45Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Options in ''menus'' */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==View list options==&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
&lt;br /&gt;
===Options in menus===&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&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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
|&lt;br /&gt;
  jump=plain&lt;br /&gt;
&lt;br /&gt;
Turns of the 'jump to' text before the list of subheading navigation links.&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;
===Phrases===&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nocount====&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6449</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6449"/>
		<updated>2009-07-16T12:15:43Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* View list options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==View list options==&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
===Options in ''menus''===&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&lt;br /&gt;
|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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
|&lt;br /&gt;
  jump=plain&lt;br /&gt;
&lt;br /&gt;
Turns of the 'jump to' text before the list of subheading navigation links.&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;
===Phrases===&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nocount====&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6448</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6448"/>
		<updated>2009-07-16T12:15:08Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Basic */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic 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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
==View list options==&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
===Options in ''menus''===&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&lt;br /&gt;
|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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
|&lt;br /&gt;
  jump=plain&lt;br /&gt;
&lt;br /&gt;
Turns of the 'jump to' text before the list of subheading navigation links.&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;
===Phrases===&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nocount====&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6447</id>
		<title>Views.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.eprints.org/w/index.php?title=Views.pl&amp;diff=6447"/>
		<updated>2009-07-16T12:14:50Z</updated>

		<summary type="html">&lt;p&gt;Laci@degas.ceu.hu: /* Basic attributes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Options avaible 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 browse definition&amp;gt; },&lt;br /&gt;
    { &amp;lt;second browse definition&amp;gt; },&lt;br /&gt;
    ...&lt;br /&gt;
    { &amp;lt;last browse definition&amp;gt; },&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
(be careful about commas and semicolons). The order of the browse 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 browse 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;
*''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 attribute =&amp;gt; value pairs enclosed into curly brackets. &lt;br /&gt;
Thus the browse views definition is an array of hashes.&lt;br /&gt;
&lt;br /&gt;
==Basic==&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&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://yourrepo/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 &lt;br /&gt;
|(deprecated) This attribute describes the field(s) by which the view is built. It has been replaced by the more general [[#Options in menus|menus]] attribute.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideempty&lt;br /&gt;
allow_null&lt;br /&gt;
new_column_at&lt;br /&gt;
render_menu&lt;br /&gt;
|These define the default values of the same attributes in all [[#Options in menus|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&lt;br /&gt;
|An array of ''[[#Options in menus|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&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&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&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;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==View list options==&lt;br /&gt;
There are options which determine how the last page in the view chain should look like. &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;
|order&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&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&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&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&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&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;
    variation =&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&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&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&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;
===Options in ''menus''===&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&lt;br /&gt;
|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 &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&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&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&lt;br /&gt;
|Possible values: ''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 below.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|hideup&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&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;
&lt;br /&gt;
    render_menu =&amp;gt; 'render_view_menu_3col_boxes',&lt;br /&gt;
&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;
&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&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;
===Variations===&lt;br /&gt;
&lt;br /&gt;
Variations is an array of string, such as&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;
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 consists of a field name, followed by zero, one or more ''options'' separated by commas. An option is either a single attribute, or an attribute, an equal sign, and the value of the attribute. Thus&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:&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;
&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;
&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;
|&lt;br /&gt;
  jump=plain&lt;br /&gt;
&lt;br /&gt;
Turns of the 'jump to' text before the list of subheading navigation links.&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;
===Phrases===&lt;br /&gt;
&lt;br /&gt;
===Standard===&lt;br /&gt;
&lt;br /&gt;
====heading_level====&lt;br /&gt;
&lt;br /&gt;
====include====&lt;br /&gt;
&lt;br /&gt;
====subheadings====&lt;br /&gt;
&lt;br /&gt;
===Extra feature===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====nocount====&lt;br /&gt;
&lt;br /&gt;
====nohtml====&lt;br /&gt;
&lt;br /&gt;
====noindex====&lt;/div&gt;</summary>
		<author><name>Laci@degas.ceu.hu</name></author>
		
	</entry>
</feed>