Location: PHPKode > scripts > Hololib > hololib/hololib.php
<?php
 /**********************************************************************
  * Holotech Function Library
  * Copyright (c) 2000 - 2006 All rights reserved.
  *
  * This is free software, in the sense of "free beer" *and* "free 
  * speech"! How cool is that? It costs nothing, and you may use and
  * modify it as desired. You may redistribute it freely, so long as it
  * is unmodified and has the documentation file attached.
  *
  * Questions, comments, praise, criticism and beer are welcome.
  * Email hide@address.com
  *
  * This library requires PHP4
  *
  **********************************************************************/

  if (isset($hl_HoloLibLoaded)) return;

  $hl_HoloLibVersion = '1.0.0';
  $hl_CodePath       = dirname(__FILE__);

 /*
  * Trim empty elements from an array
  *   $Array = The array to be trimmed
  */
  function hl_ArrayTrim(&$Array) {
    foreach ($Array as $key => $val) {
      if (!strlen($val)) unset($Array[$key]);
    }
    reset($Array);
  }

 /*
  *  Dump an array recursively
  *    $array = The array to dump
  *    $echo  = Whether to echo or return the output
  *    $text  = Output text rather than HTML
  *    $html  = Convert < and & to entities
  *    $encap = Character(s) to encapsulate array elements
  */
  function hl_ArrayDump($array, $echo = true, $text = false, $encap = "", $html = true) {
    static $nest = 0, $output = '';

    if (!is_array($array)) return;

    if ($text) {
      $B1 = '[';
      $B2 = ']';
      $NL = "\n";
      $SP = '  ';
    }
    else {
      $B1 = '<B>';
      $B2 = '</B>';
      $NL = "<BR>\n";
      $SP = '&nbsp;&nbsp;';
    }

    $LC = substr($encap, 0, 1);
    $RC = substr($encap, -1);

    $Spacer = str_repeat($SP, $nest);

    while (list($key,$el) = each($array)) {
      if (is_array($el)) {
        $output.= $Spacer.$B1.$key.$B2.$NL;
        $nest++;
        hl_ArrayDump($el, $echo, $text, $encap, $html);
        $nest--;
      }
      else {
        if (gettype($el) == "boolean") {
          $el = ($el)? $B1.'true'.$B2 : $B1.'false'.$B2;
        }
        elseif ($html && !$text) {
          $el = str_replace("&", "&amp;", $el);
          $el = str_replace("<", "&lt;", $el);
        }
        $output.= $Spacer.$LC.$key.$RC.' => '.$LC.$el.$RC.$NL;
      }
    }

    if ($nest) return;

    $Output = $output;
    $output = '';

    if ($echo) echo   $Output;
    else       return $Output;
  }

 /*
  *  Convert an array to a string list
  *    $array       = The array to convert
  *    $separator   = What to separate the elements with. Default is ', '
  *    $conjunction = What to use between the last two elements. Default is 'and'
  */
  function hl_ArrayToList(&$array, $separator = ', ', $conjunction = 'and') {
    if (ereg('^[A-Za-z]+$', $conjunction)) $conjunction = " $conjunction ";

    $LastEl = array_pop($array);

    if (count($array)) {
      $array = implode($separator, $array);
      $array.= "$conjunction$LastEl";
    }

    else $array = $LastEl;
  }

 /*
  *  +-----------------------------+
  *  | Put a box around a message. |
  *  +-----------------------------+
  *    $Message = The message to be boxed
  *    $Wrap    = Where to wrap the message
  */
  function hl_BoxIt($Message, $Wrap = 70) {
    hl_LineWrap($Message, $Wrap, "%!%");
    $Message = ereg_replace("%!%$", "", $Message);

    $Message = explode("%!%", $Message);

    $MaxLine = 0;
    while (list(,$Line) = each($Message)) {
      $MaxLine = max($MaxLine, strlen($Line));
    }
    reset($Message);

    while (list(,$Line) = each($Message)) {
      $Filler = str_repeat(" ", $MaxLine - strlen($Line));
      $Box.= "| $Line$Filler|\n";
    }

    $MaxLine++;

    $BoxCap = "+".str_repeat("-", $MaxLine)."+";

    $Box = "$BoxCap\n$Box$BoxCap";

    return $Box;
  }

 /*
  *  Break out a string, character by character, display ASCII values
  *    $string = The string to break out.
  *    $text   = Display as text rather than HTML
  */
  function hl_BreakOut($string, $text = false) {
    if ($text) {
      $B1 = '[';
      $B2 = ']';
    }
    else {
      $B1 = '<B>';
      $B2 = '</B>';
    }

    $x = 0; $char = $string[$x++];
    while (strlen($char)) {
      $cord = ord($char);
      echo $B1.$char.$B2."[$cord] ";
      $char = $string[$x++];
    }

  }

 /*
  * Generate a valid credit card number
  *   $StartWith = Starting digits, or a card type code
  *   $Digits    = The number of digits to generate
  *   $Split     = Optional split character
  *   $Size      = How big to make segments if splitting
  */
  function hl_CardGen($StartWith, $Digits = 16, $Split = '', $Size = 4) {
    srand((double)microtime()*1000000);

    if (!is_int($StartWith)) {
      switch ($StartWith) {
      case 'mcd' :
        $StartWith = '53';
        $Digits    = 16;
        break;

      case 'vis' :
        $StartWith = '42';
        $Digits    = 16;
        break;

      case 'amx' :
        $StartWith = '34';
        $Digits    = 15;
        break;

      case 'dsc' :
        $StartWith = '6011';
        $Digits    = 16;
        break;

      case 'dnc' :
        $StartWith = '300';
        $Digits    = 14;
        break;

      case 'jcb' :
        $StartWith = '3';
        $Digits    = 16;
        break;

      case 'enr' :
        $StartWith = '2014';
        $Digits    = 15;
        break;

      case 'swi' :
        $StartWith = '5';
        $Digits    = 18;
        break;

      case 'dlt' :
        $StartWith = '4';
        $Digits    = 16;
        break;
      }
    }

    $Num = $StartWith;

    while (strlen($Num) < $Digits - 1) $Num.= rand(0,9);

    $rNum = strrev($Num);

    $Total = 0;

    for ($x=0; $x<strlen($rNum); $x++) {
      $digit = substr($rNum, $x, 1);

      if ($x/2 == floor($x/2)) $digit *= 2;

      if (strlen($digit) == 2) $digit = substr($digit, 0, 1) + substr($digit, 1, 1);
      $Total += $digit;
    }

    $CheckDigit = 0;
    while (($Total + $CheckDigit) % 10 > 0) $CheckDigit++;

    $Num.= $CheckDigit;

    if (strlen($Split)) $Num = chunk_split($Num, $Size, $Split);
    $Num = ereg_replace("$Split$", '', $Num);

    return $Num;
  }

 /*
  * Given a credit card number, returns the type of card.
  *   $CardNum = The number to be evaluated
  */
  function hl_CardType($CardNum) {
  	$CardNum = ereg_replace('[^0-9]','',$CardNum);
    if (ereg('^5[1-5].{14}$',                $CardNum)) return 'mcd';
    if (ereg('^4.{15}$|^4.{12}$',            $CardNum)) return 'vis';
    if (ereg('^3[47].{13}$',                 $CardNum)) return 'amx';
    if (ereg('^6011.{12}$',                  $CardNum)) return 'dsc';
    if (ereg('^30[0-5].{11}$|^3[68].{12}$',  $CardNum)) return 'dnc';
    if (ereg('^3.{15}$|^2131|1800.{11}$',    $CardNum)) return 'jcb';
    if (ereg('^2014.{11}$|^2149.{11}$',      $CardNum)) return 'enr';
    if (!hl_LuhnMod10(                       $CardNum)) return 'bad';
    return 'unk';
  }

 /*
  * Compare two version number strings.
  *   $CheckVers = The version number to check.
  *   $PgmVers   = The version number to check against.
  */
  function hl_CheckVers($CheckVers, $PgmVers = 'PHP') {
    if (!strlen($CheckVers)) return false;

    if ($PgmVers == 'PHP') $PgmVers = phpversion();

    list($pMaj, $pMin, $pSub) = explode(".", $PgmVers);
    list($cMaj, $cMin, $cSub) = explode(".", $CheckVers);

    if ($pMaj > $cMaj) return true;
    if ($pMaj < $cMaj) return false;

    if ($pMin > $cMin) return true;
    if ($pMin < $cMin) return false;

    if ($pSub > $cSub) return true;
    if ($pSub < $cSub) return false;
    return true;
  }

 /*
  *  Generate HTML date selector fields
  *    $Prefix    = A prefix for the field names
  *    $FirstYear = The first year in the year selector; default null
  *    $NumYears  = The number of years in the year selector; default 5
  *    $YearSet   = The year to set; default 0 or $FirstYear
  *    $MonthSet  = The month to set; default 0 or January
  *    $DaySet    = The day to set; default 0 or 1
  *    $NullDate  = Whether to include null values in the fields
  *    $ShortMo   = Whether to use short month names.
  *    $Suffix    = A suffix for the field names
  *    $ZPad      = Whether to zero-pad values
  *    $Order     = The order of the fields
  *    $SetToday  = Whether to set today's date
  */
  function hl_DateSelector() {
    global $hl_Months;

    $ThisYear  = date("Y");
    $ThisMonth = date("m");
    $Today     = date("d");

    if (!func_num_args()) {
      global $hl_DateSelector;
      if (is_array($hl_DateSelector)) extract($hl_DateSelector);

      global $hl_Prefix, $hl_FirstYear, $hl_NumYears, $hl_MonthSet, $hl_DaySet,
             $hl_YearSet, $hl_YearSeq, $hl_NullDate, $hl_ShortMo, $hl_Suffix,
             $hl_ZPad, $hl_Order, $hl_SetToday;

      if (isset($hl_Prefix   )) $Prefix    = $hl_Prefix;
      if (isset($hl_FirstYear)) $FirstYear = $hl_FirstYear;
      if (isset($hl_NumYears )) $NumYears  = $hl_NumYears;
      if (isset($hl_MonthSet )) $MonthSet  = $hl_MonthSet;
      if (isset($hl_DaySet   )) $DaySet    = $hl_DaySet;
      if (isset($hl_YearSet  )) $YearSet   = $hl_YearSet;
      if (isset($hl_YearSeq  )) $YearSet   = $hl_YearSeq;
      if (isset($hl_NullDate )) $NullDate  = $hl_NullDate;
      if (isset($hl_ShortMo  )) $ShortMo   = $hl_ShortMo;
      if (isset($hl_Suffix   )) $Suffix    = $hl_Suffix;
      if (isset($hl_ZPad     )) $ZPad      = $hl_ZPad;
      if (isset($hl_Order    )) $Order     = $hl_Order;
      if (isset($hl_SetToday )) $SetToday  = $hl_SetToday;
    }

    else {
      $Parms = func_get_arg(0);
      extract($Parms);
    }

    if ($SetToday) {
      $MonthSet = $ThisMonth;
      $DaySet   = $Today;
      $YearSet  = $ThisYear;
    }

    if (!isset($MonthSet))  $MonthSet  = 0;
    if (!isset($DaySet))    $DaySet    = 0;
    if (!isset($YearSet))   $YearSet   = 0;

    if (!isset($FirstYear)) $FirstYear = $ThisYear;
    if (!isset($NumYears))  $NumYears  = 5;
    if (!isset($ZPad))      $ZPad      = false;
    if (!isset($NullDate))  $NullDate  = true;
    if (!isset($ShortMo))   $ShortMo   = false;
    if (!isset($Order))     $Order     = 'MDY';

    if (!isset($YearSeq))   $YearSeq   = 'asc';
    $YearSeq = strtolower($YearSeq);

    $zzero = ($ZPad)? "0" : "";
    $s     = ($ShortMo)? "s" : "";

    // Month Selector
    $Selector['M'] =
    "<SELECT NAME=\"{$Prefix}Month{$Suffix}\">\n";

    if ($NullDate)
      $Selector['M'].=
      "<OPTION VALUE={$zzero}0>---------</OPTION>\n";

    for ($ix=1; $ix<=12; $ix++) {
      $zero = ($ZPad && strlen($ix) < 2)? "0" : "";
      $SELECTED = ($ix == $MonthSet)? " SELECTED" : "";
      $Selector['M'].=
      "<OPTION VALUE=$zero$ix$SELECTED>".$hl_Months[$ix.$s]."</OPTION>\n";
    }
    $Selector['M'].=
    "</SELECT> &nbsp; ";

    // Day Selector
    if ($DaySet > -1) {
      $Selector['D'] =
      "<SELECT NAME=\"{$Prefix}Day{$Suffix}\">\n";

    if ($NullDate)
      $Selector['D'].=
      "<OPTION VALUE={$zzero}0>--</OPTION>\n";

      for ($ix=1; $ix<=31; $ix++) {
        $zero = ($ZPad && strlen($ix) < 2)? "0" : "";
        $SELECTED = ($ix == $DaySet)? " SELECTED" : "";
        $Selector['D'].=
        "<OPTION VALUE=$zero$ix$SELECTED> &nbsp; $ix &nbsp;</OPTION>\n";
      }
      $Selector['D'].=
      "</SELECT> &nbsp; ";
    }

    // Year Selector
    if ($YearSet > -1) {
      $Selector['Y'] =
      "<SELECT NAME=\"{$Prefix}Year{$Suffix}\">\n";

      if ($NullDate)
        $Selector['Y'].=
        "<OPTION VALUE=0000>----</OPTION>\n";

      if ($YearSeq == 'asc') {
        for ($ix=$FirstYear; $ix<$FirstYear+$NumYears; $ix++) {
          $SELECTED = ($ix == $YearSet)? " SELECTED" : "";
          $Selector['Y'].=
          "<OPTION VALUE=$ix$SELECTED> &nbsp; $ix &nbsp;</OPTION>\n";
        }
      }

      else {
        for ($ix=$FirstYear+$NumYears-1; $ix>=$FirstYear; $ix--) {
          $SELECTED = ($ix == $YearSet)? " SELECTED" : "";
          $Selector['Y'].=
          "<OPTION VALUE=$ix$SELECTED> &nbsp; $ix &nbsp;</OPTION>\n";
        }
      }

      $Selector['Y'].=
      "</SELECT> &nbsp; ";
    }

    $Order = strtoupper($Order);
    list($P1, $P2, $P3) = $Order;

    $DateSelector = $Selector[$P1].$Selector[$P2].$Selector[$P3];

    return $DateSelector;
  }

 /*
  *  Perform GET on a URL with optional auth and custom headers
  *    $URL        = URL to GET
  *    $DataStream = Optional associative array of data to include in the query
  *    $UP         = Optional username:password
  *    $Headers    = Optional associative array of custom headers
  */
  function hl_GetIt($URL, $DataStream = '', $UP='', $Headers = '') {
    // Strip http:// from the URL if present
    $URL = ereg_replace('^http://', '', $URL);

    // Separate into Host and URI
    $Host = substr($URL, 0, strpos($URL, '/'));
    $URI = strstr($URL, '/');

    // Form the query string
    if (is_array($DataStream)) {
      $QString = '';
      while (list($key, $val) = each($DataStream)) {
        if ($QString) $QString.= '&';
        $QString.= $key.'='.urlencode($val);
      }
      $URI.= '?'.$QString;
    }

    // Form auth header
    if ($UP) $AuthHeader = 'Authorization: Basic '.base64_encode($UP).'\n';

    // Form other headers
    if (is_array($Headers)) {
      while (list($HeaderName, $HeaderVal) = each($Headers)) {
        $OtherHeaders.= "$HeaderName: $HeaderVal\n";
      }
    }

    // Form the request
    $ReqHeader =
      "GET $URI HTTP/1.0\n".
      "Host: $Host\n".
      $AuthHeader.
      $OtherHeaders.
      "User-Agent: GetIt 2.0\n\n";

    // Open the connection to the host
    $socket = fsockopen($Host, 80, $errno, $errstr);
    if (!$socket) {
      $Result['errno'] = $errno;
      $Result['errstr'] = $errstr;
      return $Result;
    }

    // Send the request
    fputs($socket, $ReqHeader);

    // Receive the response
    while (!feof($socket) && $line != "0\r\n") {
      $line = fgets($socket, 128);
      $Result[] = $line;
    }

    $Return['Response'] = implode('', $Result);

    list(,$StatusLine) = each($Result);
    unset($Result[0]);
    preg_match('=HTTP/... ([0-9]{3}) (.*)=', $StatusLine, $Matches);

    $Return['Status']   = trim($Matches[0]);
    $Return['StatCode'] = $Matches[1];
    $Return['StatMesg'] = trim($Matches[2]);

    do {
      list($IX, $line) = each($Result);
      $line = trim($line);

      unset($Result[$IX]);

      if (strlen($line)) {
        list($Header, $Value) = explode(': ', $line, 2);
        $Return[$Header] = $Value;
      }
    }
    while (strlen($line));

    $Return['Body'] = implode('', $Result);

    return $Return;
  }

 /*
  *  Line-wrap a string, observing word boundaries
  *    $string = The string to be wrapped
  *    $width  = Where to break the string
  *    $break  = Break character(s). Default is linebreak.
  */
  function hl_LineWrap(&$string, $width = 75, $break = -1) {
    if ($break == -1) $break = str_replace(' ', '', "
    ");

    $segments = explode($break, $string);

    while (list($segkey, $segment) = each($segments)) {
      $rstr = ''; $cptr = 0;
      $strlen = strlen($segment);

      while ($cptr < $strlen) {
        $chunk = substr($segment, $cptr, $width);
        $breaker = '';
        if (strlen($chunk) == $width) {
          $breaker = $break;
          $chunk = ereg_replace("([ -])[^ -]*$", "\\1", $chunk);
        }
        $cptr+= strlen($chunk); $rstr.= "$chunk$breaker";
      }

      $segments[$segkey] = $rstr;
    }

    $string = implode($break, $segments);
  }

/*
  Function to validate a number with the Luhn Mod 10 formula.
  Returns true if the number is valid, false otherwise. */
  function hl_LuhnMod10($Number) {
    if (!strlen($Number)) return false;

    // The Luhn formula works right to left, so reverse the number.
    $Number = strrev($Number);

    $Total = 0;

    for ($x=0; $x<strlen($Number); $x++) {
      $digit = substr($Number,$x,1);

      // If it's an odd digit, double it
      if ($x/2 != floor($x/2)) {
        $digit *= 2;

        // If the result is two digits, add them
        if (strlen($digit) == 2)
          $digit = substr($digit,0,1) + substr($digit,1,1);
      }

      // Add the current digit, doubled and added if applicable, to the Total
      $Total += $digit;
    }

    // If the Total is evenly divisible by 10, it's cool!
    if ($Total % 10 == 0) return true; else return false;
  }

 /*
  *  Parse specified tags from HTML
  *    $HTML      = HTML to be parsed
  *    $TagList   = Comma-separated list of tags to look for
  *    $CloseTags = Find closing tags as well
  *    $Reverse   = Reverse-sort the result array.
  */
  function hl_ParseHTML($HTML, $TagList, $ParseTags = true,
                        $CloseTags = false, $Reverse = false) {

    $TagList = split(", *", $TagList);

    while (list(,$Tag) = each($TagList)) {
      $Pattern[] = "<{$Tag}[^>]*>";
      if ($CloseTags) $Pattern[] = "</{$Tag}[^>]*>";
    }

    $Pattern = '='.implode('|', $Pattern).'=i';

    preg_match_all($Pattern, $HTML, $Matches, PREG_OFFSET_CAPTURE);
    $Matches = $Matches[0];

    while (list(, $Match) = each($Matches)) {
      $Tag    = $Match[0];
      $Offset = $Match[1];

      $NumQuotes = preg_match_all('="=', $Tag, $devnul);

      // Handle > inside of "" in the tag
      while (!is_int($NumQuotes / 2)) {
        $LastQuote = strrpos($Tag, '"') + $Offset;
        $NextQuote = strpos($HTML, '"', $LastQuote + 1);

        // An unclosed quote somewhere -- avoid infinite loop
        if (!$NextQuote) {
          $Tag = $Match[0];
          break;
        }

        $NextAngle = strpos($HTML, '>', $NextQuote);

        $Tag = substr($HTML, $Offset, $NextAngle - $Offset + 1);

        $NumQuotes = preg_match_all('="=', $Tag, $devnul);

        unset($LastQuote, $NextQuote);
      }

      $TagTable[$Offset]['tag'] = $Tag;
      $TagTable[$Offset]['len'] = strlen($Tag);
    }

    if (is_array($TagTable)) {
      if ($Reverse) krsort($TagTable);
      if ($ParseTags) $TagTable = hl_ParseTag($TagTable);
      reset($TagTable);
      return $TagTable;
    }
    else return false;
  }

 /*
  *  Parse a name into first, middle, last, suffix
  *    $Name = The name to be parsed
  */
  function hl_ParseName($Name, $Predicate = false) {
    $Parts = array (
      'Prefix', 'FirstName', 'MiddleName', 'Predicate', 'LastName', 'Suffix'
    );

    $Prefices = array (
      'mr', 'mrs', 'ms', 'miss', 'sr', 'sra', 'srta', 'm', 'mme',
      'mlle', 'hr', 'fr', 'frl', 'dr', 'hon'
    );

    $Predicates = array (
      'di', 'de', 'van', 'von', 'le', 'la', 'da', 'zu', 'zum', 'auf',
      'dem', 'ap', 'des', 'del', 'dei', 'ten', "van't", 'ter', 'den',
      'al', 'bin', 'ibn', 'ferch', 'merch', 'verch', 'der', 'bon'
    );

    $Suffices = array (
      'jr', 'sr', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix', 'x'
    );

    $Name = trim($Name);
    $Name = ereg_replace(',',   ' ', $Name);
    $Name = ereg_replace('  +', ' ', $Name);

    $Name = explode(' ', $Name);

    $MidStart = 1;

    $pn_FirstName = $Name[0];
    $pn_FirstName = ereg_replace("[^A-Za-z'-]", '', $pn_FirstName);
    
    if (in_array(strtolower($pn_FirstName), $Prefices)) {
      $pn_Prefix = $pn_FirstName;
      $pn_FirstName = $Name[1];
      $MidStart = 2;
    }

    $LastPart = count($Name) - 1;
    if ($LastPart > 0) $pn_LastName = $Name[$LastPart];
    $pn_LastName = ereg_replace("[^A-Za-z'-]", '', $pn_LastName);

    if (in_array(strtolower($pn_LastName), $Suffices)) {
      $pn_Suffix = $pn_LastName;
      $LastPart--;
      if ($LastPart >= $MidStart) $pn_LastName = $Name[$LastPart];
      else                        $pn_LastName = '';
    }

    $ck_Predicate = $Name[$LastPart - 1];

    while (in_array(strtolower($ck_Predicate), $Predicates)) {
      if ($Predicate) {
        $pn_Predicate = "$ck_Predicate $pn_Predicate";
      }
      else {
        $pn_LastName = "$ck_Predicate $pn_LastName";
      }

      $LastPart--;
      $ck_Predicate = $Name[$LastPart - 1];
    }

    $pn_Predicate = trim($pn_Predicate);

    for ($x=$MidStart; $x<$LastPart; $x++) {
      $pn_MiddleName.= $Name[$x].' ';
    }

    $pn_MiddleName = trim($pn_MiddleName);

    while (list(,$Part) = each($Parts)) {
      if ($Part == 'Predicate' && !$Predicate) continue;

      $NamePart  = 'pn_'.$Part;
      $PartValue = $$NamePart;

      $Result[$Part] = $PartValue;
    }

    return $Result;
  }

 /*
  *  Parse attributes from an HTML tag
  *    $Tag = Tag to be parsed
  */
  function hl_ParseTag($Tags) {
    $Search  = array(' ', "\r", "\n");
    $Replace = array('&!nbsp;', '&!#013;', '&!#010;');

    if (!is_array($Tags)) {
      $Tags = array (
        array('tag' => $Tags, 'len' => strlen($Tags))
      );
    }

    while (list($Index, $Tag) = each($Tags)) {
      if (is_array($Tag)) $Tag = $Tag['tag'];
      else {
        unset($Tags[$Index]);
        $Tags[$Index]['tag'] = $Tag;
        $Tags[$Index]['len'] = strlen($Tag);
      }

      // Preserve spaces and line breaks in the attribute values
      preg_match_all('="[^"]*"=', $Tag, $Matches, PREG_OFFSET_CAPTURE);
      $Matches = $Matches[0];

      $Matches = array_reverse($Matches);

      while (list(,$Match) = each($Matches)) {
        $Value  = $Match[0];
        $Offset = $Match[1];

        $Tag = substr_replace($Tag, str_replace($Search, $Replace, $Value), $Offset, strlen($Value));
      }

      // Clean up the tag; one space between attributes, and none around = chars.
      $Tag = preg_replace('=^<|>$=',    '',  $Tag);
      $Tag = preg_replace("=\r|\n|\t=", ' ', $Tag);
      $Tag = preg_replace('=  +=',      ' ', $Tag);
      $Tag = preg_replace(': *= *:',    '=', $Tag);
      $Tag = trim($Tag);

      $Tag = explode(' ', $Tag);

      $SetType = true;
      while (list(,$AttVal) = each($Tag)) {
        list($Att, $Val) = explode('=', $AttVal, 2);

        $Att = strtoupper($Att);

        if (!isset($Val)) $Val = true;
        else {
          $Val = str_replace($Replace, $Search, $Val);
          $Val = preg_replace('=^"|"$=', '', $Val);
        }

        if ($SetType) {
          $Val = $Att;
          $Att = 'TAG';
          $SetType = false;
        }

        $Tags[$Index][$Att] = $Val;
      }
    }

    return $Tags;
  }

 /*
  * POST data to a URL with optional auth and custom headers
  *   $URL        = URL to POST to
  *   $DataStream = Associative array of data to POST
  *   $UP         = Optional username:password
  *   $Headers    = Optional associative array of custom headers
  */
  function hl_PostIt($URL, $DataStream, $UP='', $Headers = '') {
    // Strip http:// from the URL if present
    $URL = ereg_replace('^http://', '', $URL);

    // Separate into Host and URI
    $Host = substr($URL, 0, strpos($URL, '/'));
    $URI = strstr($URL, '/');

    // Form up the request body
    $ReqBody = '';
    while (list($key, $val) = each($DataStream)) {
      if ($ReqBody) $ReqBody.= '&';
      $ReqBody.= $key.'='.urlencode($val);
    }
    $ContentLength = strlen($ReqBody);

    // Form auth header
    if ($UP) $AuthHeader = 'Authorization: Basic '.base64_encode($UP)."\n";

    // Form other headers
    if (is_array($Headers)) {
      while (list($HeaderName, $HeaderVal) = each($Headers)) {
        $OtherHeaders.= "$HeaderName: $HeaderVal\n";
      }
    }

    // Generate the request
    $ReqHeader =
      "POST $URI HTTP/1.0\n".
      "Host: $Host\n".
      "User-Agent: PostIt 2.0\n".
      $AuthHeader.
      $OtherHeaders.
      "Content-Type: application/x-www-form-urlencoded\n".
      "Content-Length: $ContentLength\n\n".
      "$ReqBody\n";

    // Open the connection to the host
    $socket = fsockopen($Host, 80, $errno, $errstr);
    if (!$socket) {
      $Result["errno"] = $errno;
      $Result["errstr"] = $errstr;
      return $Result;
    }

    // Send the request
    fputs($socket, $ReqHeader);

    // Receive the response
    while (!feof($socket) && $line != "0\r\n") {
      $line = fgets($socket, 128);
      $Result[] = $line;
    }

    $Return['Response'] = implode('', $Result);

    list(,$StatusLine) = each($Result);
    unset($Result[0]);
    preg_match('=HTTP/... ([0-9]{3}) (.*)=', $StatusLine, $Matches);

    $Return['Status']   = trim($Matches[0]);
    $Return['StatCode'] = $Matches[1];
    $Return['StatMesg'] = trim($Matches[2]);

    do {
      list($IX, $line) = each($Result);
      $line = trim($line);

      unset($Result[$IX]);

      if (strlen($line)) {
        list($Header, $Value) = explode(': ', $line, 2);
        $Return[$Header] = $Value;
      }
    }
    while (strlen($line));

    $Return['Body'] = implode('', $Result);

    return $Return;
  }

 /*
  *  Say a number in words (uses American billions)
  *    $Number = The number to spell out
  *    $Punctuation:
  *      - Use hyphens, for example fifty-four
  *      , Use commas between thousands
  *      ^ Capitalize words
  */
  function hl_SayNum($Number, $Punctuation = '-', $Language = 'en') {
    $Numbers['en'] = array (
    'Orders' => array ('',
      'thousand', 'million', 'billion', 'trillion',
      'quadrillion', 'quintillion' // Easily extended if needed
    ),

    'Ones' => array ('',
      'one', 'two', 'three', 'four', 'five',
      'six', 'seven', 'eight', 'nine'
    ),

    'Tens' => array ('',
      'teen', 'twenty', 'thirty', 'forty', 'fifty',
      'sixty', 'seventy', 'eighty', 'ninety'
    ),

    'Teens' => array (
      10 => 'ten', 11 => 'eleven', 12 => 'twelve', 13 => 'thirteen',
      14 => 'fourteen', 15 => 'fifteen', 16 => 'sixteen', 17 => 'seventeen',
      18 => 'eighteen', 19 => 'nineteen'
    ),

    'Zero'    => 'zero',
    'Hundred' => 'hundred'
    );

    $Numbers['es'] = array (
    'Orders' => array ('',
      'mil', 'millón', 'mil millones', 'trillón',
      'quadrillion', 'quintillion' // Easily extended if needed
    ),

    'Ones' => array ('',
      'uno', 'dos', 'tres', 'cuatro', 'cinco',
      'seis', 'siete', 'ocho', 'nueve'
    ),

    'Tens' => array ('',
      'teen', 'veinte', 'treinta', 'cuarenta', 'cincuenta',
      'sesenta', 'setenta', 'ochenta', 'noventa'
    ),

    'Teens' => array (
      10 => 'diez', 11 => 'once', 12 => 'doce', 13 => 'trece',
      14 => 'catorce', 15 => 'quince', 16 => 'dieciséis', 17 => 'diecisiete',
      18 => 'dieciocho', 19 => 'diecinueve'
    ),

    'Zero' => 'cero',
    'Hundred' => 'ciento'
    );

    extract($Numbers[$Language]);

    if ($Number == 0) return $Zero;

    $Hyphen = (ereg('-',  $Punctuation))? '-' : ' ';
    $Commas =  ereg(',',  $Punctuation);
    $UCase  =  ereg('\^', $Punctuation);

    if (substr($Number, 0, 1) == '-') {
      $Sign = "minus";
      $Number = substr($Number, 1);
    }

    $Number = ereg_replace('[^0-9]', '', $Number);

    $Number = strrev($Number);
    $Segments = explode(' ', trim(chunk_split($Number, 3, ' ')));

    while (list($Order, $Segment) = each($Segments)) {
      $Segment = strrev($Segment);

      $Digit = explode(' ', trim(chunk_split($Segment, 1, ' ')));
      $Digit = array_reverse($Digit);

      if ($Digit[1]) {
        if ($Digit[1] == 1) $Segment = $Teens[$Digit[1].$Digit[0]];
        else {
          $Segment = $Tens[$Digit[1]];
          if ($Digit[0]) $Segment.= $Hyphen.$Ones[$Digit[0]];
        }
      }
      else $Segment = $Ones[$Digit[0]];

      if ($Digit[2]) $Segment = $Ones[$Digit[2]]." $Hundred ".$Segment;

      $Comma = ($Commas && $Order > 0)? ',' : '';
      if (strlen($Segment)) $SayIt = $Segment.' '.$Orders[$Order]."$Comma ".$SayIt;
    }

    $SayIt = $Sign.' '.$SayIt;
    $SayIt = trim($SayIt);

    if ($UCase) $SayIt = ucwords($SayIt);

    return $SayIt;
  }

 /*
  * Calculate the number of days, hours, minutes and seconds between two times
  *   $Time1 = The starting time, as a Unix timestamp
  *   $Time2 = The ending time, as a Unix timestamp
  */
  function hl_TimeTil($Time1, $Time2) {
    $TimeDiff = $Time2 - $Time1;

    $NumDays  = floor($TimeDiff / 86400);              $Counted = $NumDays  * 86400;
    $NumHours = floor(($TimeDiff - $Counted) / 3600);  $Counted+= $NumHours * 3600;
    $NumMins  = floor(($TimeDiff - $Counted) / 60);    $Counted+= $NumMins  * 60;
    $NumSecs  = $TimeDiff - $Counted;

    return array (
      'Days'    => $NumDays,
      'Hours'   => $NumHours,
      'Minutes' => $NumMins,
      'Seconds' => $NumSecs
    );
  }

 /*
  * Converts a string to title case
  *   $String     = The string to be converted
  *   $Separators = Optional list of word separators
  */
  function hl_TitleCase(&$String, $Separators = " \9\10\11\12\13-") {
    $Search = array (
      ' Of ', ' And ', ' Or ', ' The ', ' To '
    );

    $Replace = array (
      ' of ', ' and ', ' or ', ' the ', ' to '
    );

    if (!strlen($Separators))  $Separators = " \9\10\11\12\13-"; // Idiot-proofing
    if ($Separators[0] == "+") $Separators = " \9\10\11\12\13-".substr($Separators, 1);

    // If there's a hyphen move it to the end for the regex
    if (ereg("-", $Separators)) $Separators = str_replace("-", "", $Separators)."-";

    $String = strtolower(trim($String));

    $String = $Separators[0].$String;
    $Separators = str_replace("^", "\^", $Separators);
    while (ereg("([$Separators])([a-z])", $String, $regs)) {
      $String = str_replace($regs[0], $regs[1].strtoupper($regs[2]), $String);
    }
    $String = substr($String, 1);
    
    $String = str_replace($Search, $Replace, $String);
  }

 /*
  * Validate a credit card number
  *   $CardNum = The number to validate
  *   $Type    = Optional card-type code
  *   $Exp     = Optional expiration date
  */
  function hl_ValCard($CardNum, $Exp = "", $Type = "n/a") {
    // Check the expiration date first
    if (strlen($Exp)) {
      $Month = substr($Exp, 0, 2);
      $Year  = substr($Exp, -2);

      $WorkDate = "$Month/01/$Year";
      $WorkDate = strtotime($WorkDate);
      $LastDay  = date("t", $WorkDate);

      $Expires  = strtotime("$Month/$LastDay/$Year 23:59:59");
      if ($Expires < time()) return 0;
    }

    // Innocent until proven guilty
    $GoodCard = true;

    // Get rid of any non-digits
    $CardNum = ereg_replace("[^0-9]", "", $CardNum);

    // Perform card-specific checks, if applicable
    switch ($Type) {
    case "mcd" :
      $GoodCard = ereg("^5[1-5].{14}$", $CardNum);
      break;

    case "vis" :
      $GoodCard = ereg("^4.{15}$|^4.{12}$", $CardNum);
      break;

    case "amx" :
      $GoodCard = ereg("^3[47].{13}$", $CardNum);
      break;

    case "dsc" :
      $GoodCard = ereg("^6011.{12}$", $CardNum);
      break;

    case "dnc" :
      $GoodCard = ereg("^30[0-5].{11}$|^3[68].{12}$", $CardNum);
      break;

    case "jcb" :
      $GoodCard = ereg("^3.{15}$|^2131|1800.{11}$", $CardNum);
      break;
  
    case "dlt" :
      $GoodCard = ereg("^4.{15}$", $CardNum);
      break;

    case "swi" :
      $GoodCard = ereg("^[456].{15}$|^[456].{17,18}$", $CardNum);
      break;

    case "enr" :
      $GoodCard = ereg("^2014.{11}$|^2149.{11}$", $CardNum);
      break;
    }

    // If it passed (or bypassed) the date and card-specific checks
    // and passes the Luhn Mod 10 check, it's cool!
    return ($GoodCard && hl_LuhnMod10($CardNum));
  }

 /*
  * Validate an email address
  *   $Addr    = The address to check
  *   $Level   = The level of checking to perform
  *   $Fail    = The level at which the validation failed
  *   $Timeout = Optional timeout for mail server response
  */
  function hl_ValEmail($Addr, &$Fail, $Level = 2, $Timeout = 3) {

    // Valid Top-Level Domains
    $gTLDs = "com:net:org:edu:gov:mil:int:arpa:aero:biz:coop:info:museum:name:";
    $CCs   = 
      "ad:ae:af:ag:ai:al:am:an:ao:aq:ar:as:at:au:aw:az:ba:bb:bd:be:bf:bg:bh:".
      "bi:bj:bm:bn:bo:br:bs:bt:bv:bw:by:bz:ca:cc:cf:cd:cg:ch:ci:ck:cl:cm:cn:".
      "co:cr:cs:cu:cv:cx:cy:cz:de:dj:dk:dm:do:dz:ec:ee:eg:eh:er:es:et:fi:fj:".
      "fk:fm:fo:fr:fx:ga:gb:gd:ge:gf:gh:gi:gl:gm:gn:gp:gq:gr:gs:gt:gu:gw:gy:".
      "hk:hm:hn:hr:ht:hu:id:ie:il:in:io:iq:ir:is:it:jm:jo:jp:ke:kg:kh:ki:km:".
      "kn:kp:kr:kw:ky:kz:la:lb:lc:li:lk:lr:ls:lt:lu:lv:ly:ma:mc:md:mg:mh:mk:".
      "ml:mm:mn:mo:mp:mq:mr:ms:mt:mu:mv:mw:mx:my:mz:na:nc:ne:nf:ng:ni:nl:no:".
      "np:nr:nt:nu:nz:om:pa:pe:pf:pg:ph:pk:pl:pm:pn:pr:pt:pw:py:qa:re:ro:ru:".
      "rw:sa:sb:sc:sd:se:sg:sh:si:sj:sk:sl:sm:sn:so:sr:st:su:sv:sy:sz:tc:td:".
      "tf:tg:th:tj:tk:tm:tn:to:tp:tr:tt:tv:tw:tz:ua:ug:uk:um:us:uy:uz:va:vc:".
      "ve:vg:vi:vn:vu:wf:ws:ye:yt:yu:za:zm:zr:zw:";

    $cTLDs =
      "com:net:org:edu:gov:mil:co:ne:or:ed:go:mi:aero:biz:coop:info:museum:name:";

    $Fail = 0;
    $Addr = trim(strtolower($Addr));

    if (ereg(' ', $Addr)) $Fail = 1;

    $UD = explode('@', $Addr);
    if (sizeof($UD) != 2 || !$UD[0]) $Fail = 1;

    $Levels = explode('.', $UD[1]); $sLevels = sizeof($Levels);
    if (!$Levels[0] || !$Levels[1]) $Fail = 1;

    $tld = $Levels[$sLevels-1];
    $tld = ereg_replace('[>)}]$|]$', '', $tld);
    if (strlen($tld) < 2
    || (strlen($tld) > 3 && !ereg(":$tld:", ':arpa:aero:coop:info:museum:name:'))) $Fail = 1;

    $Level--;

    if ($Level && !$Fail) {
      $Level--;
      if (!ereg($tld.':', $gTLDs) && !ereg($tld.':', $CCs)) $Fail = 2;
    }

    if ($Level && !$Fail) {
      $cd = $sLevels - 2; $domain = $Levels[$cd].'.'.$tld;
      if (ereg($Levels[$cd].':', $cTLDs)) { $cd--; $domain = $Levels[$cd].'.'.$domain; }
    }

    if ($Level && !$Fail) {
      $Level--;
      if (!getmxrr($domain, $mxhosts, $weight)) $Fail = 3;
    }

    if ($Level && !$Fail) {
      $Level--;
      while (!$sh && list($nul, $mxhost) = each($mxhosts)) $sh = fsockopen($mxhost, 25);
      if (!$sh) $Fail=4;
    }

    if ($Level && !$Fail) {
      $Level--;
      $out = "";
      socket_set_blocking($sh, false);
      $WaitTil = time() + $Timeout;
      while ($WaitTil > time() && !$out) $out = fgets($sh, 256);
      if (!ereg('^220', $out)) $Fail = 5;
    }

    if ($sh) fclose($sh);

    if ($Fail) return false; else return true;
  }

 /*
  *  Variable Substitution function.
  *    $string    = String to be processed
  *    $KeepNulls = Keep placeholder if the variable evaluates to null
  *    $Prefix    = Variables with this prefix are skipped
  *    $Delim     = Pattern delimiters
  */
  function hl_VarSub(&$hl_string, $hl_KeepNulls = false, $hl_Prefix = '', $hl_Delim = '{}') {
    global $hl_AltPattern;

    $hl_LD  = substr($hl_Delim, 0, 1);
    $hl_RD  = substr($hl_Delim, -1);
    $hl_RD1 = $hl_RD;

    $hl_LD = quotemeta($hl_LD.$hl_LD);
    $hl_RD = quotemeta($hl_RD.$hl_RD);

    $hl_Pattern = ".$hl_LD([^$hl_RD1]*)$hl_RD.";

    $hl_NamePattern = '=[^[]*=';

    $hl_ValidPattern = ($hl_AltPattern)
      ? '^([A-Za-z_][A-Za-z0-9_]*)$'
      : '^([A-Za-z€-ÿ_][A-Za-z€-ÿ0-9_]*)$';

    preg_match_all($hl_Pattern, $hl_string, $hl_Matches);
    $hl_Variables = $hl_Matches[1];
    $hl_Matches   = $hl_Matches[0];

    // Separate the name from any indices, and globalize it.
    while (list($hl_Index, $hl_Variable) = each($hl_Variables)) {
      // Check for a length component
      if (ereg('(.*),([0-9]*\.?)$', $hl_Variable, $hl_regs)) {
        $hl_Variable              = $hl_regs[1];
        $hl_Variables[$hl_Index]  = $hl_regs[1];
        $hl_ValLength             = $hl_regs[2];

        if (ereg('([0-9]*)\.$', $hl_ValLength, $hl_regs)) {
          $hl_Ellipse[$hl_Index] = true;
          $hl_ValLength = $hl_regs[1];
        }

        $hl_ValLengths[$hl_Index] = $hl_ValLength;
      }

      preg_match($hl_NamePattern, $hl_Variable, $hl_VarMatches);
      $hl_VarName = $hl_VarMatches[0];
      global $$hl_VarName;
      $hl_VarNames[$hl_Index] = $hl_VarName;
    }

    // Process the matches
    while (list($hl_Index, $hl_Match) = each($hl_Matches)) {
      $hl_VarName   = $hl_VarNames[$hl_Index];
      $hl_ValLength = $hl_ValLengths[$hl_Index];

      if (strlen($hl_Prefix) && ereg("^$hl_Prefix", $hl_VarName)) continue;

      if (!ereg($hl_ValidPattern, $hl_VarName)) continue;

      else {
        $hl_Variable = $hl_Variables[$hl_Index];
        eval('$hl_Value = $'.$hl_Variable.';');

        if ($hl_ValLength && strlen($hl_Value) > $hl_ValLength) {
          if ($hl_Ellipse[$hl_Index])
            $hl_Value = substr($hl_Value, 0, $hl_ValLength - 3).'...';
          else
            $hl_Value = substr($hl_Value, 0, $hl_ValLength);
        }

        if ($hl_KeepNulls && !isset($hl_Value)) continue;

        $hl_Replace = $hl_Value;
      }
      $hl_string = str_replace($hl_Match, $hl_Replace, $hl_string);
    }
  }

  $hl_Months['01'] = "January";   $hl_Months['1']  = "January";
  $hl_Months['02'] = "February";  $hl_Months['2']  = "February";
  $hl_Months['03'] = "March";     $hl_Months['3']  = "March";
  $hl_Months['04'] = "April";     $hl_Months['4']  = "April";
  $hl_Months['05'] = "May";       $hl_Months['5']  = "May";
  $hl_Months['06'] = "June";      $hl_Months['6']  = "June";
  $hl_Months['07'] = "July";      $hl_Months['7']  = "July";
  $hl_Months['08'] = "August";    $hl_Months['8']  = "August";
  $hl_Months['09'] = "September"; $hl_Months['9']  = "September";
  $hl_Months['10'] = "October";
  $hl_Months['11'] = "November";
  $hl_Months['12'] = "December";

  $hl_Months['01s'] = "Jan";  $hl_Months['1s']  = "Jan";
  $hl_Months['02s'] = "Feb";  $hl_Months['2s']  = "Feb";
  $hl_Months['03s'] = "Mar";  $hl_Months['3s']  = "Mar";
  $hl_Months['04s'] = "Apr";  $hl_Months['4s']  = "Apr";
  $hl_Months['05s'] = "May";  $hl_Months['5s']  = "May";
  $hl_Months['06s'] = "Jun";  $hl_Months['6s']  = "Jun";
  $hl_Months['07s'] = "Jul";  $hl_Months['7s']  = "Jul";
  $hl_Months['08s'] = "Aug";  $hl_Months['8s']  = "Aug";
  $hl_Months['09s'] = "Sep";  $hl_Months['9s']  = "Sep";
  $hl_Months['10s'] = "Oct";
  $hl_Months['11s'] = "Nov";
  $hl_Months['12s'] = "Dec";

  $hl_HoloLibLoaded = true;
?>
Return current item: Hololib