You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2451 lines
75 KiB
2451 lines
75 KiB
<?php /* bibtexbrowser: publication lists with bibtex and PHP
|
|
<!-- __ID__ -->
|
|
|
|
bibtexbrowser is a PHP script that creates publication lists from Bibtex files.
|
|
bibtexbrowser is stable, mature and easy to install. It is used in [[users|40+ different universities]] around the globe.
|
|
|
|
+++TOC+++
|
|
|
|
=====Major features=====
|
|
* **(11/2009)** bibtexbrowser generates [[http://www.monperrus.net/martin/accurate+bibliographic+metadata+and+google+scholar|Google Scholar metadata]] so as to improve the visibility of your papers on Google Scholar.
|
|
* **(11/2009)** More and more academics use bibliographic software like [[http://www.zotero.org/|Zotero]] or [[http://www.mendeley.com/|Mendeley]]. bibtexbrowser generates [[http://ocoins.info/|COinS]] for automatic import of bibliographic entries with [[http://www.zotero.org/|Zotero]] and [[http://www.mendeley.com/|Mendeley]].
|
|
* **(10/2009)** People can subscribe to the RSS publication feed of an individual or a group so as to being kept up-to-date: bibtexbrowser generates RSS feeds for all queries (simply add &rss at the end of the URL)! [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=monperrus.bib&all&rss|demo]]
|
|
* **(02/2009)** bibtexbrowser can display all entries for an author with an academic style (i.e book, articles, conference, workshop): [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&academic=Ducasse|demo]]
|
|
* **(05/2008)**: bibtexbrowser can be used to embed a publication list into another page: [[http://www.monperrus.net/martin/|demo]]
|
|
* **(04/2007)**: bibtexbrowser is easy to install: just a single file.
|
|
|
|
=====Other features=====
|
|
* **(05/2010)** bibtexbrowser adds links to your co-author pages if you define the corresponding @string (see function addHomepageLink)
|
|
* **(01/2010)** bibtexbrowser can handle user-defined bibliographic styles
|
|
* **(10/2009)** bibtexbrowser is able to generate a bibtex file containing only the selected entries (simply add &astext at the end of the link)
|
|
* **(10/2009)** bibtexbrowser is now independent of the configuration of register_globals
|
|
* **(01/2009)** bibtexbrowser allows multi criteria search, e.g. [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&type=inproceedings&year=2004|demo]]
|
|
* bibtexbrowser replaces constants defined in @STRING
|
|
* bibtexbrowser is very fast because it keeps a compiled version of the bibtex file (PHP object serialized)
|
|
* bibtexbrowser is compatible with PHP 4.x and PHP 5.x
|
|
* bibtexbrowser can display the menu and all entries without filtering from the file name passed as parameter [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib|demo]]
|
|
* bibtexbrowser can display all entries out of a bibtex file [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&all|demo]]
|
|
* bibtexbrowser can display all entries for a given year [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&year=2004|demo]]
|
|
* bibtexbrowser can display a single bibtex entry [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&key=monperrus08d|demo]]
|
|
* bibtexbrowser can display found entries with a search word (it can be in any bib field) [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&search=ocl|demo]]
|
|
* bibtexbrowser can display all entries with a bib keyword
|
|
* bibtexbrowser outputs valid XHTML 1.0 Transitional
|
|
* bibtexbrowser can display all entries for an author [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&author=Barbara+A.+Kitchenham|demo]]
|
|
* bibtexbrowser can be used with different encodings (change the default iso-8859-1 encoding if your bib file is in utf-8 ''define('ENCODING','utf-8')'' )
|
|
|
|
|
|
=====Download=====
|
|
For feature requests, bug reports, or patch proposals, [[http://www.monperrus.net/martin/|please drop me an email ]] or comment this page. Don't hesitate to contact me to be added in the [[users|lists of bibtexbrowser users]] :-)
|
|
|
|
|
|
**[[http://www.monperrus.net/martin/bibtexbrowser.php.txt|Download bibtexbrowser]]** <?php if (is_readable('bibtexbrowser-rc.php')) {echo '<a href="http://www.monperrus.net/martin/bibtexbrowser-rc.php.txt">(Try the release candidate!)</a>';} ?>
|
|
|
|
|
|
=====Demo and screenshot=====
|
|
|
|
Demo: [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib|Here, you can browse a bibtex file dedicated to software metrics]]
|
|
|
|
<a href="bibtexbrowser-screenshot.png"><img height="500" src="bibtexbrowser-screenshot.png" alt="bibtexbrowser screenshot"/></a>
|
|
|
|
=====Basic installation=====
|
|
|
|
Create a bib file with the publication records (e.g. csgroup2008.bib) and upload it to your server.
|
|
* Use the link ''bibtexbrowser.php?bib=csgroup2008.bib'' (frameset based view)
|
|
* Use the link ''bibtexbrowser.php?bib=csgroup2008.bib&all'' (pub list sorted by year)
|
|
* Use the link ''bibtexbrowser.php?bib=csgroup2008.bib&all&academic'' (pub list sorted by publication type, then by year)
|
|
|
|
** Warning **: bibtexbrowser maintains a cached version of the parsed bibtex, for high performance, check that PHP can write in the directory containing the bibtex file.
|
|
|
|
=====How to include your publication list in your home page=====
|
|
|
|
<table border="1">
|
|
<tr><th></th><th>Sorted by year </th><th>Sorted by publication type</th></tr>
|
|
<tr><td>For a group/team/lab</td>
|
|
<td>
|
|
<?php
|
|
$_GET['bib']='csgroup2008.bib';
|
|
$_GET['all']=1;
|
|
include( 'bibtexbrowser.php' );
|
|
?>
|
|
</td>
|
|
<td>
|
|
<?php
|
|
$_GET['bib']='csgroup2008.bib';
|
|
$_GET['all']=1;
|
|
$_GET['academic']=1;
|
|
include( 'bibtexbrowser.php' );
|
|
?>
|
|
</td>
|
|
</tr><!-- end group -->
|
|
<tr><td>For an individual</td>
|
|
<td>
|
|
<?php
|
|
$_GET['bib']='mybib.bib';
|
|
$_GET['author']='Martin Monperrus';
|
|
include( 'bibtexbrowser.php' );
|
|
?>
|
|
</td>
|
|
<td>
|
|
<?php
|
|
$_GET['bib']='mybib.bib';
|
|
$_GET['academic']='Martin Monperrus';
|
|
include( 'bibtexbrowser.php' );
|
|
?>
|
|
|
|
|
|
</td>
|
|
</tr><!-- end individual -->
|
|
</table>
|
|
|
|
|
|
And tailor it with a CSS style, for example:
|
|
<style>
|
|
.date { background-color: blue; }
|
|
.rheader { font-size: large }
|
|
.bibref { padding:3px; padding-left:15px; vertical-align:top;}
|
|
.bibtitle { font-weight:bold; }
|
|
.bibbooktitle { font-style:italic; }
|
|
</style>
|
|
|
|
=====How to tailor bibtexbrowser?=====
|
|
|
|
====By modifying the CSS====
|
|
|
|
If bibtexbrowser.css exists, it will be used, otherwise bibtexbrowser uses its own embedded CSS style (see function bibtexbrowserDefaultCSS).
|
|
|
|
====By modifying the configuration parameters====
|
|
|
|
All configuration parameters are of the form ''define("PARAMETER_NAME","PARAMER_VALUE")'' at the beginning of the script. You can modify them by creating a file named "bibtexbrowser.local.php" containing the modified value. For instance:
|
|
|
|
<code>
|
|
<?php
|
|
@define("ENCODING","utf-8");// if your bibtex file is utf-8 encoded
|
|
?>
|
|
</code>
|
|
|
|
|
|
<a name="modify-bibstyle"/>
|
|
====By modifying the bibliography style ====
|
|
The bibliography style is encapsulated in a function. If you want to modify the bibliography style, you can copy the default style ([[bibtexbrowser-style-default.php.txt|source]]) in a new file, say ''bibtexbrowser-yourstyle.php'', and rename the function ''DefaultBibliographyStyle'' in say ''MyFancyBibliographyStyle''.
|
|
Then, add in the file ''bibtexbrowser.local.php'':
|
|
<code>
|
|
<?php
|
|
include( 'bibtexbrowser-yourstyle.php' );
|
|
define('BIBLIOGRAPHYSTYLE','MyFancyBibliographyStyle');
|
|
?>
|
|
</code>
|
|
|
|
[[http://www.monperrus.net/martin/bibtexbrowser-style-janos.php.txt|János Tapolcai contributed with this style, which looks like IEEE references]].
|
|
For contributing with a new style, [[http://www.monperrus.net/martin/|please drop me an email ]]
|
|
|
|
=====How to add links to the slides of a conference/workshop paper?=====
|
|
|
|
You can simply fill the ''comment'' field of the bib entry with an HTML link:
|
|
<code>
|
|
@inproceedings{foo,
|
|
author="Jean Dupont",
|
|
title="Bibtexbrowser",
|
|
year=2009,
|
|
booktitle="Proceedings of the BIB conference",
|
|
comment={<a href="myslides.pdf">[slides]</a>}
|
|
}
|
|
</code>
|
|
|
|
|
|
|
|
|
|
=====Related tools=====
|
|
|
|
Old-fashioned:
|
|
[[http://nxg.me.uk/dist/bibhtml/|bibhtml]], [[http://www.litech.org/~wkiri/bib2html/|bib2html]], [[http://ilab.usc.edu/bibTOhtml/|bibtohtml]], [[http://people.csail.mit.edu/rahimi/bibtex/|bibtextohtml]], [[http://www.lri.fr/~filliatr/bibtex2html/|bibtex2html]], [[http://people.csail.mit.edu/mernst/software/bibtex2web.html |bibtex2web]], [[http://strategoxt.org/Stratego/BibtexTools|stratego bibtex module]]
|
|
Unlike them, **bibtexbrowser is dynamic**.i.e.; generates the HTML pages on the fly. Thus, you do not need to regenerate the static HTML files each time the bib file is changed.
|
|
|
|
Heavyweight:
|
|
[[http://www.rennes.supelec.fr/ren/perso/etotel/PhpBibtexDbMng/|PHP BibTeX Database Manager]], [[http://gforge.inria.fr/projects/bibadmin/|bibadmin]], [[http://artis.imag.fr/Software/Basilic/|basilic]], [[http://phpbibman.sourceforge.net/|phpbibman]], [[http://www.aigaion.nl/|aigaion]], [[http://www.refbase.net/|refbase]], [[http://wikindx.sourceforge.net/|wikindx]], [[http://refdb.sourceforge.net/|refdb]]
|
|
Unlike them, **bibtexbrowser does not need a MySQL database**
|
|
|
|
|
|
Main competitor:
|
|
[[http://code.google.com/p/simplybibtex/|SimplyBibtex]] has the same spirit, but the project seems dead since 2006
|
|
|
|
Misc:
|
|
[[http://www.sat.ltu.se/publications/publications.m|This matlab script is similar]]
|
|
|
|
=====Copyright=====
|
|
|
|
This script is a fork from an excellent script of the University of Texas at El Paso.
|
|
|
|
(C) 2006-2007-2008-2009-2010 Martin Monperrus
|
|
(C) 2005-2006 The University of Texas at El Paso / Joel Garcia, Leonardo Ruiz, and Yoonsik Cheon
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
*/
|
|
|
|
/** Release 2009-05-19
|
|
* Added support for links to author home pages
|
|
* Improvement of documentation (cf Benoit Combemale "bug")
|
|
* Bug of Serge Barral solved (curly braces)
|
|
* encapsulated parsing/caching code of bibtex in function setDB()
|
|
*/
|
|
|
|
/** Release 2009-01-05
|
|
* Added support for new bibliographic styles (users just have to create a function and change a configuration parameter, see documentation)
|
|
* Packaged the IEEE-like bibliographic style of János Tapolcai (many thanks János), see http://www.monperrus.net/martin/bibtexbrowser-style-janos.php.txt
|
|
* Added support for external CSS (if bibtexbrowser.css exists, it is used instead of the embedded one)
|
|
* Added support for local configuration parameters in bibtexbrowser.local.php
|
|
* Bug in RSS fixed (handling of &)
|
|
* Bug found by Nelson fixed (the link to all bib entries)
|
|
*/
|
|
|
|
// *************** CONFIGURATION
|
|
// I recommend to put your changes in bibtexbrowser.local.php
|
|
// it will help you to upgrade the script with a new version
|
|
@include('bibtexbrowser.local.php');
|
|
// there is no encoding transformation from the bibtex file to the html file
|
|
// if your bibtex file contains 8 bits characters in utf-8
|
|
// change the following parameter
|
|
@define('ENCODING','iso-8859-1');//define('ENCODING','utf-8');//define('ENCODING','windows-1252');
|
|
// number of bib items per page
|
|
@define('PAGE_SIZE',isset($_GET['nopage'])?10000:25);
|
|
@define('BIBLIOGRAPHYSTYLE','DefaultBibliographyStyle');// this is the name of a function
|
|
@define('COMMA_NAMES',false);// do have authors in a comma separated form?
|
|
@define('TYPES_SIZE',10); // number of entry types per table
|
|
@define('YEAR_SIZE',20); // number of years per table
|
|
@define('AUTHORS_SIZE',30); // number of authors per table
|
|
@define('TAGS_SIZE',30); // number of keywords per table
|
|
@define('READLINE_LIMIT',1024);
|
|
@define('Q_YEAR', 'year');
|
|
@define('Q_YEAR_PAGE', 'year_page');
|
|
@define('Q_FILE', 'bib');
|
|
@define('Q_AUTHOR', 'author');
|
|
@define('Q_AUTHOR_PAGE', 'author_page');
|
|
@define('Q_TAG', 'keywords');
|
|
@define('Q_TAG_PAGE', 'keywords_page');
|
|
@define('Q_TYPE', 'type');
|
|
@define('Q_TYPE_PAGE', 'type_page');
|
|
@define('Q_ALL', 'all');
|
|
@define('Q_ENTRY', 'entry');
|
|
@define('Q_KEY', 'key');
|
|
@define('Q_SEARCH', 'search');
|
|
@define('Q_EXCLUDE', 'exclude');
|
|
@define('Q_RESULT', 'result');
|
|
@define('Q_ACADEMIC', 'academic');
|
|
@define('Q_DB', 'bibdb');
|
|
@define('AUTHOR', 'author');
|
|
@define('EDITOR', 'editor');
|
|
@define('SCHOOL', 'school');
|
|
@define('TITLE', 'title');
|
|
@define('BOOKTITLE', 'booktitle');
|
|
@define('YEAR', 'year');
|
|
@define('BUFFERSIZE',100000);
|
|
// *************** END CONFIGURATION
|
|
|
|
// for clean search engine links
|
|
// we disable url rewriting
|
|
// ... and hope that your php configuration will accept one of these
|
|
@ini_set("session.use_only_cookies",1);
|
|
@ini_set("session.use_trans_sid",0);
|
|
@ini_set("url_rewriter.tags","");
|
|
|
|
// we ensure that the pages won't get polluted
|
|
// if future versions of PHP change warning mechanisms...
|
|
|
|
@error_reporting(/*pp4php:serl*/E_ALL/*lres*/);
|
|
|
|
/** sets the database of bibtex entries (object of type BibDataBase)
|
|
* in $_GET[Q_DB]
|
|
* Uses a caching mechanism on disk for sake of performance
|
|
*/
|
|
function setDB() {
|
|
|
|
// default bib file, if no file is specified in the query string.
|
|
if (!isset($_GET[Q_FILE])) {
|
|
?>
|
|
Congratulations! bibtexbrowser is correctly installed!<br/>
|
|
Now you have to pass the name of the bibtex file as parameter (e.g. bibtexbrowser.php?bib=mybib.php)<br/>
|
|
You may browse:<br/>
|
|
<?php
|
|
foreach (glob("*.bib") as $bibfile) {
|
|
$url="?bib=".$bibfile; echo '<a href="'.$url.'">'.$bibfile.'</a><br/>';
|
|
}
|
|
exit; // we cannot set the db wtihout a bibfile
|
|
|
|
}
|
|
|
|
if (!file_exists($_GET[Q_FILE])) {
|
|
// to automate dectection of faulty links with tools such as webcheck
|
|
header('HTTP/1.1 404 Not found');
|
|
die('<b>the bib file '.$_GET[Q_FILE].' does not exist !</b>');
|
|
}
|
|
|
|
// save bandwidth and server cpu
|
|
// (imagine the number of requests from search engine bots...)
|
|
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])>filemtime($_GET[Q_FILE]))) {
|
|
header("HTTP/1.1 304 Not Modified");
|
|
exit;
|
|
}
|
|
|
|
// for sake of performance, once the bibtex file is parsed
|
|
// we try to save a "compiled" in a txt file
|
|
$compiledbib = $_GET[Q_FILE].'.txt';
|
|
$parse=true;
|
|
// do we have a compiled version ?
|
|
if (is_file($compiledbib) && is_readable($compiledbib)) {
|
|
// is it up to date ? wrt to the bib file and the script
|
|
// then upgrading with a new version of bibtexbrowser triggers a new compilation of the bib file
|
|
if (filemtime($_GET[Q_FILE])<filemtime($compiledbib) && filemtime(__FILE__)<filemtime($compiledbib)) {
|
|
$_GET[Q_DB] = unserialize(file_get_contents($compiledbib));
|
|
// basic test
|
|
// do we have an correct version of the file
|
|
if (is_a($_GET[Q_DB],'BibDataBase')) {
|
|
// at least we can switch off the parsing
|
|
$parse=false;
|
|
}
|
|
}
|
|
}
|
|
// we don't have a compiled version
|
|
if ($parse) {
|
|
//echo '<!-- parsing -->';
|
|
// then parsing the file
|
|
$db = new BibDataBase();
|
|
$db->load($_GET[Q_FILE]);
|
|
$_GET[Q_DB]=$db;
|
|
|
|
// are we able to save the compiled version ?
|
|
if ((!is_file($compiledbib) && is_writable(dirname($compiledbib))) || (is_file($compiledbib) && is_writable($compiledbib)) ) {
|
|
// we can use file_put_contents
|
|
// but don't do it for compatibility with PHP 4.3
|
|
$f = fopen($compiledbib,'w');
|
|
//we use a lock to avoid that a call to bbtexbrowser made while we write the object loads an incorrect object
|
|
if (flock($f,LOCK_EX)) fwrite($f,serialize($_GET[Q_DB]));
|
|
fclose($f);
|
|
}
|
|
//else echo '<!-- please chmod the directory containing the bibtex file to be able to keep a compiled version (much faster requests for large bibtex files) -->';
|
|
} // end parsing and saving
|
|
} // end function setDB
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////
|
|
|
|
/** This class is a generic parser of bibtex files
|
|
* It has no dependencies, i.e. it can be used outside of bibtexbrowser
|
|
* To use it, simply instantiate it and pass it an object that will receive semantic events
|
|
* The delegate is expected to have some methods
|
|
* see classes BibDBBuilder and XMLPrettyPrinter
|
|
*/
|
|
class StateBasedBibtexParser {
|
|
|
|
function StateBasedBibtexParser($bibfilename, &$delegate) {
|
|
|
|
|
|
// STATE DEFINITIONS
|
|
@define('NOTHING',1);
|
|
@define('GETTYPE',2);
|
|
@define('GETKEY',3);
|
|
@define('GETVALUE',4);
|
|
@define('GETVALUEDELIMITEDBYQUOTES',5);
|
|
@define('GETVALUEDELIMITEDBYQUOTES_ESCAPED',6);
|
|
@define('GETVALUEDELIMITEDBYCURLYBRACKETS',7);
|
|
@define('GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED',8);
|
|
@define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL',9);
|
|
@define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED',10);
|
|
@define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL',11);
|
|
@define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED',12);
|
|
@define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL',11);
|
|
@define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED',12);
|
|
|
|
|
|
$state=NOTHING;
|
|
$entrytype='';
|
|
$entrykey='';
|
|
$entryvalue='';
|
|
$finalkey='';
|
|
$entrysource='';
|
|
|
|
// metastate
|
|
$isinentry = false;
|
|
|
|
$delegate->beginFile();
|
|
|
|
|
|
$handle = fopen($bibfilename, "r");
|
|
// if you encounter this errir "Allowed memory size of xxxxx bytes exhausted"
|
|
// then decrease the size of the temp buffer below
|
|
$bufsize=min(filesize($bibfilename),BUFFERSIZE);
|
|
|
|
while (!feof($handle)) {
|
|
$sread=fread($handle,$bufsize);
|
|
//foreach(str_split($sread) as $s) {
|
|
for ( $i=0; $i < strlen( $sread ); $i++) { $s=$sread[$i];
|
|
|
|
if ($isinentry) $entrysource.=$s;
|
|
|
|
if ($state==NOTHING) {
|
|
// this is the beginning of an entry
|
|
if ($s=='@') {
|
|
$delegate->beginEntry();
|
|
$state = GETTYPE;
|
|
$isinentry = true;
|
|
$entrysource='@';
|
|
}
|
|
}
|
|
|
|
else if ($state==GETTYPE) {
|
|
// this is the beginning of a key
|
|
if ($s=='{') {
|
|
$state = GETKEY;
|
|
$delegate->setEntryType($entrytype);
|
|
$entrytype='';
|
|
}
|
|
else $entrytype=$entrytype.$s;
|
|
}
|
|
|
|
else if ($state==GETKEY) {
|
|
// now we get the value
|
|
if ($s=='=') {
|
|
$state = GETVALUE;
|
|
$finalkey=$entrykey;
|
|
$entrykey='';}
|
|
// oups we only have the key :-) anyway
|
|
else if ($s=='}') {
|
|
$state = NOTHING;$isinentry = false;$delegate->endEntry($entrysource);
|
|
$entrykey='';
|
|
}
|
|
// OK now we look for values
|
|
else if ($s==',') {
|
|
$state=GETKEY;
|
|
$delegate->setEntryKey($entrykey);
|
|
$entrykey='';}
|
|
else { $entrykey=$entrykey.$s; }
|
|
}
|
|
// we just got a =, we can now receive the value, but we don't now whether the value
|
|
// is delimited by curly brackets, double quotes or nothing
|
|
else if ($state==GETVALUE) {
|
|
|
|
// the value is delimited by double quotes
|
|
if ($s=='"') {
|
|
$state = GETVALUEDELIMITEDBYQUOTES;
|
|
$entryvalue='';}
|
|
// the value is delimited by curly brackets
|
|
else if ($s=='{') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS;
|
|
$entryvalue='';}
|
|
// the end of the key and no value found: it is the bibtex key e.g. \cite{Descartes1637}
|
|
else if ($s==',') {
|
|
$state = GETKEY;
|
|
$delegate->setEntryField(trim($finalkey),trim($entryvalue));
|
|
$entryvalue='';}
|
|
// this is the end of the value AND of the entry
|
|
else if ($s=='}') {
|
|
$state = NOTHING;$isinentry = false;
|
|
$delegate->setEntryField(trim($finalkey),trim($entryvalue));
|
|
$delegate->endEntry($entrysource);
|
|
$entryvalue='';}
|
|
else { $entryvalue=$entryvalue.$s;}
|
|
}
|
|
|
|
|
|
/* GETVALUEDELIMITEDBYCURLYBRACKETS* handle entries delimited by curly brackets and the possible nested curly brackets */
|
|
else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS) {
|
|
|
|
if ($s=='\\') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED;
|
|
$entryvalue=$entryvalue.$s;}
|
|
else if ($s=='{') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;}
|
|
else if ($s=='}') {
|
|
$state = GETVALUE;}
|
|
else { $entryvalue=$entryvalue.$s;}
|
|
}
|
|
// handle anti-slashed brackets
|
|
else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED) {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS;
|
|
$entryvalue=$entryvalue.$s;
|
|
}
|
|
// in first level of curly bracket
|
|
else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL) {
|
|
if ($s=='\\') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED;
|
|
$entryvalue=$entryvalue.$s;}
|
|
else if ($s=='{') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;}
|
|
else if ($s=='}') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS;}
|
|
else { $entryvalue=$entryvalue.$s;}
|
|
}
|
|
// handle anti-slashed brackets
|
|
else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED) {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;
|
|
$entryvalue=$entryvalue.$s;
|
|
}
|
|
|
|
// in second level of curly bracket
|
|
else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL) {
|
|
if ($s=='\\') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED;
|
|
$entryvalue=$entryvalue.$s;}
|
|
else if ($s=='{') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL;}
|
|
else if ($s=='}') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;}
|
|
else { $entryvalue=$entryvalue.$s;}
|
|
}
|
|
// handle anti-slashed brackets
|
|
else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED) {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;
|
|
$entryvalue=$entryvalue.$s;
|
|
}
|
|
|
|
// in third level of curly bracket
|
|
else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL) {
|
|
if ($s=='\\') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED;
|
|
$entryvalue=$entryvalue.$s;}
|
|
else if ($s=='}') {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;}
|
|
else { $entryvalue=$entryvalue.$s;}
|
|
}
|
|
// handle anti-slashed brackets
|
|
else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED) {
|
|
$state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL;
|
|
$entryvalue=$inentryvaluedelimitedA0.$s;
|
|
}
|
|
|
|
/* handles entries delimited by double quotes */
|
|
else if ($state==GETVALUEDELIMITEDBYQUOTES) {
|
|
|
|
if ($s=='\\') {
|
|
$state = GETVALUEDELIMITEDBYQUOTES_ESCAPED;
|
|
$inentryvaluedelimitedB=$inentryvaluedelimitedB.$s;}
|
|
else if ($s=='"') {
|
|
$state = GETVALUE;
|
|
$entryvalue=$entryvalue.$inentryvaluedelimitedB;
|
|
$inentryvaluedelimitedB='';}
|
|
else { $inentryvaluedelimitedB=@$inentryvaluedelimitedB.$s;}
|
|
}
|
|
// handle anti-double quotes
|
|
else if ($state==GETVALUEDELIMITEDBYQUOTES_ESCAPED) {
|
|
$state = GETVALUEDELIMITEDBYQUOTES;
|
|
$inentryvaluedelimitedB=$inentryvaluedelimitedB.$s;
|
|
}
|
|
|
|
} // end for
|
|
} // end while
|
|
$delegate->endFile();
|
|
fclose($handle);
|
|
} // end function
|
|
} // end class
|
|
|
|
/** This class can be used together with StateBasedBibParser */
|
|
class XMLPrettyPrinter {
|
|
function beginFile() {
|
|
header('Content-type: text/xml;');
|
|
print '<?xml version="1.0" encoding="'.ENCODING.'"?>';
|
|
print '<bibfile>';
|
|
}
|
|
|
|
|
|
function endFile() {
|
|
print '</bibfile>';
|
|
}
|
|
function setEntryField($finalkey,$entryvalue) {
|
|
print "<data>\n<key>".$finalkey."</key>\n<value>".$entryvalue."</value>\n</data>\n";
|
|
}
|
|
|
|
function setEntryType($entrytype) {
|
|
print '<type>'.$entrytype.'</type>';
|
|
}
|
|
|
|
function setEntryKey($entrykey) {
|
|
print '<keyonly>'.$entrykey.'</keyonly>';
|
|
}
|
|
|
|
function beginEntry() {
|
|
print "<entry>\n";
|
|
}
|
|
|
|
function endEntry($entrysource) {
|
|
print "</entry>\n";
|
|
}
|
|
} // end class XMLPrettyPrinter
|
|
|
|
/** This class can be used together with StateBasedBibParser */
|
|
class BibDBBuilder {
|
|
|
|
/** A hashtable from keys to bib entries (BibEntry). */
|
|
var $builtdb;
|
|
|
|
/** A hashtable of constant strings */
|
|
var $stringdb;
|
|
|
|
var $currentEntry;
|
|
|
|
function BibDBBuilder($filename) {
|
|
new StateBasedBibtexParser($filename, $this);
|
|
}
|
|
|
|
|
|
function beginFile() {
|
|
$builtdb = array();
|
|
$stringdb = array();
|
|
}
|
|
|
|
function endFile() { //nothing
|
|
}
|
|
|
|
function setEntryField($finalkey,$entryvalue) {
|
|
// first we set the key to lowercase
|
|
$finalkey=strtolower($finalkey);
|
|
|
|
|
|
// is it a constant? then we replace the value
|
|
// we support advanced features of bibtexbrowser
|
|
// see http://newton.ex.ac.uk/tex/pack/bibtex/btxdoc/node3.html
|
|
$entryvalue_array=explode('#',$entryvalue);
|
|
foreach ($entryvalue_array as $k=>$v) {
|
|
$v=strtolower($v);
|
|
if (isset($this->stringdb[$v]))
|
|
{
|
|
// this field will be formated later by xtrim and latex2html
|
|
$entryvalue_array[$k]=$this->stringdb[$v];
|
|
|
|
// we keep a trace of this replacement
|
|
// so as to produce correct bibtex snippets
|
|
$this->currentEntry->constants[$v]=$this->stringdb[$v];
|
|
}
|
|
}
|
|
$entryvalue=implode('',$entryvalue_array);
|
|
|
|
|
|
if ($finalkey!='url') $formatedvalue = xtrim(latex2html($entryvalue));
|
|
else $formatedvalue = trim($entryvalue);
|
|
|
|
$this->currentEntry->setField($finalkey,$formatedvalue);
|
|
}
|
|
|
|
function setEntryType($entrytype) {
|
|
$this->currentEntry->setType($entrytype);
|
|
}
|
|
|
|
function setEntryKey($entrykey) {
|
|
//echo "new entry:".$entrykey."\n";
|
|
$this->currentEntry->setField('key',$entrykey);
|
|
}
|
|
|
|
function beginEntry() {
|
|
$this->currentEntry = new BibEntry();
|
|
}
|
|
|
|
function endEntry($entrysource) {
|
|
$this->currentEntry->text = $entrysource;
|
|
|
|
// ignoring jabref comments
|
|
if (($this->currentEntry->getType()=='comment')) {
|
|
/* do nothing for jabref comments */
|
|
} else if ($this->currentEntry->getType()=='string') {
|
|
foreach($this->currentEntry->fields as $k => $v) {
|
|
//echo $k.' '.$v;
|
|
$k!='type' and $this->stringdb[$k]=$v;
|
|
}
|
|
} else {
|
|
$this->builtdb[$this->currentEntry->getKey()] = $this->currentEntry;
|
|
}
|
|
}
|
|
} // end class BibDBBuilder
|
|
|
|
|
|
|
|
|
|
/** extended version of the trim function
|
|
* removes linebreks, tabs, etc.
|
|
*/
|
|
function xtrim($line) {
|
|
$line = trim($line);
|
|
// we remove the unneeded line breaks
|
|
// this is *required* to correctly split author lists into names
|
|
$line = str_replace("\n\r",' ', $line);//windows like
|
|
$line = str_replace("\n",' ', $line);//unix-like
|
|
// we also replace tabs
|
|
$line = str_replace("\t",' ', $line);
|
|
// remove superfluous spaces e.g. John+++Bar
|
|
$line = preg_replace('/ {2,}/',' ', $line);
|
|
return $line;
|
|
}
|
|
|
|
/** encapsulates the conversion of a single latex chars to the corresponding HTML entity
|
|
* this works thanks to the regularity of html entities
|
|
* it expects a **lower** char
|
|
*/
|
|
function char2html($line,$latexmodifier,$char,$entitiyfragment) {
|
|
$line = str_replace('\\'.$latexmodifier.$char,'&'.$char.''.$entitiyfragment.';', $line);
|
|
$line = str_replace('\\'.$latexmodifier.'{'.$char.'}','&'.$char.''.$entitiyfragment.';', $line);
|
|
$line = str_replace('\\'.$latexmodifier.strtoupper($char),'&'.strtoupper($char).''.$entitiyfragment.';', $line);
|
|
$line = str_replace('\\'.$latexmodifier.'{'.strtoupper($char).'}','&'.strtoupper($char).''.$entitiyfragment.';', $line);
|
|
return $line;
|
|
}
|
|
|
|
/** converts latex chars to HTML entities
|
|
* it uses a naive algortihm
|
|
* I still look for a comprehensive translation table from late chars to html
|
|
* just have this http://isdc.unige.ch/Newsletter/help.html
|
|
*/
|
|
function latex2html($line) {
|
|
$line = preg_replace('/([^\\\\])~/','\\1 ', $line);
|
|
|
|
|
|
// performance increases with this test
|
|
// bug found by Serge Barral: what happens if we have curly braces only (typically to ensure case in Latex)
|
|
// added && strpos($line,'{')===false
|
|
if (strpos($line,'\\')===false && strpos($line,'{')===false) return $line;
|
|
|
|
$chars="abcdefghijklmnopqrstuvwxyz";
|
|
for($i=0;$i<strlen($chars);$i++) {
|
|
$letter=$chars[$i];
|
|
$line = char2html($line,"'",$letter,"acute");
|
|
$line = char2html($line,"`",$letter,"grave");
|
|
$line = char2html($line,"~",$letter,"tilde");
|
|
$line = char2html($line,'"',$letter,"uml");
|
|
$line = char2html($line,'^',$letter,"circ");
|
|
}
|
|
|
|
// special things
|
|
$line = str_replace('\\c{c}','ç', $line);
|
|
$line = str_replace('\\c{C}','Ç', $line);
|
|
$line = str_replace('\\cc','ç', $line);
|
|
$line = str_replace('\\cC','Ç', $line);
|
|
|
|
$line = str_replace('\\o','ø', $line);
|
|
$line = str_replace('\\O','Ø', $line);
|
|
$line = str_replace('\\&','&', $line);
|
|
|
|
// clean out extra tex curly brackets, usually used for preserving capitals
|
|
$line = str_replace('}','', $line);
|
|
$line = str_replace('{','', $line);
|
|
|
|
|
|
// and some spaces
|
|
return trim($line);
|
|
}
|
|
|
|
/** Note that & are encoded as %26 and not as & so it does not break the Z3988 URL */
|
|
function s3988($s) {return urlencode(utf8_encode($s));}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// BIB ENTRIES
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Class to represent a bibliographic entry.
|
|
*/
|
|
class BibEntry {
|
|
|
|
/** The fields (fieldName -> value) of this bib entry. */
|
|
var $fields;
|
|
|
|
/** The constants @STRINGS referred to by this entry */
|
|
var $constants;
|
|
|
|
/** The verbatim copy (i.e., whole text) of this bib entry. */
|
|
var $text;
|
|
|
|
/** Creates an empty new bib entry. Each bib entry is assigned a unique
|
|
* identification number. */
|
|
function BibEntry() {
|
|
static $id = 0;
|
|
$this->id = $id++;
|
|
$this->fields = array();
|
|
$this->constants = array();
|
|
$this->text ='';
|
|
}
|
|
|
|
/** Returns the type of this bib entry. */
|
|
function getType() {
|
|
// strtolower is important to be case-insensitive
|
|
return strtolower($this->getField(Q_TYPE));
|
|
}
|
|
|
|
/** Sets a field of this bib entry. */
|
|
function setField($name, $value) {
|
|
// bullet proofing with this strtolower
|
|
$this->fields[strtolower($name)] = $value;
|
|
}
|
|
|
|
/** Sets a type of this bib entry. */
|
|
function setType($value) {
|
|
// 2009-10-25 added trim
|
|
// to support space e.g. "@article {"
|
|
// as generated by ams.org
|
|
// thanks to Jacob Kellner
|
|
$this->fields[Q_TYPE] =trim($value);
|
|
}
|
|
|
|
/** Tries to build a good URL for this entry */
|
|
function getURL() {
|
|
if ($this->hasField('url')) return $this->getField('url');
|
|
else return "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']).'/'.basename(__FILE__).'?'.createQueryString(array('key'=>$this->getKey()));
|
|
}
|
|
|
|
/** returns a "[pdf]" link if relevant */
|
|
function getUrlLink() {
|
|
if ($this->hasField('url')) return ' <a href="'.$this->getField('url').'">[pdf]</a>';
|
|
return '';
|
|
}
|
|
|
|
/** Reruns the abstract */
|
|
function getAbstract() {
|
|
if ($this->hasField('abstract')) return $this->getField('abstract');
|
|
else return '';
|
|
}
|
|
|
|
|
|
/** Has this entry the given field? */
|
|
function hasField($name) {
|
|
return array_key_exists(strtolower($name), $this->fields);
|
|
}
|
|
|
|
/** Returns the authors of this entry. If no author field exists,
|
|
* returns the editors. If none of authors and editors exists,
|
|
* return a string 'Unknown'. */
|
|
function getAuthor() {
|
|
if (array_key_exists(AUTHOR, $this->fields)) {
|
|
return $this->fields[AUTHOR];
|
|
}
|
|
if (array_key_exists(EDITOR, $this->fields)) {
|
|
return $this->fields[EDITOR];
|
|
}
|
|
return 'Unknown';
|
|
}
|
|
|
|
/** Returns the key of this entry */
|
|
function getKey() {
|
|
return $this->getField('key');
|
|
}
|
|
|
|
/** Returns the title of this entry? */
|
|
function getTitle() {
|
|
return $this->getField('title');
|
|
}
|
|
|
|
/** Returns the publisher of this entry
|
|
* It encodes a specific logic
|
|
* */
|
|
function getPublisher() {
|
|
// citation_publisher
|
|
if ($this->hasField("publisher")) {
|
|
return $this->getField("publisher");
|
|
}
|
|
if ($this->getType()=="phdthesis") {
|
|
return $this->getField(SCHOOL);
|
|
}
|
|
if ($this->getType()=="mastersthesis") {
|
|
return $this->getField(SCHOOL);
|
|
}
|
|
|
|
if ($this->getType()=="techreport") {
|
|
return $this->getField("institution");
|
|
}
|
|
// then we don't know
|
|
return '';
|
|
}
|
|
|
|
/** Returns the authors of this entry as an array */
|
|
function getRawAuthors() {
|
|
$authors = array();
|
|
foreach (explode(' and ', $this->getAuthor()) as $author) {
|
|
$authors[]=$author;
|
|
}
|
|
return $authors;
|
|
}
|
|
|
|
/** Returns the authors of this entry as an array */
|
|
function getFormattedAuthors() {
|
|
$authors = array();
|
|
foreach (explode(' and ', $this->getAuthor()) as $author) {
|
|
$authors[]=formatAuthor($author);
|
|
}
|
|
return $authors;
|
|
}
|
|
|
|
|
|
/** Returns the authors of this entry as an array in a canonical form */
|
|
function getCanonicalAuthors() {
|
|
$authors = array();
|
|
foreach (explode(' and ', $this->getAuthor()) as $author) {
|
|
$authors[]=formatAuthorCanonical($author);
|
|
}
|
|
return $authors;
|
|
}
|
|
|
|
/** Returns the authors of this entry as an array in a comma-separated form */
|
|
function getCommaSeparatedAuthors() {
|
|
$authors = array();
|
|
foreach (explode(' and ', $this->getAuthor()) as $author) {
|
|
$authors[]=formatAuthorCommaSeparated($author);
|
|
}
|
|
return $authors;
|
|
}
|
|
|
|
/** add the link to the homepage if it is defined in a string
|
|
* e.g. @string{hp_MartinMonperrus="http://www.monperrus.net/martin"}
|
|
* The string is a concatenation of firstname, lastname, prefixed by hp_
|
|
* @thanks Eric Bodden for the idea
|
|
*/
|
|
function addHomepageLink($author) {
|
|
// hp as home page
|
|
// accents are handled normally
|
|
// e.g. @STRING{hp_Jean-MarcJézéquel="http://www.irisa.fr/prive/jezequel/"}
|
|
$homepage = strtolower('hp_'.preg_replace('/ /', '', $author));
|
|
//echo $homepage;
|
|
if (isset($_GET[Q_DB]->stringdb[$homepage]))
|
|
$author='<a href="'.$_GET[Q_DB]->stringdb[$homepage].'">'.$author.'</a>';
|
|
return $author;
|
|
}
|
|
|
|
/** Returns the authors as a string depending on the configuration parameter COMMA_NAMES */
|
|
function formattedAuthors() {
|
|
$array_authors = $this->getFormattedAuthors();
|
|
foreach ($array_authors as $k => $author) {
|
|
$array_authors[$k]=$this->addHomepageLink($author);
|
|
}
|
|
if (COMMA_NAMES) return implode('; ',$array_authors);
|
|
else return implode(', ',$array_authors);
|
|
}
|
|
|
|
|
|
|
|
/** Returns the editors of this entry as an arry */
|
|
function getEditors() {
|
|
$editors = array();
|
|
foreach (explode(' and ', $this->getField(EDITOR)) as $editor) {
|
|
$editors[]=$editor;
|
|
}
|
|
return $editors;
|
|
}
|
|
|
|
/**
|
|
* Returns a compacted string form of author names by throwing away
|
|
* all author names except for the first one and appending ", et al."
|
|
*/
|
|
function getCompactedAuthors($author){
|
|
$authors = $this->getAuthors();
|
|
$etal = count($authors) > 1 ? ', et al.' : '';
|
|
return formatAuthor($authors[0]) . $etal;
|
|
}
|
|
|
|
|
|
/** Returns the year of this entry? */
|
|
function getYear() {
|
|
return $this->getField('year');
|
|
}
|
|
|
|
/** Returns the value of the given field? */
|
|
function getField($name) {
|
|
if ($this->hasField($name))
|
|
{return $this->fields[strtolower($name)];}
|
|
else return 'missing '.$name;
|
|
}
|
|
|
|
|
|
|
|
/** Returns the fields */
|
|
function getFields() {
|
|
return $this->fields;
|
|
}
|
|
|
|
/** Returns the identification number. */
|
|
function getId() {
|
|
return $this->id;
|
|
}
|
|
|
|
function getText() {
|
|
/** Returns the verbatim text of this bib entry. */
|
|
return $this->text;
|
|
}
|
|
|
|
/** Returns true if this bib entry contains the given phrase
|
|
* in the given field. if $field is null, all fields are considered.
|
|
* Note that this method is NOT case sensitive */
|
|
function hasPhrase($phrase, $field = null) {
|
|
|
|
// 2010-01-25
|
|
// bug found by jacob kellner
|
|
// we have to search in the formatted fileds and not in the raw entry
|
|
// i.e. all latex markups are not considered for searches
|
|
// i.e. added join(" ",$this->getFields())
|
|
// and html_entity_decode
|
|
if (!$field) {
|
|
return preg_match('/'.$phrase.'/i',$this->getConstants().' '.html_entity_decode(join(" ",$this->getFields()),ENT_NOQUOTES,ENCODING));
|
|
//return stripos($this->getText(), $phrase) !== false;
|
|
}
|
|
if ($this->hasField($field) && (preg_match('/'.$phrase.'/i',$this->getField($field)) ) ) {
|
|
//if ($this->hasField($field) && (stripos($this->getField($field), $phrase) !== false) ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/** Outputs an HTML line (<tr>)with two TDS inside
|
|
*/
|
|
function toTR() {
|
|
echo '<tr class="bibline">';
|
|
echo '<td class="bibref"><a name="'.$this->getId().'"></a>['.$this->getId().']</td> ';
|
|
echo '<td class="bibitem">';
|
|
echo bib2html($this);
|
|
|
|
$href = 'href="'.basename(__FILE__).'?'.createQueryString(array(Q_KEY => $this->getKey())).'"';
|
|
echo " <a {$href}>[bib]</a>";
|
|
|
|
// returns an empty string if no url present
|
|
echo $this->getUrlLink();
|
|
|
|
if ($this->hasField('doi')) {
|
|
echo ' <a href="http://dx.doi.org/'.$this->getField("doi").'">[doi]</a>';
|
|
}
|
|
|
|
echo "</td></tr>\n";
|
|
|
|
|
|
}
|
|
|
|
/** Outputs an coins URL: see http://ocoins.info/cobg.html
|
|
* Used by Zotero, mendeley, etc.
|
|
*/
|
|
function toCoins() {
|
|
$url_parts=array();
|
|
$url_parts[]='ctx_ver=Z39.88-2004';
|
|
|
|
$type = $this->getType();
|
|
if ($type=="book") {
|
|
$url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:book');
|
|
$url_parts[]='rft.btitle='.s3988($this->getTitle());
|
|
$url_parts[]='rft.genre=book';
|
|
} else if ($type=="inproceedings") {
|
|
$url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:book');
|
|
$url_parts[]='rft.atitle='.s3988($this->getTitle());
|
|
$url_parts[]='rft.btitle='.s3988($this->getField(BOOKTITLE));
|
|
|
|
// zotero does not support with this proceeding and conference
|
|
// they give the wrong title
|
|
//$url_parts[]='rft.genre=proceeding';
|
|
//$url_parts[]='rft.genre=conference';
|
|
$url_parts[]='rft.genre=bookitem';
|
|
} else if ($type=="incollection" ) {
|
|
$url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:book');
|
|
$url_parts[]='rft.btitle='.s3988($this->getField(BOOKTITLE));
|
|
$url_parts[]='rft.atitle='.s3988($this->getTitle());
|
|
$url_parts[]='rft.genre=bookitem';
|
|
} else if ($type=="article") {
|
|
$url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:journal');
|
|
$url_parts[]='rft.atitle='.s3988($this->getTitle());
|
|
$url_parts[]='rft.jtitle='.s3988($this->getField("journal"));
|
|
$url_parts[]='rft.volume='.s3988($this->getField("volume"));
|
|
$url_parts[]='rft.issue='.s3988($this->getField("issue"));
|
|
} else { // techreport, phdthesis
|
|
$url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:book');
|
|
$url_parts[]='rft.btitle='.s3988($this->getTitle());
|
|
$url_parts[]='rft.genre=report';
|
|
}
|
|
|
|
$url_parts[]='rft.pub='.s3988($this->getPublisher());
|
|
|
|
// referent
|
|
if ($this->hasField('url')) {
|
|
$url_parts[]='rft_id='.s3988($this->getField("url"));
|
|
} else if ($this->hasField('doi')) {
|
|
$url_parts[]='rft_id='.s3988('info:doi/'.$this->getField("doi"));
|
|
}
|
|
|
|
// referrer, the id pf a collection of objects
|
|
// see also http://www.openurl.info/registry/docs/pdf/info-sid.pdf
|
|
$url_parts[]='rfr_id='.s3988('info:sid/'.$_SERVER['HTTP_HOST'].':'.$_GET[Q_FILE]);
|
|
|
|
$url_parts[]='rft.date='.s3988($this->getYear());
|
|
|
|
foreach ($this->getFormattedAuthors() as $au) $url_parts[]='rft.au='.s3988($au);
|
|
|
|
|
|
return '<span class="Z3988" title="'.implode('&',$url_parts).'"></span>';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* rebuild the set of constants used if any as a string
|
|
*/
|
|
function getConstants() {
|
|
$result='';
|
|
foreach ($this->constants as $k=>$v) {
|
|
$result.='@string{'.$k.'="'.$v."\"}\n";
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Displays a unformated (verbatim) text of the given bib entry.
|
|
* The object may be mutated to read the rest of the fields.
|
|
*/
|
|
function toEntryUnformatted() {
|
|
echo '<div class="purebibtex">';
|
|
echo $this->getConstants();
|
|
if ($this->hasField('url')) {
|
|
$url=$this->getField('url');
|
|
// this is not a parsing but a simple replacement
|
|
echo str_replace($url,'<a href="'.$url.'">'.$url.'</a>',$this->getText());
|
|
} else echo $this->getText();
|
|
echo '</div>';
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**bibtexbrowser uses this function which encapsulates the user-defined name*/
|
|
function bib2html(&$bibentry) {
|
|
$function = BIBLIOGRAPHYSTYLE;
|
|
return $function($bibentry);
|
|
}
|
|
|
|
|
|
include('bibtexbrowser-style-default.php');
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// DISPLAY MANAGEMENT
|
|
// ----------------------------------------------------------------------
|
|
|
|
|
|
/**
|
|
* Given an array of parameter, creates a query string
|
|
*/
|
|
function createQueryString($array_param) {
|
|
// first we add the name of the bib file
|
|
$array_param[Q_FILE] = urlencode($_GET[Q_FILE]);
|
|
|
|
// then a simple transformation and implode
|
|
foreach ($array_param as $key => $val) {
|
|
$array_param[$key]=$key .'='. urlencode($val);
|
|
}
|
|
return implode("&",$array_param);
|
|
}
|
|
|
|
/**
|
|
* Given a query, an array of key value pairs, returns a href string
|
|
* of the form: href="?bib=testing.bib&search=JML.
|
|
*/
|
|
function makeHref($query = NULL) {
|
|
return 'href="?'. createQueryString($query) .'"';
|
|
}
|
|
|
|
/**
|
|
* Returns the last name of an author name.
|
|
*/
|
|
function getLastName($author){
|
|
list($firstname, $lastname) = splitFullName($author);
|
|
return $lastname;
|
|
}
|
|
|
|
/**
|
|
* Returns the splitted name of an author name. The argument is assumed to be
|
|
* <FirstName LastName> or <LastName, FirstName>.
|
|
*/
|
|
function splitFullName($author){
|
|
$author = trim($author);
|
|
// the author format is "Joe Dupont"
|
|
if (strpos($author,',')===false) {
|
|
$parts=explode(' ', $author);
|
|
// get the last name
|
|
$lastname = array_pop($parts);
|
|
$firstname = implode(" ", $parts);
|
|
}
|
|
// the author format is "Dupont, J."
|
|
else {
|
|
$parts=explode(',', $author);
|
|
// get the last name
|
|
$lastname = str_replace(',','',array_shift($parts));
|
|
$firstname = implode(" ", $parts);
|
|
}
|
|
return array(trim($firstname), trim($lastname));
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Returns the formated author name w.r.t to the user preference encoded in COMMA_NAMES
|
|
*/
|
|
function formatAuthor($author){
|
|
if (COMMA_NAMES) {
|
|
return formatAuthorCommaSeparated($author);
|
|
}
|
|
else return formatAuthorCanonical($author);
|
|
}
|
|
|
|
/**
|
|
* Returns the formated author name as "FirstName LastName".
|
|
*/
|
|
function formatAuthorCanonical($author){
|
|
list($firstname, $lastname) = splitFullName($author);
|
|
if ($firstname!='') return $firstname.' '.$lastname;
|
|
else return $lastname;
|
|
}
|
|
|
|
/**
|
|
* Returns the formated author name as "LastName, FirstName".
|
|
*/
|
|
function formatAuthorCommaSeparated($author){
|
|
list($firstname, $lastname) = splitFullName($author);
|
|
if ($firstname!='') return $lastname.', '.$firstname;
|
|
else return $lastname;
|
|
}
|
|
|
|
/** New undocumented feature, used by Benoit Baudry
|
|
* see http://www.irisa.fr/triskell/perso_pro/bbaudry/publications.php
|
|
*
|
|
* $_GET['library']=1;
|
|
* $_GET['bib']='metrics.bib';
|
|
* $_GET['all']=1;
|
|
* include( 'bibtexbrowser.php' );
|
|
* setDB();
|
|
* new IndependentYearMenu();
|
|
* new Dispatcher();
|
|
*
|
|
*/
|
|
class IndependentYearMenu {
|
|
function IndependentYearMenu() {
|
|
if (!isset($_GET[Q_DB])) {die('Did you forget to call setDB() before instantiating this class?');}
|
|
$yearIndex = $_GET[Q_DB]->yearIndex();
|
|
echo '<div id="yearmenu">Year: ';
|
|
$formatedYearIndex = array();
|
|
$formatedYearIndex[] = '<a '.makeHref(array(Q_YEAR=>'.*')).'>All</a>';
|
|
foreach($yearIndex as $year) {
|
|
$formatedYearIndex[] = '<a '.makeHref(array(Q_YEAR=>$year)).'>'.$year.'</a>';
|
|
}
|
|
|
|
// by default the separator is a |
|
|
echo implode('|',$formatedYearIndex);
|
|
echo '</div>';
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* A class providing GUI controllers in a frame.
|
|
*/
|
|
class MenuManager extends BibtexBrowserDisplay {
|
|
|
|
/** The bibliographic database, an instance of class BibDataBase. */
|
|
var $db;
|
|
|
|
/** Creates a new display manager that uses the given bib database. */
|
|
function MenuManager(&$db) {
|
|
$this->db =$db;
|
|
new HTMLWrapper($this,array('robots'=>'noindex'));
|
|
}
|
|
|
|
/** function called back by HTMLWrapper */
|
|
function display() {
|
|
echo $this->searchView().'<br/>';
|
|
echo $this->typeVC().'<br/>';
|
|
echo $this->yearVC().'<br/>';
|
|
echo $this->authorVC().'<br/>';
|
|
echo $this->tagVC().'<br/>';
|
|
}
|
|
|
|
/** Displays the title in a table. */
|
|
function titleView() {
|
|
?>
|
|
<table>
|
|
<tr>
|
|
<td class="title">Generated from <?php echo $_GET[Q_FILE]; ?></td>
|
|
</tr>
|
|
</table>
|
|
<?php
|
|
}
|
|
|
|
/** Displays the search view in a form. */
|
|
function searchView() {
|
|
?>
|
|
<form action="?" method="get" target="main">
|
|
<input type="text" name="<?php echo Q_SEARCH; ?>" class="input_box" size="18"/>
|
|
<input type="hidden" name="<?php echo Q_FILE; ?>" value="<?php echo $_GET[Q_FILE]; ?>"/>
|
|
<br/>
|
|
<input type="submit" value="search" class="input_box"/>
|
|
</form>
|
|
<?php
|
|
}
|
|
|
|
/** Displays and controls the types menu in a table. */
|
|
function typeVC() {
|
|
$types = array();
|
|
$types[''] = 'all types';
|
|
foreach ($this->db->getTypes() as $type) {
|
|
$types[$type] = $type;
|
|
}
|
|
// retreive or calculate page number to display
|
|
if (isset($_GET[Q_TYPE_PAGE])) {
|
|
$page = $_GET[Q_TYPE_PAGE];
|
|
}
|
|
else $page = 1;
|
|
|
|
$this->displayMenu('Types', $types, $page, TYPES_SIZE, Q_TYPE_PAGE, Q_TYPE);
|
|
}
|
|
|
|
/** Displays and controls the authors menu in a table. */
|
|
function authorVC() {
|
|
// retrieve authors list to display
|
|
$authors = $this->db->authorIndex();
|
|
|
|
// determine the authors page to display
|
|
if (isset($_GET[Q_AUTHOR_PAGE])) {
|
|
$page = $_GET[Q_AUTHOR_PAGE];
|
|
}
|
|
else $page = 1;
|
|
|
|
|
|
$this->displayMenu('Authors', $authors, $page, AUTHORS_SIZE, Q_AUTHOR_PAGE,
|
|
Q_AUTHOR);
|
|
}
|
|
|
|
/** Displays and controls the tag menu in a table. */
|
|
function tagVC() {
|
|
// retrieve authors list to display
|
|
$tags = $this->db->tagIndex();
|
|
|
|
// determine the authors page to display
|
|
if (isset($_GET[Q_TAG_PAGE])) {
|
|
$page = $_GET[Q_TAG_PAGE];
|
|
} else $page = 1;
|
|
|
|
|
|
if (count($tags)>0) $this->displayMenu('Keywords', $tags, $page, TAGS_SIZE, Q_TAG_PAGE,
|
|
Q_TAG);
|
|
}
|
|
|
|
/** Displays and controls the tag menu in a table. */
|
|
function yearVC() {
|
|
// retrieve authors list to display
|
|
$years = $this->db->yearIndex();
|
|
|
|
// determine the authors page to display
|
|
if (isset($_GET[Q_YEAR_PAGE])) {
|
|
$page = $_GET[Q_YEAR_PAGE];
|
|
}
|
|
else $page = 1;
|
|
|
|
|
|
$this->displayMenu('Years', $years, $page, YEAR_SIZE, Q_YEAR_PAGE,
|
|
Q_YEAR);
|
|
}
|
|
|
|
/** Displays the main contents . */
|
|
function mainVC() {
|
|
$this->display->display();
|
|
}
|
|
|
|
/** Displays a list menu in a table.
|
|
*
|
|
* $title: title of the menu (string)
|
|
* $list: list of menu items (string)
|
|
* $page: page number to display (number)
|
|
* $pageSize: size of each page
|
|
* $pageKey: URL query name to send the page number to the server
|
|
* $targetKey: URL query name to send the target of the menu item
|
|
*/
|
|
function displayMenu($title, $list, $page, $pageSize, $pageKey,
|
|
$targetKey) {
|
|
$numEntries = count($list);
|
|
$startIndex = ($page - 1) * $pageSize;
|
|
$endIndex = $startIndex + $pageSize;
|
|
?>
|
|
<table style="width:100%" class="menu">
|
|
<tr>
|
|
<td>
|
|
<!-- this table is used to have the label on the left
|
|
and the navigation links on the right -->
|
|
<table style="width:100%" border="0" cellspacing="0" cellpadding="0">
|
|
<tr>
|
|
<td class="header"><b><?php echo $title; ?></b></td>
|
|
<td class="header" align="right"><b>
|
|
<?php echo $this->menuPageBar($pageKey, $numEntries, $page,
|
|
$pageSize, $startIndex, $endIndex);?></b></td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">
|
|
<?php $this->displayMenuItems($list, $startIndex, $endIndex,
|
|
$targetKey); ?>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<?php
|
|
}
|
|
|
|
/** Returns a string to displays forward and reverse page controls.
|
|
*
|
|
* $queryKey: key to send the page number as a URL query string
|
|
* $page: current page number to display
|
|
* $numEntries: number of menu items
|
|
* $start: start index of the current page
|
|
* $end: end index of the current page
|
|
*/
|
|
function menuPageBar($queryKey, $numEntries, $page, $pageSize,
|
|
$start, $end) {
|
|
|
|
$result = '';
|
|
/* // commented after the usability remarks of Benoit Combemale
|
|
// fast (2 pages) reverse (<<)
|
|
if ($start - $pageSize > 0) {
|
|
$href = makeHref(array($queryKey => $page - 2,'menu'=>''));
|
|
$result .= '<a '. $href ."><b>«</b></a>\n";
|
|
}*/
|
|
|
|
// (1 page) reverse (<)
|
|
if ($start > 0) {
|
|
$href = makeHref(array($queryKey => $page - 1,'menu'=>''));
|
|
$result .= '<a '. $href ."><b>[pred]</b></a>\n";
|
|
}
|
|
|
|
// (1 page) forward (>)
|
|
if ($end < $numEntries) {
|
|
$href = makeHref(array($queryKey => $page + 1,'menu'=>''));
|
|
$result .= '<a '. $href ."><b>[next]</b></a>\n";
|
|
}
|
|
|
|
/*// commented after the usability remarks of Benoit Combemale
|
|
// fast (2 pages) forward (>>)
|
|
if (($end + $pageSize) < $numEntries) {
|
|
$href = makeHref(array($queryKey => $page + 2,'menu'=>''));
|
|
$result .= '<a '. $href ."><b>»</b></a>\n";
|
|
}*/
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Displays menu items (anchors) from the start index (inclusive) to
|
|
* the end index (exclusive). For each menu, the following form of
|
|
* string is printed:
|
|
*
|
|
* <a href="...?bib=cheon.bib&search_author=Yoonsik+Cheon">
|
|
* Cheon, Yoonsik</a>
|
|
* <div class="mini_se"></div>
|
|
*/
|
|
function displayMenuItems($items, $startIndex, $endIndex, $queryKey) {
|
|
$index = 0;
|
|
foreach ($items as $key => $item) {
|
|
if ($index >= $startIndex && $index < $endIndex) {
|
|
$href = makeHref(array($queryKey => $key));
|
|
echo '<a '. $href .' target="main">'. $item ."</a>\n";
|
|
echo "<div class=\"mini_se\"></div>\n";
|
|
}
|
|
$index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Class to encapsulates the header formating and the powered bw footer */
|
|
class BibtexBrowserDisplay {
|
|
/** the title */
|
|
var $title;
|
|
|
|
function getTitle() { return $this->title; }
|
|
|
|
function display() { /* unimplemented */ }
|
|
|
|
/** returns the url of this display (e.g. base on the query)*/
|
|
function getURL() { return '';}
|
|
|
|
/** returns the url of the RSS */
|
|
function getRSS() { return '';}
|
|
|
|
/** Returns the powered by part */
|
|
function poweredby() {
|
|
$poweredby = "\n".'<div style="text-align:right;font-size: xx-small;opacity: 0.6;" class="poweredby">';
|
|
$poweredby .= '<!-- If you like bibtexbrowser, thanks to keep the link :-) -->';
|
|
$poweredby .= 'Powered by <a href="http://www.monperrus.net/martin/bibtexbrowser/">bibtexbrowser</a><!--v__MTIME__-->';
|
|
$poweredby .= '</div>'."\n";
|
|
return $poweredby;
|
|
}
|
|
|
|
function formatedHeader() { return "<div class=\"rheader\">{$this->title}</div>\n";}
|
|
|
|
|
|
}
|
|
|
|
/** transforms an array representing a query into a formatted string */
|
|
function query2title(&$query) {
|
|
$headers = array();
|
|
foreach($query as $k=>$v) $headers[$k] = ucwords($k).': '.ucwords($v);
|
|
// special cases
|
|
if (isset($headers[Q_ALL])) $headers[Q_ALL] = 'Publications in '.$_GET[Q_FILE];
|
|
if (isset($headers[Q_AUTHOR])) $headers[Q_AUTHOR] = 'Publications of '.$_GET[Q_AUTHOR];
|
|
return join(' & ',$headers);
|
|
}
|
|
|
|
|
|
/** Class to display a result as a set of pages. */
|
|
class PagedDisplay extends BibtexBrowserDisplay {
|
|
/** the bib entries to display. */
|
|
var $result;
|
|
|
|
/** the page number to display. */
|
|
var $page;
|
|
|
|
/** the total number of pages to display. */
|
|
var $noPages;
|
|
|
|
/** the start index to display. */
|
|
var $startIndex;
|
|
|
|
/** the end index to display. */
|
|
var $endIndex;
|
|
|
|
/** the content strategy (cf. pattern strategy) */
|
|
var $contentStrategy;
|
|
|
|
/** the query to reinject in links to different pages */
|
|
var $filter;
|
|
|
|
/** Creates an instance with the given entries and header. */
|
|
function PagedDisplay(&$result, $filter) {
|
|
$this->result = $result;
|
|
$this->filter = $filter;
|
|
// requesting a different page of the result view?
|
|
if (isset($_GET[Q_RESULT])) {
|
|
$this->setPage($_GET[Q_RESULT]);
|
|
} else $this->page = 1;
|
|
$this->setTitle();
|
|
$this->contentStrategy = new DefaultContentStrategy();
|
|
}
|
|
|
|
/** sets the $this->title of BibtexBrowserDisplay based on the $filter */
|
|
function setTitle() {
|
|
$this->title = query2title($this->filter);
|
|
if ($this->page>1) $this->title.=' - page '.$this->page;
|
|
}
|
|
|
|
/** Sets the page number to display. */
|
|
function setPage($page) {
|
|
$this->page = $page;
|
|
}
|
|
|
|
/** overrides */
|
|
function formatedHeader() { return '<div class="rheader">'.$this->title.' '.createRSSLink($this->filter).'</div>';}
|
|
|
|
/** overrides */
|
|
function getURL() { return '?'.createQueryString($this->filter);}
|
|
|
|
/** overrides */
|
|
function getRSS() { return basename(__FILE__).'?'.createQueryString($this->filter).'&rss';}
|
|
|
|
/** Displays the entries preceded with the header. */
|
|
function display() {
|
|
|
|
$page = $this->page;
|
|
|
|
// print error message if no entry.
|
|
if (empty($this->result)) {
|
|
echo "<b>No match found!</b>\n";
|
|
return;
|
|
}
|
|
|
|
$this->noPages = ceil(count($this->result) / PAGE_SIZE);
|
|
|
|
/** Displays the header stringg. */
|
|
echo $this->formatedHeader();
|
|
|
|
if ($this->noPages>1) $this->displayPageBar($this->noPages, $page);
|
|
|
|
$this->startIndex = ($page - 1) * PAGE_SIZE;
|
|
$this->endIndex =$this->startIndex + PAGE_SIZE;
|
|
|
|
$this->contentStrategy->display($this);
|
|
if ($this->noPages>1) $this->displayPageBar($this->noPages, $page);
|
|
|
|
echo $this->poweredby();
|
|
|
|
}
|
|
|
|
function isDisplayed($index) {
|
|
if ($index >= $this->startIndex && $index < $this->endIndex) return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
/** Displays a page bar consisting of clickable page numbers. */
|
|
function displayPageBar($noPages, $page) {
|
|
|
|
// bug found by benoit, first we have to reset the q_result
|
|
$this->filter[Q_RESULT] = 1;
|
|
|
|
$barSize = 10; // *2
|
|
$start = ($page - $barSize) > 0 ? $page - $barSize : 1;
|
|
$end = min($noPages, $start + $barSize * 2);
|
|
|
|
echo '<div class="menu"><center>';
|
|
|
|
// fast reverse (<<)
|
|
if ($start - $barSize*2 > 0) {
|
|
$this->filter[Q_RESULT] = $page - $barSize * 2;
|
|
$href = makeHref($this->filter);
|
|
echo '<a '. $href .">[«]</a>";
|
|
}
|
|
|
|
// reverse (<)
|
|
if ($start > 1) {
|
|
$this->filter[Q_RESULT] =$start - 1;
|
|
$href = makeHref($this->filter);
|
|
echo '<a '. $href .">[<]</a>";
|
|
}
|
|
|
|
// page numbers
|
|
foreach (range($start, $end) as $i) {
|
|
// default page is #1
|
|
// we don't duplicate URLs
|
|
if ($i > 1) $this->filter[Q_RESULT] = $i;
|
|
$href = makeHref($this->filter);
|
|
if ($i == $page) {
|
|
// don't make links for current page
|
|
echo '<b>['. $i .']</b>';
|
|
} else {
|
|
echo '<a '. $href .'>['. $i .']</a>';
|
|
}
|
|
}
|
|
|
|
// forward (>)
|
|
if ($end < $noPages) {
|
|
$this->filter[Q_RESULT] = $end + 1;
|
|
$href = makeHref($this->filter);
|
|
echo '<a '. $href .">[>]</a>";
|
|
}
|
|
|
|
// fast forward (>>)
|
|
if (($end + $barSize*2) <= $noPages) {
|
|
$this->filter[Q_RESULT] =$end + $barSize * 2;
|
|
$href = makeHref($this->filter);
|
|
echo '<a '. $href .">[»]</a>\n";
|
|
}
|
|
//print_r($this->filter);
|
|
echo '</center></div>';
|
|
}
|
|
}
|
|
|
|
/** creates an RSS link with text or image depending on the environment */
|
|
function createRSSLink($filter) {
|
|
// default label
|
|
$label='[rss]';
|
|
// auto adaptive code :-)
|
|
//if (is_file('rss.png')) $label='<img src="rss.png"/>';
|
|
return '<a href="'.basename(__FILE__).'?'.createQueryString($filter).'&rss" class="rsslink">'.$label.'</a>';
|
|
}
|
|
|
|
|
|
/**
|
|
* Displays the summary information of each bib entries of the
|
|
* current page. For each entry, this method displays the author,
|
|
* title; the bib entries are displayed grouped by the
|
|
* publication years. If the bib list is empty, an error message is
|
|
* displayed.
|
|
*/
|
|
class DefaultContentStrategy {
|
|
|
|
/** $display: an instance of PagedDisplay */
|
|
function display(&$display) {
|
|
// create a year -> entries map to display by years
|
|
$years = array();
|
|
foreach ($display->result as $e) {
|
|
$y = trim($e->getField(YEAR));
|
|
$years[$y][$e->getKey()] = $e;
|
|
}
|
|
krsort($years);
|
|
|
|
?>
|
|
|
|
<table class="result" >
|
|
<?php
|
|
|
|
$index = 0;
|
|
$refnum = count($display->result)-(($display->page-1)*PAGE_SIZE);
|
|
foreach ($years as $year => $entries) {
|
|
|
|
|
|
if ($display->isDisplayed($index)) {
|
|
?>
|
|
<tr class="date">
|
|
<td colspan="2" class="header"><?php echo $year; ?></td>
|
|
</tr>
|
|
<?php
|
|
}
|
|
// sort by keys, enable a nice sorting as Dupont2008a, Dupont2008b, Dupont2008c
|
|
krsort($entries);
|
|
foreach ($entries as $bib) {
|
|
if ($display->isDisplayed($index)) {
|
|
$bib->id = $refnum--;
|
|
$bib->toTR();
|
|
}
|
|
$index++;
|
|
|
|
} // end foreach
|
|
}
|
|
?>
|
|
</table>
|
|
<?php
|
|
} // end function
|
|
} // end class
|
|
|
|
|
|
/** Class to display en error message */
|
|
class NonExistentBibEntryError {
|
|
|
|
function NonExistentBibEntryError() {
|
|
header('HTTP/1.1 404 Not found');
|
|
?>
|
|
<b>Sorry, this bib entry does not exist.</b>
|
|
<a href="?">Back to bibtexbrowser</a>
|
|
<?php
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/** Class to display the publication records sorted by publication types. */
|
|
class AcademicDisplay extends BibtexBrowserDisplay {
|
|
|
|
/** the query */
|
|
var $query;
|
|
|
|
/**
|
|
* $entries: an array of bib entries
|
|
* $query: the array representing the query
|
|
*/
|
|
function AcademicDisplay(&$entries,&$query) {
|
|
$this->query=$query;
|
|
$this->db=new BibDataBase();
|
|
$this->db->bibdb = $entries;
|
|
$this->title = query2title($query);
|
|
}
|
|
|
|
/** overrides */
|
|
function formatedHeader() { return '<div class="rheader">'.$this->title.' '.createRSSLink($this->query).'</div>';}
|
|
|
|
|
|
/** transforms a query to HTML
|
|
* $ query is an array (e.g. array(Q_TYPE=>'book'))
|
|
* $title is a string, the title of the section
|
|
*/
|
|
function search2html($query, $title) {
|
|
$entries = $this->db->multisearch($query);
|
|
if (count($entries)>0) {
|
|
echo "\n".'<div class="header">'.$title.'</div>'."\n";
|
|
echo '<table class="result">'."\n";
|
|
foreach ($entries as $bib) {
|
|
$bib->id = $bib->getYear();
|
|
$bib->toTR();
|
|
} // end foreach
|
|
echo '</table>';
|
|
}
|
|
|
|
}
|
|
|
|
function display() {
|
|
echo $this->formatedHeader();
|
|
|
|
// Books
|
|
$this->search2html(array(Q_TYPE=>'book'),'Books');
|
|
|
|
// Journal / Bookchapters
|
|
$this->search2html(array(Q_TYPE=>'article|incollection'),'Refereed Articles and Book Chapters');
|
|
|
|
// conference papers
|
|
$this->search2html(array(Q_TYPE=>'inproceedings',Q_EXCLUDE=>'workshop'),'Refereed Conference Papers');
|
|
|
|
// workshop papers
|
|
$this->search2html(array(Q_TYPE=>'inproceedings',Q_SEARCH=>'workshop'),'Refereed Workshop Papers');
|
|
|
|
// misc and thesis
|
|
$this->search2html(array(Q_TYPE=>'misc|phdthesis|mastersthesis|techreport'),'Other Publications');
|
|
|
|
echo $this->poweredby();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Class to display a single bib entry.
|
|
* This view is optimized for Google Scholar
|
|
* */
|
|
class BibEntryDisplay extends BibtexBrowserDisplay {
|
|
|
|
/** the bib entry to display */
|
|
var $bib;
|
|
|
|
/** Creates an instance with the given bib entry and header.
|
|
* It the object is an instance of BibIndexEntry, it may be
|
|
* mutated to read the rest of the fields.
|
|
*/
|
|
function BibEntryDisplay(&$bibentry) {
|
|
$this->bib = $bibentry;
|
|
$this->title = $this->bib->getTitle().' (bibtex)';
|
|
//$this->title = $this->bib->getTitle().' (bibtex)'.$this->bib->getUrlLink();
|
|
}
|
|
|
|
|
|
function display() {
|
|
echo $this->bib->toCoins();
|
|
echo $this->formatedHeader();
|
|
echo $this->bib->toEntryUnformatted();
|
|
//echo $this->bib->getUrlLink();
|
|
|
|
echo $this->poweredby();
|
|
}
|
|
|
|
/** Creates metadata for Google Scholar
|
|
* + a description
|
|
* See http://www.monperrus.net/martin/accurate+bibliographic+metadata+and+google+scholar
|
|
* */
|
|
function metadata() {
|
|
$result=array();
|
|
$result['description']=trim(strip_tags(str_replace('"','',bib2html($this->bib))));
|
|
$result['citation_title']=$this->bib->getTitle();
|
|
$result['citation_authors']=implode('; ',$this->bib->getCommaSeparatedAuthors());
|
|
$result['citation_date']=$this->bib->getYear();
|
|
|
|
// citation_publisher
|
|
$result['citation_publisher']=$this->bib->getPublisher();
|
|
|
|
|
|
// BOOKTITLE: JOURNAL NAME OR PROCEEDINGS
|
|
if ($this->bib->getType()=="article") { // journal article
|
|
$result['citation_journal_title']=$this->bib->getField("journal");
|
|
$result['citation_volume']=$this->bib->getField("volume");
|
|
if ($this->bib->hasField("issue"))
|
|
$result['citation_issue']=$this->bib->getField("issue");
|
|
} else if ($this->bib->hasField(BOOKTITLE)) {
|
|
// this is like cat.inist.fr
|
|
// but this is not at all documented on the web
|
|
//$result['citation_conference']=$this->bib->getField(BOOKTITLE);
|
|
|
|
// this is like bibtex
|
|
// but this is not at all documented on the web
|
|
// $result['citation_booktitle']=$this->bib->getField(BOOKTITLE);
|
|
|
|
// according to the advanced search view of Google Scholar
|
|
// There is a single metadata for the containing entity (journal or proceedings)
|
|
// that's why we use it
|
|
$result['citation_journal_title']=$this->bib->getField(BOOKTITLE);
|
|
}
|
|
|
|
|
|
// generic
|
|
if ($this->bib->hasField("doi")) {
|
|
$result['citation_doi']=$this->bib->getField("doi");
|
|
}
|
|
if ($this->bib->hasField("url")) {
|
|
$result['citation_pdf_url']=$this->bib->getField("url");
|
|
}
|
|
|
|
return $result;
|
|
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// DATABASE MANAGEMENT
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Abstraction of bibliographic database to contain a set of
|
|
* bibliographic entries and maintain them.
|
|
*/
|
|
class BibDataBase {
|
|
/** A hash table from keys (e.g. Goody1994) to bib entries (BibEntry instances). */
|
|
var $bibdb;
|
|
|
|
/** A hashtable of constant strings */
|
|
var $stringdb;
|
|
|
|
/** Creates a new database by parsing bib entries from the given
|
|
* file. */
|
|
function load($filename) {
|
|
$db = new BibDBBuilder($filename);
|
|
//print_r($parser);
|
|
$this->bibdb =$db->builtdb;
|
|
$this->stringdb =$db->stringdb;
|
|
//print_r($this->stringdb);
|
|
}
|
|
|
|
/** Creates a new empty database */
|
|
function BibDataBase() {
|
|
$this->bibdb = array();
|
|
}
|
|
|
|
/** Returns all entries as an array. Each entry is an instance of
|
|
* class BibEntry. */
|
|
function getEntries() {
|
|
return $this->bibdb;
|
|
}
|
|
/** tests wheter the database contains a bib entry with $key */
|
|
function contains($key) {
|
|
return isset($this->bibdb[$key]);
|
|
}
|
|
/** Returns all entries categorized by types. The returned value is
|
|
* a hashtable from types to arrays of bib entries.
|
|
*/
|
|
function getEntriesByTypes() {
|
|
$result = array();
|
|
foreach ($this->bibdb as $b) {
|
|
$result[$b->getType()][] = $b;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/** Returns an array containing all the bib types (strings). */
|
|
function getTypes() {
|
|
$result = array();
|
|
foreach ($this->bibdb as $b) {
|
|
$result[$b->getType()] = 1;
|
|
}
|
|
$result = array_keys($result);
|
|
return $result;
|
|
}
|
|
|
|
/** Generates and returns an array consisting of all authors.
|
|
* The returned array is a hash table with keys <FirstName LastName>
|
|
* and values <LastName, FirstName>.
|
|
*/
|
|
function authorIndex(){
|
|
$result = array();
|
|
foreach ($this->bibdb as $bib) {
|
|
foreach($bib->getRawAuthors() as $a){
|
|
//we use an array because several authors can have the same lastname
|
|
@$result[getLastName($a)][$a]++;
|
|
}
|
|
}
|
|
ksort($result);
|
|
|
|
// now authors are sorted by last name
|
|
// we rebuild a new array for having good keys in author page
|
|
$realresult = array();
|
|
foreach($result as $x) {
|
|
ksort($x);
|
|
foreach($x as $v => $tmp) $realresult[$v] = formatAuthor($v);
|
|
}
|
|
|
|
return $realresult;
|
|
}
|
|
|
|
/** Generates and returns an array consisting of all tags.
|
|
*/
|
|
function tagIndex(){
|
|
$result = array();
|
|
foreach ($this->bibdb as $bib) {
|
|
if (!$bib->hasField("keywords")) continue;
|
|
$tags =preg_split('/[,;]/', $bib->getField("keywords"));
|
|
foreach($tags as $a){
|
|
$ta = trim($a);
|
|
$result[$ta] = $ta;
|
|
}
|
|
}
|
|
asort($result);
|
|
return $result;
|
|
}
|
|
|
|
/** Generates and returns an array consisting of all years.
|
|
*/
|
|
function yearIndex(){
|
|
$result = array();
|
|
foreach ($this->bibdb as $bib) {
|
|
if (!$bib->hasField("year")) continue;
|
|
$year = $bib->getField("year");
|
|
$result[$year] = $year;
|
|
}
|
|
arsort($result);
|
|
return $result;
|
|
}
|
|
|
|
/** Given its ID, return the bib entry. */
|
|
function getEntry($id){
|
|
foreach($this->bibdb as $bib) {
|
|
if($bib->getId() == $id)
|
|
return $bib;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/** Given its key, return the bib entry. */
|
|
function getEntryByKey($key) {
|
|
return $this->bibdb[$key];
|
|
}
|
|
|
|
/**
|
|
* Returns an array containing all bib entries matching the given
|
|
* type.
|
|
*/
|
|
function searchType($type){
|
|
$result = array();
|
|
foreach($this->bibdb as $bib) {
|
|
if($bib->getType() == $type)
|
|
$result[] = $bib;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/** Returns an array of bib entries (BibEntry) that satisfy the query
|
|
* $query is an hash with entry type as key and searched fragment as value
|
|
* the returned array is sorted by year
|
|
*/
|
|
function multisearch($query) {
|
|
if (count($query)<1) {return array();}
|
|
if (isset($query[Q_ALL])) return array_values($this->bibdb);
|
|
|
|
$result = array();
|
|
|
|
foreach ($this->bibdb as $bib) {
|
|
$entryisselected = true;
|
|
foreach ($query as $field => $fragment) {
|
|
if ($field==Q_SEARCH) {
|
|
// we search in the whole bib entry
|
|
if (!$bib->hasPhrase($fragment)) {
|
|
$entryisselected = false;
|
|
}
|
|
}
|
|
else if ($field==Q_EXCLUDE) {
|
|
if ($bib->hasPhrase($fragment)) {
|
|
$entryisselected = false;
|
|
}
|
|
}
|
|
else {
|
|
if (!$bib->hasPhrase($fragment, $field)) {
|
|
$entryisselected = false;
|
|
}
|
|
}
|
|
|
|
}
|
|
if ($entryisselected) $result[$bib->getYear().$bib->getKey()] = $bib;
|
|
}
|
|
krsort($result);
|
|
return $result;
|
|
}
|
|
} // end class
|
|
|
|
/* returns the default embedded CSS of bibtexbrowser */
|
|
function bibtexbrowserDefaultCSS() {
|
|
?>
|
|
|
|
/* title */
|
|
.bibtitle { font-weight:bold; }
|
|
/* author */
|
|
.bibauthor { /* nothing by default */ }
|
|
/* booktitle (e.g. proceedings title, journal name, etc )*/
|
|
.bibbooktitle { font-style:italic; }
|
|
/* publisher */
|
|
.bibpublisher { /* nothing by default */ }
|
|
|
|
|
|
.title {
|
|
color: #003366;
|
|
font-size: large;
|
|
font-weight: bold;
|
|
text-align: right;
|
|
}
|
|
|
|
.header {
|
|
background-color: #995124;
|
|
color: #FFFFFF;
|
|
padding: 1px 2px 1px 2px;
|
|
}
|
|
|
|
.rheader {
|
|
font-weight: bold;
|
|
background-color: #003366;
|
|
color: #ffffff;
|
|
padding: 2px;
|
|
margin-bottom: 10px;
|
|
border-bottom: #ff6633 2px solid;
|
|
|
|
}
|
|
.menu {
|
|
font-size: x-small;
|
|
background-color: #EFDDB4;
|
|
padding: 0px;
|
|
border: 1px solid #000000;
|
|
margin: 0px;
|
|
}
|
|
.menu a {
|
|
text-decoration: none;
|
|
color: #003366;
|
|
}
|
|
.menu a:hover {
|
|
color: #ff6633;
|
|
}
|
|
|
|
.bibref {
|
|
padding:7px;
|
|
padding-left:15px;
|
|
vertical-align:text-top;
|
|
}
|
|
|
|
.result {
|
|
padding:0px;
|
|
border: 1px solid #000000;
|
|
margin:0px;
|
|
background-color: #ffffff;
|
|
width:100%;
|
|
}
|
|
.result a {
|
|
text-decoration: none;
|
|
color: #469AF8;
|
|
}
|
|
|
|
.result a:hover {
|
|
color: #ff6633;
|
|
}
|
|
|
|
.purebibtex {
|
|
font-family: monospace;
|
|
background-color:#FFFFFF;
|
|
font-size: small;
|
|
border: 1px solid #000000;
|
|
white-space:pre;
|
|
|
|
}
|
|
.input_box{
|
|
margin-bottom : 2px;
|
|
}
|
|
.mini_se {
|
|
border: none 0;
|
|
border-top: 1px dashed #717171;
|
|
height: 1px;
|
|
}
|
|
.a_name a {
|
|
color:#469AF8;
|
|
width:130px;
|
|
}
|
|
|
|
.rsslink {
|
|
text-decoration: none;
|
|
color:#F88017;
|
|
/* could be fancy, see : http://www.feedicons.com/ for icons*/
|
|
/*background-image: url("rss.png"); text-indent: -9999px;*/
|
|
}
|
|
<?php
|
|
} // end function bibtexbrowserDefaultCSS
|
|
|
|
/** A class to wrap contents in an HTML page
|
|
withe <HTML><BODY> and TITLE */
|
|
class HTMLWrapper {
|
|
/**
|
|
* $content: an object with a display() method
|
|
* $title: title of the page
|
|
*/
|
|
function HTMLWrapper(&$content,$metatags=array()/* an array name=>value*/) {
|
|
?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo ENCODING ?>"/>
|
|
<meta name="generator" content="bibtexbrowser v__MTIME__" />
|
|
<?php if ($content->getRSS()!='') echo '<link rel="alternate" type="application/rss+xml" title="RSS" href="'.$content->getRSS().'&rss" />'; ?>
|
|
<?php foreach($metatags as $name=>$value) echo '<meta name="'.$name.'" content="'.$value.'"/>'."\n"; ?>
|
|
<title><?php echo strip_tags($content->getTitle()); ?></title>
|
|
|
|
<?php
|
|
if (is_readable('bibtexbrowser.css')) {
|
|
echo '<link href="bibtexbrowser.css" rel="stylesheet" type="text/css"/>';
|
|
}
|
|
else {
|
|
// we use the embedded css
|
|
echo '<style type="text/css"><!--';
|
|
bibtexbrowserDefaultCSS();
|
|
echo '--></style>';
|
|
}
|
|
?>
|
|
</head>
|
|
<body>
|
|
<?php $content->display();?>
|
|
</body>
|
|
</html>
|
|
<?php
|
|
exit;
|
|
} // end constructor
|
|
|
|
}
|
|
|
|
|
|
/** is used to switch between HTML wrapper and NoWrapper */
|
|
class NoWrapper {
|
|
function NoWrapper(&$content) {
|
|
echo $content->display();
|
|
}
|
|
}
|
|
|
|
/** is used to create an subset of a bibtex file */
|
|
class BibtexDisplay {
|
|
|
|
/** an array of BibEbtry */
|
|
var $results;
|
|
|
|
/** the initial query to get the results */
|
|
var $query;
|
|
|
|
function BibtexDisplay(&$results, &$query) {
|
|
$this->results=$results;
|
|
$this->query=$query;
|
|
}
|
|
|
|
function display() {
|
|
header('Content-type: text/plain; charset='.ENCODING);
|
|
echo '% '.query2title($this->query)."\n";
|
|
echo '% Encoding: '.ENCODING."\n";
|
|
foreach($this->results as $bibentry) { echo $bibentry->getText()."\n"; }
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/** is used to create an RSS feed */
|
|
class RSSDisplay {
|
|
|
|
/** an array of BibEbtry */
|
|
var $results;
|
|
|
|
/** the initial query to get the results */
|
|
var $query;
|
|
|
|
function RSSDisplay(&$results, &$query) {
|
|
$this->results=$results;
|
|
$this->query=$query;
|
|
$this->title = query2title($query);
|
|
}
|
|
|
|
/** tries to always output a valid XML/RSS string
|
|
* based on ENCODING, HTML tags, and the transformations
|
|
* that happened in latex2html */
|
|
function text2rss($desc) {
|
|
// first strip HTML tags
|
|
$desc = strip_tags($desc);
|
|
|
|
// then decode characters encoded by latex2html
|
|
$desc= html_entity_decode($desc);
|
|
|
|
// some entities may still be here, we remove them
|
|
// we replace html entities e.g. é by nothing
|
|
// however XML entities are kept (e.g. 5)
|
|
$desc = preg_replace('/&\w+;/','',$desc);
|
|
|
|
// bullet proofing ampersand
|
|
$desc = preg_replace('/&([^#])/','&$1',$desc);
|
|
|
|
// be careful of <
|
|
$desc = str_replace('<','<',$desc);
|
|
|
|
// final test with encoding:
|
|
if (!mb_check_encoding($desc,ENCODING)) {
|
|
return 'encoding error: please check the content of ENCODING';
|
|
}
|
|
|
|
return $desc;
|
|
}
|
|
|
|
|
|
function display() {
|
|
header('Content-type: application/rss+xml');
|
|
echo '<?xml version="1.0" encoding="'.ENCODING.'"?>';
|
|
//
|
|
|
|
?>
|
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
|
<channel>
|
|
<title><?php echo $this->title;?></title>
|
|
<link>http://<?php echo $_SERVER['HTTP_HOST'].htmlentities($_SERVER['REQUEST_URI']);?></link>
|
|
<atom:link href="http://<?php echo $_SERVER['HTTP_HOST'].htmlentities($_SERVER['REQUEST_URI']);?>" rel="self" type="application/rss+xml" />
|
|
<description></description>
|
|
<generator>bibtexbrowser v__MTIME__</generator>
|
|
|
|
<?php
|
|
foreach($this->results as $bibentry) {
|
|
?>
|
|
<item>
|
|
<title><?php echo $this->text2rss($bibentry->getTitle());?></title>
|
|
<link><?php echo htmlentities($bibentry->getURL());?></link>
|
|
<description>
|
|
<?php
|
|
// we are in XML, so we cannot have HTML entitites
|
|
// however the encoding is specified in preamble
|
|
echo $this->text2rss(bib2html($bibentry)."\n".$bibentry->getAbstract());
|
|
?>
|
|
</description>
|
|
<guid isPermaLink="false"><?php echo urlencode($_GET[Q_FILE].'::'.$bibentry->getKey());?></guid>
|
|
</item>
|
|
<?php } /* end foreach */?>
|
|
</channel>
|
|
</rss>
|
|
|
|
<?php
|
|
exit;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
class Dispatcher {
|
|
|
|
/** this is the query */
|
|
var $query = array();
|
|
|
|
/** this is the result of the querw: an array of BibEbtry */
|
|
var $selectedEntries = array();
|
|
|
|
/** the displayer of selected entries. The default is a paged display.
|
|
* It could also be an RSSDisplay if the rss keyword is present
|
|
*/
|
|
var $displayer = 'PagedDisplay';
|
|
|
|
/** the wrapper of selected entries. The default is an HTML wrapper
|
|
* It could also be a NoWrapper when you include your pub list in your home page
|
|
*/
|
|
var $wrapper = 'HTMLWrapper';
|
|
|
|
function Dispatcher() {
|
|
// are we in test mode, or libray mode
|
|
// then this file is just a library
|
|
if (isset($_GET['test']) || isset($_GET['library'])) {
|
|
// we unset in order to use the dispatcher afterwards
|
|
unset($_GET['test']);
|
|
unset($_GET['library']);
|
|
return;
|
|
}
|
|
|
|
// first we set the database (load from disk or parse the bibtex file)
|
|
setDB();
|
|
|
|
// is the publication list included in another page?
|
|
// strtr is used for Windows where __FILE__ contains C:\toto and SCRIPT_FILENAME contains C:/toto :-(
|
|
if (strtr(__FILE__,"\\","/")!=$_SERVER['SCRIPT_FILENAME']) $this->wrapper='NoWrapper';
|
|
|
|
// first pass, we will exit if we encounter key or menu or academic
|
|
// other wise we just create the $this->query
|
|
foreach($_GET as $keyword=>$value) {
|
|
if (method_exists($this,$keyword)) {
|
|
// if the return value is END_DISPATCH, we finish bibtexbrowser (but not the whole PHP process in case we are embedded)
|
|
if ($this->$keyword()=='END_DISPATCH') return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (count($this->query)>0) {
|
|
|
|
// first test for inconsistent queries
|
|
if (isset($this->query[Q_ALL]) && count($this->query)>1) {
|
|
// we discard the Q_ALL, it helps in embedded mode
|
|
unset($this->query[Q_ALL]);
|
|
}
|
|
|
|
$this->selectedEntries = $_GET[Q_DB]->multisearch($this->query);
|
|
|
|
// required for PHP4 to have this intermediate variable
|
|
$x = new $this->displayer($this->selectedEntries,$this->query);
|
|
new $this->wrapper($x);
|
|
}
|
|
else $this->frameset();
|
|
}
|
|
|
|
function all() {
|
|
$this->query[Q_ALL]=1;
|
|
}
|
|
|
|
function rss() {
|
|
$this->displayer='RSSDisplay';
|
|
$this->wrapper='NoWrapper';
|
|
}
|
|
|
|
function astext() {
|
|
$this->displayer='BibtexDisplay';
|
|
$this->wrapper='NoWrapper';
|
|
}
|
|
|
|
function search() { $this->query[Q_SEARCH]=$_GET[Q_SEARCH]; }
|
|
|
|
function exclude() { $this->query[Q_EXCLUDE]=$_GET[Q_EXCLUDE]; }
|
|
|
|
function year() { $this->query[Q_YEAR]=$_GET[Q_YEAR]; }
|
|
|
|
function keywords() { $this->query[Q_TAG]=$_GET[Q_TAG]; }
|
|
|
|
function author() {
|
|
$this->query[Q_AUTHOR]=$_GET[Q_AUTHOR];
|
|
}
|
|
|
|
function type() { $this->query[Q_TYPE]=$_GET[Q_TYPE]; }
|
|
|
|
function menu() {
|
|
new MenuManager($_GET[Q_DB]);
|
|
}
|
|
|
|
/** the academic keyword in URLs switch from a year based viey to a publication type based view */
|
|
function academic() {
|
|
$this->displayer='AcademicDisplay';
|
|
// backward compatibility
|
|
if($_GET[Q_ACADEMIC]!==true && $_GET[Q_ACADEMIC]!='') {
|
|
$_GET[Q_AUTHOR]=$_GET[Q_ACADEMIC];
|
|
$this->query[Q_AUTHOR]=$_GET[Q_ACADEMIC];
|
|
}
|
|
}
|
|
|
|
function key() {
|
|
if ($_GET[Q_DB]->contains($_GET[Q_KEY])) {
|
|
$bibdisplay = new BibEntryDisplay($_GET[Q_DB]->getEntryByKey($_GET[Q_KEY]));
|
|
new $this->wrapper($bibdisplay,$bibdisplay->metadata());
|
|
}
|
|
else { new NonExistentBibEntryError(); }
|
|
}
|
|
|
|
/** is used to remotely analyzed a situation */
|
|
function diagnosis() {
|
|
header('Content-type: text/plain');
|
|
echo "php version: ".phpversion()."\n";
|
|
echo "bibtexbrowser version: __MTIME__\n";
|
|
echo "dir: ".decoct(fileperms(dirname(__FILE__)))."\n";
|
|
echo "bibtex file: ".decoct(fileperms($_GET[Q_FILE]))."\n";
|
|
exit;
|
|
}
|
|
|
|
function frameset() { ?>
|
|
|
|
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta name="generator" content="bibtexbrowser v__MTIME__" />
|
|
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo ENCODING ?>"/>
|
|
<title>You are browsing <?php echo $_GET[Q_FILE]; ?> with bibtexbrowser</title>
|
|
</head>
|
|
<frameset cols="15%,*">
|
|
<frame name="menu" src="<?php echo '?'.Q_FILE.'='. urlencode($_GET[Q_FILE]).'&menu'; ?>" />
|
|
<frame name="main" src="<?php echo '?'.Q_FILE.'='. urlencode($_GET[Q_FILE]).'&'.Q_ALL; ?>" />
|
|
</frameset>
|
|
</html>
|
|
|
|
<?php
|
|
|
|
}
|
|
|
|
}
|
|
|
|
new Dispatcher();
|
|
|
|
?>
|