<?php

// $PdfLink
// $BibLink
// $UrlLink

$BibtexPdfLink = "(PDF)";
$BibtexUrlLink = "(URL)";
$BibtexBibLink = "(BIB)";

$BibtexGenerateDefaultUrlField = false;

$BibtexLang = array();

Markup("bibtexcite","inline","/\\{\\[(.*?),(.*?)\\]\\}/e","BibCite('$1', '$2')");

Markup("bibtexquery","fulltext","/\\bbibtexquery:\\[(.*?)\\]\\[(.*?)\\]\\[(.*?)\\]\\[(.*?)\\]/e","BibQuery('$1', '$2', '$3', '$4')");
Markup("bibtexsummary","fulltext","/\\bbibtexsummary:\\[(.*?),(.*?)\\]/e","BibSummary('$1', '$2')");
Markup("bibtexcomplete","fulltext","/\\bbibtexcomplete:\\[(.*?),(.*?)\\]/e","CompleteBibEntry('$1', '$2')");


SDV($HandleActions['bibentry'],'HandleBibEntry');

$BibEntries = array();

class BibtexEntry {
  var $values = array();
  var $bibfile;
  var $entryname;
  var $entrytype;

  function BibtexEntry($bibfile, $entryname)
  {
    $this->bibfile = $bibfile;
    $this->entryname = $entryname;
  }

  function evalCond($cond)
  {
    $toeval = "return (" . $cond . ");";
    $toeval = str_replace("&gt;", ">", $toeval);
    $toeval = str_replace("&lt;", "<", $toeval);
    //print $toeval."\n";
    return eval($toeval);
  }

  function evalGet($get)
  {
     $get = str_replace("\\\"", "\"", $get);
     $get = str_replace("&gt;", ">", $get);
     eval('$res = ' . $get . ';');
    return $res;
  }

  function getAuthors()
  {
    $aut = $this->get('AUTHOR');
    if ($aut == FALSE) return FALSE;
    $aut = explode(" and ", $aut);

    $ret = "";

    for ($i = 0; $i < count($aut); $i++)
      {
	$ret = $ret . $aut[$i];
	if ($i == count($aut) - 2) $ret = $ret . " and ";
	else if ($i < count($aut) - 2) $ret = $ret . ", ";
      }
    return $ret;
  }

  function getTitle()
  {
    return $this->getFormat('TITLE');
  }

  function getAbstract()
  {
    return $this->get('ABSTRACT');
  }

  function getComment()
  {
    return $this->get('COMMENT');
  }

  function getPages()
  {
    $pages = $this->get('PAGES');
    if ($pages)
    {
      $found = strpos($pages, "--");
      if (found) return str_replace("--", "-", $pages);
      else return $pages;
    }
    return "";
  }

  function get($field)
  {
  	//echo("<br>".$field."<br>");
    $val = $this->values[$field];
    if ($val == FALSE) {
    	$val = $this->values[strtolower($field)];
  		//echo("<br>".strtolower($field)."<br>");
    }
    return $val;
  }


  function getFormat($field)
  {
    $ret = $this->get($field);
    if ($ret)
    {
      $ret = str_replace("{", "", $ret);
      $ret = str_replace("}", "", $ret);
    }
    return $ret;
  }

  function getCompleteEntryUrl()
  {
    global $DefaultTitle, $FarmD, $BibtexCompleteEntriesUrl;
    global $pagename;

    $Bibfile = $this->bibfile;
    $Entryname = $this->entryname;

    if (!$BibtexCompleteEntriesUrl) $BibtexCompleteEntriesUrl = FmtPageName('$PageUrl', $pagename) . '?action=bibentry&bibfile=$Bibfile&bibref=$Entryname';

    $RetUrl = preg_replace('/\$Bibfile/', "$Bibfile", $BibtexCompleteEntriesUrl);
    $RetUrl = preg_replace('/\$Entryname/', "$Entryname", $RetUrl);
    return $RetUrl;
  }

  function getPreString($dourl = true)
  {
    global $pagename, $BibtexLang;
    $ret = "";

    $lang = $this->get("LANG");
    if ($lang && $BibtexLang[$lang])
    {
      $ret = $ret . $BibtexLang[$lang];
    }

    if ($dourl)
      $ret = $ret . "''[[" . $this->getCompleteEntryUrl() . " | " . $this->getTitle() . "]]" . "''. " . $this->getAuthors();
    else
      $ret = $ret . "''" . $this->getTitle() . "''. " . $this->getAuthors();
    return $ret;
  }

  function getPostString($dourl = true)
  {
    global $ScriptUrl, $BibtexUrlLink, $BibtexBibLink, $pagename;

    $ret = "";
    $year = $this->get("YEAR");
    if ($year)
    {
      $ret = $ret . ", ";
      $month = $this->get("MONTH");
      if ($month)
      {
	$ret = $ret . $month . " ";
      }
      $ret = $ret . $year;
    }

    $note = $this->get("NOTE");
    if ($note)
    {
      $ret = $ret . ". (''$note'')";
    }
    $ret = $ret . ".";

/*    if (!$dourl)
    { */
      $url = $this->get("URL");
		// Try and get url from bib2html_dl_pdf
      if (!$url) $url = $this->get("bib2html_dl_pdf");
      if ($url) {
	  	$ret = $ret . " [[" . $url . " | $BibtexUrlLink]]";
	  }
/*    } */

    $pdf = $this->get("PDF");
    if ($pdf)
    {
      global $BibtexPdfUrl, $BibtexPdfLink, $UploadUrlFmt;
      if (!$BibtexPdfUrl) $BibtexPdfUrl = FmtPageName('$UploadUrlFmt$UploadPrefixFmt', $pagename) . "/";  /* AdV - 27.6.2006 */
      $ret = $ret . " [[$BibtexPdfUrl" . $pdf . " | $BibtexPdfLink]][==]";
    }

    if ($dourl) $ret = $ret . " [[" . $this->getCompleteEntryUrl() . "#" . $this->entryname . "Bib | $BibtexBibLink]]";

    return $ret;
  }

  function cite()
  {
    $ret = "([[" . $this->getCompleteEntryUrl() . " | " . $this->entryname . "]])";
    return $ret;
  }

  function getBibEntry()
  {
    global $BibtexSilentFields, $BibtexGenerateDefaultUrlField;

    $ret = $ret . "@@@" . $this->entrytype . " { " . $this->entryname . ",\\\\\n";

    while (list($key, $value)=each($this->values))
    {
      if ($BibtexSilentFields && in_array($key, $BibtexSilentFields)) continue;
      $ret = $ret . "&nbsp;&nbsp;&nbsp;&nbsp;" . $key . " = { " . $value . " },\\\\\n";
    }

    if ($BibtexGenerateDefaultUrlField && ($this->get("URL") == false)) $ret = $ret . "&nbsp;&nbsp;&nbsp;&nbsp;URL = { " . $this->getCompleteEntryUrl() . " },\\\\\n";
    $ret = $ret . "}@@\n";

    return $ret;
  }

  function getCompleteEntry()
  {
    $ret = "[[#" . $this->entryname . "]]\n!!!" . $this->entryname . "\n";
    $ret = $ret . '<div class="indent">' . $this->getSummary(false) . "</div>";
    $abstract = $this->getAbstract();
    if ($abstract)
    {
      $ret = $ret . "\n'''Abstract:'''\n" . '<div class="indent">' . $abstract . "</div>";
    }
    $comment = $this->getComment();
    if ($comment)
    {
      $ret = $ret . "\n'''Comment:'''\n" . '<div class="indent">' . $comment . "</div>";
    }
    $ret = $ret . "[[#" . $this->entryname . "Bib]]\n";
    $ret = $ret . "\n'''Bibtex entry:'''\n" . '<div class="indent">' . $this->getBibEntry() . "</div>";
    return $ret;
  }

  function getSolePageEntry()
  {
    $ret = "!" . $this->entryname . "\n";
    $ret = $ret . "\n!!!Summary\n";
    $ret = $ret . $this->getSummary(false) . "\n";
    $abstract = $this->getAbstract();
    if ($abstract)
    {
      $ret = $ret . "\n!!!Abstract\n" . $abstract . "\n";
    }
    $comment = $this->getComment();
    if ($comment)
    {
      $ret = $ret . "\n!!!Comment\n" . $comment . "\n";
    }
    $ret = $ret . "[[#" . $this->entryname . "Bib]]\n";
    $ret = $ret . "\n!!!Bibtex entry\n" . $this->getBibEntry() . "\n";
    return $ret;
  }
}

class PhdThesis extends BibtexEntry {
  function PhdThesis($bibfile, $entryname)
  {
    parent::BibtexEntry($bibfile, $entryname);
    $this->entrytype = "PHDTHESIS";
  }

  function getSummary($dourl = true)
  {
    $ret = parent::getPreString($dourl);
    $ret = $ret . ". PhD thesis";
    $school = parent::get("SCHOOL");
    if ($school)
    {
      $ret = $ret . ", ''" . $school . "''";
    }
    return $ret . parent::getPostString($dourl);
  }
}

class MasterThesis extends BibtexEntry {
  function MasterThesis($bibfile, $entryname)
  {
    parent::BibtexEntry($bibfile, $entryname);
    $this->entrytype = "MASTERSTHESIS";
  }

  function getSummary($dourl = true)
  {
    $ret = parent::getPreString($dourl);
    $ret = $ret . ". Master's thesis";
    $school = parent::get("SCHOOL");
    if ($school)
    {
      $ret = $ret . ", ''" . $school . "''";
    }
    return $ret . parent::getPostString($dourl);
  }
}

class TechReport extends BibtexEntry {
  function TechReport($bibfile, $entryname)
  {
    parent::BibtexEntry($bibfile, $entryname);
    $this->entrytype = "TECHREPORT";
  }

  function getSummary($dourl = true)
  {
    $ret = parent::getPreString($dourl);
    $type = parent::get("TYPE");
    if ( $type )
       $ret = $ret . ". $type";
    else
       $ret = $ret . ". Technical report";
    $number = parent::get("NUMBER");
    if ($number)
       $ret = $ret . " $number";
    $institution = parent::get("INSTITUTION");
    if ($institution)
    {
      $ret = $ret . ", ''" . $institution . "''";
    }
    return $ret . parent::getPostString($dourl);
  }
}

class Article extends BibtexEntry {
  function Article($bibfile, $entryname)
  {
    parent::BibtexEntry($bibfile, $entryname);
    $this->entrytype = "ARTICLE";
  }

  function getSummary($dourl = true)
  {
    $ret = parent::getPreString($dourl);
    $journal = parent::get("JOURNAL");
    if ($journal)
    {
      $ret = $ret . ". ''" . $journal . "''";
      $volume = parent::get("VOLUME");
      if ($volume)
      {
	$ret = $ret . ", " . $volume;
	$number = parent::get("NUMBER");
	if ($number)
	{
	  $ret = $ret . "(" . $number . ")";
	}
	$pages = parent::getPages();
	if ($pages)
	{
	  $ret = $ret . ":" . $pages;
	}
      }
    }
    return $ret . parent::getPostString($dourl);
  }
}

class InProceedings extends BibtexEntry
{
  function InProceedings($bibfile, $entryname)
  {
    parent::BibtexEntry($bibfile, $entryname);
    $this->entrytype = "INPROCEEDINGS";
  }

  function getSummary($dourl = true)
  {
    $ret = parent::getPreString($dourl);
    $booktitle = parent::get("BOOKTITLE");
    if ($booktitle)
    {
      $ret = $ret . ". In " . $booktitle . "";
      $pages = $this->getPages();
      if ($pages) $ret = $ret . ", " . $pages;
      $address = parent::get("ADDRESS");
      if ($address) $ret = $ret . ", " . $address;
      $organization = parent::get("ORGANIZATION");
      if ($organization) $ret = $ret . ". " . $organization;
    }

    return $ret . parent::getPostString($dourl);
  }

  function getPages()
  {
    $pages = parent::getPages();
    if ($pages)
    {
      if (strpos($pages, "-")) return "pages " . $pages;
      else return "page " . $pages;
    }
    return $pages;
  }
}

class InCollection extends BibtexEntry {
  function InCollection($bibfile, $entryname)
  {
    parent::BibtexEntry($bibfile, $entryname);
    $this->entrytype = "INCOLLECTION";
  }

  function getSummary($dourl = true)
  {
    $ret = parent::getPreString($dourl);
    $booktitle = parent::get("BOOKTITLE");
    if ($booktitle)
    {
      $ret = $ret . ". In " . $booktitle . "";
      $pages = $this->getPages();
      if ($pages) $ret = $ret . ", " . $pages . ".";
      $publisher = parent::get("PUBLISHER");
      if ($publisher) $ret = $ret . $publisher . ", ";
    }
    return $ret . parent::getPostString($dourl);

  }

  function getPages()
  {
    $pages = parent::getPages();
    if ($pages)
    {
      if (strpos($pages, "-")) return "pages " . $pages;
      else return "page " . $pages;
    }
    return $pages;
  }
}

class Book extends BibtexEntry {
  function Book($bibfile, $entryname)
  {
    parent::BibtexEntry($bibfile, $entryname);
    $this->entrytype = "BOOK";
  }

  function getSummary($dourl = true)
  {
    $ret = parent::getPreString($dourl);
    $publisher = parent::get("PUBLISHER");
    if ($publisher) $ret = $ret . $publisher . ", ";
    $ret = $ret . parent::getPostString($dourl);
    return $ret;
  }
}

class InBook extends BibtexEntry {
  function InBook($bibfile, $entryname)
  {
    parent::BibtexEntry($bibfile, $entryname);
    $this->entrytype = "INBOOK";
  }

  function getPreString($dourl = true)
  {
    global $pagename, $BibtexLang;
    $ret = "";

    $lang = $this->get("LANG");
    if ($lang && $BibtexLang[$lang])
    {
      $ret = $ret . $BibtexLang[$lang];
    }

    $chapter = parent::get("CHAPTER");
    if ($dourl)
      $ret = $ret . "''[[" . $this->getCompleteEntryUrl() . " | " . $chapter . "]]" . "''. " . $this->getAuthors();
    else
      $ret = $ret . "''" . $chapter . "''. " . $this->getAuthors();
    return $ret;
  }

  function getSummary($dourl = true)
  {
    $ret = $this->getPreString($dourl);
    $ret = $ret . ", in " . parent::getTitle();
    $publisher = parent::get("PUBLISHER");
    if ($publisher) $ret = $ret . ". $publisher";
    $ret = $ret . parent::getPostString($dourl);
    return $ret;
  }
}

class Proceedings extends BibtexEntry {
      function Proceedings($bibfile, $entryname)
      {
         parent::BibtexEntry($bibfile, $entryname);
         $this->entrytype = "PROCEEDINGS";
      }

      function getSummary($dourl = true)
      {
         $ret = parent::getPreString($dourl);
         $editor = parent::get("EDITOR");
         if ($editor)
            $ret = $ret . $editor .", editor. ";

         $volume = parent::get("VOLUME");
         if ($volume)
         {
            $ret = $ret . "volume " . $volume;
            $series = parent::get("SERIES");
            if ( $series != "" )
               $ret = $ret . " of ''$series''";
         }
         $address = parent::get("ADDRESS");
         if ($address)
            $ret = $ret . ", $address";
         $orga = parent::get("ORGANIZATION");
         if ($orga)
            $ret = $ret . ", $orga";
         $publisher = parent::get("PUBLISHER");
         if ($publisher)
            $ret = $ret . ", $publisher";
         $ret = $ret . parent::getPostString($dourl);
         return $ret;
      }
}

class Misc extends BibtexEntry {
  function Misc($bibfile, $entryname)
  {
    parent::BibtexEntry($bibfile, $entryname);
    $this->entrytype = "MISC";
  }

  function getSummary($dourl = true)
  {
    $ret = parent::getPreString($dourl);
    $howpublished = parent::get("HOWPUBLISHED");
    if ($howpublished) $ret = $ret . ". " . $howpublished;
    $ret = $ret . parent::getPostString($dourl);
    return $ret;
  }
}

function sortByField($a, $b)
{
  global $SortField;
  $f1 = $a->evalGet($SortField);
  $f2 = $b->evalGet($SortField);

  if ($f1 == $f2) return 0;

  return ($f1 < $f2) ? -1 : 1;
}

function BibQuery($files, $cond, $sort, $max)
{
  global $BibEntries, $SortField;

  $ret = '';

  $files = trim($files);
  $cond = trim($cond);
  $sort = trim($sort);

  if ($sort[0] == '!') { $reverse = true; $sort = substr($sort, 1); }
  else $reverse = false;

  if ($cond == '') $cond = 'true';

  if (!$BibEntries[$files]) ParseBibFile($files);

  $res = array();
  $bibselectedentries = $BibEntries[$files];
  while (list($key, $value)=each($bibselectedentries))
    {
      if ($value->evalCond($cond)) $res[] = $value;
    }

  if ($sort != '')
    {
      $SortField = $sort;
      usort($res, "sortByField");
    }

  if ($reverse) $res = array_reverse($res);

  if ($max != '') $res = array_slice($res, 0, (int) $max);

  while (list($key, $value)=each($res))
    {
      $ret .= "*" . $value->getSummary() . "\n";
    }

  return $ret;
}

function HandleBibEntry($pagename)
{
  global $HTTP_GET_VARS, $PageStartFmt, $PageEndFmt, $PageHeaderFmt, $ScriptUrl, $bibentry, $bibfile, $bibref;
  $bibfile = $HTTP_GET_VARS['bibfile'];
  $bibref = $HTTP_GET_VARS['bibref'];
  SDV($ScriptUrl, FmtPageName('$PageUrl', $pagename));

  $bibentry = GetEntry($bibfile, $bibref);

  $page = array('timefmt'=>@$GLOBALS['CurrentTime'],
		'author'=>@$GLOBALS['Author']);
//  SetPageVars($pagename,$page, (bibentry != false ? $bibentry->getTitle() : ""));

  $PageHeaderFmt = "";
  SDV($HandleBibtexFmt,array(&$PageStartFmt,
    'function:PrintCompleteEntry',&$PageEndFmt));
  PrintFmt($pagename,$HandleBibtexFmt);
}

function PrintCompleteEntry()
{
  global $bibentry, $bibfile, $bibref, $pagename;
  if ($bibentry == false) echo MarkupToHTML($pagename, "%red%Invalid BibTex Entry: [" . $bibfile . ", " . $bibref . "]!");
  else
    {
      echo MarkupToHTML($pagename, $bibentry->getSolePageEntry());
    }
}

function GetEntry($bib, $ref)
{
    global $BibEntries;
    $ref = trim($ref);
    $bib = trim($bib);
    $bibtable = $BibEntries[$bib];
    if ($bibtable == false)
    {
      ParseBibFile($bib);
      $bibtable = $BibEntries[$bib];
    }
    $bibref = $bibtable[$ref];
    if ($bibref == false)
      return false;
    return $bibref;
}

function BibCite($bib, $ref)
{
  $entry = GetEntry($bib, $ref);
  if ($entry == false) return "%red%Invalid BibTex Entry!";
  return $entry->cite();
}

function CompleteBibEntry($bib, $ref)
{
  $entry = GetEntry($bib, $ref);
  if ($entry == false) return "%red%Invalid BibTex Entry!";
  return $entry->getCompleteEntry();
}

function BibSummary($bib, $ref)
{
  $entry = GetEntry($bib, $ref);
  if ($entry == false) return "%red%Invalid BibTex Entry!";
  return $entry->getSummary();
}

function ParseEntries($fname, $entries)
{
   global $BibEntries;
   // entries is a array with already splitted bib file
   // $entries[0] -> not interessting
   // $entries[1] -> array filled with entries type
   // $entries[2] -> array filled with entries key
   // $entries[3] -> array filled with the key = value....
   $nb_entries = count($entries[0]);

   $bibfileentry = array();
   for ($i = 0 ; $i < $nb_entries ; ++$i)
   {
      $entrytype = strtoupper($entries[1][$i]);
      $entryname = $entries[2][$i];

      if ($entrytype == "ARTICLE") $entry = new Article($fname, $entryname);
      else if ($entrytype == "INPROCEEDINGS") $entry = new InProceedings($fname, $entryname);
      else if ($entrytype == "PHDTHESIS") $entry = new PhdThesis($fname, $entryname);
      else if ($entrytype == "MASTERSTHESIS") $entry = new MasterThesis($fname, $entryname);
      else if ($entrytype == "INCOLLECTION") $entry = new InCollection($fname, $entryname);
      else if ($entrytype == "BOOK") $entry = new Book($fname, $entryname);
      else if ($entrytype == "INBOOK") $entry = new InBook($fname, $entryname);
      else if ($entrytype == "TECHREPORT") $entry = new TechReport($fname, $entryname);
      else if ($entrytype == "PROCEEDINGS") $entry = new Proceedings($fname, $entryname);
      else $entry = new Misc($fname, $entryname);

      // match all keys
      preg_match_all("/(\w+)\s*=\s*([^¶]+)¶?/", $entries[3][$i], $all_keys);

      for ($j = 0 ; $j < count($all_keys[0]) ; $j++)
      {
	$key = strtoupper($all_keys[1][$j]);
	$value = $all_keys[2][$j];
	// Remove the leading and ending braces or quotes if they exist.
	$value = preg_replace('/^\s*{(.*)}\s*$/', '\1', $value);
	// TODO: only run this regexp if the former didn't match
	$value = preg_replace('/^\s*"(.*)"\s*$/', '\1', $value);

	$entry->values[$key] = $value;
         // $all_keys[0] -> not interessting
         // $all_keys[1] -> array filled with keys
         // $all_keys[2] -> array filled with values
      }
      $bibfileentry[$entryname] = $entry;
   }

   $BibEntries[$fname] = $bibfileentry;
}


function ParseBib($bib_file, $bib_file_string)
{
// first split the bib file into several part
// first let's do an ugly trick to replace the first { and the last } of each bib entry by another special char (to help with regexp)

   $count=0;
   for ($i = 0 ; $i < strlen($bib_file_string) ; $i++)
   {
      if ($bib_file_string[$i] == '{')
      {
         if ($count==0)
            $bib_file_string[$i] = '¤';
         $count++;
      }
      else if ($bib_file_string[$i] == '}')
      {
         $count--;
         if ($count==0)
            $bib_file_string[$i] = '¤';
      }
      else if ($bib_file_string[$i] == ',' && $count == 1)
	 $bib_file_string[$i] = '¶';
   }

   $nb_bibentry = preg_match_all("/@(\w+)\s*¤\s*([^¶]+)¶([^¤]*)¤/", $bib_file_string, $matches);
   ParseEntries($bib_file, $matches);
}

function ParseBibFile($bib_file)
{
  global $BibtexBibDir, $pagename;
  if (!$BibtexBibDir) $BibtexBibDir = FmtPageName('$UploadDir$UploadPrefixFmt', $pagename) . "/"; /* AdV - 27.6.2006 */
  //print $BibtexBibDir;
  //print $bib_file;
   $f = fopen($BibtexBibDir . $bib_file, "r");
   $bib_file_string = "";
   if ($f)
   {
      while (!feof($f))
      {
         $bib_file_string = $bib_file_string . fgets($f, 1024);
      }

      $bib_file_string = preg_replace("/\n/", "", $bib_file_string);

      ParseBib($bib_file, $bib_file_string);
      //print $bib_file_string;
      return true;
   }
   print "<font color=#FF0000>Can't open file</font><br>\n";
   return false;
}

$UploadExts['bib'] = 'text/plain';

?>