diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fe258fd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.dat
+vendor
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 8fb8394..3fe911b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,8 @@ php:
script:
- curl -L -o reflectivedoc.php https://www.monperrus.net/martin/reflectivedoc.php.txt
- curl -L -o gakowiki-syntax.php https://www.monperrus.net/martin/gakowiki-syntax.php.txt
- - phpunit bibtexbrowser-test.php
+ - cp ./src/bibtexbrowser.php ./tests/
+ - cp ./src/bibacid-utf8.bib ./tests/
+ - phpunit tests/bibtexbrowser-test.php
sudo: false
diff --git a/bibtexbrowser-cli.php b/bin/bibtexbrowser-cli.php
similarity index 100%
rename from bibtexbrowser-cli.php
rename to bin/bibtexbrowser-cli.php
diff --git a/composer.json b/composer.json
index 84301f5..c0281b5 100644
--- a/composer.json
+++ b/composer.json
@@ -11,6 +11,18 @@
}
],
"require": {
- "php": ">=4"
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Monperrus\\BibtexBrowser\\": "src/"
+ }
+ },
+ "scripts": {
+ "serve": "@php -S localhost:29896 -t public/"
+ },
+ "require-dev": {
+ "monolog/monolog": "^1.23",
+ "kint-php/kint": "^2.2"
}
}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..59127f8
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,203 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "fa3a6762d454ebe3dce634e74511aae2",
+ "packages": [],
+ "packages-dev": [
+ {
+ "name": "kint-php/kint",
+ "version": "2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/kint-php/kint.git",
+ "reference": "b091715eadaf6e1a7ef927f3e81d1004611d2aea"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/kint-php/kint/zipball/b091715eadaf6e1a7ef927f3e81d1004611d2aea",
+ "reference": "b091715eadaf6e1a7ef927f3e81d1004611d2aea",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.1.2"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^2.0",
+ "phpunit/phpunit": "^4.0",
+ "symfony/finder": "^2.6"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "init.php"
+ ],
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Rokas Šleinius",
+ "homepage": "https://github.com/raveren"
+ },
+ {
+ "name": "Jonathan Vollebregt",
+ "homepage": "https://github.com/jnvsor"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/kint-php/kint/graphs/contributors"
+ }
+ ],
+ "description": "Kint - debugging tool for PHP developers",
+ "homepage": "https://kint-php.github.io/kint/",
+ "keywords": [
+ "debug",
+ "kint",
+ "php"
+ ],
+ "time": "2017-09-06T17:46:03+00:00"
+ },
+ {
+ "name": "monolog/monolog",
+ "version": "1.23.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4",
+ "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0",
+ "psr/log": "~1.0"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0.0"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "^2.4.9 || ^3.0",
+ "doctrine/couchdb": "~1.0@dev",
+ "graylog2/gelf-php": "~1.0",
+ "jakub-onderka/php-parallel-lint": "0.9",
+ "php-amqplib/php-amqplib": "~2.4",
+ "php-console/php-console": "^3.1.3",
+ "phpunit/phpunit": "~4.5",
+ "phpunit/phpunit-mock-objects": "2.3.0",
+ "ruflin/elastica": ">=0.90 <3.0",
+ "sentry/sentry": "^0.13",
+ "swiftmailer/swiftmailer": "^5.3|^6.0"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-mongo": "Allow sending log messages to a MongoDB server",
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+ "php-console/php-console": "Allow sending log messages to Google Chrome",
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
+ "sentry/sentry": "Allow sending log messages to a Sentry server"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Monolog\\": "src/Monolog"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "http://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ],
+ "time": "2017-06-19T01:22:40+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "time": "2016-10-10T12:19:37+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {
+ "php": ">=4"
+ },
+ "platform-dev": []
+}
diff --git a/bibacid-utf8.bib b/public/bibacid-utf8.bib
similarity index 100%
rename from bibacid-utf8.bib
rename to public/bibacid-utf8.bib
diff --git a/public/embed.php b/public/embed.php
new file mode 100644
index 0000000..d1ba77e
--- /dev/null
+++ b/public/embed.php
@@ -0,0 +1,25 @@
+
+
+
+
+HTML;
+
+$_GET['library']=1;
+require_once('../src/bibtexbrowser.php');
+$db = new BibDataBase();
+$db->load('bibacid-utf8.bib');
+$query = array('year'=>'1997');
+$entries=$db->multisearch($query);
+uasort($entries, 'compare_bib_entries');
+foreach ($entries as $bibentry) {
+ print $bibentry->toHTML()."
";
+}
+
+print <<
+
+HTML;
+exit;
diff --git a/public/index.php b/public/index.php
new file mode 100644
index 0000000..8e45e1a
--- /dev/null
+++ b/public/index.php
@@ -0,0 +1,16 @@
+ "bibacid-utf8.bib",
+ "all" => 1,
+ "author" => "",
+ "academic" => 1
+);
+
+$browser = new Bibliography($config);
+$browser->print();
diff --git a/src/BibDBBuilder.php b/src/BibDBBuilder.php
new file mode 100644
index 0000000..3939734
--- /dev/null
+++ b/src/BibDBBuilder.php
@@ -0,0 +1,161 @@
+
+ $empty_array = array();
+ $db = new BibDBBuilder(); // see also factory method createBibDBBuilder
+ $db->build('bibacid-utf8.bib'); // parses bib file
+ print_r($db->builtdb);// an associated array key -> BibEntry objects
+ print_r($db->stringdb);// an associated array key -> strings representing @string
+
+ notes:
+ method build can be used several times, bibtex entries are accumulated in the builder
+*/
+class BibDBBuilder extends ParserDelegate {
+
+ /** A hashtable from keys to bib entries (BibEntry). */
+ var $builtdb = array();
+
+ /** A hashtable of constant strings */
+ var $stringdb = array();
+
+ var $filename;
+
+ var $currentEntry;
+
+ function build($bibfilename, $handle = NULL) {
+
+ $this->filename = $bibfilename;
+ if ($handle == NULL) {
+ $handle = fopen($bibfilename, "r");
+ }
+
+ if (!$handle) die ('cannot open '.$bibfilename);
+
+ $parser = new StateBasedBibtexParser($this);
+ $parser->parse($handle);
+ fclose($handle);
+ //print_r(array_keys($this->builtdb));
+ //print_r($this->builtdb);
+ }
+
+
+ function getBuiltDb() {
+ //print_r($this->builtdb);
+ return $this->builtdb;
+ }
+
+ function beginFile() {
+ }
+
+ function endFile() {
+ // resolving crossrefs
+ // we are careful with PHP 4 semantics
+ foreach (array_keys($this->builtdb) as $key) {
+ $bib = $this->builtdb[$key];
+ if ($bib->hasField('crossref')) {
+ if (isset($this->builtdb[$bib->getField('crossref')])) {
+ $crossrefEntry = $this->builtdb[$bib->getField('crossref')];
+ $bib->crossref = $crossrefEntry;
+ foreach($crossrefEntry->getFields() as $k => $v) {
+ // copying the fields of the cross ref
+ // only if they don't exist yet
+ if (!$bib->hasField($k)) {
+ $bib->setField($k,$v);
+ }
+ }
+ }
+ }
+ }
+ //print_r($this->builtdb);
+ }
+
+ function setEntryField($fieldkey,$entryvalue) {
+ $fieldkey=trim($fieldkey);
+ // support for Bibtex concatenation
+ // see http://newton.ex.ac.uk/tex/pack/bibtex/btxdoc/node3.html
+ // (?$v) {
+ // spaces are allowed when using # and they are not taken into account
+ // however # is not itself replaced by a space
+ // warning: @strings are not case sensitive
+ // see http://newton.ex.ac.uk/tex/pack/bibtex/btxdoc/node3.html
+ $stringKey=strtolower(trim($v));
+ if (isset($this->stringdb[$stringKey]))
+ {
+ // this field will be formated later by xtrim and latex2html
+ $entryvalue_array[$k]=$this->stringdb[$stringKey]->value;
+
+ // we keep a trace of this replacement
+ // so as to produce correct bibtex snippets
+ $this->currentEntry->constants[$stringKey]=$this->stringdb[$stringKey]->value;
+ }
+ }
+ $entryvalue=implode('',$entryvalue_array);
+
+ $this->currentEntry->setField($fieldkey,$entryvalue);
+ }
+
+ function setEntryType($entrytype) {
+ $this->currentEntry->setType($entrytype);
+ }
+
+ function setEntryKey($entrykey) {
+ //echo "new entry:".$entrykey."\n";
+ $this->currentEntry->setKey($entrykey);
+ }
+
+ function beginEntry() {
+ $this->currentEntry = createBibEntry();
+ $this->currentEntry->setFile($this->filename);
+ }
+
+ function endEntry($entrysource) {
+
+ // we add a timestamp
+ $this->currentEntry->timestamp();
+
+ // we add a key if there is no key
+ if (!$this->currentEntry->hasField(Q_KEY) && $this->currentEntry->getType()!='string') {
+ $this->currentEntry->setField(Q_KEY,md5($entrysource));
+ }
+
+ // we set the fulltext
+ $this->currentEntry->text = $entrysource;
+
+ // we format the author names in a special field
+ // to enable search
+ if ($this->currentEntry->hasField('author')) {
+ $this->currentEntry->setField(Q_INNER_AUTHOR,$this->currentEntry->getFormattedAuthorsString());
+
+ foreach($this->currentEntry->getCanonicalAuthors() as $author) {
+ $homepage_key = $this->currentEntry->getHomePageKey($author);
+ if (isset($this->stringdb[$homepage_key])) {
+ $this->currentEntry->homepages[$homepage_key] = $this->stringdb[$homepage_key]->value;
+ }
+ }
+ }
+
+ // ignoring jabref comments
+ if (($this->currentEntry->getType()=='comment')) {
+ /* do nothing for jabref comments */
+ }
+
+ // we add it to the string database
+ else if ($this->currentEntry->getType()=='string') {
+ foreach($this->currentEntry->fields as $k => $v) {
+ $k!=Q_INNER_TYPE and $this->stringdb[$k] = new StringEntry($k,$v,$this->filename);
+ }
+ }
+
+ // we add it to the database
+ else {
+ $this->builtdb[$this->currentEntry->getKey()] = $this->currentEntry;
+ }
+ }
+
+} // end class BibDBBuilder
diff --git a/src/Bibliography.php b/src/Bibliography.php
new file mode 100644
index 0000000..f1f9c8a
--- /dev/null
+++ b/src/Bibliography.php
@@ -0,0 +1,26 @@
+ null,
+ "all" => null,
+ "author" => null,
+ "library" => null,
+ "academic" => null);
+
+ public function __construct($userConfig = array())
+ {
+ // (PHP 5 >= 5.3.0, PHP 7)
+ // $userConfig precedent over defaultConfig; $_GET over $userConfig
+ $_GET = array_replace($this->defaultConfig, $userConfig, $_GET);
+ }
+
+ public function print()
+ {
+ require_once "bibtexbrowser.php";
+ }
+}
diff --git a/src/Definitions.php b/src/Definitions.php
new file mode 100644
index 0000000..65d8c9d
--- /dev/null
+++ b/src/Definitions.php
@@ -0,0 +1,195 @@
+ 0 if str1 is greater than str2, and 0 if they are equal.
+ // can be @define('ORDER_FUNCTION','compare_bib_entry_by_title');
+ // can be @define('ORDER_FUNCTION','compare_bib_entry_by_bibtex_order');
+ @define('ORDER_FUNCTION','compare_bib_entry_by_year');
+ @define('ORDER_FUNCTION_FINE','compare_bib_entry_by_month');
+
+ // only displaying the n newest entries
+ @define('BIBTEXBROWSER_NEWEST',5);
+
+ @define('BIBTEXBROWSER_NO_DEFAULT', false);
+
+ // BIBTEXBROWSER_LINK_STYLE defines which function to use to display the links of a bibtex entry
+ @define('BIBTEXBROWSER_LINK_STYLE','bib2links_default'); // can be 'nothing' (a function that does nothing)
+
+ // do we add [bibtex] links ?
+ @define('BIBTEXBROWSER_BIBTEX_LINKS',true);
+ // do we add [pdf] links ?
+ @define('BIBTEXBROWSER_PDF_LINKS',true);
+ // do we add [doi] links ?
+ @define('BIBTEXBROWSER_DOI_LINKS',true);
+ // do we add [gsid] links (Google Scholar)?
+ @define('BIBTEXBROWSER_GSID_LINKS',true);
+
+ // should pdf, doi, url, gsid links be opened in a new window?
+ @define('BIBTEXBROWSER_LINKS_TARGET','_self');// can be _blank (new window), _top (with frames)
+
+ // should authors be linked to [none/homepage/resultpage]
+ // none: nothing
+ // their homepage if defined as @strings
+ // their publication lists according to this bibtex
+ @define('BIBTEXBROWSER_AUTHOR_LINKS','homepage');
+
+ // BIBTEXBROWSER_LAYOUT defines the HTML rendering layout of the produced HTML
+ // may be table/list/ordered_list/definition/none (for , , , nothing resp.).
+ // for list/ordered_list, the abbrevations are not taken into account (see ABBRV_TYPE)
+ // for ordered_list, the index is given by HTML directly (in increasing order)
+ @define('BIBTEXBROWSER_LAYOUT','table');
+
+ // should the original bibtex be displayed or a reconstructed one with filtering
+ // values: original/reconstructed
+ // warning, with reconstructed, the latex markup for accents/diacritics is lost
+ @define('BIBTEXBROWSER_BIBTEX_VIEW','original');
+ // a list of fields that will not be shown in the bibtex view if BIBTEXBROWSER_BIBTEX_VIEW=reconstructed
+ @define('BIBTEXBROWSER_BIBTEX_VIEW_FILTEREDOUT','comment|note|file');
+
+ // should Latex macros be executed (e.g. \'e -> é
+ @define('BIBTEXBROWSER_USE_LATEX2HTML',true);
+
+ // Which is the first html level that should be used in embedded mode?
+ @define('BIBTEXBROWSER_HTMLHEADINGLEVEL', 2);
+
+ @define('BIBTEXBROWSER_ACADEMIC_TOC', false);
+
+ @define('BIBTEXBROWSER_DEBUG',false);
+
+ // how to print authors names?
+ // default => as in the bibtex file
+ // USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT = true => "Meyer, Herbert"
+ // USE_INITIALS_FOR_NAMES = true => "Meyer H"
+ // USE_FIRST_THEN_LAST => Herbert Meyer
+ @define('USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT',false);// output authors in a comma separated form, e.g. "Meyer, H"?
+ @define('USE_INITIALS_FOR_NAMES',false); // use only initials for all first names?
+ @define('USE_FIRST_THEN_LAST',false); // use only initials for all first names?
+ @define('FORCE_NAMELIST_SEPARATOR', ''); // if non-empty, use this to separate multiple names regardless of USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT
+ @define('LAST_AUTHOR_SEPARATOR',' and ');
+
+ @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_YEAR_INPRESS', 'in press');
+ @define('Q_YEAR_ACCEPTED', 'accepted');
+ @define('Q_YEAR_SUBMITTED', 'submitted');
+ @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');// used for queries
+ @define('Q_TYPE_PAGE', 'type_page');
+ @define('Q_ALL', 'all');
+ @define('Q_ENTRY', 'entry');
+ @define('Q_KEY', 'key');
+ @define('Q_KEYS', 'keys'); // filter entries using a url-encoded, JSON-encoded array of bibtex keys
+ @define('Q_SEARCH', 'search');
+ @define('Q_EXCLUDE', 'exclude');
+ @define('Q_RESULT', 'result');
+ @define('Q_ACADEMIC', 'academic');
+ @define('Q_DB', 'bibdb');
+ @define('Q_LATEST', 'latest');
+ @define('Q_RANGE', 'range');
+ @define('AUTHOR', 'author');
+ @define('EDITOR', 'editor');
+ @define('SCHOOL', 'school');
+ @define('TITLE', 'title');
+ @define('BOOKTITLE', 'booktitle');
+ @define('YEAR', 'year');
+ @define('BUFFERSIZE',100000);
+ @define('MULTIPLE_BIB_SEPARATOR',';');
+ @define('METADATA_GS',true);
+ @define('METADATA_DC',true);
+ @define('METADATA_OPENGRAPH',true);
+ @define('METADATA_EPRINTS',false);
+
+ // define sort order for special values in 'year' field
+ // highest number is sorted first
+ // don't exceed 0 though, since the values are added to PHP_INT_MAX
+ @define('ORDER_YEAR_INPRESS', -0);
+ @define('ORDER_YEAR_ACCEPTED', -1);
+ @define('ORDER_YEAR_SUBMITTED', -2);
+ @define('ORDER_YEAR_OTHERNONINT', -3);
+
+
+ // in embedded mode, we still need a URL for displaying bibtex entries alone
+ // this is usually resolved to bibtexbrowser.php
+ // but can be overridden in bibtexbrowser.local.php
+ // for instance with @define('BIBTEXBROWSER_URL',''); // links to the current page with ?
+ //@define('BIBTEXBROWSER_URL',basename(__FILE__));
+ @define('BIBTEXBROWSER_URL',parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
+
+ // *************** END CONFIGURATION
+
+ define('Q_INNER_AUTHOR', '_author');// internally used for representing the author
+ define('Q_INNER_TYPE', 'x-bibtex-type');// used for representing the type of the bibtex entry internally
+ @define('Q_INNER_KEYS_INDEX', '_keys-index');// used for storing indices in $_GET[Q_KEYS] array
+ }
+}
diff --git a/src/ParserDelegate.php b/src/ParserDelegate.php
new file mode 100644
index 0000000..629af5d
--- /dev/null
+++ b/src/ParserDelegate.php
@@ -0,0 +1,27 @@
+delegate = $delegate;
+ }
+
+ public function parse($handle) {
+ if (gettype($handle) == 'string') { throw new Exception('oops'); }
+ $delegate = $this->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',13);
+ @define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED',14);
+
+
+ $state=NOTHING;
+ $entrytype='';
+ $entrykey='';
+ $entryvalue='';
+ $fieldvaluepart='';
+ $finalkey='';
+ $entrysource='';
+
+ // metastate
+ $isinentry = false;
+
+ $delegate->beginFile();
+
+ // if you encounter this error "Allowed memory size of xxxxx bytes exhausted"
+ // then decrease the size of the temp buffer below
+ $bufsize=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;
+ $fieldvaluepart='';
+ $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;
+ }
+ // the value is delimited by curly brackets
+ else if ($s=='{') {
+ $state = GETVALUEDELIMITEDBYCURLYBRACKETS;
+ }
+ // 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($finalkey,$entryvalue);
+ $entryvalue=''; // resetting the value buffer
+ }
+ // this is the end of the value AND of the entry
+ else if ($s=='}') {
+ $state = NOTHING;
+ $delegate->setEntryField($finalkey,$entryvalue);
+ $isinentry = false;$delegate->endEntry($entrysource);
+ $entryvalue=''; // resetting the value buffer
+ }
+ else if ($s==' ' || $s=="\t" || $s=="\n" || $s=="\r" ) {
+ // blank characters are not taken into account when values are not in quotes or curly brackets
+ }
+ 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;
+ $entryvalue=$entryvalue.$s;
+ $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYTOP');
+ $fieldvaluepart='';
+ }
+ else if ($s=='}') { // end entry
+ $state = GETVALUE;
+ $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYTOP');
+ }
+ else {
+ $entryvalue=$entryvalue.$s;
+ $fieldvaluepart=$fieldvaluepart.$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;$entryvalue=$entryvalue.$s;}
+ else if ($s=='}') {
+ $state = GETVALUEDELIMITEDBYCURLYBRACKETS;
+ $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYONE');
+ $fieldvaluepart='';
+ $entryvalue=$entryvalue.$s;
+ }
+ else {
+ $entryvalue=$entryvalue.$s;
+ $fieldvaluepart=$fieldvaluepart.$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;$entryvalue=$entryvalue.$s;}
+ else if ($s=='}') {
+ $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;}
+ 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;$entryvalue=$entryvalue.$s;}
+ else { $entryvalue=$entryvalue.$s;}
+ }
+ // handle anti-slashed brackets
+ else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED) {
+ $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL;
+ $entryvalue=$entryvalue.$s;
+ }
+
+ /* handles entries delimited by double quotes */
+ else if ($state==GETVALUEDELIMITEDBYQUOTES) {
+
+ if ($s=='\\') {
+ $state = GETVALUEDELIMITEDBYQUOTES_ESCAPED;
+ $entryvalue=$entryvalue.$s;}
+ else if ($s=='"') {
+ $state = GETVALUE;
+ }
+ else { $entryvalue=$entryvalue.$s;}
+ }
+ // handle anti-double quotes
+ else if ($state==GETVALUEDELIMITEDBYQUOTES_ESCAPED) {
+ $state = GETVALUEDELIMITEDBYQUOTES;
+ $entryvalue=$entryvalue.$s;
+ }
+
+ } // end for
+ } // end while
+ $delegate->endFile();
+ //$d = $this->delegate;print_r($d);
+ } // end function
+} // end class
diff --git a/src/StringEntry.php b/src/StringEntry.php
new file mode 100644
index 0000000..0f54186
--- /dev/null
+++ b/src/StringEntry.php
@@ -0,0 +1,19 @@
+name=$key;
+ $this->value=$value;
+ $this->filename=$filename;
+ }
+
+ public function toString()
+ {
+ return '@string{'.$this->name.'={'.$this->value.'}}';
+ }
+} // end class StringEntry
diff --git a/src/XMLPrettyPrinter.php b/src/XMLPrettyPrinter.php
new file mode 100644
index 0000000..ce414f3
--- /dev/null
+++ b/src/XMLPrettyPrinter.php
@@ -0,0 +1,40 @@
+';
+ print '';
+ }
+
+ public function endFile() {
+ print '';
+ }
+
+ public function setEntryField($finalkey,$entryvalue) {
+ print "\n".$finalkey."\n".$entryvalue."\n\n";
+ }
+
+ public function setEntryType($entrytype) {
+ print ''.$entrytype.'';
+ }
+
+ public function setEntryKey($entrykey) {
+ print ''.$entrykey.'';
+ }
+
+ public function beginEntry() {
+ print "\n";
+ }
+
+ public function endEntry($entrysource) {
+ print "\n";
+ }
+} // end class XMLPrettyPrinter
diff --git a/src/bibacid-utf8.bib b/src/bibacid-utf8.bib
new file mode 100644
index 0000000..1c04146
--- /dev/null
+++ b/src/bibacid-utf8.bib
@@ -0,0 +1,231 @@
+
+
+@string{foo="Foo"}
+@string{bar=foo#" Bar"}
+
+
+%% test the home page feature
+@string{hp_J.Abounader="http://www.google.com"}
+
+@inproceedings{classical,
+ author = {J. Abounader and D. Tooj},
+ title = bar,
+ institution = {Queen's University, Kingston, ON.},
+ year = {1997}
+}
+
+%% testing the abstract
+@inproceedings{with_abstract,
+ author = {J. Abounader and D. Tooj},
+ title = {This is with abstract},
+ institution = {Queen's University, Kingston, ON.},
+ year = {1997},
+ abstract = {This is an abstract
+ on several lines}
+}
+
+
+%% using double quotes
+%% also Took test the advanced search
+@TECHREPORT{dquotes,
+ author = "J. Abounader and Tooj, D.",
+ title = "using double quotes ",
+ institution = "Queen's University, Kingston, ON.",
+ year = "1997"
+}
+
+
+%% using single value (year)
+@TECHREPORT{singlevalue,
+ author = {The },
+ title = {The year},
+ institution = {Queen's University, Kingston, ON.},
+ year = 1997
+}
+
+
+%% no new line
+@TECHREPORT{Abounader1997e, author = {J. Abounader and D. Lamb}, title = "using double quotes", institution = {Queen's University, Kingston, ON.}, year = 1997 }
+
+
+
+%% intersting: bibtex does not allow \} in brackets enclosed entries and \" in quotes enclosed entries
+
+%% escaped quotes
+@TECHREPORT{notallowed1,
+ author = {J. Abounader and D. Lamb},
+ title = "escaped \"quotes\"",
+ institution = {Queen's University, Kingston, ON.},
+ year = {1997}
+}
+
+%% escaped braces
+@TECHREPORT{notallowed2,
+ author = {J. Abounader \} and D. Lamb},
+ title = "escaped braces",
+ institution = {Queen's University, Kingston, ON.},
+ year = {1997}
+}
+
+@article{testsearch1,
+ author = {Jacob G{\"o}del},
+ title = {using Banach Space},
+ year = {1997}
+}
+@article{testsearch2,
+ author = {Jacob {G}{\"{o}}del},
+ title = {using banach space},
+ year = {1997}
+}
+@article{testsearch3,
+ author = {Jacob {G\"{o}del}},
+ title = {using {Banach} Space},
+ year = {1997}
+}
+@article{testsearch4,
+ author = {Jacob Gödel},
+ title = {using {B}anach Space},
+ year = {1997}
+}
+@article{testsearch5,
+ author = {Jacob Gödel},
+ title = {using {Banach Space}},
+ year = {1997}
+}
+
+
+
+%% bug from Jakob Kellner
+%% copied from ams.org
+@article {MR1841330,
+ AUTHOR = {Lejay, Antoine},
+ TITLE = {Homogenization of divergence-form operators with lower-order
+ terms in random media},
+ JOURNAL = {Probab. Theory Related Fields},
+ FJOURNAL = {Probability Theory and Related Fields},
+ VOLUME = {120},
+ YEAR = {2001},
+ NUMBER = {2},
+ PAGES = {255--276},
+ ISSN = {0178-8051},
+ CODEN = {PTRFEU},
+ MRCLASS = {35B27 (31C25 35R60 60H30 60J60)},
+ MRNUMBER = {MR1841330 (2002g:35023)},
+MRREVIEWER = {Jean-Fran{\c{c}}ois Clouet},
+ DOI = {10.1007/PL00008783},
+ URL = {http://dx.doi.org/10.1007/PL00008783},
+}
+
+@article{serge,
+ author = "Serge Bug",
+ title = "curly {braces} in quote",
+ year = 2010
+}
+
+@article{cediltest,
+ author = "Serge Bug",
+ title = "\ccurly \c{c}urly {\c{c}}urly ",
+ year = 2010
+}
+
+
+%%%%% now testing the string concatenation
+@string{str1="toto"}
+@string{str2="titi"}
+
+@book{stgringconcat:test1,
+ author = {J. Abounader and D. Lamb},
+ title = str1#str2,
+ institution = {Queen's University, Kingston, ON.},
+ year = {1997}
+}
+
+% with space
+@bookchapter{stgringconcat:test2,
+ author = {J. Abounader and D. Lamb},
+ title = str1 # str2,
+ institution = {Queen's University, Kingston, ON.},
+ year = {1997}
+}
+
+% with another value
+@inbook{stgringconcat:test3,
+ author = {J. Abounader and D. Lamb},
+ title = str1 # {3344},
+ institution = {Queen's University, Kingston, ON.},
+ year = {1997}
+}
+
+
+%% Saturday, October 09 2010
+%% taken from http://en.wikipedia.org/wiki/BibTeX
+@PROCEEDINGS {conference:06,
+ editor = {First Editor and Second Editor},
+ title = {Proceedings of the Xth Conference on XYZ},
+ booktitle = {Proceedings of the Xth Conference on XYZ},
+ year = {2006},
+ month = oct,
+}
+
+@INPROCEEDINGS {author:06,
+ title = {Some publication title},
+ author = {First Author and Second Author},
+ crossref = {conference:06},
+ pages = {330?331},
+}
+
+
+%% Thursday, October 28 2010
+%% two test cases for special key
+@INPROCEEDINGS {author+06,
+ title = {Some publication title},
+ author = {First Author and Second Author},
+ year = {2011},
+}
+
+@INPROCEEDINGS { author06 ,
+ title = {Some publication title},
+ author = {First Author and Second Author},
+ year = {2011},
+}
+
+%% testing the accented i and j
+@INPROCEEDINGS {paper000,
+ title = {Some publication title},
+ author = {F\`\irst A\`{\i}thor and S{\`\i}cond Author\`\I},
+ year = {2011},
+}
+
+%% bug reported by Mark Hereld
+@misc{mark,
+ title = {Bug in Urls},
+ author = {Mark Hereld},
+ howpublished = {\url{http://foo.com/under_score.html}},
+ year = {2011},
+}
+
+%% handling of percentage
+@misc{mark,
+ title = {Percentage \%},
+ abstract = {Percentage \%},
+ author = {MM},
+ year = {2015},
+}
+
+% bug https://github.com/monperrus/bibtexbrowser/issues/40
+@Article{Baldwin2014Quantum,
+ Doi = {10.1103/PhysRevA.90.012110},
+ Url = {http://link.aps.org/doi/10.1103/PhysRevA.90.012110}
+}
+
+@article{croatiantest,
+ author = "Strabi{\'{c}} Strabi\'{c}",
+ title = "Fancy accents bug",
+ year = 2015
+}
+
+@article{kjsdf 8,
+ title = "Entry with + in the key",
+ author = "Foo Bar",
+ year = 2017
+}
diff --git a/bibtexbrowser.php b/src/bibtexbrowser.php
old mode 100755
new mode 100644
similarity index 90%
rename from bibtexbrowser.php
rename to src/bibtexbrowser.php
index 613de6d..681d260
--- a/bibtexbrowser.php
+++ b/src/bibtexbrowser.php
@@ -15,6 +15,12 @@ License, or (at your option) any later version.
*/
+use Monperrus\BibtexBrowser\StateBasedBibtexParser;
+use Monperrus\BibtexBrowser\ParserDelegate;
+use Monperrus\BibtexBrowser\XMLPrettyPrinter;
+use Monperrus\BibtexBrowser\StringEntry;
+use Monperrus\BibtexBrowser\BibDBBuilder;
+
// it is be possible to include( 'bibtexbrowser.php' ); several times in the same script
// added on Wednesday, June 01 2011, bug found by Carlos Bras
if (!defined('BIBTEXBROWSER')) {
@@ -226,7 +232,8 @@ if (defined('ENCODING')) {
// this is usually resolved to bibtexbrowser.php
// but can be overridden in bibtexbrowser.local.php
// for instance with @define('BIBTEXBROWSER_URL',''); // links to the current page with ?
-@define('BIBTEXBROWSER_URL',basename(__FILE__));
+//@define('BIBTEXBROWSER_URL',basename(__FILE__));
+@define('BIBTEXBROWSER_URL','');
// *************** END CONFIGURATION
@@ -243,6 +250,8 @@ define('Q_INNER_TYPE', 'x-bibtex-type');// used for representing the type of the
function nothing() {}
+
+
function config_value($key) {
global $CONFIGURATION;
if (isset($CONFIGURATION[$key])) { return $CONFIGURATION[$key]; }
@@ -325,7 +334,7 @@ function _zetDB($bibtex_filenames) {
// to automate dectection of faulty links with tools such as webcheck
header('HTTP/1.1 404 Not found');
// escape $bib to prevent XSS
- $escapedBib = htmlEntities($bib, ENT_QUOTES);
+ htmlEntities($bib, ENT_QUOTES);
die('the bib file '.$escapedBib.' does not exist !');
}
} // end for each
@@ -467,7 +476,6 @@ if (!function_exists('createMenuManager')) {
function createMenuManager() { $x = new MenuManager(); return $x;}
}
-
////////////////////////////////////////////////////////
/** is a generic parser of bibtex files.
@@ -481,472 +489,11 @@ notes:
- It has no dependencies, it can be used outside of bibtexbrowser
- The delegate is expected to have some methods, see classes BibDBBuilder and XMLPrettyPrinter
*/
-class StateBasedBibtexParser {
-
- var $delegate;
-
- function __construct($delegate) {
- $this->delegate = $delegate;
- }
-
- function parse($handle) {
- if (gettype($handle) == 'string') { throw new Exception('oops'); }
- $delegate = $this->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',13);
- @define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED',14);
-
-
- $state=NOTHING;
- $entrytype='';
- $entrykey='';
- $entryvalue='';
- $fieldvaluepart='';
- $finalkey='';
- $entrysource='';
-
- // metastate
- $isinentry = false;
-
- $delegate->beginFile();
-
- // if you encounter this error "Allowed memory size of xxxxx bytes exhausted"
- // then decrease the size of the temp buffer below
- $bufsize=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;
- $fieldvaluepart='';
- $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;
- }
- // the value is delimited by curly brackets
- else if ($s=='{') {
- $state = GETVALUEDELIMITEDBYCURLYBRACKETS;
- }
- // 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($finalkey,$entryvalue);
- $entryvalue=''; // resetting the value buffer
- }
- // this is the end of the value AND of the entry
- else if ($s=='}') {
- $state = NOTHING;
- $delegate->setEntryField($finalkey,$entryvalue);
- $isinentry = false;$delegate->endEntry($entrysource);
- $entryvalue=''; // resetting the value buffer
- }
- else if ($s==' ' || $s=="\t" || $s=="\n" || $s=="\r" ) {
- // blank characters are not taken into account when values are not in quotes or curly brackets
- }
- 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;
- $entryvalue=$entryvalue.$s;
- $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYTOP');
- $fieldvaluepart='';
- }
- else if ($s=='}') { // end entry
- $state = GETVALUE;
- $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYTOP');
- }
- else {
- $entryvalue=$entryvalue.$s;
- $fieldvaluepart=$fieldvaluepart.$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;$entryvalue=$entryvalue.$s;}
- else if ($s=='}') {
- $state = GETVALUEDELIMITEDBYCURLYBRACKETS;
- $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYONE');
- $fieldvaluepart='';
- $entryvalue=$entryvalue.$s;
- }
- else {
- $entryvalue=$entryvalue.$s;
- $fieldvaluepart=$fieldvaluepart.$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;$entryvalue=$entryvalue.$s;}
- else if ($s=='}') {
- $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;}
- 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;$entryvalue=$entryvalue.$s;}
- else { $entryvalue=$entryvalue.$s;}
- }
- // handle anti-slashed brackets
- else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED) {
- $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL;
- $entryvalue=$entryvalue.$s;
- }
-
- /* handles entries delimited by double quotes */
- else if ($state==GETVALUEDELIMITEDBYQUOTES) {
-
- if ($s=='\\') {
- $state = GETVALUEDELIMITEDBYQUOTES_ESCAPED;
- $entryvalue=$entryvalue.$s;}
- else if ($s=='"') {
- $state = GETVALUE;
- }
- else { $entryvalue=$entryvalue.$s;}
- }
- // handle anti-double quotes
- else if ($state==GETVALUEDELIMITEDBYQUOTES_ESCAPED) {
- $state = GETVALUEDELIMITEDBYQUOTES;
- $entryvalue=$entryvalue.$s;
- }
-
- } // end for
- } // end while
- $delegate->endFile();
- //$d = $this->delegate;print_r($d);
- } // end function
-} // end class
-
-/** a default empty implementation of a delegate for StateBasedBibtexParser */
-class ParserDelegate {
-
- function beginFile() {}
-
- function endFile() {}
-
- function setEntryField($finalkey,$entryvalue) {}
-
- function setEntryType($entrytype) {}
-
- function setEntryKey($entrykey) {}
-
- function beginEntry() {}
-
- function endEntry($entrysource) {}
-
- /** called for each sub parts of type {part} of a field value
- * for now, only CURLYTOP and CURLYONE events
- */
- function entryValuePart($key, $value, $type) {}
-
-} // end class ParserDelegate
-
-
-/** is a possible delegate for StateBasedBibParser.
-usage:
-see snippet of [[#StateBasedBibParser]]
-*/
-class XMLPrettyPrinter extends ParserDelegate {
- function beginFile() {
- header('Content-type: text/xml;');
- print '';
- print '';
- }
-
-
- function endFile() {
- print '';
- }
- function setEntryField($finalkey,$entryvalue) {
- print "\n".$finalkey."\n".$entryvalue."\n\n";
- }
-
- function setEntryType($entrytype) {
- print ''.$entrytype.'';
- }
-
- function setEntryKey($entrykey) {
- print ''.$entrykey.'';
- }
-
- function beginEntry() {
- print "\n";
- }
-
- function endEntry($entrysource) {
- print "\n";
- }
-} // end class XMLPrettyPrinter
-
-/** represents @string{k=v} */
-class StringEntry {
- function __construct($k, $v, $filename) {
- $this->name=$k;
- $this->value=$v;
- $this->filename=$filename;
- }
-
- function toString() {
- return '@string{'.$this->name.'={'.$this->value.'}}';
- }
-} // end class StringEntry
-
-
-
-
-/** builds arrays of BibEntry objects from a bibtex file.
-usage:
-
- $empty_array = array();
- $db = new BibDBBuilder(); // see also factory method createBibDBBuilder
- $db->build('bibacid-utf8.bib'); // parses bib file
- print_r($db->builtdb);// an associated array key -> BibEntry objects
- print_r($db->stringdb);// an associated array key -> strings representing @string
-
-notes:
- method build can be used several times, bibtex entries are accumulated in the builder
-*/
-class BibDBBuilder extends ParserDelegate {
-
- /** A hashtable from keys to bib entries (BibEntry). */
- var $builtdb = array();
-
- /** A hashtable of constant strings */
- var $stringdb = array();
-
- var $filename;
-
- var $currentEntry;
-
- function build($bibfilename, $handle = NULL) {
-
- $this->filename = $bibfilename;
- if ($handle == NULL) {
- $handle = fopen($bibfilename, "r");
- }
-
- if (!$handle) die ('cannot open '.$bibfilename);
-
- $parser = new StateBasedBibtexParser($this);
- $parser->parse($handle);
- fclose($handle);
- //print_r(array_keys($this->builtdb));
- //print_r($this->builtdb);
- }
-
-
- function getBuiltDb() {
- //print_r($this->builtdb);
- return $this->builtdb;
- }
-
- function beginFile() {
- }
-
- function endFile() {
- // resolving crossrefs
- // we are careful with PHP 4 semantics
- foreach (array_keys($this->builtdb) as $key) {
- $bib = $this->builtdb[$key];
- if ($bib->hasField('crossref')) {
- if (isset($this->builtdb[$bib->getField('crossref')])) {
- $crossrefEntry = $this->builtdb[$bib->getField('crossref')];
- $bib->crossref = $crossrefEntry;
- foreach($crossrefEntry->getFields() as $k => $v) {
- // copying the fields of the cross ref
- // only if they don't exist yet
- if (!$bib->hasField($k)) {
- $bib->setField($k,$v);
- }
- }
- }
- }
- }
- //print_r($this->builtdb);
- }
-
- function setEntryField($fieldkey,$entryvalue) {
- $fieldkey=trim($fieldkey);
- // support for Bibtex concatenation
- // see http://newton.ex.ac.uk/tex/pack/bibtex/btxdoc/node3.html
- // (?$v) {
- // spaces are allowed when using # and they are not taken into account
- // however # is not itself replaced by a space
- // warning: @strings are not case sensitive
- // see http://newton.ex.ac.uk/tex/pack/bibtex/btxdoc/node3.html
- $stringKey=strtolower(trim($v));
- if (isset($this->stringdb[$stringKey]))
- {
- // this field will be formated later by xtrim and latex2html
- $entryvalue_array[$k]=$this->stringdb[$stringKey]->value;
-
- // we keep a trace of this replacement
- // so as to produce correct bibtex snippets
- $this->currentEntry->constants[$stringKey]=$this->stringdb[$stringKey]->value;
- }
- }
- $entryvalue=implode('',$entryvalue_array);
-
- $this->currentEntry->setField($fieldkey,$entryvalue);
- }
-
- function setEntryType($entrytype) {
- $this->currentEntry->setType($entrytype);
- }
-
- function setEntryKey($entrykey) {
- //echo "new entry:".$entrykey."\n";
- $this->currentEntry->setKey($entrykey);
- }
-
- function beginEntry() {
- $this->currentEntry = createBibEntry();
- $this->currentEntry->setFile($this->filename);
- }
-
- function endEntry($entrysource) {
-
- // we add a timestamp
- $this->currentEntry->timestamp();
-
- // we add a key if there is no key
- if (!$this->currentEntry->hasField(Q_KEY) && $this->currentEntry->getType()!='string') {
- $this->currentEntry->setField(Q_KEY,md5($entrysource));
- }
-
- // we set the fulltext
- $this->currentEntry->text = $entrysource;
-
- // we format the author names in a special field
- // to enable search
- if ($this->currentEntry->hasField('author')) {
- $this->currentEntry->setField(Q_INNER_AUTHOR,$this->currentEntry->getFormattedAuthorsString());
-
- foreach($this->currentEntry->getCanonicalAuthors() as $author) {
- $homepage_key = $this->currentEntry->getHomePageKey($author);
- if (isset($this->stringdb[$homepage_key])) {
- $this->currentEntry->homepages[$homepage_key] = $this->stringdb[$homepage_key]->value;
- }
- }
- }
-
- // ignoring jabref comments
- if (($this->currentEntry->getType()=='comment')) {
- /* do nothing for jabref comments */
- }
-
- // we add it to the string database
- else if ($this->currentEntry->getType()=='string') {
- foreach($this->currentEntry->fields as $k => $v) {
- $k!=Q_INNER_TYPE and $this->stringdb[$k] = new StringEntry($k,$v,$this->filename);
- }
- }
-
- // we add it to the database
- else {
- $this->builtdb[$this->currentEntry->getKey()] = $this->currentEntry;
- }
- }
-
-} // end class BibDBBuilder
-
@@ -1228,7 +775,7 @@ class BibEntry {
// we assume that "comment" is never latex code
// but instead could contain HTML code (with links using the character "~" for example)
// so "comment" is not transformed too
- if ($name!='url' && $name!='comment'
+ if ($name!='url' && $name!='comment'
&& !preg_match('/^hp_/',$name) // homepage links should not be transformed with latex2html
) {
$value = $this->transformValue($value);
@@ -4089,7 +3636,6 @@ dd {
<BODY> and TITLE)
usage:
@@ -4103,6 +3649,7 @@ usage:
getTitle()
* $title: title of the page
*/
+
function HTMLTemplate($content) {
// when we load a page with AJAX
@@ -4139,20 +3686,20 @@ if (method_exists($content, 'getTitle')) {
// now the CSS
echo '';
?>
-
@@ -4529,7 +4076,7 @@ class Dispatcher {
}
// should call method display() on $x
- $fun = $this->wrapper;
+ $fun = BIBTEXBROWSER_DEFAULT_TEMPLATE;//$this->wrapper;
$fun($x);
$this->clearQuery();
@@ -4539,7 +4086,7 @@ class Dispatcher {
// if some contents have already been sent, for instance if we are included
// this means doing nothing
if ( headers_sent() == false ) { /* to avoid sending an unnecessary frameset */
- header("Location: ".$_SERVER['SCRIPT_NAME']."?frameset&bib=".$_GET[Q_FILE]);
+ header("Location: ".$_SERVER['SCRIPT_NAME']."?frameset&bib=".$_GET[Q_FILE]);
}
}
}
@@ -4666,7 +4213,8 @@ class Dispatcher {
function menu() {
$menu = createMenuManager();
$menu->setDB($this->getDB());
- $fun = $this->wrapper;
+ // why does //$this->wrapper; = no wrapper?
+ $fun = BIBTEXBROWSER_DEFAULT_TEMPLATE;
$fun($menu);
return 'END_DISPATCH';
}
@@ -4757,7 +4305,7 @@ class Dispatcher {
extract_css_classes($first_entry->toHTML());
-
+
// IEEE style
bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','JanosBibliographyStyle');
$this->assertEquals("Foo Bar and Jane Doe, \"An Article\", In New Results, vol. 5, pp. 1-2, 2009.\n ",strip_tags($first_entry->toHTML()));
@@ -646,7 +646,7 @@ class BTBTest extends PHPUnit_Framework_TestCase {
ob_get_clean();
$this->assertEquals("[2]", $btb->getEntryByKey('aKey')->getAbbrv());
$this->assertEquals("[1]", $btb->getEntryByKey('aKey-withSlash')->getAbbrv());
-
+
}
function test_identity() {
diff --git a/bibtexbrowser-documentation.wiki b/wiki/bibtexbrowser-documentation.wiki
similarity index 100%
rename from bibtexbrowser-documentation.wiki
rename to wiki/bibtexbrowser-documentation.wiki
diff --git a/bibtexbrowser-users.wiki b/wiki/bibtexbrowser-users.wiki
similarity index 100%
rename from bibtexbrowser-users.wiki
rename to wiki/bibtexbrowser-users.wiki